@zenfs/core 0.12.1 → 0.12.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/backends/backend.d.ts +1 -1
- package/dist/backends/fetch.d.ts +1 -1
- package/dist/backends/index/fs.d.ts +2 -1
- package/dist/backends/index/index.d.ts +2 -1
- package/dist/backends/overlay.d.ts +4 -3
- package/dist/backends/overlay.js +1 -1
- package/dist/backends/port/fs.d.ts +5 -1
- package/dist/backends/port/fs.js +13 -10
- package/dist/browser.min.js +4 -8
- package/dist/browser.min.js.map +3 -3
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/cred.d.ts +2 -1
- package/dist/emulation/async.d.ts +6 -5
- package/dist/emulation/index.d.ts +1 -1
- package/dist/emulation/index.js +1 -1
- package/dist/emulation/promises.d.ts +5 -5
- package/dist/emulation/promises.js +31 -51
- package/dist/emulation/shared.d.ts +8 -2
- package/dist/emulation/shared.js +18 -1
- package/dist/emulation/streams.d.ts +1 -1
- package/dist/emulation/sync.d.ts +5 -5
- package/dist/emulation/sync.js +94 -76
- package/dist/error.d.ts +1 -1
- package/dist/error.js +1 -1
- package/dist/file.d.ts +7 -23
- package/dist/file.js +33 -80
- package/dist/filesystem.d.ts +35 -31
- package/dist/filesystem.js +10 -14
- package/dist/stats.d.ts +17 -17
- package/dist/stats.js +42 -49
- package/dist/utils.d.ts +2 -2
- package/license.md +2 -26
- package/package.json +2 -2
- package/readme.md +1 -1
- package/src/backends/backend.ts +1 -1
- package/src/backends/fetch.ts +1 -1
- package/src/backends/index/fs.ts +2 -1
- package/src/backends/index/index.ts +2 -1
- package/src/backends/overlay.ts +7 -4
- package/src/backends/port/fs.ts +14 -10
- package/src/config.ts +1 -1
- package/src/cred.ts +2 -1
- package/src/emulation/async.ts +8 -7
- package/src/emulation/index.ts +1 -1
- package/src/emulation/promises.ts +40 -54
- package/src/emulation/shared.ts +24 -3
- package/src/emulation/streams.ts +1 -1
- package/src/emulation/sync.ts +100 -87
- package/src/error.ts +1 -1
- package/src/file.ts +35 -88
- package/src/filesystem.ts +40 -32
- package/src/stats.ts +47 -59
- package/src/utils.ts +2 -2
package/dist/file.js
CHANGED
|
@@ -1,21 +1,7 @@
|
|
|
1
|
-
import { ErrnoError, Errno } from './error.js';
|
|
2
1
|
import { O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY, S_IFMT } from './emulation/constants.js';
|
|
2
|
+
import { Errno, ErrnoError } from './error.js';
|
|
3
3
|
import { size_max } from './inode.js';
|
|
4
4
|
import { Stats } from './stats.js';
|
|
5
|
-
/**
|
|
6
|
-
* @hidden
|
|
7
|
-
*/
|
|
8
|
-
export var ActionType;
|
|
9
|
-
(function (ActionType) {
|
|
10
|
-
// Indicates that the code should not do anything.
|
|
11
|
-
ActionType[ActionType["NOP"] = 0] = "NOP";
|
|
12
|
-
// Indicates that the code should throw an exception.
|
|
13
|
-
ActionType[ActionType["THROW"] = 1] = "THROW";
|
|
14
|
-
// Indicates that the code should truncate the file, but only if it is a file.
|
|
15
|
-
ActionType[ActionType["TRUNCATE"] = 2] = "TRUNCATE";
|
|
16
|
-
// Indicates that the code should create the file.
|
|
17
|
-
ActionType[ActionType["CREATE"] = 3] = "CREATE";
|
|
18
|
-
})(ActionType || (ActionType = {}));
|
|
19
5
|
const validFlags = ['r', 'r+', 'rs', 'rs+', 'w', 'wx', 'w+', 'wx+', 'a', 'ax', 'a+', 'ax+'];
|
|
20
6
|
export function parseFlag(flag) {
|
|
21
7
|
if (typeof flag === 'number') {
|
|
@@ -117,21 +103,6 @@ export function isSynchronous(flag) {
|
|
|
117
103
|
export function isExclusive(flag) {
|
|
118
104
|
return flag.indexOf('x') !== -1;
|
|
119
105
|
}
|
|
120
|
-
export function pathExistsAction(flag) {
|
|
121
|
-
if (isExclusive(flag)) {
|
|
122
|
-
return ActionType.THROW;
|
|
123
|
-
}
|
|
124
|
-
if (isTruncating(flag)) {
|
|
125
|
-
return ActionType.TRUNCATE;
|
|
126
|
-
}
|
|
127
|
-
return ActionType.NOP;
|
|
128
|
-
}
|
|
129
|
-
export function pathNotExistsAction(flag) {
|
|
130
|
-
if ((isWriteable(flag) || isAppendable(flag)) && flag !== 'r+') {
|
|
131
|
-
return ActionType.CREATE;
|
|
132
|
-
}
|
|
133
|
-
return ActionType.THROW;
|
|
134
|
-
}
|
|
135
106
|
export class File {
|
|
136
107
|
[Symbol.asyncDispose]() {
|
|
137
108
|
return this.close();
|
|
@@ -191,7 +162,7 @@ export class PreloadFile extends File {
|
|
|
191
162
|
this.stats = stats;
|
|
192
163
|
this._buffer = _buffer;
|
|
193
164
|
this._position = 0;
|
|
194
|
-
this.
|
|
165
|
+
this.dirty = false;
|
|
195
166
|
/*
|
|
196
167
|
Note:
|
|
197
168
|
This invariant is *not* maintained once the file starts getting modified.
|
|
@@ -203,7 +174,7 @@ export class PreloadFile extends File {
|
|
|
203
174
|
if (isReadable(this.flag)) {
|
|
204
175
|
throw new Error(`Size mismatch: buffer length ${_buffer.byteLength}, stats size ${this.stats.size}`);
|
|
205
176
|
}
|
|
206
|
-
this.
|
|
177
|
+
this.dirty = true;
|
|
207
178
|
}
|
|
208
179
|
/**
|
|
209
180
|
* Get the underlying buffer for this file. Mutating not recommended and will mess up dirty tracking.
|
|
@@ -234,18 +205,18 @@ export class PreloadFile extends File {
|
|
|
234
205
|
this._position = newPos;
|
|
235
206
|
}
|
|
236
207
|
async sync() {
|
|
237
|
-
if (!this.
|
|
208
|
+
if (!this.dirty) {
|
|
238
209
|
return;
|
|
239
210
|
}
|
|
240
211
|
await this.fs.sync(this.path, this._buffer, this.stats);
|
|
241
|
-
this.
|
|
212
|
+
this.dirty = false;
|
|
242
213
|
}
|
|
243
214
|
syncSync() {
|
|
244
|
-
if (!this.
|
|
215
|
+
if (!this.dirty) {
|
|
245
216
|
return;
|
|
246
217
|
}
|
|
247
218
|
this.fs.syncSync(this.path, this._buffer, this.stats);
|
|
248
|
-
this.
|
|
219
|
+
this.dirty = false;
|
|
249
220
|
}
|
|
250
221
|
async close() {
|
|
251
222
|
await this.sync();
|
|
@@ -267,39 +238,32 @@ export class PreloadFile extends File {
|
|
|
267
238
|
}
|
|
268
239
|
/**
|
|
269
240
|
* Asynchronous truncate.
|
|
270
|
-
* @param
|
|
241
|
+
* @param length
|
|
271
242
|
*/
|
|
272
|
-
async truncate(
|
|
273
|
-
this.truncateSync(
|
|
274
|
-
|
|
275
|
-
return this.sync();
|
|
276
|
-
}
|
|
243
|
+
async truncate(length) {
|
|
244
|
+
this.truncateSync(length);
|
|
245
|
+
return this.sync();
|
|
277
246
|
}
|
|
278
247
|
/**
|
|
279
248
|
* Synchronous truncate.
|
|
280
|
-
* @param
|
|
249
|
+
* @param length
|
|
281
250
|
*/
|
|
282
|
-
truncateSync(
|
|
283
|
-
this.
|
|
251
|
+
truncateSync(length) {
|
|
252
|
+
this.dirty = true;
|
|
284
253
|
if (!isWriteable(this.flag)) {
|
|
285
254
|
throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode.');
|
|
286
255
|
}
|
|
287
256
|
this.stats.mtimeMs = Date.now();
|
|
288
|
-
if (
|
|
289
|
-
const
|
|
290
|
-
// Write will set stats.size
|
|
291
|
-
this.writeSync(
|
|
292
|
-
if (isSynchronous(this.flag)) {
|
|
293
|
-
this.syncSync();
|
|
294
|
-
}
|
|
257
|
+
if (length > this._buffer.length) {
|
|
258
|
+
const data = new Uint8Array(length - this._buffer.length);
|
|
259
|
+
// Write will set stats.size and handle syncing.
|
|
260
|
+
this.writeSync(data, 0, data.length, this._buffer.length);
|
|
295
261
|
return;
|
|
296
262
|
}
|
|
297
|
-
this.stats.size =
|
|
298
|
-
// Truncate
|
|
299
|
-
this._buffer = this._buffer.
|
|
300
|
-
|
|
301
|
-
this.syncSync();
|
|
302
|
-
}
|
|
263
|
+
this.stats.size = length;
|
|
264
|
+
// Truncate.
|
|
265
|
+
this._buffer = this._buffer.slice(0, length);
|
|
266
|
+
this.syncSync();
|
|
303
267
|
}
|
|
304
268
|
/**
|
|
305
269
|
* Write buffer to the file.
|
|
@@ -313,7 +277,7 @@ export class PreloadFile extends File {
|
|
|
313
277
|
* data should be written. If position is null, the data will be written at
|
|
314
278
|
* the current position.
|
|
315
279
|
*/
|
|
316
|
-
async write(buffer, offset = 0, length = this.stats.size, position =
|
|
280
|
+
async write(buffer, offset = 0, length = this.stats.size, position = this.position) {
|
|
317
281
|
const bytesWritten = this.writeSync(buffer, offset, length, position);
|
|
318
282
|
await this.sync();
|
|
319
283
|
return bytesWritten;
|
|
@@ -331,9 +295,8 @@ export class PreloadFile extends File {
|
|
|
331
295
|
* the current position.
|
|
332
296
|
* @returns bytes written
|
|
333
297
|
*/
|
|
334
|
-
writeSync(buffer, offset = 0, length = this.stats.size, position =
|
|
335
|
-
this.
|
|
336
|
-
position ?? (position = this.position);
|
|
298
|
+
writeSync(buffer, offset = 0, length = this.stats.size, position = this.position) {
|
|
299
|
+
this.dirty = true;
|
|
337
300
|
if (!isWriteable(this.flag)) {
|
|
338
301
|
throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode.');
|
|
339
302
|
}
|
|
@@ -356,11 +319,8 @@ export class PreloadFile extends File {
|
|
|
356
319
|
this._buffer.set(slice, position);
|
|
357
320
|
const bytesWritten = slice.byteLength;
|
|
358
321
|
this.stats.mtimeMs = Date.now();
|
|
359
|
-
if (isSynchronous(this.flag)) {
|
|
360
|
-
this.syncSync();
|
|
361
|
-
return bytesWritten;
|
|
362
|
-
}
|
|
363
322
|
this.position = position + bytesWritten;
|
|
323
|
+
this.syncSync();
|
|
364
324
|
return bytesWritten;
|
|
365
325
|
}
|
|
366
326
|
/**
|
|
@@ -392,6 +352,7 @@ export class PreloadFile extends File {
|
|
|
392
352
|
if (!isReadable(this.flag)) {
|
|
393
353
|
throw new ErrnoError(Errno.EPERM, 'File not opened with a readable mode.');
|
|
394
354
|
}
|
|
355
|
+
this.dirty = true;
|
|
395
356
|
position ?? (position = this.position);
|
|
396
357
|
let end = position + length;
|
|
397
358
|
if (end > this.stats.size) {
|
|
@@ -400,6 +361,7 @@ export class PreloadFile extends File {
|
|
|
400
361
|
this.stats.atimeMs = Date.now();
|
|
401
362
|
this._position = end;
|
|
402
363
|
const bytesRead = end - position;
|
|
364
|
+
this.syncSync();
|
|
403
365
|
if (bytesRead == 0) {
|
|
404
366
|
// No copy/read. Return immediatly for better performance
|
|
405
367
|
return bytesRead;
|
|
@@ -419,7 +381,7 @@ export class PreloadFile extends File {
|
|
|
419
381
|
* @param mode
|
|
420
382
|
*/
|
|
421
383
|
chmodSync(mode) {
|
|
422
|
-
this.
|
|
384
|
+
this.dirty = true;
|
|
423
385
|
this.stats.chmod(mode);
|
|
424
386
|
this.syncSync();
|
|
425
387
|
}
|
|
@@ -437,7 +399,7 @@ export class PreloadFile extends File {
|
|
|
437
399
|
* @param gid
|
|
438
400
|
*/
|
|
439
401
|
chownSync(uid, gid) {
|
|
440
|
-
this.
|
|
402
|
+
this.dirty = true;
|
|
441
403
|
this.stats.chown(uid, gid);
|
|
442
404
|
this.syncSync();
|
|
443
405
|
}
|
|
@@ -445,27 +407,18 @@ export class PreloadFile extends File {
|
|
|
445
407
|
this.utimesSync(atime, mtime);
|
|
446
408
|
}
|
|
447
409
|
utimesSync(atime, mtime) {
|
|
448
|
-
this.
|
|
410
|
+
this.dirty = true;
|
|
449
411
|
this.stats.atime = atime;
|
|
450
412
|
this.stats.mtime = mtime;
|
|
451
413
|
this.syncSync();
|
|
452
414
|
}
|
|
453
|
-
isDirty() {
|
|
454
|
-
return this._dirty;
|
|
455
|
-
}
|
|
456
|
-
/**
|
|
457
|
-
* Resets the dirty bit. Should only be called after a sync has completed successfully.
|
|
458
|
-
*/
|
|
459
|
-
resetDirty() {
|
|
460
|
-
this._dirty = false;
|
|
461
|
-
}
|
|
462
415
|
_setType(type) {
|
|
463
|
-
this.
|
|
416
|
+
this.dirty = true;
|
|
464
417
|
this.stats.mode = (this.stats.mode & ~S_IFMT) | type;
|
|
465
418
|
return this.sync();
|
|
466
419
|
}
|
|
467
420
|
_setTypeSync(type) {
|
|
468
|
-
this.
|
|
421
|
+
this.dirty = true;
|
|
469
422
|
this.stats.mode = (this.stats.mode & ~S_IFMT) | type;
|
|
470
423
|
this.syncSync();
|
|
471
424
|
}
|
package/dist/filesystem.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Cred } from './cred.js';
|
|
2
2
|
import { type File } from './file.js';
|
|
3
|
-
import type
|
|
3
|
+
import { type Stats } from './stats.js';
|
|
4
4
|
export type FileContents = ArrayBufferView | string;
|
|
5
5
|
/**
|
|
6
6
|
* Metadata about a FileSystem
|
|
@@ -34,27 +34,40 @@ export interface FileSystemMetadata {
|
|
|
34
34
|
* @default false
|
|
35
35
|
*/
|
|
36
36
|
noAsyncCache: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* The optimal block size to use with the file system
|
|
39
|
+
* @default 4096
|
|
40
|
+
*/
|
|
41
|
+
blockSize?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Total number of (file) nodes available
|
|
44
|
+
*/
|
|
45
|
+
totalNodes?: number;
|
|
46
|
+
/**
|
|
47
|
+
* Number of free (file) nodes available
|
|
48
|
+
*/
|
|
49
|
+
freeNodes?: number;
|
|
50
|
+
/**
|
|
51
|
+
* The type of the FS
|
|
52
|
+
*/
|
|
53
|
+
type: number;
|
|
37
54
|
}
|
|
38
55
|
/**
|
|
39
56
|
* Structure for a filesystem. All ZenFS backends must extend this.
|
|
40
57
|
*
|
|
41
|
-
* This class includes
|
|
58
|
+
* This class includes default implementations for `exists` and `existsSync`
|
|
42
59
|
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* - Every path is an absolute path. `.`, `..`, and other items are resolved into an absolute form.
|
|
46
|
-
* - All arguments are present. Any optional arguments at the Node API level have been passed in with their default values.
|
|
60
|
+
* If you are extending this class, note that every path is an absolute path and all arguments are present.
|
|
47
61
|
*/
|
|
48
62
|
export declare abstract class FileSystem {
|
|
49
63
|
/**
|
|
50
64
|
* Get metadata about the current file system
|
|
51
65
|
*/
|
|
52
66
|
metadata(): FileSystemMetadata;
|
|
53
|
-
constructor(
|
|
67
|
+
constructor();
|
|
54
68
|
ready(): Promise<void>;
|
|
55
69
|
/**
|
|
56
|
-
* Asynchronous rename.
|
|
57
|
-
* are given to the completion callback.
|
|
70
|
+
* Asynchronous rename.
|
|
58
71
|
*/
|
|
59
72
|
abstract rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;
|
|
60
73
|
/**
|
|
@@ -70,26 +83,24 @@ export declare abstract class FileSystem {
|
|
|
70
83
|
*/
|
|
71
84
|
abstract statSync(path: string, cred: Cred): Stats;
|
|
72
85
|
/**
|
|
73
|
-
* Opens the file at path
|
|
74
|
-
* @param
|
|
86
|
+
* Opens the file at `path` with the given flag. The file must exist.
|
|
87
|
+
* @param path The path to open.
|
|
75
88
|
* @param flag The flag to use when opening the file.
|
|
76
89
|
*/
|
|
77
90
|
abstract openFile(path: string, flag: string, cred: Cred): Promise<File>;
|
|
78
91
|
/**
|
|
79
|
-
* Opens the file at path
|
|
80
|
-
* @param
|
|
92
|
+
* Opens the file at `path` with the given flag. The file must exist.
|
|
93
|
+
* @param path The path to open.
|
|
81
94
|
* @param flag The flag to use when opening the file.
|
|
82
95
|
* @return A File object corresponding to the opened file.
|
|
83
96
|
*/
|
|
84
97
|
abstract openFileSync(path: string, flag: string, cred: Cred): File;
|
|
85
98
|
/**
|
|
86
|
-
* Create the file at path
|
|
87
|
-
* flag.
|
|
99
|
+
* Create the file at `path` with the given mode. Then, open it with the given flag.
|
|
88
100
|
*/
|
|
89
101
|
abstract createFile(path: string, flag: string, mode: number, cred: Cred): Promise<File>;
|
|
90
102
|
/**
|
|
91
|
-
* Create the file at path
|
|
92
|
-
* flag.
|
|
103
|
+
* Create the file at `path` with the given mode. Then, open it with the given flag.
|
|
93
104
|
*/
|
|
94
105
|
abstract createFileSync(path: string, flag: string, mode: number, cred: Cred): File;
|
|
95
106
|
/**
|
|
@@ -110,21 +121,16 @@ export declare abstract class FileSystem {
|
|
|
110
121
|
abstract rmdirSync(path: string, cred: Cred): void;
|
|
111
122
|
/**
|
|
112
123
|
* Asynchronous `mkdir`.
|
|
113
|
-
* @param mode Mode to make the directory using.
|
|
114
|
-
* the filesystem doesn't support permissions.
|
|
124
|
+
* @param mode Mode to make the directory using.
|
|
115
125
|
*/
|
|
116
126
|
abstract mkdir(path: string, mode: number, cred: Cred): Promise<void>;
|
|
117
127
|
/**
|
|
118
128
|
* Synchronous `mkdir`.
|
|
119
|
-
* @param mode Mode to make the directory using.
|
|
120
|
-
* the filesystem doesn't support permissions.
|
|
129
|
+
* @param mode Mode to make the directory using.
|
|
121
130
|
*/
|
|
122
131
|
abstract mkdirSync(path: string, mode: number, cred: Cred): void;
|
|
123
132
|
/**
|
|
124
133
|
* Asynchronous `readdir`. Reads the contents of a directory.
|
|
125
|
-
*
|
|
126
|
-
* The callback gets two arguments `(err, files)` where `files` is an array of
|
|
127
|
-
* the names of the files in the directory excluding `'.'` and `'..'`.
|
|
128
134
|
*/
|
|
129
135
|
abstract readdir(path: string, cred: Cred): Promise<string[]>;
|
|
130
136
|
/**
|
|
@@ -211,13 +217,11 @@ declare abstract class AsyncFS extends FileSystem {
|
|
|
211
217
|
/**
|
|
212
218
|
* Async() implements synchronous methods on an asynchronous file system
|
|
213
219
|
*
|
|
214
|
-
* Implementing classes must define
|
|
215
|
-
* by:
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
* - During application loading, the contents of the async file system can be reloaded into
|
|
220
|
-
* the synchronous store, if desired.
|
|
220
|
+
* Implementing classes must define `_sync` for the synchronous file system used as a cache.
|
|
221
|
+
* Synchronous methods on an asynchronous FS are implemented by:
|
|
222
|
+
* - Performing operations over the in-memory copy,
|
|
223
|
+
* while asynchronously pipelining them to the backing store.
|
|
224
|
+
* - During loading, the contents of the async file system are eloaded into the synchronous store.
|
|
221
225
|
*
|
|
222
226
|
*/
|
|
223
227
|
export declare function Async<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => AsyncFS) & T;
|
package/dist/filesystem.js
CHANGED
|
@@ -2,15 +2,13 @@ import { ErrnoError, Errno } from './error.js';
|
|
|
2
2
|
import { rootCred } from './cred.js';
|
|
3
3
|
import { join } from './emulation/path.js';
|
|
4
4
|
import { PreloadFile, parseFlag } from './file.js';
|
|
5
|
+
import { ZenFsType } from './stats.js';
|
|
5
6
|
/**
|
|
6
7
|
* Structure for a filesystem. All ZenFS backends must extend this.
|
|
7
8
|
*
|
|
8
|
-
* This class includes
|
|
9
|
+
* This class includes default implementations for `exists` and `existsSync`
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* - Every path is an absolute path. `.`, `..`, and other items are resolved into an absolute form.
|
|
13
|
-
* - All arguments are present. Any optional arguments at the Node API level have been passed in with their default values.
|
|
11
|
+
* If you are extending this class, note that every path is an absolute path and all arguments are present.
|
|
14
12
|
*/
|
|
15
13
|
export class FileSystem {
|
|
16
14
|
/**
|
|
@@ -24,10 +22,10 @@ export class FileSystem {
|
|
|
24
22
|
freeSpace: 0,
|
|
25
23
|
noResizableBuffers: false,
|
|
26
24
|
noAsyncCache: false,
|
|
25
|
+
type: ZenFsType,
|
|
27
26
|
};
|
|
28
27
|
}
|
|
29
|
-
|
|
30
|
-
constructor(options) { }
|
|
28
|
+
constructor() { }
|
|
31
29
|
async ready() { }
|
|
32
30
|
/**
|
|
33
31
|
* Test whether or not the given path exists by checking with the file system.
|
|
@@ -99,13 +97,11 @@ export function Sync(FS) {
|
|
|
99
97
|
/**
|
|
100
98
|
* Async() implements synchronous methods on an asynchronous file system
|
|
101
99
|
*
|
|
102
|
-
* Implementing classes must define
|
|
103
|
-
* by:
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* - During application loading, the contents of the async file system can be reloaded into
|
|
108
|
-
* the synchronous store, if desired.
|
|
100
|
+
* Implementing classes must define `_sync` for the synchronous file system used as a cache.
|
|
101
|
+
* Synchronous methods on an asynchronous FS are implemented by:
|
|
102
|
+
* - Performing operations over the in-memory copy,
|
|
103
|
+
* while asynchronously pipelining them to the backing store.
|
|
104
|
+
* - During loading, the contents of the async file system are eloaded into the synchronous store.
|
|
109
105
|
*
|
|
110
106
|
*/
|
|
111
107
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
package/dist/stats.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
import type * as Node from 'fs';
|
|
3
|
-
import { Cred } from './cred.js';
|
|
3
|
+
import type { Cred } from './cred.js';
|
|
4
4
|
/**
|
|
5
5
|
* Indicates the type of the given file. Applied to 'mode'.
|
|
6
6
|
*/
|
|
@@ -57,11 +57,9 @@ export interface StatsLike<T extends number | bigint = number | bigint> {
|
|
|
57
57
|
* Common code used by both Stats and BigIntStats.
|
|
58
58
|
*/
|
|
59
59
|
export declare abstract class StatsCommon<T extends number | bigint> implements Node.StatsBase<T>, StatsLike {
|
|
60
|
-
protected abstract _isBigint:
|
|
61
|
-
protected get _typename(): string;
|
|
62
|
-
protected get _typename_inverse(): string;
|
|
60
|
+
protected abstract _isBigint: T extends bigint ? true : false;
|
|
63
61
|
protected _convert(arg: number | bigint | string | boolean): T;
|
|
64
|
-
blocks: T;
|
|
62
|
+
get blocks(): T;
|
|
65
63
|
/**
|
|
66
64
|
* Unix-style file mode (e.g. 0o644) that includes the type of the item.
|
|
67
65
|
* Type of the item can be FILE, DIRECTORY, SYMLINK, or SOCKET
|
|
@@ -184,27 +182,26 @@ export declare abstract class StatsCommon<T extends number | bigint> implements
|
|
|
184
182
|
* Attribute descriptions are from `man 2 stat'
|
|
185
183
|
* @see http://nodejs.org/api/fs.html#fs_class_fs_stats
|
|
186
184
|
* @see http://man7.org/linux/man-pages/man2/stat.2.html
|
|
185
|
+
* @internal
|
|
187
186
|
*/
|
|
188
187
|
export declare class Stats extends StatsCommon<number> implements Node.Stats, StatsLike {
|
|
189
|
-
protected _isBigint:
|
|
190
|
-
/**
|
|
191
|
-
* Clones the stats object.
|
|
192
|
-
* @deprecated use `new Stats(stats)`
|
|
193
|
-
*/
|
|
194
|
-
static clone(stats: Stats): Stats;
|
|
188
|
+
protected _isBigint: false;
|
|
195
189
|
}
|
|
196
190
|
/**
|
|
197
191
|
* Stats with bigint
|
|
198
192
|
* @todo Implement with bigint instead of wrapping Stats
|
|
193
|
+
* @internal
|
|
199
194
|
*/
|
|
200
195
|
export declare class BigIntStats extends StatsCommon<bigint> implements Node.BigIntStats, StatsLike {
|
|
201
|
-
protected _isBigint:
|
|
202
|
-
/**
|
|
203
|
-
* Clone a stats object.
|
|
204
|
-
* @deprecated use `new BigIntStats(stats)`
|
|
205
|
-
*/
|
|
206
|
-
static clone(stats: BigIntStats | Stats): BigIntStats;
|
|
196
|
+
protected _isBigint: true;
|
|
207
197
|
}
|
|
198
|
+
/**
|
|
199
|
+
* @internal
|
|
200
|
+
*/
|
|
201
|
+
export declare const ZenFsType = 525687744115;
|
|
202
|
+
/**
|
|
203
|
+
* @hidden
|
|
204
|
+
*/
|
|
208
205
|
export declare class StatsFs implements Node.StatsFsBase<number> {
|
|
209
206
|
/** Type of file system. */
|
|
210
207
|
type: number;
|
|
@@ -221,6 +218,9 @@ export declare class StatsFs implements Node.StatsFsBase<number> {
|
|
|
221
218
|
/** Free file nodes in file system. */
|
|
222
219
|
ffree: number;
|
|
223
220
|
}
|
|
221
|
+
/**
|
|
222
|
+
* @hidden
|
|
223
|
+
*/
|
|
224
224
|
export declare class BigIntStatsFs implements Node.StatsFsBase<bigint> {
|
|
225
225
|
/** Type of file system. */
|
|
226
226
|
type: bigint;
|
package/dist/stats.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { S_IFDIR, S_IFLNK, S_IFMT, S_IFREG, S_IRWXG, S_IRWXO, S_IRWXU } from './emulation/constants.js';
|
|
1
|
+
import { S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFREG, S_IFSOCK, S_IRWXG, S_IRWXO, S_IRWXU } from './emulation/constants.js';
|
|
2
|
+
import { size_max } from './inode.js';
|
|
2
3
|
/**
|
|
3
4
|
* Indicates the type of the given file. Applied to 'mode'.
|
|
4
5
|
*/
|
|
@@ -13,15 +14,12 @@ export var FileType;
|
|
|
13
14
|
* Common code used by both Stats and BigIntStats.
|
|
14
15
|
*/
|
|
15
16
|
export class StatsCommon {
|
|
16
|
-
get _typename() {
|
|
17
|
-
return this._isBigint ? 'bigint' : 'number';
|
|
18
|
-
}
|
|
19
|
-
get _typename_inverse() {
|
|
20
|
-
return this._isBigint ? 'number' : 'bigint';
|
|
21
|
-
}
|
|
22
17
|
_convert(arg) {
|
|
23
18
|
return (this._isBigint ? BigInt(arg) : Number(arg));
|
|
24
19
|
}
|
|
20
|
+
get blocks() {
|
|
21
|
+
return this._convert(Math.ceil(Number(this.size) / 512));
|
|
22
|
+
}
|
|
25
23
|
get atime() {
|
|
26
24
|
return new Date(Number(this.atimeMs));
|
|
27
25
|
}
|
|
@@ -78,16 +76,15 @@ export class StatsCommon {
|
|
|
78
76
|
* group ID of owner
|
|
79
77
|
*/
|
|
80
78
|
this.gid = this._convert(0);
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
this.
|
|
84
|
-
this.
|
|
85
|
-
this.
|
|
86
|
-
this.
|
|
87
|
-
this.
|
|
88
|
-
this.
|
|
89
|
-
this.
|
|
90
|
-
this.ino = resolveT(ino, 0);
|
|
79
|
+
const now = Date.now();
|
|
80
|
+
this.atimeMs = this._convert(atimeMs ?? now);
|
|
81
|
+
this.mtimeMs = this._convert(mtimeMs ?? now);
|
|
82
|
+
this.ctimeMs = this._convert(ctimeMs ?? now);
|
|
83
|
+
this.birthtimeMs = this._convert(birthtimeMs ?? now);
|
|
84
|
+
this.uid = this._convert(uid ?? 0);
|
|
85
|
+
this.gid = this._convert(gid ?? 0);
|
|
86
|
+
this.size = this._convert(size ?? 0);
|
|
87
|
+
this.ino = this._convert(ino ?? 0);
|
|
91
88
|
const itemType = Number(mode) & S_IFMT || FileType.FILE;
|
|
92
89
|
if (mode) {
|
|
93
90
|
this.mode = this._convert(mode);
|
|
@@ -102,8 +99,6 @@ export class StatsCommon {
|
|
|
102
99
|
this.mode = this._convert(0o777);
|
|
103
100
|
}
|
|
104
101
|
}
|
|
105
|
-
// number of 512B blocks allocated
|
|
106
|
-
this.blocks = this._convert(Math.ceil(Number(size) / 512));
|
|
107
102
|
// Check if mode also includes top-most bits, which indicate the file's type.
|
|
108
103
|
if ((this.mode & S_IFMT) == 0) {
|
|
109
104
|
this.mode = (this.mode | this._convert(itemType));
|
|
@@ -129,16 +124,16 @@ export class StatsCommon {
|
|
|
129
124
|
}
|
|
130
125
|
// Currently unsupported
|
|
131
126
|
isSocket() {
|
|
132
|
-
return
|
|
127
|
+
return (this.mode & S_IFMT) === S_IFSOCK;
|
|
133
128
|
}
|
|
134
129
|
isBlockDevice() {
|
|
135
|
-
return
|
|
130
|
+
return (this.mode & S_IFMT) === S_IFBLK;
|
|
136
131
|
}
|
|
137
132
|
isCharacterDevice() {
|
|
138
|
-
return
|
|
133
|
+
return (this.mode & S_IFMT) === S_IFCHR;
|
|
139
134
|
}
|
|
140
135
|
isFIFO() {
|
|
141
|
-
return
|
|
136
|
+
return (this.mode & S_IFMT) === S_IFIFO;
|
|
142
137
|
}
|
|
143
138
|
/**
|
|
144
139
|
* Checks if a given user/group has access to this item
|
|
@@ -194,16 +189,16 @@ export class StatsCommon {
|
|
|
194
189
|
}
|
|
195
190
|
}
|
|
196
191
|
get atimeNs() {
|
|
197
|
-
return BigInt(this.atimeMs);
|
|
192
|
+
return BigInt(this.atimeMs) * 1000n;
|
|
198
193
|
}
|
|
199
194
|
get mtimeNs() {
|
|
200
|
-
return BigInt(this.mtimeMs);
|
|
195
|
+
return BigInt(this.mtimeMs) * 1000n;
|
|
201
196
|
}
|
|
202
197
|
get ctimeNs() {
|
|
203
|
-
return BigInt(this.ctimeMs);
|
|
198
|
+
return BigInt(this.ctimeMs) * 1000n;
|
|
204
199
|
}
|
|
205
200
|
get birthtimeNs() {
|
|
206
|
-
return BigInt(this.birthtimeMs);
|
|
201
|
+
return BigInt(this.birthtimeMs) * 1000n;
|
|
207
202
|
}
|
|
208
203
|
}
|
|
209
204
|
/**
|
|
@@ -212,44 +207,39 @@ export class StatsCommon {
|
|
|
212
207
|
* Attribute descriptions are from `man 2 stat'
|
|
213
208
|
* @see http://nodejs.org/api/fs.html#fs_class_fs_stats
|
|
214
209
|
* @see http://man7.org/linux/man-pages/man2/stat.2.html
|
|
210
|
+
* @internal
|
|
215
211
|
*/
|
|
216
212
|
export class Stats extends StatsCommon {
|
|
217
213
|
constructor() {
|
|
218
214
|
super(...arguments);
|
|
219
215
|
this._isBigint = false;
|
|
220
216
|
}
|
|
221
|
-
/**
|
|
222
|
-
* Clones the stats object.
|
|
223
|
-
* @deprecated use `new Stats(stats)`
|
|
224
|
-
*/
|
|
225
|
-
static clone(stats) {
|
|
226
|
-
return new Stats(stats);
|
|
227
|
-
}
|
|
228
217
|
}
|
|
229
218
|
Stats;
|
|
230
219
|
/**
|
|
231
220
|
* Stats with bigint
|
|
232
221
|
* @todo Implement with bigint instead of wrapping Stats
|
|
222
|
+
* @internal
|
|
233
223
|
*/
|
|
234
224
|
export class BigIntStats extends StatsCommon {
|
|
235
225
|
constructor() {
|
|
236
226
|
super(...arguments);
|
|
237
227
|
this._isBigint = true;
|
|
238
228
|
}
|
|
239
|
-
/**
|
|
240
|
-
* Clone a stats object.
|
|
241
|
-
* @deprecated use `new BigIntStats(stats)`
|
|
242
|
-
*/
|
|
243
|
-
static clone(stats) {
|
|
244
|
-
return new BigIntStats(stats);
|
|
245
|
-
}
|
|
246
229
|
}
|
|
230
|
+
/**
|
|
231
|
+
* @internal
|
|
232
|
+
*/
|
|
233
|
+
export const ZenFsType = 0x7a656e6673; // 'z' 'e' 'n' 'f' 's'
|
|
234
|
+
/**
|
|
235
|
+
* @hidden
|
|
236
|
+
*/
|
|
247
237
|
export class StatsFs {
|
|
248
238
|
constructor() {
|
|
249
239
|
/** Type of file system. */
|
|
250
|
-
this.type =
|
|
240
|
+
this.type = 0x7a656e6673;
|
|
251
241
|
/** Optimal transfer block size. */
|
|
252
|
-
this.bsize =
|
|
242
|
+
this.bsize = 4096;
|
|
253
243
|
/** Total data blocks in file system. */
|
|
254
244
|
this.blocks = 0;
|
|
255
245
|
/** Free blocks in file system. */
|
|
@@ -257,17 +247,20 @@ export class StatsFs {
|
|
|
257
247
|
/** Available blocks for unprivileged users */
|
|
258
248
|
this.bavail = 0;
|
|
259
249
|
/** Total file nodes in file system. */
|
|
260
|
-
this.files =
|
|
250
|
+
this.files = size_max;
|
|
261
251
|
/** Free file nodes in file system. */
|
|
262
|
-
this.ffree =
|
|
252
|
+
this.ffree = size_max;
|
|
263
253
|
}
|
|
264
254
|
}
|
|
255
|
+
/**
|
|
256
|
+
* @hidden
|
|
257
|
+
*/
|
|
265
258
|
export class BigIntStatsFs {
|
|
266
259
|
constructor() {
|
|
267
260
|
/** Type of file system. */
|
|
268
|
-
this.type =
|
|
261
|
+
this.type = 0x7a656e6673n;
|
|
269
262
|
/** Optimal transfer block size. */
|
|
270
|
-
this.bsize =
|
|
263
|
+
this.bsize = 4096n;
|
|
271
264
|
/** Total data blocks in file system. */
|
|
272
265
|
this.blocks = 0n;
|
|
273
266
|
/** Free blocks in file system. */
|
|
@@ -275,8 +268,8 @@ export class BigIntStatsFs {
|
|
|
275
268
|
/** Available blocks for unprivileged users */
|
|
276
269
|
this.bavail = 0n;
|
|
277
270
|
/** Total file nodes in file system. */
|
|
278
|
-
this.files =
|
|
271
|
+
this.files = BigInt(size_max);
|
|
279
272
|
/** Free file nodes in file system. */
|
|
280
|
-
this.ffree =
|
|
273
|
+
this.ffree = BigInt(size_max);
|
|
281
274
|
}
|
|
282
275
|
}
|