@zenfs/core 1.8.8 → 1.9.0
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/backend.js +7 -4
- package/dist/backends/fetch.d.ts +23 -32
- package/dist/backends/fetch.js +94 -134
- package/dist/backends/index.d.ts +1 -4
- package/dist/backends/index.js +1 -4
- package/dist/backends/memory.d.ts +7 -5
- package/dist/backends/memory.js +6 -4
- package/dist/backends/overlay.d.ts +4 -5
- package/dist/backends/overlay.js +16 -20
- package/dist/backends/passthrough.d.ts +3 -3
- package/dist/backends/passthrough.js +4 -6
- package/dist/backends/port/fs.d.ts +4 -5
- package/dist/backends/port/fs.js +7 -12
- package/dist/backends/port/rpc.d.ts +1 -1
- package/dist/backends/port/rpc.js +15 -13
- package/dist/backends/store/fs.d.ts +51 -40
- package/dist/backends/store/fs.js +347 -241
- package/dist/backends/store/map.d.ts +41 -0
- package/dist/backends/store/map.js +45 -0
- package/dist/backends/store/simple.d.ts +10 -58
- package/dist/backends/store/simple.js +8 -115
- package/dist/backends/store/store.d.ts +111 -44
- package/dist/backends/store/store.js +230 -38
- package/dist/config.d.ts +7 -3
- package/dist/config.js +17 -14
- package/dist/context.d.ts +1 -1
- package/dist/context.js +1 -1
- package/dist/index.d.ts +1 -5
- package/dist/index.js +1 -5
- package/dist/{devices.d.ts → internal/devices.d.ts} +4 -4
- package/dist/{devices.js → internal/devices.js} +18 -14
- package/dist/{file.d.ts → internal/file.d.ts} +3 -2
- package/dist/{file.js → internal/file.js} +17 -12
- package/dist/{backends/store → internal}/file_index.d.ts +13 -3
- package/dist/{backends/store → internal}/file_index.js +28 -5
- package/dist/{filesystem.d.ts → internal/filesystem.d.ts} +99 -32
- package/dist/internal/filesystem.js +83 -0
- package/dist/internal/index.d.ts +9 -0
- package/dist/internal/index.js +9 -0
- package/dist/internal/index_fs.d.ts +56 -0
- package/dist/internal/index_fs.js +184 -0
- package/dist/{backends/store → internal}/inode.d.ts +6 -1
- package/dist/{backends/store → internal}/inode.js +14 -6
- package/dist/internal/log.d.ts +132 -0
- package/dist/internal/log.js +177 -0
- package/dist/mixins/async.d.ts +2 -2
- package/dist/mixins/async.js +19 -16
- package/dist/mixins/mutexed.d.ts +9 -3
- package/dist/mixins/mutexed.js +22 -3
- package/dist/mixins/readonly.d.ts +2 -2
- package/dist/mixins/readonly.js +4 -3
- package/dist/mixins/shared.d.ts +1 -1
- package/dist/mixins/sync.d.ts +2 -2
- package/dist/stats.d.ts +2 -3
- package/dist/stats.js +7 -5
- package/dist/utils.d.ts +2 -15
- package/dist/utils.js +10 -47
- package/dist/vfs/async.d.ts +2 -2
- package/dist/vfs/async.js +3 -3
- package/dist/vfs/dir.js +1 -1
- package/dist/vfs/promises.d.ts +6 -6
- package/dist/vfs/promises.js +54 -49
- package/dist/vfs/shared.d.ts +3 -3
- package/dist/vfs/shared.js +16 -10
- package/dist/vfs/streams.js +1 -1
- package/dist/vfs/sync.d.ts +1 -2
- package/dist/vfs/sync.js +14 -15
- package/dist/vfs/types.d.ts +1 -0
- package/dist/vfs/watchers.d.ts +5 -1
- package/dist/vfs/watchers.js +16 -19
- package/package.json +3 -3
- package/readme.md +12 -12
- package/scripts/test.js +15 -3
- package/tests/backend/fetch.test.ts +49 -0
- package/tests/backend/port.test.ts +130 -0
- package/tests/common/context.test.ts +9 -4
- package/tests/common.ts +21 -3
- package/tests/data/image.jpg +0 -0
- package/tests/data/utf8.txt +1 -0
- package/tests/fetch/config.js +40 -0
- package/tests/fetch/fetch.ts +20 -0
- package/tests/fetch/run.sh +3 -3
- package/tests/fetch/{server.ts → server.js} +15 -11
- package/tests/fs/directory.test.ts +1 -1
- package/tests/fs/errors.test.ts +1 -1
- package/tests/fs/links.test.ts +1 -1
- package/tests/fs/open.test.ts +1 -1
- package/tests/fs/permissions.test.ts +2 -3
- package/tests/fs/rename.test.ts +1 -1
- package/tests/fs/stat.test.ts +1 -1
- package/tests/fs/times.test.ts +1 -1
- package/tests/fs/watch.test.ts +21 -22
- package/tests/fs/writeFile.test.ts +8 -7
- package/tests/readme.md +3 -3
- package/tests/setup/_overlay.ts +7 -0
- package/tests/setup/context.ts +2 -2
- package/tests/setup/index.ts +3 -3
- package/tests/setup/memory.ts +2 -2
- package/tests/setup/port.ts +2 -2
- package/tests/setup.ts +25 -5
- package/tests/tsconfig.json +3 -2
- package/dist/backends/store/index_fs.d.ts +0 -34
- package/dist/backends/store/index_fs.js +0 -67
- package/dist/filesystem.js +0 -52
- package/tests/fetch/cow+fetch.ts +0 -13
- package/tests/port/channel.test.ts +0 -39
- package/tests/port/config.test.ts +0 -30
- package/tests/port/remote.test.ts +0 -32
- package/tests/port/timeout.test.ts +0 -48
- /package/dist/{credentials.d.ts → internal/credentials.d.ts} +0 -0
- /package/dist/{credentials.js → internal/credentials.js} +0 -0
- /package/dist/{error.d.ts → internal/error.d.ts} +0 -0
- /package/dist/{error.js → internal/error.js} +0 -0
- /package/tests/{port → backend}/config.worker.js +0 -0
- /package/tests/{port → backend}/remote.worker.js +0 -0
package/dist/utils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type * as fs from 'node:fs';
|
|
2
2
|
import type { ClassLike, OptionalTuple } from 'utilium';
|
|
3
|
-
import { ErrnoError } from './error.js';
|
|
3
|
+
import { ErrnoError } from './internal/error.js';
|
|
4
4
|
import type { AbsolutePath } from './vfs/path.js';
|
|
5
5
|
declare global {
|
|
6
6
|
function atob(data: string): string;
|
|
@@ -79,19 +79,6 @@ export declare function randomBigInt(): bigint;
|
|
|
79
79
|
/**
|
|
80
80
|
* Prevents infinite loops
|
|
81
81
|
* @internal
|
|
82
|
+
* @deprecated Use `canary` from Utilium
|
|
82
83
|
*/
|
|
83
84
|
export declare function canary(path?: string, syscall?: string): () => void;
|
|
84
|
-
/**
|
|
85
|
-
* A wrapper for throwing things.
|
|
86
|
-
* Used in expressions.
|
|
87
|
-
* @todo Remove once `throw` is allowed in expressions
|
|
88
|
-
* @see https://github.com/tc39/proposal-throw-expressions
|
|
89
|
-
* @internal @hidden
|
|
90
|
-
*/
|
|
91
|
-
export declare function _throw(e: unknown): never;
|
|
92
|
-
/**
|
|
93
|
-
* Grows a buffer if it isn't large enough
|
|
94
|
-
* @returns The original buffer if resized successfully, or a newly created buffer
|
|
95
|
-
* @internal Not for external use!
|
|
96
|
-
*/
|
|
97
|
-
export declare function growBuffer<T extends ArrayBufferLike | ArrayBufferView>(buffer: T, newByteLength: number): T;
|
package/dist/utils.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Errno, ErrnoError } from './internal/error.js';
|
|
2
|
+
import { log_deprecated } from './internal/log.js';
|
|
3
3
|
import { resolve } from './vfs/path.js';
|
|
4
4
|
/**
|
|
5
5
|
* Encodes a string into a buffer
|
|
@@ -122,74 +122,37 @@ export function normalizePath(p) {
|
|
|
122
122
|
export function normalizeOptions(options, encoding = 'utf8', flag, mode = 0) {
|
|
123
123
|
if (typeof options != 'object' || options === null) {
|
|
124
124
|
return {
|
|
125
|
-
encoding: typeof options == 'string' ? options : encoding !== null && encoding !== void 0 ? encoding : null,
|
|
125
|
+
encoding: typeof options == 'string' ? options : (encoding !== null && encoding !== void 0 ? encoding : null),
|
|
126
126
|
flag,
|
|
127
127
|
mode,
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
130
|
return {
|
|
131
|
-
encoding: typeof (options === null || options === void 0 ? void 0 : options.encoding) == 'string' ? options.encoding : encoding !== null && encoding !== void 0 ? encoding : null,
|
|
131
|
+
encoding: typeof (options === null || options === void 0 ? void 0 : options.encoding) == 'string' ? options.encoding : (encoding !== null && encoding !== void 0 ? encoding : null),
|
|
132
132
|
flag: typeof (options === null || options === void 0 ? void 0 : options.flag) == 'string' ? options.flag : flag,
|
|
133
133
|
mode: normalizeMode('mode' in options ? options === null || options === void 0 ? void 0 : options.mode : null, mode),
|
|
134
134
|
};
|
|
135
135
|
}
|
|
136
|
+
/* node:coverage disable */
|
|
137
|
+
import { randomHex } from 'utilium';
|
|
136
138
|
/**
|
|
137
139
|
* Generate a random ino
|
|
138
140
|
* @internal @deprecated @hidden
|
|
139
141
|
*/
|
|
140
142
|
export function randomBigInt() {
|
|
143
|
+
log_deprecated('randomBigInt');
|
|
141
144
|
return BigInt('0x' + randomHex(8));
|
|
142
145
|
}
|
|
143
146
|
/**
|
|
144
147
|
* Prevents infinite loops
|
|
145
148
|
* @internal
|
|
149
|
+
* @deprecated Use `canary` from Utilium
|
|
146
150
|
*/
|
|
147
151
|
export function canary(path, syscall) {
|
|
152
|
+
log_deprecated('canary');
|
|
148
153
|
const timeout = setTimeout(() => {
|
|
149
154
|
throw ErrnoError.With('EDEADLK', path, syscall);
|
|
150
155
|
}, 5000);
|
|
151
156
|
return () => clearTimeout(timeout);
|
|
152
157
|
}
|
|
153
|
-
|
|
154
|
-
* A wrapper for throwing things.
|
|
155
|
-
* Used in expressions.
|
|
156
|
-
* @todo Remove once `throw` is allowed in expressions
|
|
157
|
-
* @see https://github.com/tc39/proposal-throw-expressions
|
|
158
|
-
* @internal @hidden
|
|
159
|
-
*/
|
|
160
|
-
export function _throw(e) {
|
|
161
|
-
throw e;
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Grows a buffer if it isn't large enough
|
|
165
|
-
* @returns The original buffer if resized successfully, or a newly created buffer
|
|
166
|
-
* @internal Not for external use!
|
|
167
|
-
*/
|
|
168
|
-
export function growBuffer(buffer, newByteLength) {
|
|
169
|
-
if (buffer.byteLength >= newByteLength)
|
|
170
|
-
return buffer;
|
|
171
|
-
if (ArrayBuffer.isView(buffer)) {
|
|
172
|
-
const newBuffer = growBuffer(buffer.buffer, newByteLength);
|
|
173
|
-
return new buffer.constructor(newBuffer, buffer.byteOffset, newByteLength);
|
|
174
|
-
}
|
|
175
|
-
const isShared = typeof SharedArrayBuffer !== 'undefined' && buffer instanceof SharedArrayBuffer;
|
|
176
|
-
// Note: If true, the buffer must be resizable/growable because of the first check.
|
|
177
|
-
if (buffer.maxByteLength > newByteLength) {
|
|
178
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
179
|
-
isShared ? buffer.grow(newByteLength) : buffer.resize(newByteLength);
|
|
180
|
-
return buffer;
|
|
181
|
-
}
|
|
182
|
-
if (isShared) {
|
|
183
|
-
const newBuffer = new SharedArrayBuffer(newByteLength);
|
|
184
|
-
new Uint8Array(newBuffer).set(new Uint8Array(buffer));
|
|
185
|
-
return newBuffer;
|
|
186
|
-
}
|
|
187
|
-
try {
|
|
188
|
-
return buffer.transfer(newByteLength);
|
|
189
|
-
}
|
|
190
|
-
catch {
|
|
191
|
-
const newBuffer = new ArrayBuffer(newByteLength);
|
|
192
|
-
new Uint8Array(newBuffer).set(new Uint8Array(buffer));
|
|
193
|
-
return newBuffer;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
158
|
+
/* node:coverage enable */
|
package/dist/vfs/async.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type * as fs from 'node:fs';
|
|
2
2
|
import type { V_Context } from '../context.js';
|
|
3
|
-
import type { FileContents } from '../filesystem.js';
|
|
4
3
|
import type { Stats } from '../stats.js';
|
|
5
4
|
import type { Callback } from '../utils.js';
|
|
6
5
|
import type { Dir, Dirent } from './dir.js';
|
|
6
|
+
import type { FileContents } from './types.js';
|
|
7
7
|
import { Buffer } from 'buffer';
|
|
8
|
-
import { ErrnoError } from '../error.js';
|
|
8
|
+
import { ErrnoError } from '../internal/error.js';
|
|
9
9
|
import { BigIntStats } from '../stats.js';
|
|
10
10
|
import * as promises from './promises.js';
|
|
11
11
|
import { ReadStream, WriteStream } from './streams.js';
|
package/dist/vfs/async.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Buffer } from 'buffer';
|
|
2
|
-
import { Errno, ErrnoError } from '../error.js';
|
|
2
|
+
import { Errno, ErrnoError } from '../internal/error.js';
|
|
3
3
|
import { BigIntStats } from '../stats.js';
|
|
4
4
|
import { normalizeMode, normalizePath } from '../utils.js';
|
|
5
5
|
import { R_OK } from './constants.js';
|
|
@@ -476,10 +476,10 @@ export function createWriteStream(path, options) {
|
|
|
476
476
|
},
|
|
477
477
|
destroy(error, callback) {
|
|
478
478
|
callback(error);
|
|
479
|
-
handle === null || handle === void 0 ? void 0 : handle.close().then(() => callback(error)).catch(callback);
|
|
479
|
+
void (handle === null || handle === void 0 ? void 0 : handle.close().then(() => callback(error)).catch(callback));
|
|
480
480
|
},
|
|
481
481
|
final(callback) {
|
|
482
|
-
handle === null || handle === void 0 ? void 0 : handle.close().then(() => callback()).catch(callback);
|
|
482
|
+
void (handle === null || handle === void 0 ? void 0 : handle.close().then(() => callback()).catch(callback));
|
|
483
483
|
},
|
|
484
484
|
});
|
|
485
485
|
stream.path = path.toString();
|
package/dist/vfs/dir.js
CHANGED
package/dist/vfs/promises.d.ts
CHANGED
|
@@ -4,10 +4,9 @@ import type { Stream } from 'node:stream';
|
|
|
4
4
|
import type { ReadableStream as TReadableStream } from 'node:stream/web';
|
|
5
5
|
import type { Interface as ReadlineInterface } from 'readline';
|
|
6
6
|
import type { V_Context } from '../context.js';
|
|
7
|
-
import type { File } from '../file.js';
|
|
8
|
-
import type { FileContents } from '../filesystem.js';
|
|
7
|
+
import type { File } from '../internal/file.js';
|
|
9
8
|
import type { Stats } from '../stats.js';
|
|
10
|
-
import type { InternalOptions, NullEnc, ReaddirOptions, ReaddirOptsI, ReaddirOptsU } from './types.js';
|
|
9
|
+
import type { FileContents, InternalOptions, NullEnc, ReaddirOptions, ReaddirOptsI, ReaddirOptsU } from './types.js';
|
|
11
10
|
import { Buffer } from 'buffer';
|
|
12
11
|
import '../polyfills.js';
|
|
13
12
|
import { BigIntStats } from '../stats.js';
|
|
@@ -26,6 +25,7 @@ export declare class FileHandle implements promises.FileHandle {
|
|
|
26
25
|
*/
|
|
27
26
|
readonly file: File;
|
|
28
27
|
constructor(fdOrFile: number | File, context?: V_Context | undefined);
|
|
28
|
+
private _emitChange;
|
|
29
29
|
/**
|
|
30
30
|
* Asynchronous fchown(2) - Change ownership of a file.
|
|
31
31
|
*/
|
|
@@ -296,9 +296,9 @@ export declare function lutimes(this: V_Context, path: fs.PathLike, atime: fs.Ti
|
|
|
296
296
|
*/
|
|
297
297
|
export declare function realpath(this: V_Context, path: fs.PathLike, options: fs.BufferEncodingOption): Promise<Buffer>;
|
|
298
298
|
export declare function realpath(this: V_Context, path: fs.PathLike, options?: fs.EncodingOption | BufferEncoding): Promise<string>;
|
|
299
|
-
export declare function watch(this: V_Context, filename: fs.PathLike, options?: fs.WatchOptions | BufferEncoding):
|
|
300
|
-
export declare function watch(this: V_Context, filename: fs.PathLike, options: fs.WatchOptions | fs.BufferEncodingOption):
|
|
301
|
-
export declare function watch(this: V_Context, filename: fs.PathLike, options?: fs.WatchOptions | string):
|
|
299
|
+
export declare function watch(this: V_Context, filename: fs.PathLike, options?: fs.WatchOptions | BufferEncoding): AsyncIterableIterator<promises.FileChangeInfo<string>>;
|
|
300
|
+
export declare function watch(this: V_Context, filename: fs.PathLike, options: fs.WatchOptions | fs.BufferEncodingOption): AsyncIterableIterator<promises.FileChangeInfo<Buffer>>;
|
|
301
|
+
export declare function watch(this: V_Context, filename: fs.PathLike, options?: fs.WatchOptions | string): AsyncIterableIterator<promises.FileChangeInfo<string>> | AsyncIterableIterator<promises.FileChangeInfo<Buffer>>;
|
|
302
302
|
export declare function access(this: V_Context, path: fs.PathLike, mode?: number): Promise<void>;
|
|
303
303
|
/**
|
|
304
304
|
* Asynchronous `rm`. Removes files or directories (recursively).
|
package/dist/vfs/promises.js
CHANGED
|
@@ -51,9 +51,9 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
51
51
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
52
|
});
|
|
53
53
|
import { Buffer } from 'buffer';
|
|
54
|
-
import { credentials } from '../credentials.js';
|
|
55
|
-
import { Errno, ErrnoError } from '../error.js';
|
|
56
|
-
import { flagToMode, isAppendable, isExclusive, isReadable, isTruncating, isWriteable, parseFlag } from '../file.js';
|
|
54
|
+
import { credentials } from '../internal/credentials.js';
|
|
55
|
+
import { Errno, ErrnoError } from '../internal/error.js';
|
|
56
|
+
import { flagToMode, isAppendable, isExclusive, isReadable, isTruncating, isWriteable, parseFlag } from '../internal/file.js';
|
|
57
57
|
import '../polyfills.js';
|
|
58
58
|
import { BigIntStats } from '../stats.js';
|
|
59
59
|
import { decodeUTF8, normalizeMode, normalizeOptions, normalizePath, normalizeTime } from '../utils.js';
|
|
@@ -73,12 +73,16 @@ export class FileHandle {
|
|
|
73
73
|
this.fd = isFile ? file2fd(fdOrFile) : fdOrFile;
|
|
74
74
|
this.file = isFile ? fdOrFile : fd2file(fdOrFile);
|
|
75
75
|
}
|
|
76
|
+
_emitChange() {
|
|
77
|
+
var _a, _b, _c;
|
|
78
|
+
emitChange(this.context, 'change', this.file.path.slice((_c = (_b = (_a = this.context) === null || _a === void 0 ? void 0 : _a.root) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0));
|
|
79
|
+
}
|
|
76
80
|
/**
|
|
77
81
|
* Asynchronous fchown(2) - Change ownership of a file.
|
|
78
82
|
*/
|
|
79
83
|
async chown(uid, gid) {
|
|
80
84
|
await this.file.chown(uid, gid);
|
|
81
|
-
|
|
85
|
+
this._emitChange();
|
|
82
86
|
}
|
|
83
87
|
/**
|
|
84
88
|
* Asynchronous fchmod(2) - Change permissions of a file.
|
|
@@ -90,7 +94,7 @@ export class FileHandle {
|
|
|
90
94
|
throw new ErrnoError(Errno.EINVAL, 'Invalid mode.');
|
|
91
95
|
}
|
|
92
96
|
await this.file.chmod(numMode);
|
|
93
|
-
|
|
97
|
+
this._emitChange();
|
|
94
98
|
}
|
|
95
99
|
/**
|
|
96
100
|
* Asynchronous fdatasync(2) - synchronize a file's in-core state with storage device.
|
|
@@ -114,7 +118,7 @@ export class FileHandle {
|
|
|
114
118
|
throw new ErrnoError(Errno.EINVAL);
|
|
115
119
|
}
|
|
116
120
|
await this.file.truncate(length);
|
|
117
|
-
|
|
121
|
+
this._emitChange();
|
|
118
122
|
}
|
|
119
123
|
/**
|
|
120
124
|
* Asynchronously change file timestamps of the file.
|
|
@@ -123,7 +127,7 @@ export class FileHandle {
|
|
|
123
127
|
*/
|
|
124
128
|
async utimes(atime, mtime) {
|
|
125
129
|
await this.file.utimes(normalizeTime(atime), normalizeTime(mtime));
|
|
126
|
-
|
|
130
|
+
this._emitChange();
|
|
127
131
|
}
|
|
128
132
|
/**
|
|
129
133
|
* Asynchronously append data to a file, creating the file if it does not exist. The underlying file will _not_ be closed automatically.
|
|
@@ -145,7 +149,7 @@ export class FileHandle {
|
|
|
145
149
|
}
|
|
146
150
|
const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding) : data;
|
|
147
151
|
await this.file.write(encodedData, 0, encodedData.length);
|
|
148
|
-
|
|
152
|
+
this._emitChange();
|
|
149
153
|
}
|
|
150
154
|
async read(buffer, offset, length, position) {
|
|
151
155
|
if (typeof offset == 'object' && offset != null) {
|
|
@@ -262,7 +266,7 @@ export class FileHandle {
|
|
|
262
266
|
}
|
|
263
267
|
position !== null && position !== void 0 ? position : (position = this.file.position);
|
|
264
268
|
const bytesWritten = await this.file.write(buffer, offset, length, position);
|
|
265
|
-
|
|
269
|
+
this._emitChange();
|
|
266
270
|
return { buffer: data, bytesWritten };
|
|
267
271
|
}
|
|
268
272
|
/**
|
|
@@ -286,7 +290,7 @@ export class FileHandle {
|
|
|
286
290
|
}
|
|
287
291
|
const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding) : data;
|
|
288
292
|
await this.file.write(encodedData, 0, encodedData.length, 0);
|
|
289
|
-
|
|
293
|
+
this._emitChange();
|
|
290
294
|
}
|
|
291
295
|
/**
|
|
292
296
|
* Asynchronous close(2) - close a `FileHandle`.
|
|
@@ -378,13 +382,13 @@ export async function rename(oldPath, newPath) {
|
|
|
378
382
|
try {
|
|
379
383
|
if (src.mountPoint == dst.mountPoint) {
|
|
380
384
|
await src.fs.rename(src.path, dst.path);
|
|
381
|
-
emitChange('rename', oldPath.toString());
|
|
382
|
-
emitChange('change', newPath.toString());
|
|
385
|
+
emitChange(this, 'rename', oldPath.toString());
|
|
386
|
+
emitChange(this, 'change', newPath.toString());
|
|
383
387
|
return;
|
|
384
388
|
}
|
|
385
389
|
await writeFile.call(this, newPath, await readFile(oldPath));
|
|
386
390
|
await unlink.call(this, oldPath);
|
|
387
|
-
emitChange('rename', oldPath.toString());
|
|
391
|
+
emitChange(this, 'rename', oldPath.toString());
|
|
388
392
|
}
|
|
389
393
|
catch (e) {
|
|
390
394
|
throw fixError(e, { [src.path]: oldPath, [dst.path]: newPath });
|
|
@@ -459,7 +463,7 @@ export async function unlink(path) {
|
|
|
459
463
|
throw ErrnoError.With('EACCES', resolved, 'unlink');
|
|
460
464
|
}
|
|
461
465
|
await fs.unlink(resolved);
|
|
462
|
-
emitChange('rename', path.toString());
|
|
466
|
+
emitChange(this, 'rename', path.toString());
|
|
463
467
|
}
|
|
464
468
|
catch (e) {
|
|
465
469
|
throw fixError(e, { [resolved]: path });
|
|
@@ -470,8 +474,7 @@ unlink;
|
|
|
470
474
|
* Manually apply setuid/setgid.
|
|
471
475
|
*/
|
|
472
476
|
async function applySetId(file, uid, gid) {
|
|
473
|
-
|
|
474
|
-
if ((_a = file.fs.metadata().features) === null || _a === void 0 ? void 0 : _a.includes('setid'))
|
|
477
|
+
if (file.fs.attributes.has('setid'))
|
|
475
478
|
return;
|
|
476
479
|
const parent = await file.fs.stat(dirname(file.path));
|
|
477
480
|
await file.chown(parent.mode & constants.S_ISUID ? parent.uid : uid, // manually apply setuid/setgid
|
|
@@ -633,7 +636,7 @@ export async function rmdir(path) {
|
|
|
633
636
|
throw ErrnoError.With('EACCES', resolved, 'rmdir');
|
|
634
637
|
}
|
|
635
638
|
await fs.rmdir(resolved);
|
|
636
|
-
emitChange('rename', path.toString());
|
|
639
|
+
emitChange(this, 'rename', path.toString());
|
|
637
640
|
}
|
|
638
641
|
catch (e) {
|
|
639
642
|
throw fixError(e, { [resolved]: path });
|
|
@@ -655,7 +658,7 @@ export async function mkdir(path, options) {
|
|
|
655
658
|
}
|
|
656
659
|
await fs.mkdir(resolved, mode, { uid, gid });
|
|
657
660
|
await applySetId(await fs.openFile(resolved, 'r+'), uid, gid);
|
|
658
|
-
emitChange('rename', path.toString());
|
|
661
|
+
emitChange(this, 'rename', path.toString());
|
|
659
662
|
return;
|
|
660
663
|
}
|
|
661
664
|
const dirs = [];
|
|
@@ -669,7 +672,7 @@ export async function mkdir(path, options) {
|
|
|
669
672
|
}
|
|
670
673
|
await fs.mkdir(dir, mode, { uid, gid });
|
|
671
674
|
await applySetId(await fs.openFile(dir, 'r+'), uid, gid);
|
|
672
|
-
emitChange('rename', dir);
|
|
675
|
+
emitChange(this, 'rename', dir);
|
|
673
676
|
}
|
|
674
677
|
return root.length == 1 ? dirs[0] : (_b = dirs[0]) === null || _b === void 0 ? void 0 : _b.slice(root.length);
|
|
675
678
|
}
|
|
@@ -984,36 +987,38 @@ export async function realpath(path, options) {
|
|
|
984
987
|
}
|
|
985
988
|
realpath;
|
|
986
989
|
export function watch(filename, options = {}) {
|
|
987
|
-
const
|
|
990
|
+
const watcher = new FSWatcher(this, filename.toString(), typeof options !== 'string' ? options : { encoding: options });
|
|
991
|
+
// A queue to hold change events, since we need to resolve them in the async iterator
|
|
992
|
+
const eventQueue = [];
|
|
993
|
+
let done = false;
|
|
994
|
+
watcher.on('change', (eventType, filename) => {
|
|
995
|
+
var _a;
|
|
996
|
+
(_a = eventQueue.shift()) === null || _a === void 0 ? void 0 : _a({ value: { eventType, filename }, done: false });
|
|
997
|
+
});
|
|
998
|
+
function cleanup() {
|
|
999
|
+
done = true;
|
|
1000
|
+
watcher.close();
|
|
1001
|
+
for (const resolve of eventQueue) {
|
|
1002
|
+
resolve({ value: null, done });
|
|
1003
|
+
}
|
|
1004
|
+
eventQueue.length = 0; // Clear the queue
|
|
1005
|
+
return Promise.resolve({ value: null, done: true });
|
|
1006
|
+
}
|
|
988
1007
|
return {
|
|
1008
|
+
async next() {
|
|
1009
|
+
if (done)
|
|
1010
|
+
return Promise.resolve({ value: null, done });
|
|
1011
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
1012
|
+
eventQueue.push(resolve);
|
|
1013
|
+
return promise;
|
|
1014
|
+
},
|
|
1015
|
+
return: cleanup,
|
|
1016
|
+
throw: cleanup,
|
|
1017
|
+
async [Symbol.asyncDispose]() {
|
|
1018
|
+
await cleanup();
|
|
1019
|
+
},
|
|
989
1020
|
[Symbol.asyncIterator]() {
|
|
990
|
-
|
|
991
|
-
// A queue to hold change events, since we need to resolve them in the async iterator
|
|
992
|
-
const eventQueue = [];
|
|
993
|
-
watcher.on('change', (eventType, filename) => {
|
|
994
|
-
var _a;
|
|
995
|
-
(_a = eventQueue.shift()) === null || _a === void 0 ? void 0 : _a({ value: { eventType, filename }, done: false });
|
|
996
|
-
});
|
|
997
|
-
function cleanup() {
|
|
998
|
-
watcher.close();
|
|
999
|
-
for (const resolve of eventQueue) {
|
|
1000
|
-
resolve({ value: null, done: true });
|
|
1001
|
-
}
|
|
1002
|
-
eventQueue.length = 0; // Clear the queue
|
|
1003
|
-
return Promise.resolve({ value: null, done: true });
|
|
1004
|
-
}
|
|
1005
|
-
return {
|
|
1006
|
-
async next() {
|
|
1007
|
-
const { promise, resolve } = Promise.withResolvers();
|
|
1008
|
-
eventQueue.push(resolve);
|
|
1009
|
-
return promise;
|
|
1010
|
-
},
|
|
1011
|
-
return: cleanup,
|
|
1012
|
-
throw: cleanup,
|
|
1013
|
-
[Symbol.asyncDispose]() {
|
|
1014
|
-
return Promise.resolve();
|
|
1015
|
-
},
|
|
1016
|
-
};
|
|
1021
|
+
return this;
|
|
1017
1022
|
},
|
|
1018
1023
|
};
|
|
1019
1024
|
}
|
|
@@ -1093,7 +1098,7 @@ export async function copyFile(src, dest, mode) {
|
|
|
1093
1098
|
throw new ErrnoError(Errno.EEXIST, 'Destination file already exists.', dest, 'copyFile');
|
|
1094
1099
|
}
|
|
1095
1100
|
await writeFile.call(this, dest, await readFile.call(this, src));
|
|
1096
|
-
emitChange('rename', dest.toString());
|
|
1101
|
+
emitChange(this, 'rename', dest.toString());
|
|
1097
1102
|
}
|
|
1098
1103
|
copyFile;
|
|
1099
1104
|
/**
|
|
@@ -1187,7 +1192,7 @@ export function glob(pattern, opt) {
|
|
|
1187
1192
|
if (exclude((withFileTypes ? entry : fullPath)))
|
|
1188
1193
|
continue;
|
|
1189
1194
|
/**
|
|
1190
|
-
* @todo
|
|
1195
|
+
* @todo is the pattern.source check correct?
|
|
1191
1196
|
*/
|
|
1192
1197
|
if ((await stat(fullPath)).isDirectory() && regexPatterns.some(pattern => pattern.source.includes('.*'))) {
|
|
1193
1198
|
yield* recursiveList(fullPath);
|
package/dist/vfs/shared.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type * as fs from 'node:fs';
|
|
2
|
-
import type { File } from '../file.js';
|
|
3
|
-
import type { FileSystem } from '../filesystem.js';
|
|
2
|
+
import type { File } from '../internal/file.js';
|
|
3
|
+
import type { FileSystem } from '../internal/filesystem.js';
|
|
4
4
|
import { type BoundContext, type V_Context } from '../context.js';
|
|
5
|
-
import { ErrnoError } from '../error.js';
|
|
5
|
+
import { ErrnoError } from '../internal/error.js';
|
|
6
6
|
import { type AbsolutePath } from './path.js';
|
|
7
7
|
/**
|
|
8
8
|
* @internal @hidden
|
package/dist/vfs/shared.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
// Utilities and shared data
|
|
2
2
|
import { InMemory } from '../backends/memory.js';
|
|
3
3
|
import { bindContext } from '../context.js';
|
|
4
|
-
import { Errno, ErrnoError } from '../error.js';
|
|
4
|
+
import { Errno, ErrnoError } from '../internal/error.js';
|
|
5
|
+
import { alert, debug, err, info, log_deprecated, notice, warn } from '../internal/log.js';
|
|
5
6
|
import { normalizePath } from '../utils.js';
|
|
6
7
|
import { paths as pathCache } from './cache.js';
|
|
7
8
|
import { size_max } from './constants.js';
|
|
8
9
|
import { join, resolve } from './path.js';
|
|
10
|
+
import { ZenFsType } from '../stats.js';
|
|
9
11
|
// descriptors
|
|
10
12
|
/**
|
|
11
13
|
* @internal @hidden
|
|
@@ -41,29 +43,32 @@ mount('/', InMemory.create({ name: 'root' }));
|
|
|
41
43
|
* @internal
|
|
42
44
|
*/
|
|
43
45
|
export function mount(mountPoint, fs) {
|
|
44
|
-
if (mountPoint[0]
|
|
46
|
+
if (mountPoint[0] != '/')
|
|
45
47
|
mountPoint = '/' + mountPoint;
|
|
46
|
-
}
|
|
47
48
|
mountPoint = resolve(mountPoint);
|
|
48
49
|
if (mounts.has(mountPoint)) {
|
|
49
|
-
throw new ErrnoError(Errno.EINVAL, 'Mount point ' + mountPoint + ' is already in use.');
|
|
50
|
+
throw err(new ErrnoError(Errno.EINVAL, 'Mount point ' + mountPoint + ' is already in use.'));
|
|
50
51
|
}
|
|
52
|
+
fs._mountPoint = mountPoint;
|
|
51
53
|
mounts.set(mountPoint, fs);
|
|
54
|
+
info(`Mounted ${fs.name} on ${mountPoint}`);
|
|
55
|
+
debug(`${fs.name} attributes: ${[...fs.attributes].map(([k, v]) => (v !== undefined && v !== null ? k + '=' + v : v)).join(', ')}`);
|
|
52
56
|
pathCache.clear();
|
|
53
57
|
}
|
|
54
58
|
/**
|
|
55
59
|
* Unmounts the file system at `mountPoint`.
|
|
56
60
|
*/
|
|
57
61
|
export function umount(mountPoint) {
|
|
58
|
-
if (mountPoint[0]
|
|
62
|
+
if (mountPoint[0] != '/')
|
|
59
63
|
mountPoint = '/' + mountPoint;
|
|
60
|
-
}
|
|
61
64
|
mountPoint = resolve(mountPoint);
|
|
62
65
|
if (!mounts.has(mountPoint)) {
|
|
63
|
-
|
|
66
|
+
warn(mountPoint + ' is already unmounted.');
|
|
67
|
+
return;
|
|
64
68
|
}
|
|
65
69
|
mounts.delete(mountPoint);
|
|
66
70
|
pathCache.clear();
|
|
71
|
+
notice('Unmounted ' + mountPoint);
|
|
67
72
|
}
|
|
68
73
|
/**
|
|
69
74
|
* Gets the internal `FileSystem` for the path, then returns it along with the path relative to the FS' root
|
|
@@ -83,7 +88,7 @@ export function resolveMount(path, ctx) {
|
|
|
83
88
|
return { fs, path, mountPoint, root };
|
|
84
89
|
}
|
|
85
90
|
}
|
|
86
|
-
throw new ErrnoError(Errno.EIO, 'No file system');
|
|
91
|
+
throw alert(new ErrnoError(Errno.EIO, 'No file system', path));
|
|
87
92
|
}
|
|
88
93
|
/**
|
|
89
94
|
* Reverse maps the paths in text from the mounted FileSystem to the global path
|
|
@@ -118,6 +123,7 @@ export function fixError(e, paths) {
|
|
|
118
123
|
* @internal @deprecated
|
|
119
124
|
*/
|
|
120
125
|
export function mountObject(mounts) {
|
|
126
|
+
log_deprecated('mountObject');
|
|
121
127
|
if ('/' in mounts) {
|
|
122
128
|
umount('/');
|
|
123
129
|
}
|
|
@@ -130,10 +136,10 @@ export function mountObject(mounts) {
|
|
|
130
136
|
* @internal @hidden
|
|
131
137
|
*/
|
|
132
138
|
export function _statfs(fs, bigint) {
|
|
133
|
-
const md = fs.
|
|
139
|
+
const md = fs.usage();
|
|
134
140
|
const bs = md.blockSize || 4096;
|
|
135
141
|
return {
|
|
136
|
-
type: (bigint ? BigInt : Number)(
|
|
142
|
+
type: (bigint ? BigInt : Number)(fs.id),
|
|
137
143
|
bsize: (bigint ? BigInt : Number)(bs),
|
|
138
144
|
ffree: (bigint ? BigInt : Number)(md.freeNodes || size_max),
|
|
139
145
|
files: (bigint ? BigInt : Number)(md.totalNodes || size_max),
|
package/dist/vfs/streams.js
CHANGED
package/dist/vfs/sync.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type * as fs from 'node:fs';
|
|
2
2
|
import type { V_Context } from '../context.js';
|
|
3
|
-
import type { FileContents } from '../filesystem.js';
|
|
4
3
|
import type { Stats } from '../stats.js';
|
|
5
|
-
import type { InternalOptions, NullEnc, ReaddirOptions, ReaddirOptsI, ReaddirOptsU } from './types.js';
|
|
4
|
+
import type { FileContents, InternalOptions, NullEnc, ReaddirOptions, ReaddirOptsI, ReaddirOptsU } from './types.js';
|
|
6
5
|
import { Buffer } from 'buffer';
|
|
7
6
|
import { BigIntStats } from '../stats.js';
|
|
8
7
|
import { Dir, Dirent } from './dir.js';
|
package/dist/vfs/sync.js
CHANGED
|
@@ -51,9 +51,9 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
51
51
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
52
|
});
|
|
53
53
|
import { Buffer } from 'buffer';
|
|
54
|
-
import { credentials } from '../credentials.js';
|
|
55
|
-
import { Errno, ErrnoError } from '../error.js';
|
|
56
|
-
import { flagToMode, isAppendable, isExclusive, isReadable, isTruncating, isWriteable, parseFlag } from '../file.js';
|
|
54
|
+
import { credentials } from '../internal/credentials.js';
|
|
55
|
+
import { Errno, ErrnoError } from '../internal/error.js';
|
|
56
|
+
import { flagToMode, isAppendable, isExclusive, isReadable, isTruncating, isWriteable, parseFlag } from '../internal/file.js';
|
|
57
57
|
import { BigIntStats } from '../stats.js';
|
|
58
58
|
import { decodeUTF8, normalizeMode, normalizeOptions, normalizePath, normalizeTime } from '../utils.js';
|
|
59
59
|
import * as cache from './cache.js';
|
|
@@ -74,13 +74,13 @@ export function renameSync(oldPath, newPath) {
|
|
|
74
74
|
try {
|
|
75
75
|
if (oldMount === newMount) {
|
|
76
76
|
oldMount.fs.renameSync(oldMount.path, newMount.path);
|
|
77
|
-
emitChange('rename', oldPath.toString());
|
|
78
|
-
emitChange('change', newPath.toString());
|
|
77
|
+
emitChange(this, 'rename', oldPath.toString());
|
|
78
|
+
emitChange(this, 'change', newPath.toString());
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
81
81
|
writeFileSync.call(this, newPath, readFileSync(oldPath));
|
|
82
82
|
unlinkSync.call(this, oldPath);
|
|
83
|
-
emitChange('rename', oldPath.toString());
|
|
83
|
+
emitChange(this, 'rename', oldPath.toString());
|
|
84
84
|
}
|
|
85
85
|
catch (e) {
|
|
86
86
|
throw fixError(e, { [oldMount.path]: oldPath, [newMount.path]: newPath });
|
|
@@ -158,7 +158,7 @@ export function unlinkSync(path) {
|
|
|
158
158
|
throw ErrnoError.With('EACCES', resolved, 'unlink');
|
|
159
159
|
}
|
|
160
160
|
fs.unlinkSync(resolved);
|
|
161
|
-
emitChange('rename', path.toString());
|
|
161
|
+
emitChange(this, 'rename', path.toString());
|
|
162
162
|
}
|
|
163
163
|
catch (e) {
|
|
164
164
|
throw fixError(e, { [resolved]: path });
|
|
@@ -169,8 +169,7 @@ unlinkSync;
|
|
|
169
169
|
* Manually apply setuid/setgid.
|
|
170
170
|
*/
|
|
171
171
|
function applySetId(file, uid, gid) {
|
|
172
|
-
|
|
173
|
-
if ((_a = file.fs.metadata().features) === null || _a === void 0 ? void 0 : _a.includes('setid'))
|
|
172
|
+
if (file.fs.attributes.has('setid'))
|
|
174
173
|
return;
|
|
175
174
|
const parent = file.fs.statSync(dirname(file.path));
|
|
176
175
|
file.chownSync(parent.mode & constants.S_ISUID ? parent.uid : uid, // manually apply setuid/setgid
|
|
@@ -287,7 +286,7 @@ export function writeFileSync(path, data, _options = {}) {
|
|
|
287
286
|
preserveSymlinks: true,
|
|
288
287
|
}), false);
|
|
289
288
|
file.writeSync(encodedData, 0, encodedData.byteLength, 0);
|
|
290
|
-
emitChange('change', path.toString());
|
|
289
|
+
emitChange(this, 'change', path.toString());
|
|
291
290
|
}
|
|
292
291
|
catch (e_3) {
|
|
293
292
|
env_3.error = e_3;
|
|
@@ -378,7 +377,7 @@ export function writeSync(fd, data, posOrOff, lenOrEnc, pos) {
|
|
|
378
377
|
const file = fd2file(fd);
|
|
379
378
|
position !== null && position !== void 0 ? position : (position = file.position);
|
|
380
379
|
const bytesWritten = file.writeSync(buffer, offset, length, position);
|
|
381
|
-
emitChange('change', file.path);
|
|
380
|
+
emitChange(this, 'change', file.path);
|
|
382
381
|
return bytesWritten;
|
|
383
382
|
}
|
|
384
383
|
writeSync;
|
|
@@ -435,7 +434,7 @@ export function rmdirSync(path) {
|
|
|
435
434
|
throw ErrnoError.With('EACCES', resolved, 'rmdir');
|
|
436
435
|
}
|
|
437
436
|
fs.rmdirSync(resolved);
|
|
438
|
-
emitChange('rename', path.toString());
|
|
437
|
+
emitChange(this, 'rename', path.toString());
|
|
439
438
|
}
|
|
440
439
|
catch (e) {
|
|
441
440
|
throw fixError(e, { [resolved]: path });
|
|
@@ -470,7 +469,7 @@ export function mkdirSync(path, options) {
|
|
|
470
469
|
}
|
|
471
470
|
fs.mkdirSync(dir, mode, { uid, gid });
|
|
472
471
|
applySetId(fs.openFileSync(dir, 'r+'), uid, gid);
|
|
473
|
-
emitChange('rename', dir);
|
|
472
|
+
emitChange(this, 'rename', dir);
|
|
474
473
|
}
|
|
475
474
|
return root.length == 1 ? dirs[0] : (_b = dirs[0]) === null || _b === void 0 ? void 0 : _b.slice(root.length);
|
|
476
475
|
}
|
|
@@ -747,7 +746,7 @@ export function copyFileSync(source, destination, flags) {
|
|
|
747
746
|
throw new ErrnoError(Errno.EEXIST, 'Destination file already exists.', destination, 'copyFile');
|
|
748
747
|
}
|
|
749
748
|
writeFileSync.call(this, destination, readFileSync(source));
|
|
750
|
-
emitChange('rename', destination.toString());
|
|
749
|
+
emitChange(this, 'rename', destination.toString());
|
|
751
750
|
}
|
|
752
751
|
copyFileSync;
|
|
753
752
|
/**
|
|
@@ -868,7 +867,7 @@ export function globSync(pattern, options = {}) {
|
|
|
868
867
|
if (exclude((withFileTypes ? entry : fullPath)))
|
|
869
868
|
continue;
|
|
870
869
|
/**
|
|
871
|
-
* @todo
|
|
870
|
+
* @todo is the pattern.source check correct?
|
|
872
871
|
*/
|
|
873
872
|
if (statSync(fullPath).isDirectory() && regexPatterns.some(pattern => pattern.source.includes('.*'))) {
|
|
874
873
|
recursiveList(fullPath);
|