@zenfs/core 0.9.6 → 0.9.7
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/ApiError.d.ts +4 -3
- package/dist/ApiError.js +1 -1
- package/dist/backends/AsyncStore.d.ts +3 -2
- package/dist/backends/AsyncStore.js +12 -5
- package/dist/backends/InMemory.d.ts +1 -1
- package/dist/backends/Index.d.ts +7 -10
- package/dist/backends/Index.js +7 -5
- package/dist/backends/Overlay.js +1 -1
- package/dist/backends/SyncStore.d.ts +6 -6
- package/dist/backends/SyncStore.js +4 -4
- package/dist/backends/backend.d.ts +5 -4
- package/dist/backends/backend.js +2 -2
- package/dist/browser.min.js +4 -4
- package/dist/browser.min.js.map +3 -3
- package/dist/config.d.ts +1 -1
- package/dist/config.js +2 -2
- package/dist/emulation/async.d.ts +76 -77
- package/dist/emulation/async.js +42 -42
- package/dist/emulation/dir.js +6 -5
- package/dist/emulation/promises.d.ts +106 -102
- package/dist/emulation/promises.js +61 -65
- package/dist/emulation/shared.d.ts +1 -7
- package/dist/emulation/shared.js +1 -1
- package/dist/emulation/streams.js +3 -2
- package/dist/emulation/sync.d.ts +71 -64
- package/dist/emulation/sync.js +39 -40
- package/dist/file.d.ts +4 -4
- package/dist/file.js +7 -5
- package/dist/filesystem.d.ts +1 -1
- package/dist/filesystem.js +3 -0
- package/dist/mutex.js +2 -2
- package/dist/stats.d.ts +7 -7
- package/dist/stats.js +50 -10
- package/dist/utils.d.ts +5 -5
- package/dist/utils.js +4 -3
- package/package.json +3 -3
- package/readme.md +2 -2
- package/src/ApiError.ts +3 -1
- package/src/backends/AsyncStore.ts +14 -8
- package/src/backends/Index.ts +14 -10
- package/src/backends/Overlay.ts +3 -3
- package/src/backends/SyncStore.ts +8 -8
- package/src/backends/backend.ts +7 -5
- package/src/config.ts +5 -5
- package/src/emulation/async.ts +188 -196
- package/src/emulation/dir.ts +6 -6
- package/src/emulation/promises.ts +181 -173
- package/src/emulation/shared.ts +2 -9
- package/src/emulation/streams.ts +9 -8
- package/src/emulation/sync.ts +159 -159
- package/src/file.ts +11 -9
- package/src/filesystem.ts +11 -7
- package/src/mutex.ts +3 -3
- package/src/stats.ts +32 -23
- package/src/utils.ts +10 -9
- package/tsconfig.json +2 -1
package/src/file.ts
CHANGED
|
@@ -181,12 +181,12 @@ export abstract class File {
|
|
|
181
181
|
/**
|
|
182
182
|
* Get the current file position.
|
|
183
183
|
*/
|
|
184
|
-
public abstract position
|
|
184
|
+
public abstract position: number;
|
|
185
185
|
|
|
186
186
|
/**
|
|
187
187
|
* The path to the file
|
|
188
188
|
*/
|
|
189
|
-
public abstract readonly path
|
|
189
|
+
public abstract readonly path: string;
|
|
190
190
|
|
|
191
191
|
/**
|
|
192
192
|
* Asynchronous `stat`.
|
|
@@ -241,7 +241,7 @@ export abstract class File {
|
|
|
241
241
|
* the current position.
|
|
242
242
|
* @returns Promise resolving to the new length of the buffer
|
|
243
243
|
*/
|
|
244
|
-
public abstract write(buffer: Uint8Array, offset?: number, length?: number, position?: number): Promise<number>;
|
|
244
|
+
public abstract write(buffer: Uint8Array, offset?: number, length?: number, position?: number | null): Promise<number>;
|
|
245
245
|
|
|
246
246
|
/**
|
|
247
247
|
* Write buffer to the file.
|
|
@@ -255,7 +255,7 @@ export abstract class File {
|
|
|
255
255
|
* data should be written. If position is null, the data will be written at
|
|
256
256
|
* the current position.
|
|
257
257
|
*/
|
|
258
|
-
public abstract writeSync(buffer: Uint8Array, offset?: number, length?: number, position?: number): number;
|
|
258
|
+
public abstract writeSync(buffer: Uint8Array, offset?: number, length?: number, position?: number | null): number;
|
|
259
259
|
|
|
260
260
|
/**
|
|
261
261
|
* Read data from the file.
|
|
@@ -468,7 +468,7 @@ export class PreloadFile<FS extends FileSystem> extends File {
|
|
|
468
468
|
* Asynchronous truncate.
|
|
469
469
|
* @param len
|
|
470
470
|
*/
|
|
471
|
-
public truncate(len: number): Promise<void> {
|
|
471
|
+
public async truncate(len: number): Promise<void> {
|
|
472
472
|
this.truncateSync(len);
|
|
473
473
|
if (isSynchronous(this.flag)) {
|
|
474
474
|
return this.sync();
|
|
@@ -515,7 +515,9 @@ export class PreloadFile<FS extends FileSystem> extends File {
|
|
|
515
515
|
* the current position.
|
|
516
516
|
*/
|
|
517
517
|
public async write(buffer: Uint8Array, offset: number = 0, length: number = this.stats.size, position: number = 0): Promise<number> {
|
|
518
|
-
|
|
518
|
+
const bytesWritten = this.writeSync(buffer, offset, length, position);
|
|
519
|
+
await this.sync();
|
|
520
|
+
return bytesWritten;
|
|
519
521
|
}
|
|
520
522
|
|
|
521
523
|
/**
|
|
@@ -541,7 +543,7 @@ export class PreloadFile<FS extends FileSystem> extends File {
|
|
|
541
543
|
if (endFp > this.stats.size) {
|
|
542
544
|
this.stats.size = endFp;
|
|
543
545
|
if (endFp > this._buffer.byteLength) {
|
|
544
|
-
if (this._buffer.buffer.resizable && this._buffer.buffer.maxByteLength <= endFp) {
|
|
546
|
+
if (this._buffer.buffer.resizable && this._buffer.buffer.maxByteLength! <= endFp) {
|
|
545
547
|
this._buffer.buffer.resize(endFp);
|
|
546
548
|
} else {
|
|
547
549
|
// Extend the buffer!
|
|
@@ -594,7 +596,7 @@ export class PreloadFile<FS extends FileSystem> extends File {
|
|
|
594
596
|
* position.
|
|
595
597
|
* @returns number of bytes written
|
|
596
598
|
*/
|
|
597
|
-
public readSync(buffer: ArrayBufferView, offset: number = 0, length: number = this.stats.size, position
|
|
599
|
+
public readSync(buffer: ArrayBufferView, offset: number = 0, length: number = this.stats.size, position?: number): number {
|
|
598
600
|
if (!isReadable(this.flag)) {
|
|
599
601
|
throw new ApiError(ErrorCode.EPERM, 'File not opened with a readable mode.');
|
|
600
602
|
}
|
|
@@ -610,7 +612,7 @@ export class PreloadFile<FS extends FileSystem> extends File {
|
|
|
610
612
|
// No copy/read. Return immediatly for better performance
|
|
611
613
|
return bytesRead;
|
|
612
614
|
}
|
|
613
|
-
new Uint8Array(buffer.buffer).set(this._buffer.slice(position, end), offset);
|
|
615
|
+
new Uint8Array(buffer.buffer, 0, length).set(this._buffer.slice(position, end), offset);
|
|
614
616
|
return bytesRead;
|
|
615
617
|
}
|
|
616
618
|
|
package/src/filesystem.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { join } from './emulation/path.js';
|
|
|
5
5
|
import { PreloadFile, parseFlag, type File } from './file.js';
|
|
6
6
|
import type { Stats } from './stats.js';
|
|
7
7
|
|
|
8
|
-
export type FileContents =
|
|
8
|
+
export type FileContents = ArrayBufferView | string;
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Metadata about a FileSystem
|
|
@@ -218,7 +218,8 @@ declare abstract class SyncFileSystem extends FileSystem {
|
|
|
218
218
|
/**
|
|
219
219
|
* Implements the asynchronous API in terms of the synchronous API.
|
|
220
220
|
*/
|
|
221
|
-
|
|
221
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
222
|
+
export function Sync<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => SyncFileSystem) & T {
|
|
222
223
|
abstract class _SyncFileSystem extends FS implements SyncFileSystem {
|
|
223
224
|
public async exists(path: string, cred: Cred): Promise<boolean> {
|
|
224
225
|
return this.existsSync(path, cred);
|
|
@@ -290,7 +291,8 @@ declare abstract class AsyncFileSystem extends FileSystem {
|
|
|
290
291
|
syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
|
|
291
292
|
}
|
|
292
293
|
|
|
293
|
-
|
|
294
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
295
|
+
type AsyncMethods = ExtractProperties<FileSystem, (...args: any[]) => Promise<unknown>>;
|
|
294
296
|
|
|
295
297
|
/**
|
|
296
298
|
* @internal
|
|
@@ -311,7 +313,8 @@ type AsyncOperation = {
|
|
|
311
313
|
* the synchronous store, if desired.
|
|
312
314
|
*
|
|
313
315
|
*/
|
|
314
|
-
|
|
316
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
317
|
+
export function Async<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => AsyncFileSystem) & T {
|
|
315
318
|
abstract class _AsyncFileSystem extends FS implements AsyncFileSystem {
|
|
316
319
|
/**
|
|
317
320
|
* Queue of pending asynchronous operations.
|
|
@@ -323,7 +326,7 @@ export function Async<T extends abstract new (...args) => FileSystem>(FS: T): (a
|
|
|
323
326
|
|
|
324
327
|
public queueDone(): Promise<void> {
|
|
325
328
|
return new Promise(resolve => {
|
|
326
|
-
const check = () => (this._queueRunning ? setTimeout(check) : resolve());
|
|
329
|
+
const check = (): unknown => (this._queueRunning ? setTimeout(check) : resolve());
|
|
327
330
|
check();
|
|
328
331
|
});
|
|
329
332
|
}
|
|
@@ -440,7 +443,7 @@ export function Async<T extends abstract new (...args) => FileSystem>(FS: T): (a
|
|
|
440
443
|
return;
|
|
441
444
|
}
|
|
442
445
|
|
|
443
|
-
const [method, ...args] = this._queue.shift()
|
|
446
|
+
const [method, ...args] = this._queue.shift()!;
|
|
444
447
|
// @ts-expect-error 2556 (since ...args is not correctly picked up as being a tuple)
|
|
445
448
|
await this[method](...args);
|
|
446
449
|
await this._next();
|
|
@@ -482,7 +485,8 @@ declare abstract class ReadonlyFileSystem extends FileSystem {
|
|
|
482
485
|
/**
|
|
483
486
|
* Implements the non-readonly methods to throw `EROFS`
|
|
484
487
|
*/
|
|
485
|
-
|
|
488
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
489
|
+
export function Readonly<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => ReadonlyFileSystem) & T {
|
|
486
490
|
abstract class _ReadonlyFileSystem extends FS implements ReadonlyFileSystem {
|
|
487
491
|
public metadata(): FileSystemMetadata {
|
|
488
492
|
return { ...super.metadata(), readonly: true };
|
package/src/mutex.ts
CHANGED
|
@@ -8,9 +8,9 @@ export class Mutex {
|
|
|
8
8
|
public lock(path: string): Promise<void> {
|
|
9
9
|
return new Promise(resolve => {
|
|
10
10
|
if (this._locks.has(path)) {
|
|
11
|
-
this._locks.get(path)
|
|
11
|
+
this._locks.get(path)!.push(resolve);
|
|
12
12
|
} else {
|
|
13
|
-
this._locks.set(path, []);
|
|
13
|
+
this._locks.set(path, [resolve]);
|
|
14
14
|
}
|
|
15
15
|
});
|
|
16
16
|
}
|
|
@@ -20,7 +20,7 @@ export class Mutex {
|
|
|
20
20
|
throw new Error('unlock of a non-locked mutex');
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
const next = this._locks.get(path)
|
|
23
|
+
const next = this._locks.get(path)?.shift();
|
|
24
24
|
/*
|
|
25
25
|
don't unlock - we want to queue up next for the
|
|
26
26
|
end of the current task execution, but we don't
|
package/src/stats.ts
CHANGED
|
@@ -120,7 +120,7 @@ export abstract class StatsCommon<T extends number | bigint> implements Node.Sta
|
|
|
120
120
|
/**
|
|
121
121
|
* Some file systems stash data on stats objects.
|
|
122
122
|
*/
|
|
123
|
-
public fileData?: Uint8Array
|
|
123
|
+
public fileData?: Uint8Array;
|
|
124
124
|
|
|
125
125
|
/**
|
|
126
126
|
* time of last access, in milliseconds since epoch
|
|
@@ -185,15 +185,16 @@ export abstract class StatsCommon<T extends number | bigint> implements Node.Sta
|
|
|
185
185
|
*/
|
|
186
186
|
constructor({ atimeMs, mtimeMs, ctimeMs, birthtimeMs, uid, gid, size, mode, ino }: Partial<StatsLike> = {}) {
|
|
187
187
|
const currentTime = Date.now();
|
|
188
|
-
const resolveT = (val: number | bigint, _default: number) =>
|
|
188
|
+
const resolveT = (val: number | bigint | undefined, _default: number) =>
|
|
189
|
+
<T>(typeof val == this._typename ? val : this._convert(typeof val == this._typename_inverse ? val! : _default));
|
|
189
190
|
this.atimeMs = resolveT(atimeMs, currentTime);
|
|
190
191
|
this.mtimeMs = resolveT(mtimeMs, currentTime);
|
|
191
192
|
this.ctimeMs = resolveT(ctimeMs, currentTime);
|
|
192
193
|
this.birthtimeMs = resolveT(birthtimeMs, currentTime);
|
|
193
194
|
this.uid = resolveT(uid, 0);
|
|
194
195
|
this.gid = resolveT(gid, 0);
|
|
195
|
-
this.size =
|
|
196
|
-
this.ino =
|
|
196
|
+
this.size = resolveT(size, 0);
|
|
197
|
+
this.ino = resolveT(ino, 0);
|
|
197
198
|
const itemType: FileType = Number(mode) & S_IFMT || FileType.FILE;
|
|
198
199
|
|
|
199
200
|
if (mode) {
|
|
@@ -312,6 +313,19 @@ export abstract class StatsCommon<T extends number | bigint> implements Node.Sta
|
|
|
312
313
|
this.gid = this._convert(gid);
|
|
313
314
|
}
|
|
314
315
|
}
|
|
316
|
+
|
|
317
|
+
public get atimeNs(): bigint {
|
|
318
|
+
return BigInt(this.atimeMs);
|
|
319
|
+
}
|
|
320
|
+
public get mtimeNs(): bigint {
|
|
321
|
+
return BigInt(this.mtimeMs);
|
|
322
|
+
}
|
|
323
|
+
public get ctimeNs(): bigint {
|
|
324
|
+
return BigInt(this.ctimeMs);
|
|
325
|
+
}
|
|
326
|
+
public get birthtimeNs(): bigint {
|
|
327
|
+
return BigInt(this.birthtimeMs);
|
|
328
|
+
}
|
|
315
329
|
}
|
|
316
330
|
|
|
317
331
|
/**
|
|
@@ -341,11 +355,6 @@ Stats satisfies typeof Node.Stats;
|
|
|
341
355
|
export class BigIntStats extends StatsCommon<bigint> implements Node.BigIntStats, StatsLike {
|
|
342
356
|
protected _isBigint = true;
|
|
343
357
|
|
|
344
|
-
public atimeNs: bigint;
|
|
345
|
-
public mtimeNs: bigint;
|
|
346
|
-
public ctimeNs: bigint;
|
|
347
|
-
public birthtimeNs: bigint;
|
|
348
|
-
|
|
349
358
|
/**
|
|
350
359
|
* Clone a stats object.
|
|
351
360
|
* @deprecated use `new BigIntStats(stats)`
|
|
@@ -357,34 +366,34 @@ export class BigIntStats extends StatsCommon<bigint> implements Node.BigIntStats
|
|
|
357
366
|
|
|
358
367
|
export class StatsFs implements Node.StatsFsBase<number> {
|
|
359
368
|
/** Type of file system. */
|
|
360
|
-
public type: number;
|
|
369
|
+
public type: number = 0;
|
|
361
370
|
/** Optimal transfer block size. */
|
|
362
|
-
public bsize: number;
|
|
371
|
+
public bsize: number = 0;
|
|
363
372
|
/** Total data blocks in file system. */
|
|
364
|
-
public blocks: number;
|
|
373
|
+
public blocks: number = 0;
|
|
365
374
|
/** Free blocks in file system. */
|
|
366
|
-
public bfree: number;
|
|
375
|
+
public bfree: number = 0;
|
|
367
376
|
/** Available blocks for unprivileged users */
|
|
368
|
-
public bavail: number;
|
|
377
|
+
public bavail: number = 0;
|
|
369
378
|
/** Total file nodes in file system. */
|
|
370
|
-
public files: number;
|
|
379
|
+
public files: number = 0;
|
|
371
380
|
/** Free file nodes in file system. */
|
|
372
|
-
public ffree: number;
|
|
381
|
+
public ffree: number = 0;
|
|
373
382
|
}
|
|
374
383
|
|
|
375
384
|
export class BigIntStatsFs implements Node.StatsFsBase<bigint> {
|
|
376
385
|
/** Type of file system. */
|
|
377
|
-
public type: bigint;
|
|
386
|
+
public type: bigint = 0n;
|
|
378
387
|
/** Optimal transfer block size. */
|
|
379
|
-
public bsize: bigint;
|
|
388
|
+
public bsize: bigint = 0n;
|
|
380
389
|
/** Total data blocks in file system. */
|
|
381
|
-
public blocks: bigint;
|
|
390
|
+
public blocks: bigint = 0n;
|
|
382
391
|
/** Free blocks in file system. */
|
|
383
|
-
public bfree: bigint;
|
|
392
|
+
public bfree: bigint = 0n;
|
|
384
393
|
/** Available blocks for unprivileged users */
|
|
385
|
-
public bavail: bigint;
|
|
394
|
+
public bavail: bigint = 0n;
|
|
386
395
|
/** Total file nodes in file system. */
|
|
387
|
-
public files: bigint;
|
|
396
|
+
public files: bigint = 0n;
|
|
388
397
|
/** Free file nodes in file system. */
|
|
389
|
-
public ffree: bigint;
|
|
398
|
+
public ffree: bigint = 0n;
|
|
390
399
|
}
|
package/src/utils.ts
CHANGED
|
@@ -114,7 +114,7 @@ export function levenshtein(a: string, b: string): number {
|
|
|
114
114
|
/**
|
|
115
115
|
* @hidden
|
|
116
116
|
*/
|
|
117
|
-
export const setImmediate = typeof globalThis.setImmediate == 'function' ? globalThis.setImmediate : cb => setTimeout(cb, 0);
|
|
117
|
+
export const setImmediate = typeof globalThis.setImmediate == 'function' ? globalThis.setImmediate : (cb: () => unknown) => setTimeout(cb, 0);
|
|
118
118
|
|
|
119
119
|
/**
|
|
120
120
|
* Encodes a string into a buffer
|
|
@@ -173,7 +173,7 @@ export function encodeDirListing(data: Record<string, bigint>): Uint8Array {
|
|
|
173
173
|
|
|
174
174
|
export type Callback<Args extends unknown[] = []> = (e?: ApiError, ...args: OptionalTuple<Args>) => unknown;
|
|
175
175
|
|
|
176
|
-
import type { EncodingOption, OpenMode, WriteFileOptions } from 'node:fs';
|
|
176
|
+
import type { EncodingOption, OpenMode, PathLike, WriteFileOptions } from 'node:fs';
|
|
177
177
|
|
|
178
178
|
/**
|
|
179
179
|
* converts Date or number to a integer UNIX timestamp
|
|
@@ -238,7 +238,8 @@ export function normalizeTime(time: string | number | Date): Date {
|
|
|
238
238
|
* Normalizes a path
|
|
239
239
|
* @internal
|
|
240
240
|
*/
|
|
241
|
-
export function normalizePath(p:
|
|
241
|
+
export function normalizePath(p: PathLike): string {
|
|
242
|
+
p = p.toString();
|
|
242
243
|
// Node doesn't allow null characters in paths.
|
|
243
244
|
if (p.includes('\x00')) {
|
|
244
245
|
throw new ApiError(ErrorCode.EINVAL, 'Path must be a string without null bytes.');
|
|
@@ -258,21 +259,21 @@ export function normalizePath(p: string): string {
|
|
|
258
259
|
* @internal
|
|
259
260
|
*/
|
|
260
261
|
export function normalizeOptions(
|
|
261
|
-
options
|
|
262
|
-
encoding: BufferEncoding = 'utf8',
|
|
263
|
-
flag
|
|
262
|
+
options: WriteFileOptions | (EncodingOption & { flag?: OpenMode }) | undefined,
|
|
263
|
+
encoding: BufferEncoding | null = 'utf8',
|
|
264
|
+
flag: string,
|
|
264
265
|
mode: number = 0
|
|
265
|
-
): { encoding
|
|
266
|
+
): { encoding?: BufferEncoding | null; flag: string; mode: number } {
|
|
266
267
|
if (typeof options != 'object' || options === null) {
|
|
267
268
|
return {
|
|
268
|
-
encoding: typeof options == 'string' ? options : encoding,
|
|
269
|
+
encoding: typeof options == 'string' ? options : encoding ?? null,
|
|
269
270
|
flag,
|
|
270
271
|
mode,
|
|
271
272
|
};
|
|
272
273
|
}
|
|
273
274
|
|
|
274
275
|
return {
|
|
275
|
-
encoding: typeof options?.encoding == 'string' ? options.encoding : encoding,
|
|
276
|
+
encoding: typeof options?.encoding == 'string' ? options.encoding : encoding ?? null,
|
|
276
277
|
flag: typeof options?.flag == 'string' ? options.flag : flag,
|
|
277
278
|
mode: normalizeMode('mode' in options ? options?.mode : null, mode),
|
|
278
279
|
};
|