0
# Core File System API
1
2
Complete Node.js fs API implementation providing drop-in replacement functionality with synchronous, callback, and promise-based methods for all file system operations.
3
4
## Core Imports
5
6
```typescript
7
import { fs, vol, Volume, memfs, createFsFromVolume } from "memfs";
8
```
9
10
## Capabilities
11
12
### Volume Class
13
14
Core file system volume that implements the complete Node.js fs API.
15
16
```typescript { .api }
17
/**
18
* Core file system volume class implementing complete Node.js fs API
19
*/
20
export class Volume {
21
// Static factory methods for creating volumes from JSON
22
static fromJSON(json: DirectoryJSON, cwd?: string): Volume;
23
static fromNestedJSON(json: NestedDirectoryJSON, cwd?: string): Volume;
24
25
// Promise-based API matching Node.js fs.promises
26
promises: FsPromisesApi;
27
28
// Stream constructors
29
ReadStream: new (...args: any[]) => ReadStream;
30
WriteStream: new (...args: any[]) => WriteStream;
31
StatWatcher: new () => StatWatcher;
32
FSWatcher: new () => FSWatcher;
33
}
34
```
35
36
**Usage Examples:**
37
38
```typescript
39
import { Volume, memfs } from "memfs";
40
41
// Create volume from nested JSON structure
42
const vol = Volume.fromNestedJSON({
43
'/app': {
44
'package.json': '{"name": "my-app"}',
45
'src': {
46
'index.js': 'console.log("Hello");'
47
}
48
}
49
});
50
51
// Create file system from JSON with current working directory
52
const { fs, vol: customVol } = memfs({
53
'config.json': '{"port": 3000}',
54
'logs': null // empty directory
55
}, '/app');
56
57
// Use volume directly
58
vol.writeFileSync('/test.txt', 'Hello World!');
59
const content = vol.readFileSync('/test.txt', 'utf8');
60
```
61
62
### Synchronous File Operations
63
64
All Node.js synchronous file operations with identical signatures and behavior.
65
66
```typescript { .api }
67
// File reading and writing
68
readFileSync(path: PathLike, options?: { encoding?: BufferEncoding | null; flag?: string } | BufferEncoding | null): string | Buffer;
69
writeFileSync(path: PathLike, data: string | Buffer | Uint8Array, options?: WriteFileOptions): void;
70
appendFileSync(path: PathLike, data: string | Buffer | Uint8Array, options?: WriteFileOptions): void;
71
72
// File metadata and operations
73
accessSync(path: PathLike, mode?: number): void;
74
existsSync(path: PathLike): boolean;
75
copyFileSync(src: PathLike, dest: PathLike, mode?: number): void;
76
unlinkSync(path: PathLike): void;
77
truncateSync(path: PathLike, len?: number): void;
78
79
// File descriptor operations
80
openSync(path: PathLike, flags: string | number, mode?: string | number): number;
81
closeSync(fd: number): void;
82
readSync(fd: number, buffer: Buffer | Uint8Array, offset: number, length: number, position: number | null): number;
83
writeSync(fd: number, buffer: Buffer | Uint8Array, offset?: number, length?: number, position?: number): number;
84
writeSync(fd: number, string: string, position?: number, encoding?: BufferEncoding): number;
85
ftruncateSync(fd: number, len?: number): void;
86
fdatasyncSync(fd: number): void;
87
fsyncSync(fd: number): void;
88
89
// File statistics
90
statSync(path: PathLike, options?: StatOptions): Stats;
91
lstatSync(path: PathLike, options?: StatOptions): Stats;
92
fstatSync(fd: number, options?: StatOptions): Stats;
93
statfsSync(path: PathLike, options?: StatfsOptions): StatFs;
94
95
// File permissions and ownership
96
chmodSync(path: PathLike, mode: string | number): void;
97
fchmodSync(fd: number, mode: string | number): void;
98
lchmodSync(path: PathLike, mode: string | number): void;
99
chownSync(path: PathLike, uid: number, gid: number): void;
100
fchownSync(fd: number, uid: number, gid: number): void;
101
lchownSync(path: PathLike, uid: number, gid: number): void;
102
103
// File timestamps
104
utimesSync(path: PathLike, atime: string | number | Date, mtime: string | number | Date): void;
105
futimesSync(fd: number, atime: string | number | Date, mtime: string | number | Date): void;
106
lutimesSync(path: PathLike, atime: string | number | Date, mtime: string | number | Date): void;
107
108
// Path resolution
109
realpathSync(path: PathLike, options?: { encoding?: BufferEncoding | null }): string;
110
realpathSync.native(path: PathLike, options?: { encoding?: BufferEncoding | null }): string;
111
```
112
113
**Usage Examples:**
114
115
```typescript
116
import { fs } from "memfs";
117
118
// File operations
119
fs.writeFileSync('/data.txt', 'Hello World!');
120
const content = fs.readFileSync('/data.txt', 'utf8');
121
fs.appendFileSync('/data.txt', '\nNew line');
122
123
// File descriptor operations
124
const fd = fs.openSync('/data.txt', 'r');
125
const buffer = Buffer.alloc(1024);
126
const bytesRead = fs.readSync(fd, buffer, 0, 1024, 0);
127
fs.closeSync(fd);
128
129
// File metadata
130
const stats = fs.statSync('/data.txt');
131
console.log(stats.size, stats.isFile(), stats.mtime);
132
133
// File permissions
134
fs.chmodSync('/data.txt', 0o644);
135
fs.utimesSync('/data.txt', new Date(), new Date());
136
```
137
138
### Synchronous Directory Operations
139
140
Complete directory management with creation, reading, and removal capabilities.
141
142
```typescript { .api }
143
// Directory creation and removal
144
mkdirSync(path: PathLike, options?: MakeDirectoryOptions | string | number): void;
145
mkdtempSync(prefix: string, options?: { encoding?: BufferEncoding | null }): string;
146
rmdirSync(path: PathLike, options?: RmDirOptions): void;
147
rmSync(path: PathLike, options?: RmOptions): void;
148
cpSync(src: PathLike, dest: PathLike, options?: CpOptions): void;
149
150
// Directory reading
151
readdirSync(path: PathLike, options?: { encoding?: BufferEncoding | null; withFileTypes?: false }): string[];
152
readdirSync(path: PathLike, options: { encoding: "buffer"; withFileTypes?: false } | "buffer"): Buffer[];
153
readdirSync(path: PathLike, options?: { encoding?: BufferEncoding | null; withFileTypes: true }): Dirent[];
154
opendirSync(path: PathLike, options?: OpenDirOptions): Dir;
155
156
// Link operations
157
linkSync(existingPath: PathLike, newPath: PathLike): void;
158
symlinkSync(target: PathLike, path: PathLike, type?: string): void;
159
readlinkSync(path: PathLike, options?: { encoding?: BufferEncoding | null }): string;
160
161
// Glob operations
162
globSync(pattern: string, options?: GlobOptions): string[];
163
```
164
165
**Usage Examples:**
166
167
```typescript
168
import { fs } from "memfs";
169
170
// Directory operations
171
fs.mkdirSync('/app/src', { recursive: true });
172
fs.mkdtempSync('/tmp/temp-');
173
174
// Directory reading
175
const files = fs.readdirSync('/app');
176
const entries = fs.readdirSync('/app', { withFileTypes: true });
177
entries.forEach(entry => {
178
if (entry.isDirectory()) {
179
console.log(`Directory: ${entry.name}`);
180
} else {
181
console.log(`File: ${entry.name}`);
182
}
183
});
184
185
// Link operations
186
fs.linkSync('/app/src/index.js', '/app/main.js');
187
fs.symlinkSync('../config.json', '/app/src/config.json');
188
const target = fs.readlinkSync('/app/src/config.json');
189
190
// Glob pattern matching
191
const jsFiles = fs.globSync('/app/**/*.js');
192
```
193
194
### Callback File System API
195
196
Complete callback-based API matching Node.js fs module exactly, with error-first callback pattern.
197
198
```typescript { .api }
199
// File operations with callbacks
200
readFile(path: PathLike, options?: { encoding?: BufferEncoding | null; flag?: string } | BufferEncoding | null, callback?: (err: NodeJS.ErrnoException | null, data: string | Buffer) => void): void;
201
writeFile(path: PathLike, data: string | Buffer | Uint8Array, options: WriteFileOptions, callback: NoParamCallback): void;
202
writeFile(path: PathLike, data: string | Buffer | Uint8Array, callback: NoParamCallback): void;
203
appendFile(path: PathLike, data: string | Buffer | Uint8Array, options: WriteFileOptions, callback: NoParamCallback): void;
204
appendFile(path: PathLike, data: string | Buffer | Uint8Array, callback: NoParamCallback): void;
205
206
// Directory operations with callbacks
207
mkdir(path: PathLike, options: MakeDirectoryOptions, callback: (err: NodeJS.ErrnoException | null, path?: string) => void): void;
208
mkdir(path: PathLike, callback: NoParamCallback): void;
209
readdir(path: PathLike, options: { encoding: BufferEncoding | null; withFileTypes: false } | BufferEncoding | null, callback: (err: NodeJS.ErrnoException | null, files: string[]) => void): void;
210
readdir(path: PathLike, options: { encoding: "buffer"; withFileTypes: false } | "buffer", callback: (err: NodeJS.ErrnoException | null, files: Buffer[]) => void): void;
211
readdir(path: PathLike, options: { encoding?: BufferEncoding | null; withFileTypes: true }, callback: (err: NodeJS.ErrnoException | null, files: Dirent[]) => void): void;
212
readdir(path: PathLike, callback: (err: NodeJS.ErrnoException | null, files: string[]) => void): void;
213
214
// Stream creation
215
createReadStream(path: PathLike, options?: string | { flags?: string; encoding?: BufferEncoding; fd?: number; mode?: number; autoClose?: boolean; start?: number; end?: number; highWaterMark?: number }): ReadStream;
216
createWriteStream(path: PathLike, options?: string | { flags?: string; encoding?: BufferEncoding; fd?: number; mode?: number; autoClose?: boolean; start?: number; highWaterMark?: number }): WriteStream;
217
218
// File watching
219
watch(filename: PathLike, options?: { encoding?: BufferEncoding | null; persistent?: boolean; recursive?: boolean } | BufferEncoding | null, listener?: (eventType: string, filename: string | Buffer) => void): FSWatcher;
220
watchFile(filename: PathLike, options: { bigint?: boolean; persistent?: boolean; interval?: number }, listener: (curr: Stats, prev: Stats) => void): StatWatcher;
221
watchFile(filename: PathLike, listener: (curr: Stats, prev: Stats) => void): StatWatcher;
222
unwatchFile(filename: PathLike, listener?: (curr: Stats, prev: Stats) => void): void;
223
```
224
225
**Usage Examples:**
226
227
```typescript
228
import { fs } from "memfs";
229
230
// Callback-based file operations
231
fs.readFile('/data.txt', 'utf8', (err, data) => {
232
if (err) throw err;
233
console.log(data);
234
});
235
236
fs.writeFile('/output.txt', 'Hello', (err) => {
237
if (err) throw err;
238
console.log('File written!');
239
});
240
241
// Callback-based directory operations
242
fs.mkdir('/app/logs', { recursive: true }, (err) => {
243
if (err) throw err;
244
245
fs.readdir('/app', (err, files) => {
246
if (err) throw err;
247
console.log('Files:', files);
248
});
249
});
250
251
// Stream operations
252
const readStream = fs.createReadStream('/large-file.txt');
253
const writeStream = fs.createWriteStream('/copy.txt');
254
readStream.pipe(writeStream);
255
256
// File watching
257
const watcher = fs.watch('/app', { recursive: true }, (eventType, filename) => {
258
console.log(`File ${filename} ${eventType}`);
259
});
260
```
261
262
### Promise File System API
263
264
Modern promise-based API available via `fs.promises` with async/await support.
265
266
```typescript { .api }
267
/**
268
* Promise-based file system API accessed via fs.promises
269
*/
270
export interface FsPromisesApi {
271
// File operations
272
readFile(path: PathLike, options?: { encoding?: BufferEncoding | null; flag?: string } | BufferEncoding | null): Promise<string | Buffer>;
273
writeFile(path: PathLike, data: string | Buffer | Uint8Array, options?: WriteFileOptions): Promise<void>;
274
appendFile(path: PathLike, data: string | Buffer | Uint8Array, options?: WriteFileOptions): Promise<void>;
275
access(path: PathLike, mode?: number): Promise<void>;
276
copyFile(src: PathLike, dest: PathLike, mode?: number): Promise<void>;
277
unlink(path: PathLike): Promise<void>;
278
truncate(path: PathLike, len?: number): Promise<void>;
279
280
// File handle operations
281
open(path: PathLike, flags: string | number, mode?: string | number): Promise<FileHandle>;
282
283
// Directory operations
284
mkdir(path: PathLike, options?: MakeDirectoryOptions): Promise<string | void>;
285
readdir(path: PathLike, options?: { encoding?: BufferEncoding | null; withFileTypes?: false }): Promise<string[]>;
286
readdir(path: PathLike, options: { encoding: "buffer"; withFileTypes?: false } | "buffer"): Promise<Buffer[]>;
287
readdir(path: PathLike, options: { encoding?: BufferEncoding | null; withFileTypes: true }): Promise<Dirent[]>;
288
rmdir(path: PathLike, options?: RmDirOptions): Promise<void>;
289
rm(path: PathLike, options?: RmOptions): Promise<void>;
290
291
// File statistics
292
stat(path: PathLike, options?: StatOptions): Promise<Stats>;
293
lstat(path: PathLike, options?: StatOptions): Promise<Stats>;
294
295
// File watching
296
watch(filename: PathLike, options?: { encoding?: BufferEncoding | null; persistent?: boolean; recursive?: boolean }): AsyncIterableIterator<{ eventType: string; filename: string | Buffer }>;
297
298
// File handle constructor
299
FileHandle: new (...args: any[]) => FileHandle;
300
}
301
```
302
303
**Usage Examples:**
304
305
```typescript
306
import { fs } from "memfs";
307
308
async function example() {
309
try {
310
// File operations with async/await
311
await fs.promises.writeFile('/data.txt', 'Hello World!');
312
const content = await fs.promises.readFile('/data.txt', 'utf8');
313
console.log(content);
314
315
// Directory operations
316
await fs.promises.mkdir('/app/logs', { recursive: true });
317
const files = await fs.promises.readdir('/app');
318
319
// File handle operations
320
const fileHandle = await fs.promises.open('/data.txt', 'r');
321
const buffer = Buffer.alloc(1024);
322
const result = await fileHandle.read(buffer, 0, 1024, 0);
323
await fileHandle.close();
324
325
// File statistics
326
const stats = await fs.promises.stat('/data.txt');
327
console.log('File size:', stats.size);
328
329
} catch (error) {
330
console.error('Error:', error);
331
}
332
}
333
334
// File watching with async iteration
335
async function watchFiles() {
336
try {
337
for await (const { eventType, filename } of fs.promises.watch('/app')) {
338
console.log(`${filename} ${eventType}`);
339
}
340
} catch (error) {
341
console.error('Watch error:', error);
342
}
343
}
344
```
345
346
### JSON Structure Types
347
348
Type definitions for creating file systems from JSON representations.
349
350
```typescript { .api }
351
/**
352
* Nested directory structure allowing directories and files
353
*/
354
export type NestedDirectoryJSON<T = string | Buffer> = {
355
[key: string]: T | NestedDirectoryJSON<T> | null;
356
};
357
358
/**
359
* Flat directory structure with absolute paths
360
*/
361
export type DirectoryJSON<T = string | Buffer> = {
362
[key: string]: T | null;
363
};
364
365
/**
366
* Utility function to flatten nested JSON to flat structure
367
*/
368
export function flattenJSON<T>(
369
nestedJSON: NestedDirectoryJSON<T>,
370
prefix?: string
371
): DirectoryJSON<T>;
372
```
373
374
**Usage Examples:**
375
376
```typescript
377
import { memfs, Volume, NestedDirectoryJSON } from "memfs";
378
379
// Nested JSON structure
380
const nestedStructure: NestedDirectoryJSON = {
381
'/app': {
382
'package.json': JSON.stringify({ name: 'my-app', version: '1.0.0' }),
383
'src': {
384
'index.js': 'console.log("Hello World!");',
385
'utils': {
386
'helper.js': 'module.exports = { format: s => s.trim() };'
387
}
388
},
389
'tests': {
390
'index.test.js': 'test("should work", () => { expect(true).toBe(true); });'
391
},
392
'logs': null, // empty directory
393
'README.md': '# My App\n\nA simple application.'
394
}
395
};
396
397
// Create file system from nested structure
398
const { fs } = memfs(nestedStructure);
399
400
// Flat JSON structure (direct path mapping)
401
const flatStructure = {
402
'/app/package.json': '{"name": "my-app"}',
403
'/app/src/index.js': 'console.log("Hello");',
404
'/app/logs': null
405
};
406
407
const vol = Volume.fromJSON(flatStructure);
408
```
409
410
## Type Definitions
411
412
```typescript { .api }
413
// Path-like types
414
export type PathLike = string | Buffer | URL;
415
416
// Option interfaces
417
export interface WriteFileOptions {
418
encoding?: BufferEncoding | null;
419
mode?: string | number;
420
flag?: string;
421
}
422
423
export interface StatOptions {
424
bigint?: boolean;
425
}
426
427
export interface StatfsOptions {
428
bigint?: boolean;
429
}
430
431
export interface MakeDirectoryOptions {
432
recursive?: boolean;
433
mode?: string | number;
434
}
435
436
export interface RmDirOptions {
437
maxRetries?: number;
438
recursive?: boolean;
439
retryDelay?: number;
440
}
441
442
export interface RmOptions {
443
force?: boolean;
444
maxRetries?: number;
445
recursive?: boolean;
446
retryDelay?: number;
447
}
448
449
export interface CpOptions {
450
dereference?: boolean;
451
errorOnExist?: boolean;
452
filter?: (source: string, destination: string) => boolean | Promise<boolean>;
453
force?: boolean;
454
preserveTimestamps?: boolean;
455
recursive?: boolean;
456
}
457
458
export interface OpenDirOptions {
459
encoding?: BufferEncoding;
460
bufferSize?: number;
461
}
462
463
export interface GlobOptions {
464
cwd?: string;
465
root?: string;
466
dot?: boolean;
467
nomount?: boolean;
468
mark?: boolean;
469
nosort?: boolean;
470
stat?: boolean;
471
silent?: boolean;
472
strict?: boolean;
473
cache?: { [path: string]: any };
474
statCache?: { [path: string]: Stats | false };
475
symlinks?: { [path: string]: boolean };
476
nounique?: boolean;
477
nonull?: boolean;
478
debug?: boolean;
479
nobrace?: boolean;
480
noglobstar?: boolean;
481
noext?: boolean;
482
nocase?: boolean;
483
matchBase?: boolean;
484
nodir?: boolean;
485
ignore?: string | string[];
486
follow?: boolean;
487
realpath?: boolean;
488
nonegate?: boolean;
489
nocomment?: boolean;
490
minimatch?: any;
491
flipNegate?: boolean;
492
}
493
494
// Callback types
495
export type NoParamCallback = (err: NodeJS.ErrnoException | null) => void;
496
```