0
# PNPM Create CAFS Store
1
2
PNPM Create CAFS Store provides functionality for creating Content Addressable File System (CAFS) store controllers within the pnpm package manager ecosystem. It implements package importing mechanisms with multiple strategies for efficiently managing package files in the pnpm global store.
3
4
## Package Information
5
6
- **Package Name**: @pnpm/create-cafs-store
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `pnpm add @pnpm/create-cafs-store`
10
11
## Core Imports
12
13
```typescript
14
import { createCafsStore, createPackageImporterAsync, type CafsLocker } from "@pnpm/create-cafs-store";
15
```
16
17
For CommonJS:
18
19
```javascript
20
const { createCafsStore, createPackageImporterAsync } = require("@pnpm/create-cafs-store");
21
```
22
23
## Basic Usage
24
25
```typescript
26
import { createCafsStore } from "@pnpm/create-cafs-store";
27
28
// Create a CAFS store controller
29
const cafsStore = createCafsStore("/path/to/pnpm-store", {
30
packageImportMethod: "hardlink",
31
ignoreFile: (filename) => filename.startsWith("."),
32
});
33
34
// The store provides CAFS operations and package importing
35
const tempDir = await cafsStore.tempDir();
36
const result = cafsStore.addFilesFromDir("/path/to/package");
37
38
// Import a package using the built-in importer
39
const importResult = cafsStore.importPackage("/target/path", {
40
filesResponse: packageFilesResponse,
41
force: false,
42
requiresBuild: false,
43
});
44
```
45
46
## Capabilities
47
48
### Create CAFS Store
49
50
Creates a complete CAFS store controller with package importing capabilities.
51
52
```typescript { .api }
53
function createCafsStore(
54
storeDir: string,
55
opts?: {
56
ignoreFile?: (filename: string) => boolean;
57
importPackage?: ImportIndexedPackage;
58
packageImportMethod?: 'auto' | 'hardlink' | 'copy' | 'clone' | 'clone-or-copy';
59
cafsLocker?: CafsLocker;
60
}
61
): Cafs;
62
```
63
64
**Parameters:**
65
- `storeDir` (string): Directory path for the CAFS store
66
- `opts` (optional object): Configuration options
67
- `ignoreFile`: Function to determine if a file should be ignored during operations
68
- `importPackage`: Custom package importer function for indexed packages
69
- `packageImportMethod`: Strategy for importing package files (defaults to 'auto')
70
- `cafsLocker`: CAFS locking mechanism to prevent concurrent access issues
71
72
**Returns:** `Cafs` interface providing complete store operations including file operations, package importing, and temporary directory creation
73
74
### Create Package Importer (Async)
75
76
Creates an asynchronous package importer function with configurable import strategies.
77
78
```typescript { .api }
79
function createPackageImporterAsync(
80
opts: {
81
importIndexedPackage?: ImportIndexedPackageAsync;
82
packageImportMethod?: 'auto' | 'hardlink' | 'copy' | 'clone' | 'clone-or-copy';
83
storeDir: string;
84
}
85
): ImportPackageFunctionAsync;
86
```
87
88
**Parameters:**
89
- `opts` (object): Configuration options
90
- `importIndexedPackage`: Custom async package importer for indexed packages
91
- `packageImportMethod`: Strategy for importing package files
92
- `storeDir`: Directory path for the store
93
94
**Returns:** `ImportPackageFunctionAsync` function that can import packages asynchronously
95
96
## Types
97
98
### CafsLocker
99
100
Type for CAFS locking mechanism to prevent concurrent access to the same files.
101
102
```typescript { .api }
103
type CafsLocker = Map<string, number>;
104
```
105
106
A map that tracks file paths to lock counts, ensuring thread-safe operations on the CAFS store.
107
108
### Cafs Interface
109
110
Complete interface returned by `createCafsStore` providing all CAFS operations.
111
112
```typescript { .api }
113
interface Cafs {
114
/** Directory path of the CAFS store */
115
storeDir: string;
116
117
/** Add files from a directory to the store */
118
addFilesFromDir: (dir: string) => AddToStoreResult;
119
120
/** Add files from a tarball buffer to the store */
121
addFilesFromTarball: (buffer: Buffer) => AddToStoreResult;
122
123
/** Get the file path for an index file in CAFS */
124
getIndexFilePathInCafs: (integrity: string | IntegrityLike, fileType: FileType) => string;
125
126
/** Get the file path based on file mode in CAFS */
127
getFilePathByModeInCafs: (integrity: string | IntegrityLike, mode: number) => string;
128
129
/** Import a package using the configured strategy */
130
importPackage: ImportPackageFunction;
131
132
/** Create a temporary directory within the store */
133
tempDir: () => Promise<string>;
134
}
135
```
136
137
### Import Function Types
138
139
Types for package import operations with different synchronization models.
140
141
```typescript { .api }
142
type ImportPackageFunction = (
143
to: string,
144
opts: ImportPackageOpts
145
) => { isBuilt: boolean; importMethod: string | undefined };
146
147
type ImportPackageFunctionAsync = (
148
to: string,
149
opts: ImportPackageOpts
150
) => Promise<{ isBuilt: boolean; importMethod: string | undefined }>;
151
152
type ImportIndexedPackage = (
153
to: string,
154
opts: ImportOptions
155
) => string | undefined;
156
157
type ImportIndexedPackageAsync = (
158
to: string,
159
opts: ImportOptions
160
) => Promise<string | undefined>;
161
```
162
163
### Import Options
164
165
Configuration options for package import operations.
166
167
```typescript { .api }
168
interface ImportPackageOpts {
169
/** Disable relinking of local directory dependencies */
170
disableRelinkLocalDirDeps?: boolean;
171
172
/** Whether the package requires building */
173
requiresBuild?: boolean;
174
175
/** Cache key for side effects */
176
sideEffectsCacheKey?: string;
177
178
/** Package files response containing file metadata */
179
filesResponse: PackageFilesResponse;
180
181
/** Force import even if files exist */
182
force: boolean;
183
184
/** Keep existing modules directory */
185
keepModulesDir?: boolean;
186
}
187
188
interface ImportOptions {
189
/** Disable relinking of local directory dependencies */
190
disableRelinkLocalDirDeps?: boolean;
191
192
/** Map of file paths to their locations in CAFS */
193
filesMap: Record<string, string>;
194
195
/** Force import operation */
196
force: boolean;
197
198
/** Source location of the resolved package */
199
resolvedFrom: ResolvedFrom;
200
201
/** Keep existing modules directory */
202
keepModulesDir?: boolean;
203
}
204
```
205
206
### Package Files Types
207
208
Types for package file metadata and responses.
209
210
```typescript { .api }
211
type PackageFiles = Record<string, PackageFileInfo>;
212
213
interface PackageFileInfo {
214
/** Last check timestamp (nullable for backward compatibility) */
215
checkedAt?: number;
216
217
/** File integrity hash */
218
integrity: string;
219
220
/** File permission mode */
221
mode: number;
222
223
/** File size in bytes */
224
size: number;
225
}
226
227
type PackageFilesResponse = {
228
/** Source location of resolved package */
229
resolvedFrom: ResolvedFrom;
230
231
/** Import method to use for this package */
232
packageImportMethod?: 'auto' | 'hardlink' | 'copy' | 'clone' | 'clone-or-copy';
233
234
/** Side effects applied to package files */
235
sideEffects?: SideEffects;
236
237
/** Whether package requires building */
238
requiresBuild: boolean;
239
} & (
240
| { unprocessed?: false; filesIndex: Record<string, string> }
241
| { unprocessed: true; filesIndex: PackageFiles }
242
);
243
244
type ResolvedFrom = 'store' | 'local-dir' | 'remote';
245
246
type SideEffects = Record<string, SideEffectsDiff>;
247
248
interface SideEffectsDiff {
249
/** Files deleted by side effects */
250
deleted?: string[];
251
252
/** Files added by side effects */
253
added?: PackageFiles;
254
}
255
```
256
257
### File and Store Types
258
259
Additional types for file operations and store results.
260
261
```typescript { .api }
262
type FileType = 'exec' | 'nonexec' | 'index';
263
264
interface FilesIndex {
265
/** File metadata mapped by filename */
266
[filename: string]: {
267
/** File permission mode */
268
mode: number;
269
/** File size in bytes */
270
size: number;
271
} & FileWriteResult;
272
}
273
274
interface FileWriteResult {
275
/** Timestamp when file integrity was checked */
276
checkedAt: number;
277
/** Full path to the file in CAFS */
278
filePath: string;
279
/** File integrity hash */
280
integrity: IntegrityLike;
281
}
282
283
type IntegrityLike = string | {
284
algorithm: string;
285
digest: string;
286
options?: any[];
287
};
288
289
interface AddToStoreResult {
290
/** File integrity mappings with metadata */
291
filesIndex: FilesIndex;
292
293
/** Package manifest if available */
294
manifest?: DependencyManifest;
295
}
296
297
type DependencyManifest = {
298
/** Package name */
299
name?: string;
300
/** Package version */
301
version?: string;
302
/** Package dependencies */
303
dependencies?: Record<string, string>;
304
/** Other manifest properties */
305
[key: string]: any;
306
};
307
```
308
309
## Package Import Methods
310
311
The package supports multiple import strategies optimized for different use cases:
312
313
- **`'auto'`**: Automatically choose the best method based on package and system characteristics
314
- **`'hardlink'`**: Use hard links for maximum efficiency when filesystem supports it
315
- **`'copy'`**: Copy files, ensuring complete independence but using more disk space
316
- **`'clone'`**: Clone files with copy-on-write semantics when available
317
- **`'clone-or-copy'`**: Attempt cloning, fall back to copying if not supported
318
319
The system automatically selects `'clone-or-copy'` for packages that require building to ensure build outputs don't affect the original store files.
320
321
## Usage Patterns
322
323
### Custom Import Strategy
324
325
```typescript
326
import { createPackageImporterAsync } from "@pnpm/create-cafs-store";
327
328
// Create a custom async importer
329
const packageImporter = createPackageImporterAsync({
330
storeDir: "/path/to/store",
331
packageImportMethod: "clone-or-copy",
332
});
333
334
// Use in package installation
335
const result = await packageImporter("/target/path", {
336
filesResponse: packageFilesResponse,
337
force: false,
338
requiresBuild: true,
339
});
340
341
console.log(`Package imported using: ${result.importMethod}`);
342
console.log(`Package was pre-built: ${result.isBuilt}`);
343
```
344
345
### Store with Custom File Filtering
346
347
```typescript
348
import { createCafsStore } from "@pnpm/create-cafs-store";
349
350
const store = createCafsStore("/pnpm-store", {
351
ignoreFile: (filename) => {
352
// Ignore dotfiles and temporary files
353
return filename.startsWith(".") || filename.endsWith(".tmp");
354
},
355
packageImportMethod: "hardlink",
356
});
357
358
// Add files with filtering applied
359
const result = store.addFilesFromDir("/package/source");
360
```
361
362
## Error Handling
363
364
The package integrates with pnpm's error handling system. Common error scenarios include:
365
366
- **Store Directory Access**: Ensure the store directory exists and is writable
367
- **File System Permissions**: Import methods may fail if target directories aren't writable
368
- **Concurrent Access**: Use `CafsLocker` to prevent concurrent modifications to the same files
369
- **Invalid Package Data**: `PackageFilesResponse` must contain valid integrity hashes and file metadata