@zenfs/core 0.4.1 → 0.5.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/FileIndex.d.ts +14 -18
- package/dist/FileIndex.js +5 -5
- package/dist/backends/AsyncMirror.d.ts +8 -8
- package/dist/backends/AsyncMirror.js +8 -8
- package/dist/backends/AsyncStore.d.ts +6 -6
- package/dist/backends/AsyncStore.js +2 -2
- package/dist/backends/Locked.d.ts +5 -5
- package/dist/backends/Overlay.d.ts +6 -6
- package/dist/backends/Overlay.js +12 -12
- package/dist/backends/SyncStore.d.ts +8 -8
- package/dist/backends/SyncStore.js +2 -2
- package/dist/backends/backend.d.ts +1 -1
- package/dist/backends/backend.js +1 -1
- package/dist/browser.min.js +4 -4
- package/dist/browser.min.js.map +4 -4
- package/dist/config.js +1 -2
- package/dist/cred.d.ts +2 -3
- package/dist/cred.js +8 -15
- package/dist/emulation/promises.js +10 -10
- package/dist/emulation/shared.js +2 -2
- package/dist/emulation/sync.js +10 -10
- package/dist/file.d.ts +16 -100
- package/dist/file.js +113 -204
- package/dist/filesystem.d.ts +11 -11
- package/dist/stats.d.ts +18 -2
- package/dist/stats.js +40 -4
- package/license.md +3 -3
- package/package.json +5 -5
- package/readme.md +12 -12
package/dist/file.js
CHANGED
|
@@ -16,209 +16,118 @@ export var ActionType;
|
|
|
16
16
|
// Indicates that the code should create the file.
|
|
17
17
|
ActionType[ActionType["CREATE"] = 3] = "CREATE";
|
|
18
18
|
})(ActionType = ActionType || (ActionType = {}));
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
* - r+: Open file for reading and writing. An exception occurs if the file does not exist.
|
|
24
|
-
* - rs: Open file for reading in synchronous mode. Instructs the filesystem to not cache writes.
|
|
25
|
-
* - rs+: Open file for reading and writing, and opens the file in synchronous mode.
|
|
26
|
-
* - w: Open file for writing. The file is created (if it does not exist) or truncated (if it exists).
|
|
27
|
-
* - wx: Like 'w' but opens the file in exclusive mode.
|
|
28
|
-
* - w+: Open file for reading and writing. The file is created (if it does not exist) or truncated (if it exists).
|
|
29
|
-
* - wx+: Like 'w+' but opens the file in exclusive mode.
|
|
30
|
-
* - a: Open file for appending. The file is created if it does not exist.
|
|
31
|
-
* - ax: Like 'a' but opens the file in exclusive mode.
|
|
32
|
-
* - a+: Open file for reading and appending. The file is created if it does not exist.
|
|
33
|
-
* - ax+: Like 'a+' but opens the file in exclusive mode.
|
|
34
|
-
*
|
|
35
|
-
* Exclusive mode ensures that the file path is newly created.
|
|
36
|
-
*/
|
|
37
|
-
export class FileFlag {
|
|
38
|
-
/**
|
|
39
|
-
* Get an object representing the given file flag.
|
|
40
|
-
* @param flag The string or number representing the flag
|
|
41
|
-
* @return The FileFlag object representing the flag
|
|
42
|
-
* @throw when the flag string is invalid
|
|
43
|
-
*/
|
|
44
|
-
static Get(flag) {
|
|
45
|
-
// Check cache first.
|
|
46
|
-
if (!FileFlag.cache.has(flag)) {
|
|
47
|
-
FileFlag.cache.set(flag, new FileFlag(flag));
|
|
48
|
-
}
|
|
49
|
-
return FileFlag.cache.get(flag);
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* @param flag The string or number representing the flag
|
|
53
|
-
* @throw when the flag is invalid
|
|
54
|
-
*/
|
|
55
|
-
constructor(flag) {
|
|
56
|
-
if (typeof flag == 'number') {
|
|
57
|
-
flag = FileFlag.StringOf(flag);
|
|
58
|
-
}
|
|
59
|
-
if (!FileFlag.validStrings.includes(flag)) {
|
|
60
|
-
throw new ApiError(ErrorCode.EINVAL, 'Invalid flag string: ' + flag);
|
|
61
|
-
}
|
|
62
|
-
this._flag = flag;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* @param flag The number representing the flag
|
|
66
|
-
* @returns The string representing the flag
|
|
67
|
-
* @throws when the flag number is invalid
|
|
68
|
-
*/
|
|
69
|
-
static StringOf(flag) {
|
|
70
|
-
// based on https://github.com/nodejs/node/blob/abbdc3efaa455e6c907ebef5409ac8b0f222f969/lib/internal/fs/utils.js#L619
|
|
71
|
-
switch (flag) {
|
|
72
|
-
case O_RDONLY:
|
|
73
|
-
return 'r';
|
|
74
|
-
case O_RDONLY | O_SYNC:
|
|
75
|
-
return 'rs';
|
|
76
|
-
case O_RDWR:
|
|
77
|
-
return 'r+';
|
|
78
|
-
case O_RDWR | O_SYNC:
|
|
79
|
-
return 'rs+';
|
|
80
|
-
case O_TRUNC | O_CREAT | O_WRONLY:
|
|
81
|
-
return 'w';
|
|
82
|
-
case O_TRUNC | O_CREAT | O_WRONLY | O_EXCL:
|
|
83
|
-
return 'wx';
|
|
84
|
-
case O_TRUNC | O_CREAT | O_RDWR:
|
|
85
|
-
return 'w+';
|
|
86
|
-
case O_TRUNC | O_CREAT | O_RDWR | O_EXCL:
|
|
87
|
-
return 'wx+';
|
|
88
|
-
case O_APPEND | O_CREAT | O_WRONLY:
|
|
89
|
-
return 'a';
|
|
90
|
-
case O_APPEND | O_CREAT | O_WRONLY | O_EXCL:
|
|
91
|
-
return 'ax';
|
|
92
|
-
case O_APPEND | O_CREAT | O_RDWR:
|
|
93
|
-
return 'a+';
|
|
94
|
-
case O_APPEND | O_CREAT | O_RDWR | O_EXCL:
|
|
95
|
-
return 'ax+';
|
|
96
|
-
default:
|
|
97
|
-
throw new ApiError(ErrorCode.EINVAL, 'Invalid flag number: ' + flag);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* @param flag The string representing the flag
|
|
102
|
-
* @returns The number representing the flag
|
|
103
|
-
* @throws when the flag string is invalid
|
|
104
|
-
*/
|
|
105
|
-
static NumberOf(flag) {
|
|
106
|
-
switch (flag) {
|
|
107
|
-
case 'r':
|
|
108
|
-
return O_RDONLY;
|
|
109
|
-
case 'rs':
|
|
110
|
-
return O_RDONLY | O_SYNC;
|
|
111
|
-
case 'r+':
|
|
112
|
-
return O_RDWR;
|
|
113
|
-
case 'rs+':
|
|
114
|
-
return O_RDWR | O_SYNC;
|
|
115
|
-
case 'w':
|
|
116
|
-
return O_TRUNC | O_CREAT | O_WRONLY;
|
|
117
|
-
case 'wx':
|
|
118
|
-
return O_TRUNC | O_CREAT | O_WRONLY | O_EXCL;
|
|
119
|
-
case 'w+':
|
|
120
|
-
return O_TRUNC | O_CREAT | O_RDWR;
|
|
121
|
-
case 'wx+':
|
|
122
|
-
return O_TRUNC | O_CREAT | O_RDWR | O_EXCL;
|
|
123
|
-
case 'a':
|
|
124
|
-
return O_APPEND | O_CREAT | O_WRONLY;
|
|
125
|
-
case 'ax':
|
|
126
|
-
return O_APPEND | O_CREAT | O_WRONLY | O_EXCL;
|
|
127
|
-
case 'a+':
|
|
128
|
-
return O_APPEND | O_CREAT | O_RDWR;
|
|
129
|
-
case 'ax+':
|
|
130
|
-
return O_APPEND | O_CREAT | O_RDWR | O_EXCL;
|
|
131
|
-
default:
|
|
132
|
-
throw new ApiError(ErrorCode.EINVAL, 'Invalid flag string: ' + flag);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Get the underlying flag string for this flag.
|
|
137
|
-
*/
|
|
138
|
-
toString() {
|
|
139
|
-
return this._flag;
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Get the equivalent mode (0b0xxx: read, write, execute)
|
|
143
|
-
* Note: Execute will always be 0
|
|
144
|
-
*/
|
|
145
|
-
get mode() {
|
|
146
|
-
let mode = 0;
|
|
147
|
-
mode <<= 1;
|
|
148
|
-
mode += +this.isReadable();
|
|
149
|
-
mode <<= 1;
|
|
150
|
-
mode += +this.isWriteable();
|
|
151
|
-
mode <<= 1;
|
|
152
|
-
return mode;
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Returns true if the file is readable.
|
|
156
|
-
*/
|
|
157
|
-
isReadable() {
|
|
158
|
-
return this._flag.indexOf('r') != -1 || this._flag.indexOf('+') != -1;
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Returns true if the file is writeable.
|
|
162
|
-
*/
|
|
163
|
-
isWriteable() {
|
|
164
|
-
return this._flag.indexOf('w') != -1 || this._flag.indexOf('a') != -1 || this._flag.indexOf('+') != -1;
|
|
19
|
+
const validFlags = ['r', 'r+', 'rs', 'rs+', 'w', 'wx', 'w+', 'wx+', 'a', 'ax', 'a+', 'ax+'];
|
|
20
|
+
export function parseFlag(flag) {
|
|
21
|
+
if (typeof flag === 'number') {
|
|
22
|
+
return flagToString(flag);
|
|
165
23
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
*/
|
|
169
|
-
isTruncating() {
|
|
170
|
-
return this._flag.indexOf('w') !== -1;
|
|
24
|
+
if (!validFlags.includes(flag)) {
|
|
25
|
+
throw new Error('Invalid flag string: ' + flag);
|
|
171
26
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
27
|
+
return flag;
|
|
28
|
+
}
|
|
29
|
+
export function flagToString(flag) {
|
|
30
|
+
switch (flag) {
|
|
31
|
+
case O_RDONLY:
|
|
32
|
+
return 'r';
|
|
33
|
+
case O_RDONLY | O_SYNC:
|
|
34
|
+
return 'rs';
|
|
35
|
+
case O_RDWR:
|
|
36
|
+
return 'r+';
|
|
37
|
+
case O_RDWR | O_SYNC:
|
|
38
|
+
return 'rs+';
|
|
39
|
+
case O_TRUNC | O_CREAT | O_WRONLY:
|
|
40
|
+
return 'w';
|
|
41
|
+
case O_TRUNC | O_CREAT | O_WRONLY | O_EXCL:
|
|
42
|
+
return 'wx';
|
|
43
|
+
case O_TRUNC | O_CREAT | O_RDWR:
|
|
44
|
+
return 'w+';
|
|
45
|
+
case O_TRUNC | O_CREAT | O_RDWR | O_EXCL:
|
|
46
|
+
return 'wx+';
|
|
47
|
+
case O_APPEND | O_CREAT | O_WRONLY:
|
|
48
|
+
return 'a';
|
|
49
|
+
case O_APPEND | O_CREAT | O_WRONLY | O_EXCL:
|
|
50
|
+
return 'ax';
|
|
51
|
+
case O_APPEND | O_CREAT | O_RDWR:
|
|
52
|
+
return 'a+';
|
|
53
|
+
case O_APPEND | O_CREAT | O_RDWR | O_EXCL:
|
|
54
|
+
return 'ax+';
|
|
55
|
+
default:
|
|
56
|
+
throw new Error('Invalid flag number: ' + flag);
|
|
177
57
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
58
|
+
}
|
|
59
|
+
export function flagToNumber(flag) {
|
|
60
|
+
switch (flag) {
|
|
61
|
+
case 'r':
|
|
62
|
+
return O_RDONLY;
|
|
63
|
+
case 'rs':
|
|
64
|
+
return O_RDONLY | O_SYNC;
|
|
65
|
+
case 'r+':
|
|
66
|
+
return O_RDWR;
|
|
67
|
+
case 'rs+':
|
|
68
|
+
return O_RDWR | O_SYNC;
|
|
69
|
+
case 'w':
|
|
70
|
+
return O_TRUNC | O_CREAT | O_WRONLY;
|
|
71
|
+
case 'wx':
|
|
72
|
+
return O_TRUNC | O_CREAT | O_WRONLY | O_EXCL;
|
|
73
|
+
case 'w+':
|
|
74
|
+
return O_TRUNC | O_CREAT | O_RDWR;
|
|
75
|
+
case 'wx+':
|
|
76
|
+
return O_TRUNC | O_CREAT | O_RDWR | O_EXCL;
|
|
77
|
+
case 'a':
|
|
78
|
+
return O_APPEND | O_CREAT | O_WRONLY;
|
|
79
|
+
case 'ax':
|
|
80
|
+
return O_APPEND | O_CREAT | O_WRONLY | O_EXCL;
|
|
81
|
+
case 'a+':
|
|
82
|
+
return O_APPEND | O_CREAT | O_RDWR;
|
|
83
|
+
case 'ax+':
|
|
84
|
+
return O_APPEND | O_CREAT | O_RDWR | O_EXCL;
|
|
85
|
+
default:
|
|
86
|
+
throw new Error('Invalid flag string: ' + flag);
|
|
183
87
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
88
|
+
}
|
|
89
|
+
export function flagToMode(flag) {
|
|
90
|
+
let mode = 0;
|
|
91
|
+
mode <<= 1;
|
|
92
|
+
mode += +isReadable(flag);
|
|
93
|
+
mode <<= 1;
|
|
94
|
+
mode += +isWriteable(flag);
|
|
95
|
+
mode <<= 1;
|
|
96
|
+
return mode;
|
|
97
|
+
}
|
|
98
|
+
export function isReadable(flag) {
|
|
99
|
+
return flag.indexOf('r') !== -1 || flag.indexOf('+') !== -1;
|
|
100
|
+
}
|
|
101
|
+
export function isWriteable(flag) {
|
|
102
|
+
return flag.indexOf('w') !== -1 || flag.indexOf('a') !== -1 || flag.indexOf('+') !== -1;
|
|
103
|
+
}
|
|
104
|
+
export function isTruncating(flag) {
|
|
105
|
+
return flag.indexOf('w') !== -1;
|
|
106
|
+
}
|
|
107
|
+
export function isAppendable(flag) {
|
|
108
|
+
return flag.indexOf('a') !== -1;
|
|
109
|
+
}
|
|
110
|
+
export function isSynchronous(flag) {
|
|
111
|
+
return flag.indexOf('s') !== -1;
|
|
112
|
+
}
|
|
113
|
+
export function isExclusive(flag) {
|
|
114
|
+
return flag.indexOf('x') !== -1;
|
|
115
|
+
}
|
|
116
|
+
export function pathExistsAction(flag) {
|
|
117
|
+
if (isExclusive(flag)) {
|
|
118
|
+
return ActionType.THROW;
|
|
189
119
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
* appropriate response to the path existing.
|
|
193
|
-
*/
|
|
194
|
-
pathExistsAction() {
|
|
195
|
-
if (this.isExclusive()) {
|
|
196
|
-
return ActionType.THROW;
|
|
197
|
-
}
|
|
198
|
-
if (this.isTruncating()) {
|
|
199
|
-
return ActionType.TRUNCATE;
|
|
200
|
-
}
|
|
201
|
-
return ActionType.NOP;
|
|
120
|
+
if (isTruncating(flag)) {
|
|
121
|
+
return ActionType.TRUNCATE;
|
|
202
122
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
if ((this.isWriteable() || this.isAppendable()) && this._flag != 'r+') {
|
|
209
|
-
return ActionType.CREATE;
|
|
210
|
-
}
|
|
211
|
-
return ActionType.THROW;
|
|
123
|
+
return ActionType.NOP;
|
|
124
|
+
}
|
|
125
|
+
export function pathNotExistsAction(flag) {
|
|
126
|
+
if ((isWriteable(flag) || isAppendable(flag)) && flag !== 'r+') {
|
|
127
|
+
return ActionType.CREATE;
|
|
212
128
|
}
|
|
129
|
+
return ActionType.THROW;
|
|
213
130
|
}
|
|
214
|
-
/**
|
|
215
|
-
* Contains cached FileMode instances.
|
|
216
|
-
*/
|
|
217
|
-
FileFlag.cache = new Map();
|
|
218
|
-
/**
|
|
219
|
-
* Array of valid mode strings.
|
|
220
|
-
*/
|
|
221
|
-
FileFlag.validStrings = ['r', 'r+', 'rs', 'rs+', 'w', 'wx', 'w+', 'wx+', 'a', 'ax', 'a+', 'ax+'];
|
|
222
131
|
export class File {
|
|
223
132
|
/**
|
|
224
133
|
* Asynchronous `datasync`.
|
|
@@ -284,7 +193,7 @@ export class PreloadFile extends File {
|
|
|
284
193
|
if (this.stats.size == _buffer.byteLength) {
|
|
285
194
|
return;
|
|
286
195
|
}
|
|
287
|
-
if (this.flag
|
|
196
|
+
if (isReadable(this.flag)) {
|
|
288
197
|
throw new Error(`Size mismatch: buffer length ${_buffer.byteLength}, stats size ${this.stats.size}`);
|
|
289
198
|
}
|
|
290
199
|
this._dirty = true;
|
|
@@ -305,7 +214,7 @@ export class PreloadFile extends File {
|
|
|
305
214
|
* @return The current file position.
|
|
306
215
|
*/
|
|
307
216
|
get position() {
|
|
308
|
-
if (this.flag
|
|
217
|
+
if (isAppendable(this.flag)) {
|
|
309
218
|
return this.stats.size;
|
|
310
219
|
}
|
|
311
220
|
return this._position;
|
|
@@ -335,7 +244,7 @@ export class PreloadFile extends File {
|
|
|
335
244
|
*/
|
|
336
245
|
truncate(len) {
|
|
337
246
|
this.truncateSync(len);
|
|
338
|
-
if (this.flag
|
|
247
|
+
if (isSynchronous(this.flag) && !this.fs.metadata().synchronous) {
|
|
339
248
|
return this.sync();
|
|
340
249
|
}
|
|
341
250
|
}
|
|
@@ -345,7 +254,7 @@ export class PreloadFile extends File {
|
|
|
345
254
|
*/
|
|
346
255
|
truncateSync(len) {
|
|
347
256
|
this._dirty = true;
|
|
348
|
-
if (!this.flag
|
|
257
|
+
if (!isWriteable(this.flag)) {
|
|
349
258
|
throw new ApiError(ErrorCode.EPERM, 'File not opened with a writeable mode.');
|
|
350
259
|
}
|
|
351
260
|
this.stats.mtimeMs = Date.now();
|
|
@@ -353,7 +262,7 @@ export class PreloadFile extends File {
|
|
|
353
262
|
const buf = new Uint8Array(len - this._buffer.length);
|
|
354
263
|
// Write will set stats.size for us.
|
|
355
264
|
this.writeSync(buf, 0, buf.length, this._buffer.length);
|
|
356
|
-
if (this.flag
|
|
265
|
+
if (isSynchronous(this.flag) && this.fs.metadata().synchronous) {
|
|
357
266
|
this.syncSync();
|
|
358
267
|
}
|
|
359
268
|
return;
|
|
@@ -361,7 +270,7 @@ export class PreloadFile extends File {
|
|
|
361
270
|
this.stats.size = len;
|
|
362
271
|
// Truncate buffer to 'len'.
|
|
363
272
|
this._buffer = this._buffer.subarray(0, len);
|
|
364
|
-
if (this.flag
|
|
273
|
+
if (isSynchronous(this.flag) && this.fs.metadata().synchronous) {
|
|
365
274
|
this.syncSync();
|
|
366
275
|
}
|
|
367
276
|
}
|
|
@@ -396,7 +305,7 @@ export class PreloadFile extends File {
|
|
|
396
305
|
writeSync(buffer, offset = 0, length = this.stats.size, position = 0) {
|
|
397
306
|
this._dirty = true;
|
|
398
307
|
position ?? (position = this.position);
|
|
399
|
-
if (!this.flag
|
|
308
|
+
if (!isWriteable(this.flag)) {
|
|
400
309
|
throw new ApiError(ErrorCode.EPERM, 'File not opened with a writeable mode.');
|
|
401
310
|
}
|
|
402
311
|
const endFp = position + length;
|
|
@@ -417,7 +326,7 @@ export class PreloadFile extends File {
|
|
|
417
326
|
this._buffer.set(buffer.slice(offset, offset + length), position);
|
|
418
327
|
const len = this._buffer.byteOffset;
|
|
419
328
|
this.stats.mtimeMs = Date.now();
|
|
420
|
-
if (this.flag
|
|
329
|
+
if (isSynchronous(this.flag)) {
|
|
421
330
|
this.syncSync();
|
|
422
331
|
return len;
|
|
423
332
|
}
|
|
@@ -450,7 +359,7 @@ export class PreloadFile extends File {
|
|
|
450
359
|
* @returns number of bytes written
|
|
451
360
|
*/
|
|
452
361
|
readSync(buffer, offset = 0, length = this.stats.size, position = 0) {
|
|
453
|
-
if (!this.flag
|
|
362
|
+
if (!isReadable(this.flag)) {
|
|
454
363
|
throw new ApiError(ErrorCode.EPERM, 'File not opened with a readable mode.');
|
|
455
364
|
}
|
|
456
365
|
position ?? (position = this.position);
|
package/dist/filesystem.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ApiError } from './ApiError.js';
|
|
2
2
|
import type { Stats } from './stats.js';
|
|
3
|
-
import type { File
|
|
3
|
+
import type { File } from './file.js';
|
|
4
4
|
import type { Cred } from './cred.js';
|
|
5
5
|
export type NoArgCallback = (e?: ApiError) => unknown;
|
|
6
6
|
export type TwoArgCallback<T> = (e?: ApiError, rv?: T) => unknown;
|
|
@@ -71,24 +71,24 @@ export declare abstract class FileSystem {
|
|
|
71
71
|
* @param p The path to open.
|
|
72
72
|
* @param flag The flag to use when opening the file.
|
|
73
73
|
*/
|
|
74
|
-
abstract openFile(path: string, flag:
|
|
74
|
+
abstract openFile(path: string, flag: string, cred: Cred): Promise<File>;
|
|
75
75
|
/**
|
|
76
76
|
* Opens the file at path p with the given flag. The file must exist.
|
|
77
77
|
* @param p The path to open.
|
|
78
78
|
* @param flag The flag to use when opening the file.
|
|
79
79
|
* @return A File object corresponding to the opened file.
|
|
80
80
|
*/
|
|
81
|
-
abstract openFileSync(path: string, flag:
|
|
81
|
+
abstract openFileSync(path: string, flag: string, cred: Cred): File;
|
|
82
82
|
/**
|
|
83
83
|
* Create the file at path p with the given mode. Then, open it with the given
|
|
84
84
|
* flag.
|
|
85
85
|
*/
|
|
86
|
-
abstract createFile(path: string, flag:
|
|
86
|
+
abstract createFile(path: string, flag: string, mode: number, cred: Cred): Promise<File>;
|
|
87
87
|
/**
|
|
88
88
|
* Create the file at path p with the given mode. Then, open it with the given
|
|
89
89
|
* flag.
|
|
90
90
|
*/
|
|
91
|
-
abstract createFileSync(path: string, flag:
|
|
91
|
+
abstract createFileSync(path: string, flag: string, mode: number, cred: Cred): File;
|
|
92
92
|
/**
|
|
93
93
|
* Asynchronous `unlink`.
|
|
94
94
|
*/
|
|
@@ -162,8 +162,8 @@ declare abstract class SyncFileSystem extends FileSystem {
|
|
|
162
162
|
exists(path: string, cred: Cred): Promise<boolean>;
|
|
163
163
|
rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;
|
|
164
164
|
stat(path: string, cred: Cred): Promise<Stats>;
|
|
165
|
-
createFile(path: string, flag:
|
|
166
|
-
openFile(path: string, flag:
|
|
165
|
+
createFile(path: string, flag: string, mode: number, cred: Cred): Promise<File>;
|
|
166
|
+
openFile(path: string, flag: string, cred: Cred): Promise<File>;
|
|
167
167
|
unlink(path: string, cred: Cred): Promise<void>;
|
|
168
168
|
rmdir(path: string, cred: Cred): Promise<void>;
|
|
169
169
|
mkdir(path: string, mode: number, cred: Cred): Promise<void>;
|
|
@@ -182,8 +182,8 @@ declare abstract class AsyncFileSystem {
|
|
|
182
182
|
metadata(): FileSystemMetadata;
|
|
183
183
|
renameSync(oldPath: string, newPath: string, cred: Cred): void;
|
|
184
184
|
statSync(path: string, cred: Cred): Stats;
|
|
185
|
-
createFileSync(path: string, flag:
|
|
186
|
-
openFileSync(path: string, flag:
|
|
185
|
+
createFileSync(path: string, flag: string, mode: number, cred: Cred): File;
|
|
186
|
+
openFileSync(path: string, flag: string, cred: Cred): File;
|
|
187
187
|
unlinkSync(path: string, cred: Cred): void;
|
|
188
188
|
rmdirSync(path: string, cred: Cred): void;
|
|
189
189
|
mkdirSync(path: string, mode: number, cred: Cred): void;
|
|
@@ -199,8 +199,8 @@ declare abstract class ReadonlyFileSystem {
|
|
|
199
199
|
metadata(): FileSystemMetadata;
|
|
200
200
|
rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;
|
|
201
201
|
renameSync(oldPath: string, newPath: string, cred: Cred): void;
|
|
202
|
-
createFile(path: string, flag:
|
|
203
|
-
createFileSync(path: string, flag:
|
|
202
|
+
createFile(path: string, flag: string, mode: number, cred: Cred): Promise<File>;
|
|
203
|
+
createFileSync(path: string, flag: string, mode: number, cred: Cred): File;
|
|
204
204
|
unlink(path: string, cred: Cred): Promise<void>;
|
|
205
205
|
unlinkSync(path: string, cred: Cred): void;
|
|
206
206
|
rmdir(path: string, cred: Cred): Promise<void>;
|
package/dist/stats.d.ts
CHANGED
|
@@ -154,10 +154,10 @@ export declare abstract class StatsCommon<T extends number | bigint> implements
|
|
|
154
154
|
*/
|
|
155
155
|
hasAccess(mode: number, cred: Cred): boolean;
|
|
156
156
|
/**
|
|
157
|
-
* Convert the current stats object into a
|
|
157
|
+
* Convert the current stats object into a credentials object
|
|
158
158
|
* @internal
|
|
159
159
|
*/
|
|
160
|
-
|
|
160
|
+
cred(uid?: number, gid?: number): Cred;
|
|
161
161
|
/**
|
|
162
162
|
* Change the mode of the file. We use this helper function to prevent messing
|
|
163
163
|
* up the type of the file, which is encoded in mode.
|
|
@@ -202,3 +202,19 @@ export declare class BigIntStats extends StatsCommon<bigint> implements Node.Big
|
|
|
202
202
|
*/
|
|
203
203
|
static clone(stats: BigIntStats | Stats): BigIntStats;
|
|
204
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
* @returns true if stats is a file.
|
|
207
|
+
*/
|
|
208
|
+
export declare function isFile(stats: StatsLike): boolean;
|
|
209
|
+
/**
|
|
210
|
+
* @returns True if stats is a directory.
|
|
211
|
+
*/
|
|
212
|
+
export declare function isDirectory(stats: StatsLike): boolean;
|
|
213
|
+
/**
|
|
214
|
+
* @returns true if stats is a symbolic link
|
|
215
|
+
*/
|
|
216
|
+
export declare function isSymbolicLink(stats: StatsLike): boolean;
|
|
217
|
+
export declare function isSocket(): boolean;
|
|
218
|
+
export declare function isBlockDevice(): boolean;
|
|
219
|
+
export declare function isCharacterDevice(): boolean;
|
|
220
|
+
export declare function isFIFO(): boolean;
|
package/dist/stats.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Cred } from './cred.js';
|
|
2
1
|
import { S_IFDIR, S_IFLNK, S_IFMT, S_IFREG } from './emulation/constants.js';
|
|
3
2
|
/**
|
|
4
3
|
* Indicates the type of the given file. Applied to 'mode'.
|
|
@@ -177,11 +176,18 @@ export class StatsCommon {
|
|
|
177
176
|
return !result;
|
|
178
177
|
}
|
|
179
178
|
/**
|
|
180
|
-
* Convert the current stats object into a
|
|
179
|
+
* Convert the current stats object into a credentials object
|
|
181
180
|
* @internal
|
|
182
181
|
*/
|
|
183
|
-
|
|
184
|
-
return
|
|
182
|
+
cred(uid = Number(this.uid), gid = Number(this.gid)) {
|
|
183
|
+
return {
|
|
184
|
+
uid,
|
|
185
|
+
gid,
|
|
186
|
+
suid: Number(this.uid),
|
|
187
|
+
sgid: Number(this.gid),
|
|
188
|
+
euid: uid,
|
|
189
|
+
egid: gid,
|
|
190
|
+
};
|
|
185
191
|
}
|
|
186
192
|
/**
|
|
187
193
|
* Change the mode of the file. We use this helper function to prevent messing
|
|
@@ -246,3 +252,33 @@ export class BigIntStats extends StatsCommon {
|
|
|
246
252
|
}
|
|
247
253
|
}
|
|
248
254
|
BigIntStats;
|
|
255
|
+
/**
|
|
256
|
+
* @returns true if stats is a file.
|
|
257
|
+
*/
|
|
258
|
+
export function isFile(stats) {
|
|
259
|
+
return (Number(stats.mode) & S_IFMT) === S_IFREG;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* @returns True if stats is a directory.
|
|
263
|
+
*/
|
|
264
|
+
export function isDirectory(stats) {
|
|
265
|
+
return (Number(stats.mode) & S_IFMT) === S_IFDIR;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* @returns true if stats is a symbolic link
|
|
269
|
+
*/
|
|
270
|
+
export function isSymbolicLink(stats) {
|
|
271
|
+
return (Number(stats.mode) & S_IFMT) === S_IFLNK;
|
|
272
|
+
}
|
|
273
|
+
export function isSocket() {
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
export function isBlockDevice() {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
export function isCharacterDevice() {
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
export function isFIFO() {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
package/license.md
CHANGED
|
@@ -22,8 +22,8 @@ SOFTWARE.
|
|
|
22
22
|
|
|
23
23
|
This license applies to all parts of ZenFS, except for the following items:
|
|
24
24
|
|
|
25
|
-
-
|
|
26
|
-
|
|
25
|
+
- The test fixtures located in `test/fixtures/node`. Their license follows:
|
|
26
|
+
"""
|
|
27
27
|
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
|
28
28
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
29
29
|
of this software and associated documentation files (the "Software"), to
|
|
@@ -42,4 +42,4 @@ This license applies to all parts of ZenFS, except for the following items:
|
|
|
42
42
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
43
43
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
44
44
|
IN THE SOFTWARE.
|
|
45
|
-
|
|
45
|
+
"""
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenfs/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "A filesystem in your browser",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist",
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
|
-
"format": "prettier --write
|
|
45
|
-
"format:check": "prettier --check
|
|
46
|
-
"lint": "eslint src
|
|
44
|
+
"format": "prettier --write .",
|
|
45
|
+
"format:check": "prettier --check .",
|
|
46
|
+
"lint": "eslint src tests && tsc -p tsconfig.json --noEmit",
|
|
47
47
|
"test": "cross-env NODE_OPTIONS=--experimental-vm-modules npx jest",
|
|
48
48
|
"build": "node scripts/build.js",
|
|
49
49
|
"build:docs": "typedoc --out docs --name ZenFS src/index.ts",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"esbuild": "^0.17.18",
|
|
66
66
|
"eslint": "^8.36.0",
|
|
67
67
|
"jest": "^29.5.0",
|
|
68
|
-
"prettier": "^2.
|
|
68
|
+
"prettier": "^3.2.5",
|
|
69
69
|
"ts-jest": "^29.1.0",
|
|
70
70
|
"typedoc": "^0.25.1",
|
|
71
71
|
"typescript": "^4.9.5"
|
package/readme.md
CHANGED
|
@@ -1,27 +1,25 @@
|
|
|
1
1
|
# ZenFS
|
|
2
2
|
|
|
3
|
-
ZenFS is a file system that emulates the [
|
|
3
|
+
ZenFS is a file system that emulates the [NodeJS filesystem API](http://nodejs.org/api/fs.html).
|
|
4
4
|
|
|
5
|
-
It works using a system of backends, which are used by ZenFS to store and retrieve data. ZenFS can also integrate
|
|
5
|
+
It works using a system of backends, which are used by ZenFS to store and retrieve data. ZenFS can also integrate with other tools.
|
|
6
6
|
|
|
7
7
|
ZenFS is a fork of [BrowserFS](https://github.com/jvilk/BrowserFS).
|
|
8
8
|
|
|
9
9
|
## Backends
|
|
10
10
|
|
|
11
|
-
ZenFS is
|
|
11
|
+
ZenFS is modular and extensible. The core includes a few built-in backends:
|
|
12
12
|
|
|
13
|
-
- `InMemory`: Stores files in-memory.
|
|
14
|
-
- `Overlay`:
|
|
15
|
-
- `AsyncMirror`: Use an asynchronous backend synchronously.
|
|
13
|
+
- `InMemory`: Stores files in-memory. This is cleared when the runtime ends (e.g. a user navigating away from a web page or a Node process exiting)
|
|
14
|
+
- `Overlay`: Use read-only file system as read-write by overlaying a writable file system on top of it.
|
|
15
|
+
- `AsyncMirror`: Use an asynchronous backend synchronously. This is very helpful for asynchronous backends
|
|
16
16
|
|
|
17
17
|
> [!NOTE]
|
|
18
18
|
> When constructed, `AsyncMirror` loads the entire contents of the async file system into a synchronous backend. It performs operations on the synchronous file system and then queues them to be mirrored onto the asynchronous backend.
|
|
19
19
|
|
|
20
|
-
More backends can be defined by separate libraries
|
|
20
|
+
ZenFS supports a number of other backends. Many are provided as seperate packages under `@zenfs`. More backends can be defined by separate libraries by extending the `FileSystem` class and/or providing a `Backend` object.
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
For more information, see the [API documentation for ZenFS](https://zen-fs.github.io/core).
|
|
22
|
+
For more information, see the [docs](https://zen-fs.github.io/core).
|
|
25
23
|
|
|
26
24
|
## Installing
|
|
27
25
|
|
|
@@ -32,10 +30,12 @@ npm install @zenfs/core
|
|
|
32
30
|
## Usage
|
|
33
31
|
|
|
34
32
|
> [!NOTE]
|
|
35
|
-
> The examples are written in ESM.
|
|
33
|
+
> The examples are written in ESM.
|
|
34
|
+
> If you are using CJS, you can `require` the package.
|
|
35
|
+
> If using a browser environment without support for `type=module` in `script` tags, you can add a `script` tag to your HTML pointing to the `browser.min.js` and use ZenFS with the global `ZenFS` object.
|
|
36
36
|
|
|
37
37
|
```js
|
|
38
|
-
import fs from '@zenfs/core';
|
|
38
|
+
import fs from '@zenfs/core'; // You can also use the named export, `fs`
|
|
39
39
|
|
|
40
40
|
fs.writeFileSync('/test.txt', 'Cool, I can do this in any JS environment (including browsers)!');
|
|
41
41
|
|