@componentor/fs 3.0.24 → 3.0.26
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/index.d.mts +92 -11
- package/dist/index.js +1234 -483
- package/dist/index.js.map +1 -1
- package/dist/workers/async-relay.worker.js +5 -5
- package/dist/workers/async-relay.worker.js.map +1 -1
- package/dist/workers/repair.worker.js +42 -6
- package/dist/workers/repair.worker.js.map +1 -1
- package/dist/workers/server.worker.js +47 -11
- package/dist/workers/server.worker.js.map +1 -1
- package/dist/workers/sync-relay.worker.js +61 -23
- package/dist/workers/sync-relay.worker.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -160,147 +160,6 @@ function statusToError(status, syscall, path) {
|
|
|
160
160
|
return createError(code, syscall, path);
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
// src/methods/readFile.ts
|
|
164
|
-
var decoder2 = new TextDecoder();
|
|
165
|
-
function readFileSync(syncRequest, filePath, options) {
|
|
166
|
-
const encoding = typeof options === "string" ? options : options?.encoding;
|
|
167
|
-
const buf = encodeRequest(OP.READ, filePath);
|
|
168
|
-
const { status, data } = syncRequest(buf);
|
|
169
|
-
if (status !== 0) throw statusToError(status, "read", filePath);
|
|
170
|
-
const result = data ?? new Uint8Array(0);
|
|
171
|
-
if (encoding) return decoder2.decode(result);
|
|
172
|
-
return result;
|
|
173
|
-
}
|
|
174
|
-
async function readFile(asyncRequest, filePath, options) {
|
|
175
|
-
const encoding = typeof options === "string" ? options : options?.encoding;
|
|
176
|
-
const { status, data } = await asyncRequest(OP.READ, filePath);
|
|
177
|
-
if (status !== 0) throw statusToError(status, "read", filePath);
|
|
178
|
-
const result = data ?? new Uint8Array(0);
|
|
179
|
-
if (encoding) return decoder2.decode(result);
|
|
180
|
-
return result;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// src/methods/writeFile.ts
|
|
184
|
-
var encoder2 = new TextEncoder();
|
|
185
|
-
function writeFileSync(syncRequest, filePath, data, options) {
|
|
186
|
-
const opts = typeof options === "string" ? { } : options;
|
|
187
|
-
const encoded = typeof data === "string" ? encoder2.encode(data) : data;
|
|
188
|
-
const flags = opts?.flush === true ? 1 : 0;
|
|
189
|
-
const buf = encodeRequest(OP.WRITE, filePath, flags, encoded);
|
|
190
|
-
const { status } = syncRequest(buf);
|
|
191
|
-
if (status !== 0) throw statusToError(status, "write", filePath);
|
|
192
|
-
}
|
|
193
|
-
async function writeFile(asyncRequest, filePath, data, options) {
|
|
194
|
-
const opts = typeof options === "string" ? { } : options;
|
|
195
|
-
const flags = opts?.flush === true ? 1 : 0;
|
|
196
|
-
const encoded = typeof data === "string" ? encoder2.encode(data) : data;
|
|
197
|
-
const { status } = await asyncRequest(OP.WRITE, filePath, flags, encoded);
|
|
198
|
-
if (status !== 0) throw statusToError(status, "write", filePath);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// src/methods/appendFile.ts
|
|
202
|
-
var encoder3 = new TextEncoder();
|
|
203
|
-
function appendFileSync(syncRequest, filePath, data, options) {
|
|
204
|
-
const encoded = typeof data === "string" ? encoder3.encode(data) : data;
|
|
205
|
-
const buf = encodeRequest(OP.APPEND, filePath, 0, encoded);
|
|
206
|
-
const { status } = syncRequest(buf);
|
|
207
|
-
if (status !== 0) throw statusToError(status, "appendFile", filePath);
|
|
208
|
-
}
|
|
209
|
-
async function appendFile(asyncRequest, filePath, data, options) {
|
|
210
|
-
const encoded = typeof data === "string" ? encoder3.encode(data) : data;
|
|
211
|
-
const { status } = await asyncRequest(OP.APPEND, filePath, 0, encoded);
|
|
212
|
-
if (status !== 0) throw statusToError(status, "appendFile", filePath);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// src/methods/exists.ts
|
|
216
|
-
function existsSync(syncRequest, filePath) {
|
|
217
|
-
const buf = encodeRequest(OP.EXISTS, filePath);
|
|
218
|
-
const { data } = syncRequest(buf);
|
|
219
|
-
return data ? data[0] === 1 : false;
|
|
220
|
-
}
|
|
221
|
-
async function exists(asyncRequest, filePath) {
|
|
222
|
-
const { data } = await asyncRequest(OP.EXISTS, filePath);
|
|
223
|
-
return data ? data[0] === 1 : false;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// src/methods/mkdir.ts
|
|
227
|
-
var decoder3 = new TextDecoder();
|
|
228
|
-
function mkdirSync(syncRequest, filePath, options) {
|
|
229
|
-
const opts = typeof options === "number" ? { } : options;
|
|
230
|
-
const flags = opts?.recursive ? 1 : 0;
|
|
231
|
-
const buf = encodeRequest(OP.MKDIR, filePath, flags);
|
|
232
|
-
const { status, data } = syncRequest(buf);
|
|
233
|
-
if (status !== 0) throw statusToError(status, "mkdir", filePath);
|
|
234
|
-
return data ? decoder3.decode(data) : void 0;
|
|
235
|
-
}
|
|
236
|
-
async function mkdir(asyncRequest, filePath, options) {
|
|
237
|
-
const opts = typeof options === "number" ? { } : options;
|
|
238
|
-
const flags = opts?.recursive ? 1 : 0;
|
|
239
|
-
const { status, data } = await asyncRequest(OP.MKDIR, filePath, flags);
|
|
240
|
-
if (status !== 0) throw statusToError(status, "mkdir", filePath);
|
|
241
|
-
return data ? decoder3.decode(data) : void 0;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// src/methods/rmdir.ts
|
|
245
|
-
function rmdirSync(syncRequest, filePath, options) {
|
|
246
|
-
const flags = options?.recursive ? 1 : 0;
|
|
247
|
-
const buf = encodeRequest(OP.RMDIR, filePath, flags);
|
|
248
|
-
const { status } = syncRequest(buf);
|
|
249
|
-
if (status !== 0) throw statusToError(status, "rmdir", filePath);
|
|
250
|
-
}
|
|
251
|
-
async function rmdir(asyncRequest, filePath, options) {
|
|
252
|
-
const flags = options?.recursive ? 1 : 0;
|
|
253
|
-
const { status } = await asyncRequest(OP.RMDIR, filePath, flags);
|
|
254
|
-
if (status !== 0) throw statusToError(status, "rmdir", filePath);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// src/methods/rm.ts
|
|
258
|
-
function rmSync(syncRequest, filePath, options) {
|
|
259
|
-
const flags = (options?.recursive ? 1 : 0) | (options?.force ? 2 : 0);
|
|
260
|
-
const buf = encodeRequest(OP.UNLINK, filePath, flags);
|
|
261
|
-
const { status } = syncRequest(buf);
|
|
262
|
-
if (status === 3) {
|
|
263
|
-
const rmdirBuf = encodeRequest(OP.RMDIR, filePath, flags);
|
|
264
|
-
const rmdirResult = syncRequest(rmdirBuf);
|
|
265
|
-
if (rmdirResult.status !== 0) {
|
|
266
|
-
if (options?.force && rmdirResult.status === 1) return;
|
|
267
|
-
throw statusToError(rmdirResult.status, "rm", filePath);
|
|
268
|
-
}
|
|
269
|
-
return;
|
|
270
|
-
}
|
|
271
|
-
if (status !== 0) {
|
|
272
|
-
if (options?.force && status === 1) return;
|
|
273
|
-
throw statusToError(status, "rm", filePath);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
async function rm(asyncRequest, filePath, options) {
|
|
277
|
-
const flags = (options?.recursive ? 1 : 0) | (options?.force ? 2 : 0);
|
|
278
|
-
const { status } = await asyncRequest(OP.UNLINK, filePath, flags);
|
|
279
|
-
if (status === 3) {
|
|
280
|
-
const { status: s2 } = await asyncRequest(OP.RMDIR, filePath, flags);
|
|
281
|
-
if (s2 !== 0) {
|
|
282
|
-
if (options?.force && s2 === 1) return;
|
|
283
|
-
throw statusToError(s2, "rm", filePath);
|
|
284
|
-
}
|
|
285
|
-
return;
|
|
286
|
-
}
|
|
287
|
-
if (status !== 0) {
|
|
288
|
-
if (options?.force && status === 1) return;
|
|
289
|
-
throw statusToError(status, "rm", filePath);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// src/methods/unlink.ts
|
|
294
|
-
function unlinkSync(syncRequest, filePath) {
|
|
295
|
-
const buf = encodeRequest(OP.UNLINK, filePath);
|
|
296
|
-
const { status } = syncRequest(buf);
|
|
297
|
-
if (status !== 0) throw statusToError(status, "unlink", filePath);
|
|
298
|
-
}
|
|
299
|
-
async function unlink(asyncRequest, filePath) {
|
|
300
|
-
const { status } = await asyncRequest(OP.UNLINK, filePath);
|
|
301
|
-
if (status !== 0) throw statusToError(status, "unlink", filePath);
|
|
302
|
-
}
|
|
303
|
-
|
|
304
163
|
// src/vfs/layout.ts
|
|
305
164
|
var VFS_MAGIC = 1447449377;
|
|
306
165
|
var VFS_VERSION = 1;
|
|
@@ -339,8 +198,8 @@ var INODE = {
|
|
|
339
198
|
// uint32 - byte offset into path table
|
|
340
199
|
PATH_LENGTH: 8,
|
|
341
200
|
// uint16 - length of path string
|
|
342
|
-
|
|
343
|
-
// uint16
|
|
201
|
+
NLINK: 10,
|
|
202
|
+
// uint16 - hard link count
|
|
344
203
|
MODE: 12,
|
|
345
204
|
// uint32 - permissions (e.g. 0o100644)
|
|
346
205
|
SIZE: 16,
|
|
@@ -408,6 +267,7 @@ function decodeStats(data) {
|
|
|
408
267
|
const uid = view.getUint32(37, true);
|
|
409
268
|
const gid = view.getUint32(41, true);
|
|
410
269
|
const ino = view.getUint32(45, true);
|
|
270
|
+
const nlink = data.byteLength >= 53 ? view.getUint32(49, true) : 1;
|
|
411
271
|
const isFile = type === INODE_TYPE.FILE;
|
|
412
272
|
const isDirectory = type === INODE_TYPE.DIRECTORY;
|
|
413
273
|
const isSymlink = type === INODE_TYPE.SYMLINK;
|
|
@@ -422,7 +282,7 @@ function decodeStats(data) {
|
|
|
422
282
|
dev: 0,
|
|
423
283
|
ino,
|
|
424
284
|
mode,
|
|
425
|
-
nlink
|
|
285
|
+
nlink,
|
|
426
286
|
uid,
|
|
427
287
|
gid,
|
|
428
288
|
rdev: 0,
|
|
@@ -439,7 +299,57 @@ function decodeStats(data) {
|
|
|
439
299
|
birthtime: new Date(ctimeMs)
|
|
440
300
|
};
|
|
441
301
|
}
|
|
442
|
-
function
|
|
302
|
+
function decodeStatsBigInt(data) {
|
|
303
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
304
|
+
const type = view.getUint8(0);
|
|
305
|
+
const mode = view.getUint32(1, true);
|
|
306
|
+
const size = view.getFloat64(5, true);
|
|
307
|
+
const mtimeMs = view.getFloat64(13, true);
|
|
308
|
+
const ctimeMs = view.getFloat64(21, true);
|
|
309
|
+
const atimeMs = view.getFloat64(29, true);
|
|
310
|
+
const uid = view.getUint32(37, true);
|
|
311
|
+
const gid = view.getUint32(41, true);
|
|
312
|
+
const ino = view.getUint32(45, true);
|
|
313
|
+
const nlink = data.byteLength >= 53 ? view.getUint32(49, true) : 1;
|
|
314
|
+
const isFile = type === INODE_TYPE.FILE;
|
|
315
|
+
const isDirectory = type === INODE_TYPE.DIRECTORY;
|
|
316
|
+
const isSymlink = type === INODE_TYPE.SYMLINK;
|
|
317
|
+
const atimeMsBigInt = BigInt(Math.trunc(atimeMs));
|
|
318
|
+
const mtimeMsBigInt = BigInt(Math.trunc(mtimeMs));
|
|
319
|
+
const ctimeMsBigInt = BigInt(Math.trunc(ctimeMs));
|
|
320
|
+
return {
|
|
321
|
+
isFile: () => isFile,
|
|
322
|
+
isDirectory: () => isDirectory,
|
|
323
|
+
isBlockDevice: () => false,
|
|
324
|
+
isCharacterDevice: () => false,
|
|
325
|
+
isSymbolicLink: () => isSymlink,
|
|
326
|
+
isFIFO: () => false,
|
|
327
|
+
isSocket: () => false,
|
|
328
|
+
dev: 0n,
|
|
329
|
+
ino: BigInt(ino),
|
|
330
|
+
mode: BigInt(mode),
|
|
331
|
+
nlink: BigInt(nlink),
|
|
332
|
+
uid: BigInt(uid),
|
|
333
|
+
gid: BigInt(gid),
|
|
334
|
+
rdev: 0n,
|
|
335
|
+
size: BigInt(Math.trunc(size)),
|
|
336
|
+
blksize: 4096n,
|
|
337
|
+
blocks: BigInt(Math.ceil(size / 512)),
|
|
338
|
+
atimeMs: atimeMsBigInt,
|
|
339
|
+
mtimeMs: mtimeMsBigInt,
|
|
340
|
+
ctimeMs: ctimeMsBigInt,
|
|
341
|
+
birthtimeMs: ctimeMsBigInt,
|
|
342
|
+
atime: new Date(atimeMs),
|
|
343
|
+
mtime: new Date(mtimeMs),
|
|
344
|
+
ctime: new Date(ctimeMs),
|
|
345
|
+
birthtime: new Date(ctimeMs),
|
|
346
|
+
atimeNs: atimeMsBigInt * 1000000n,
|
|
347
|
+
mtimeNs: mtimeMsBigInt * 1000000n,
|
|
348
|
+
ctimeNs: ctimeMsBigInt * 1000000n,
|
|
349
|
+
birthtimeNs: ctimeMsBigInt * 1000000n
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
function decodeDirents(data, parentPath = "") {
|
|
443
353
|
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
444
354
|
const count = view.getUint32(0, true);
|
|
445
355
|
const decoder9 = new TextDecoder();
|
|
@@ -456,6 +366,8 @@ function decodeDirents(data) {
|
|
|
456
366
|
const isSymlink = type === INODE_TYPE.SYMLINK;
|
|
457
367
|
entries.push({
|
|
458
368
|
name,
|
|
369
|
+
parentPath,
|
|
370
|
+
path: parentPath,
|
|
459
371
|
isFile: () => isFile,
|
|
460
372
|
isDirectory: () => isDirectory,
|
|
461
373
|
isBlockDevice: () => false,
|
|
@@ -482,96 +394,6 @@ function decodeNames(data) {
|
|
|
482
394
|
return names;
|
|
483
395
|
}
|
|
484
396
|
|
|
485
|
-
// src/methods/readdir.ts
|
|
486
|
-
function readdirSync(syncRequest, filePath, options) {
|
|
487
|
-
const opts = typeof options === "string" ? { } : options;
|
|
488
|
-
const flags = opts?.withFileTypes ? 1 : 0;
|
|
489
|
-
const buf = encodeRequest(OP.READDIR, filePath, flags);
|
|
490
|
-
const { status, data } = syncRequest(buf);
|
|
491
|
-
if (status !== 0) throw statusToError(status, "readdir", filePath);
|
|
492
|
-
if (!data) return [];
|
|
493
|
-
return opts?.withFileTypes ? decodeDirents(data) : decodeNames(data);
|
|
494
|
-
}
|
|
495
|
-
async function readdir(asyncRequest, filePath, options) {
|
|
496
|
-
const opts = typeof options === "string" ? { } : options;
|
|
497
|
-
const flags = opts?.withFileTypes ? 1 : 0;
|
|
498
|
-
const { status, data } = await asyncRequest(OP.READDIR, filePath, flags);
|
|
499
|
-
if (status !== 0) throw statusToError(status, "readdir", filePath);
|
|
500
|
-
if (!data) return [];
|
|
501
|
-
return opts?.withFileTypes ? decodeDirents(data) : decodeNames(data);
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
// src/methods/stat.ts
|
|
505
|
-
function statSync(syncRequest, filePath) {
|
|
506
|
-
const buf = encodeRequest(OP.STAT, filePath);
|
|
507
|
-
const { status, data } = syncRequest(buf);
|
|
508
|
-
if (status !== 0) throw statusToError(status, "stat", filePath);
|
|
509
|
-
return decodeStats(data);
|
|
510
|
-
}
|
|
511
|
-
function lstatSync(syncRequest, filePath) {
|
|
512
|
-
const buf = encodeRequest(OP.LSTAT, filePath);
|
|
513
|
-
const { status, data } = syncRequest(buf);
|
|
514
|
-
if (status !== 0) throw statusToError(status, "lstat", filePath);
|
|
515
|
-
return decodeStats(data);
|
|
516
|
-
}
|
|
517
|
-
async function stat(asyncRequest, filePath) {
|
|
518
|
-
const { status, data } = await asyncRequest(OP.STAT, filePath);
|
|
519
|
-
if (status !== 0) throw statusToError(status, "stat", filePath);
|
|
520
|
-
return decodeStats(data);
|
|
521
|
-
}
|
|
522
|
-
async function lstat(asyncRequest, filePath) {
|
|
523
|
-
const { status, data } = await asyncRequest(OP.LSTAT, filePath);
|
|
524
|
-
if (status !== 0) throw statusToError(status, "lstat", filePath);
|
|
525
|
-
return decodeStats(data);
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
// src/methods/rename.ts
|
|
529
|
-
var encoder4 = new TextEncoder();
|
|
530
|
-
function renameSync(syncRequest, oldPath, newPath) {
|
|
531
|
-
const buf = encodeTwoPathRequest(OP.RENAME, oldPath, newPath);
|
|
532
|
-
const { status } = syncRequest(buf);
|
|
533
|
-
if (status !== 0) throw statusToError(status, "rename", oldPath);
|
|
534
|
-
}
|
|
535
|
-
async function rename(asyncRequest, oldPath, newPath) {
|
|
536
|
-
const path2Bytes = encoder4.encode(newPath);
|
|
537
|
-
const payload = new Uint8Array(4 + path2Bytes.byteLength);
|
|
538
|
-
new DataView(payload.buffer).setUint32(0, path2Bytes.byteLength, true);
|
|
539
|
-
payload.set(path2Bytes, 4);
|
|
540
|
-
const { status } = await asyncRequest(OP.RENAME, oldPath, 0, payload);
|
|
541
|
-
if (status !== 0) throw statusToError(status, "rename", oldPath);
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
// src/methods/copyFile.ts
|
|
545
|
-
var encoder5 = new TextEncoder();
|
|
546
|
-
function copyFileSync(syncRequest, src, dest, mode) {
|
|
547
|
-
const buf = encodeTwoPathRequest(OP.COPY, src, dest, mode ?? 0);
|
|
548
|
-
const { status } = syncRequest(buf);
|
|
549
|
-
if (status !== 0) throw statusToError(status, "copyFile", src);
|
|
550
|
-
}
|
|
551
|
-
async function copyFile(asyncRequest, src, dest, mode) {
|
|
552
|
-
const path2Bytes = encoder5.encode(dest);
|
|
553
|
-
const payload = new Uint8Array(4 + path2Bytes.byteLength);
|
|
554
|
-
new DataView(payload.buffer).setUint32(0, path2Bytes.byteLength, true);
|
|
555
|
-
payload.set(path2Bytes, 4);
|
|
556
|
-
const { status } = await asyncRequest(OP.COPY, src, mode ?? 0, payload);
|
|
557
|
-
if (status !== 0) throw statusToError(status, "copyFile", src);
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
// src/methods/truncate.ts
|
|
561
|
-
function truncateSync(syncRequest, filePath, len = 0) {
|
|
562
|
-
const lenBuf = new Uint8Array(4);
|
|
563
|
-
new DataView(lenBuf.buffer).setUint32(0, len, true);
|
|
564
|
-
const buf = encodeRequest(OP.TRUNCATE, filePath, 0, lenBuf);
|
|
565
|
-
const { status } = syncRequest(buf);
|
|
566
|
-
if (status !== 0) throw statusToError(status, "truncate", filePath);
|
|
567
|
-
}
|
|
568
|
-
async function truncate(asyncRequest, filePath, len) {
|
|
569
|
-
const lenBuf = new Uint8Array(4);
|
|
570
|
-
new DataView(lenBuf.buffer).setUint32(0, len ?? 0, true);
|
|
571
|
-
const { status } = await asyncRequest(OP.TRUNCATE, filePath, 0, lenBuf);
|
|
572
|
-
if (status !== 0) throw statusToError(status, "truncate", filePath);
|
|
573
|
-
}
|
|
574
|
-
|
|
575
397
|
// src/constants.ts
|
|
576
398
|
var constants = {
|
|
577
399
|
// File access constants
|
|
@@ -616,29 +438,677 @@ var constants = {
|
|
|
616
438
|
S_IXOTH: 1
|
|
617
439
|
};
|
|
618
440
|
|
|
619
|
-
// src/methods/
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
441
|
+
// src/methods/open.ts
|
|
442
|
+
var encoder2 = new TextEncoder();
|
|
443
|
+
var decoder2 = new TextDecoder();
|
|
444
|
+
function parseFlags(flags) {
|
|
445
|
+
switch (flags) {
|
|
446
|
+
case "r":
|
|
447
|
+
return constants.O_RDONLY;
|
|
448
|
+
case "r+":
|
|
449
|
+
return constants.O_RDWR;
|
|
450
|
+
case "w":
|
|
451
|
+
return constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC;
|
|
452
|
+
case "w+":
|
|
453
|
+
return constants.O_RDWR | constants.O_CREAT | constants.O_TRUNC;
|
|
454
|
+
case "a":
|
|
455
|
+
return constants.O_WRONLY | constants.O_CREAT | constants.O_APPEND;
|
|
456
|
+
case "a+":
|
|
457
|
+
return constants.O_RDWR | constants.O_CREAT | constants.O_APPEND;
|
|
458
|
+
case "wx":
|
|
459
|
+
return constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC | constants.O_EXCL;
|
|
460
|
+
case "wx+":
|
|
461
|
+
return constants.O_RDWR | constants.O_CREAT | constants.O_TRUNC | constants.O_EXCL;
|
|
462
|
+
case "ax":
|
|
463
|
+
return constants.O_WRONLY | constants.O_CREAT | constants.O_APPEND | constants.O_EXCL;
|
|
464
|
+
case "ax+":
|
|
465
|
+
return constants.O_RDWR | constants.O_CREAT | constants.O_APPEND | constants.O_EXCL;
|
|
466
|
+
default:
|
|
467
|
+
return constants.O_RDONLY;
|
|
468
|
+
}
|
|
624
469
|
}
|
|
625
|
-
|
|
626
|
-
const
|
|
627
|
-
|
|
470
|
+
function openSync(syncRequest, filePath, flags = "r", _mode) {
|
|
471
|
+
const numFlags = typeof flags === "string" ? parseFlags(flags) : flags;
|
|
472
|
+
const buf = encodeRequest(OP.OPEN, filePath, numFlags);
|
|
473
|
+
const { status, data } = syncRequest(buf);
|
|
474
|
+
if (status !== 0) throw statusToError(status, "open", filePath);
|
|
475
|
+
return new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true);
|
|
476
|
+
}
|
|
477
|
+
function closeSync(syncRequest, fd) {
|
|
478
|
+
const fdBuf = new Uint8Array(4);
|
|
479
|
+
new DataView(fdBuf.buffer).setUint32(0, fd, true);
|
|
480
|
+
const buf = encodeRequest(OP.CLOSE, "", 0, fdBuf);
|
|
481
|
+
const { status } = syncRequest(buf);
|
|
482
|
+
if (status !== 0) throw statusToError(status, "close", String(fd));
|
|
483
|
+
}
|
|
484
|
+
function readSync(syncRequest, fd, buffer, offset = 0, length = buffer.byteLength, position = null) {
|
|
485
|
+
const fdBuf = new Uint8Array(16);
|
|
486
|
+
const dv = new DataView(fdBuf.buffer);
|
|
487
|
+
dv.setUint32(0, fd, true);
|
|
488
|
+
dv.setUint32(4, length, true);
|
|
489
|
+
dv.setFloat64(8, position ?? -1, true);
|
|
490
|
+
const buf = encodeRequest(OP.FREAD, "", 0, fdBuf);
|
|
491
|
+
const { status, data } = syncRequest(buf);
|
|
492
|
+
if (status !== 0) throw statusToError(status, "read", String(fd));
|
|
493
|
+
if (data) {
|
|
494
|
+
buffer.set(data.subarray(0, Math.min(data.byteLength, length)), offset);
|
|
495
|
+
return data.byteLength;
|
|
496
|
+
}
|
|
497
|
+
return 0;
|
|
498
|
+
}
|
|
499
|
+
function writeSyncFd(syncRequest, fd, bufferOrString, offsetOrPosition, lengthOrEncoding, position) {
|
|
500
|
+
let writeData;
|
|
501
|
+
let pos;
|
|
502
|
+
if (typeof bufferOrString === "string") {
|
|
503
|
+
writeData = encoder2.encode(bufferOrString);
|
|
504
|
+
pos = offsetOrPosition != null ? offsetOrPosition : null;
|
|
505
|
+
} else {
|
|
506
|
+
const offset = offsetOrPosition ?? 0;
|
|
507
|
+
const length = lengthOrEncoding != null ? lengthOrEncoding : bufferOrString.byteLength;
|
|
508
|
+
pos = position ?? null;
|
|
509
|
+
writeData = bufferOrString.subarray(offset, offset + length);
|
|
510
|
+
}
|
|
511
|
+
const fdBuf = new Uint8Array(12 + writeData.byteLength);
|
|
512
|
+
const dv = new DataView(fdBuf.buffer);
|
|
513
|
+
dv.setUint32(0, fd, true);
|
|
514
|
+
dv.setFloat64(4, pos ?? -1, true);
|
|
515
|
+
fdBuf.set(writeData, 12);
|
|
516
|
+
const buf = encodeRequest(OP.FWRITE, "", 0, fdBuf);
|
|
517
|
+
const { status, data } = syncRequest(buf);
|
|
518
|
+
if (status !== 0) throw statusToError(status, "write", String(fd));
|
|
519
|
+
return data ? new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true) : 0;
|
|
520
|
+
}
|
|
521
|
+
function fstatSync(syncRequest, fd) {
|
|
522
|
+
const fdBuf = new Uint8Array(4);
|
|
523
|
+
new DataView(fdBuf.buffer).setUint32(0, fd, true);
|
|
524
|
+
const buf = encodeRequest(OP.FSTAT, "", 0, fdBuf);
|
|
525
|
+
const { status, data } = syncRequest(buf);
|
|
526
|
+
if (status !== 0) throw statusToError(status, "fstat", String(fd));
|
|
527
|
+
return decodeStats(data);
|
|
528
|
+
}
|
|
529
|
+
function ftruncateSync(syncRequest, fd, len = 0) {
|
|
530
|
+
const fdBuf = new Uint8Array(12);
|
|
531
|
+
const dv = new DataView(fdBuf.buffer);
|
|
532
|
+
dv.setUint32(0, fd, true);
|
|
533
|
+
dv.setFloat64(4, len, true);
|
|
534
|
+
const buf = encodeRequest(OP.FTRUNCATE, "", 0, fdBuf);
|
|
535
|
+
const { status } = syncRequest(buf);
|
|
536
|
+
if (status !== 0) throw statusToError(status, "ftruncate", String(fd));
|
|
537
|
+
}
|
|
538
|
+
function fdatasyncSync(syncRequest, fd) {
|
|
539
|
+
const buf = encodeRequest(OP.FSYNC, "");
|
|
540
|
+
const { status } = syncRequest(buf);
|
|
541
|
+
if (status !== 0) throw statusToError(status, "fdatasync", String(fd));
|
|
542
|
+
}
|
|
543
|
+
async function open(asyncRequest, filePath, flags, _mode) {
|
|
544
|
+
const numFlags = typeof flags === "string" ? parseFlags(flags ?? "r") : flags ?? 0;
|
|
545
|
+
const { status, data } = await asyncRequest(OP.OPEN, filePath, numFlags);
|
|
546
|
+
if (status !== 0) throw statusToError(status, "open", filePath);
|
|
547
|
+
const fd = new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true);
|
|
548
|
+
return createFileHandle(fd, asyncRequest);
|
|
549
|
+
}
|
|
550
|
+
function createFileHandle(fd, asyncRequest) {
|
|
551
|
+
return {
|
|
552
|
+
fd,
|
|
553
|
+
async read(buffer, offset = 0, length = buffer.byteLength, position = null) {
|
|
554
|
+
const { status, data } = await asyncRequest(OP.FREAD, "", 0, null, void 0, { fd, length, position: position ?? -1 });
|
|
555
|
+
if (status !== 0) throw statusToError(status, "read", String(fd));
|
|
556
|
+
const bytesRead = data ? data.byteLength : 0;
|
|
557
|
+
if (data) buffer.set(data.subarray(0, Math.min(bytesRead, length)), offset);
|
|
558
|
+
return { bytesRead, buffer };
|
|
559
|
+
},
|
|
560
|
+
async write(bufferOrString, offsetOrPosition, lengthOrEncoding, position) {
|
|
561
|
+
let writeData;
|
|
562
|
+
let pos;
|
|
563
|
+
let resultBuffer;
|
|
564
|
+
if (typeof bufferOrString === "string") {
|
|
565
|
+
resultBuffer = encoder2.encode(bufferOrString);
|
|
566
|
+
writeData = resultBuffer;
|
|
567
|
+
pos = offsetOrPosition != null ? offsetOrPosition : -1;
|
|
568
|
+
} else {
|
|
569
|
+
resultBuffer = bufferOrString;
|
|
570
|
+
const offset = offsetOrPosition ?? 0;
|
|
571
|
+
const length = lengthOrEncoding != null ? lengthOrEncoding : bufferOrString.byteLength;
|
|
572
|
+
pos = position != null ? position : -1;
|
|
573
|
+
writeData = bufferOrString.subarray(offset, offset + length);
|
|
574
|
+
}
|
|
575
|
+
const { status, data } = await asyncRequest(OP.FWRITE, "", 0, null, void 0, { fd, data: writeData, position: pos });
|
|
576
|
+
if (status !== 0) throw statusToError(status, "write", String(fd));
|
|
577
|
+
const bytesWritten = data ? new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true) : 0;
|
|
578
|
+
return { bytesWritten, buffer: resultBuffer };
|
|
579
|
+
},
|
|
580
|
+
async readFile(options) {
|
|
581
|
+
const encoding = typeof options === "string" ? options : options?.encoding;
|
|
582
|
+
const { status, data } = await asyncRequest(OP.FREAD, "", 0, null, void 0, { fd, length: Number.MAX_SAFE_INTEGER, position: 0 });
|
|
583
|
+
if (status !== 0) throw statusToError(status, "read", String(fd));
|
|
584
|
+
const result = data ?? new Uint8Array(0);
|
|
585
|
+
if (encoding) return decoder2.decode(result);
|
|
586
|
+
return result;
|
|
587
|
+
},
|
|
588
|
+
async writeFile(data, _options) {
|
|
589
|
+
const encoded = typeof data === "string" ? encoder2.encode(data) : data;
|
|
590
|
+
const { status } = await asyncRequest(OP.FWRITE, "", 0, null, void 0, { fd, data: encoded, position: 0 });
|
|
591
|
+
if (status !== 0) throw statusToError(status, "write", String(fd));
|
|
592
|
+
},
|
|
593
|
+
async truncate(len = 0) {
|
|
594
|
+
const { status } = await asyncRequest(OP.FTRUNCATE, "", 0, null, void 0, { fd, length: len });
|
|
595
|
+
if (status !== 0) throw statusToError(status, "ftruncate", String(fd));
|
|
596
|
+
},
|
|
597
|
+
async stat() {
|
|
598
|
+
const { status, data } = await asyncRequest(OP.FSTAT, "", 0, null, void 0, { fd });
|
|
599
|
+
if (status !== 0) throw statusToError(status, "fstat", String(fd));
|
|
600
|
+
return decodeStats(data);
|
|
601
|
+
},
|
|
602
|
+
async sync() {
|
|
603
|
+
await asyncRequest(OP.FSYNC, "");
|
|
604
|
+
},
|
|
605
|
+
async datasync() {
|
|
606
|
+
await asyncRequest(OP.FSYNC, "");
|
|
607
|
+
},
|
|
608
|
+
async close() {
|
|
609
|
+
const { status } = await asyncRequest(OP.CLOSE, "", 0, null, void 0, { fd });
|
|
610
|
+
if (status !== 0) throw statusToError(status, "close", String(fd));
|
|
611
|
+
}
|
|
612
|
+
};
|
|
628
613
|
}
|
|
629
614
|
|
|
630
|
-
// src/
|
|
615
|
+
// src/encoding.ts
|
|
616
|
+
function decodeBuffer(data, encoding) {
|
|
617
|
+
switch (encoding) {
|
|
618
|
+
case "utf8":
|
|
619
|
+
case "utf-8":
|
|
620
|
+
return new TextDecoder("utf-8").decode(data);
|
|
621
|
+
case "latin1":
|
|
622
|
+
case "binary": {
|
|
623
|
+
let result = "";
|
|
624
|
+
for (let i = 0; i < data.length; i++) {
|
|
625
|
+
result += String.fromCharCode(data[i]);
|
|
626
|
+
}
|
|
627
|
+
return result;
|
|
628
|
+
}
|
|
629
|
+
case "ascii": {
|
|
630
|
+
let result = "";
|
|
631
|
+
for (let i = 0; i < data.length; i++) {
|
|
632
|
+
result += String.fromCharCode(data[i] & 127);
|
|
633
|
+
}
|
|
634
|
+
return result;
|
|
635
|
+
}
|
|
636
|
+
case "base64": {
|
|
637
|
+
let binary = "";
|
|
638
|
+
for (let i = 0; i < data.length; i++) {
|
|
639
|
+
binary += String.fromCharCode(data[i]);
|
|
640
|
+
}
|
|
641
|
+
return btoa(binary);
|
|
642
|
+
}
|
|
643
|
+
case "hex": {
|
|
644
|
+
let hex = "";
|
|
645
|
+
for (let i = 0; i < data.length; i++) {
|
|
646
|
+
hex += data[i].toString(16).padStart(2, "0");
|
|
647
|
+
}
|
|
648
|
+
return hex;
|
|
649
|
+
}
|
|
650
|
+
case "ucs2":
|
|
651
|
+
case "ucs-2":
|
|
652
|
+
case "utf16le":
|
|
653
|
+
case "utf-16le":
|
|
654
|
+
return new TextDecoder("utf-16le").decode(data);
|
|
655
|
+
default:
|
|
656
|
+
return new TextDecoder("utf-8").decode(data);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
function encodeString(str, encoding) {
|
|
660
|
+
switch (encoding) {
|
|
661
|
+
case "utf8":
|
|
662
|
+
case "utf-8":
|
|
663
|
+
return new TextEncoder().encode(str);
|
|
664
|
+
case "latin1":
|
|
665
|
+
case "binary": {
|
|
666
|
+
const buf = new Uint8Array(str.length);
|
|
667
|
+
for (let i = 0; i < str.length; i++) {
|
|
668
|
+
buf[i] = str.charCodeAt(i) & 255;
|
|
669
|
+
}
|
|
670
|
+
return buf;
|
|
671
|
+
}
|
|
672
|
+
case "ascii": {
|
|
673
|
+
const buf = new Uint8Array(str.length);
|
|
674
|
+
for (let i = 0; i < str.length; i++) {
|
|
675
|
+
buf[i] = str.charCodeAt(i) & 127;
|
|
676
|
+
}
|
|
677
|
+
return buf;
|
|
678
|
+
}
|
|
679
|
+
case "base64": {
|
|
680
|
+
const binary = atob(str);
|
|
681
|
+
const buf = new Uint8Array(binary.length);
|
|
682
|
+
for (let i = 0; i < binary.length; i++) {
|
|
683
|
+
buf[i] = binary.charCodeAt(i);
|
|
684
|
+
}
|
|
685
|
+
return buf;
|
|
686
|
+
}
|
|
687
|
+
case "hex": {
|
|
688
|
+
const len = str.length >>> 1;
|
|
689
|
+
const buf = new Uint8Array(len);
|
|
690
|
+
for (let i = 0; i < len; i++) {
|
|
691
|
+
buf[i] = parseInt(str.slice(i * 2, i * 2 + 2), 16);
|
|
692
|
+
}
|
|
693
|
+
return buf;
|
|
694
|
+
}
|
|
695
|
+
case "ucs2":
|
|
696
|
+
case "ucs-2":
|
|
697
|
+
case "utf16le":
|
|
698
|
+
case "utf-16le": {
|
|
699
|
+
const buf = new Uint8Array(str.length * 2);
|
|
700
|
+
for (let i = 0; i < str.length; i++) {
|
|
701
|
+
const code = str.charCodeAt(i);
|
|
702
|
+
buf[i * 2] = code & 255;
|
|
703
|
+
buf[i * 2 + 1] = code >>> 8 & 255;
|
|
704
|
+
}
|
|
705
|
+
return buf;
|
|
706
|
+
}
|
|
707
|
+
default:
|
|
708
|
+
return new TextEncoder().encode(str);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// src/methods/readFile.ts
|
|
713
|
+
new TextDecoder();
|
|
714
|
+
function readFileSync(syncRequest, filePath, options) {
|
|
715
|
+
const encoding = typeof options === "string" ? options : options?.encoding;
|
|
716
|
+
const flag = typeof options === "string" ? void 0 : options?.flag;
|
|
717
|
+
if (!flag || flag === "r") {
|
|
718
|
+
const buf = encodeRequest(OP.READ, filePath);
|
|
719
|
+
const { status, data } = syncRequest(buf);
|
|
720
|
+
if (status !== 0) throw statusToError(status, "read", filePath);
|
|
721
|
+
const result = data ?? new Uint8Array(0);
|
|
722
|
+
if (encoding) return decodeBuffer(result, encoding);
|
|
723
|
+
return result;
|
|
724
|
+
}
|
|
725
|
+
const fd = openSync(syncRequest, filePath, flag);
|
|
726
|
+
try {
|
|
727
|
+
const chunks = [];
|
|
728
|
+
let totalRead = 0;
|
|
729
|
+
const chunkSize = 64 * 1024;
|
|
730
|
+
while (true) {
|
|
731
|
+
const chunk = new Uint8Array(chunkSize);
|
|
732
|
+
const bytesRead = readSync(syncRequest, fd, chunk, 0, chunkSize, totalRead);
|
|
733
|
+
if (bytesRead === 0) break;
|
|
734
|
+
chunks.push(chunk.subarray(0, bytesRead));
|
|
735
|
+
totalRead += bytesRead;
|
|
736
|
+
if (bytesRead < chunkSize) break;
|
|
737
|
+
}
|
|
738
|
+
let result;
|
|
739
|
+
if (chunks.length === 0) {
|
|
740
|
+
result = new Uint8Array(0);
|
|
741
|
+
} else if (chunks.length === 1) {
|
|
742
|
+
result = chunks[0];
|
|
743
|
+
} else {
|
|
744
|
+
result = new Uint8Array(totalRead);
|
|
745
|
+
let offset = 0;
|
|
746
|
+
for (const chunk of chunks) {
|
|
747
|
+
result.set(chunk, offset);
|
|
748
|
+
offset += chunk.byteLength;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
if (encoding) return decodeBuffer(result, encoding);
|
|
752
|
+
return result;
|
|
753
|
+
} finally {
|
|
754
|
+
closeSync(syncRequest, fd);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
async function readFile(asyncRequest, filePath, options) {
|
|
758
|
+
const encoding = typeof options === "string" ? options : options?.encoding;
|
|
759
|
+
const flag = typeof options === "string" ? void 0 : options?.flag;
|
|
760
|
+
if (!flag || flag === "r") {
|
|
761
|
+
const { status, data } = await asyncRequest(OP.READ, filePath);
|
|
762
|
+
if (status !== 0) throw statusToError(status, "read", filePath);
|
|
763
|
+
const result = data ?? new Uint8Array(0);
|
|
764
|
+
if (encoding) return decodeBuffer(result, encoding);
|
|
765
|
+
return result;
|
|
766
|
+
}
|
|
767
|
+
const handle = await open(asyncRequest, filePath, flag);
|
|
768
|
+
try {
|
|
769
|
+
const result = await handle.readFile(encoding ? encoding : void 0);
|
|
770
|
+
return result;
|
|
771
|
+
} finally {
|
|
772
|
+
await handle.close();
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
// src/methods/writeFile.ts
|
|
777
|
+
var encoder3 = new TextEncoder();
|
|
778
|
+
function writeFileSync(syncRequest, filePath, data, options) {
|
|
779
|
+
const opts = typeof options === "string" ? { encoding: options } : options;
|
|
780
|
+
const encoded = typeof data === "string" ? opts?.encoding ? encodeString(data, opts.encoding) : encoder3.encode(data) : data;
|
|
781
|
+
const flag = opts?.flag;
|
|
782
|
+
if (!flag || flag === "w") {
|
|
783
|
+
const flags = opts?.flush === true ? 1 : 0;
|
|
784
|
+
const buf = encodeRequest(OP.WRITE, filePath, flags, encoded);
|
|
785
|
+
const { status } = syncRequest(buf);
|
|
786
|
+
if (status !== 0) throw statusToError(status, "write", filePath);
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
const fd = openSync(syncRequest, filePath, flag);
|
|
790
|
+
try {
|
|
791
|
+
writeSyncFd(syncRequest, fd, encoded, 0, encoded.byteLength, 0);
|
|
792
|
+
} finally {
|
|
793
|
+
closeSync(syncRequest, fd);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
async function writeFile(asyncRequest, filePath, data, options) {
|
|
797
|
+
const opts = typeof options === "string" ? { encoding: options } : options;
|
|
798
|
+
const encoded = typeof data === "string" ? opts?.encoding ? encodeString(data, opts.encoding) : encoder3.encode(data) : data;
|
|
799
|
+
const flag = opts?.flag;
|
|
800
|
+
if (!flag || flag === "w") {
|
|
801
|
+
const flags = opts?.flush === true ? 1 : 0;
|
|
802
|
+
const { status } = await asyncRequest(OP.WRITE, filePath, flags, encoded);
|
|
803
|
+
if (status !== 0) throw statusToError(status, "write", filePath);
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
const handle = await open(asyncRequest, filePath, flag);
|
|
807
|
+
try {
|
|
808
|
+
await handle.writeFile(encoded);
|
|
809
|
+
} finally {
|
|
810
|
+
await handle.close();
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
// src/methods/appendFile.ts
|
|
815
|
+
var encoder4 = new TextEncoder();
|
|
816
|
+
function appendFileSync(syncRequest, filePath, data, options) {
|
|
817
|
+
const encoded = typeof data === "string" ? encoder4.encode(data) : data;
|
|
818
|
+
const buf = encodeRequest(OP.APPEND, filePath, 0, encoded);
|
|
819
|
+
const { status } = syncRequest(buf);
|
|
820
|
+
if (status !== 0) throw statusToError(status, "appendFile", filePath);
|
|
821
|
+
}
|
|
822
|
+
async function appendFile(asyncRequest, filePath, data, options) {
|
|
823
|
+
const encoded = typeof data === "string" ? encoder4.encode(data) : data;
|
|
824
|
+
const { status } = await asyncRequest(OP.APPEND, filePath, 0, encoded);
|
|
825
|
+
if (status !== 0) throw statusToError(status, "appendFile", filePath);
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
// src/methods/exists.ts
|
|
829
|
+
function existsSync(syncRequest, filePath) {
|
|
830
|
+
const buf = encodeRequest(OP.EXISTS, filePath);
|
|
831
|
+
const { data } = syncRequest(buf);
|
|
832
|
+
return data ? data[0] === 1 : false;
|
|
833
|
+
}
|
|
834
|
+
async function exists(asyncRequest, filePath) {
|
|
835
|
+
const { data } = await asyncRequest(OP.EXISTS, filePath);
|
|
836
|
+
return data ? data[0] === 1 : false;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
// src/methods/mkdir.ts
|
|
631
840
|
var decoder4 = new TextDecoder();
|
|
841
|
+
function mkdirSync(syncRequest, filePath, options) {
|
|
842
|
+
const opts = typeof options === "number" ? { } : options;
|
|
843
|
+
const flags = opts?.recursive ? 1 : 0;
|
|
844
|
+
const buf = encodeRequest(OP.MKDIR, filePath, flags);
|
|
845
|
+
const { status, data } = syncRequest(buf);
|
|
846
|
+
if (status !== 0) throw statusToError(status, "mkdir", filePath);
|
|
847
|
+
return data ? decoder4.decode(data) : void 0;
|
|
848
|
+
}
|
|
849
|
+
async function mkdir(asyncRequest, filePath, options) {
|
|
850
|
+
const opts = typeof options === "number" ? { } : options;
|
|
851
|
+
const flags = opts?.recursive ? 1 : 0;
|
|
852
|
+
const { status, data } = await asyncRequest(OP.MKDIR, filePath, flags);
|
|
853
|
+
if (status !== 0) throw statusToError(status, "mkdir", filePath);
|
|
854
|
+
return data ? decoder4.decode(data) : void 0;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
// src/methods/rmdir.ts
|
|
858
|
+
function rmdirSync(syncRequest, filePath, options) {
|
|
859
|
+
const flags = options?.recursive ? 1 : 0;
|
|
860
|
+
const buf = encodeRequest(OP.RMDIR, filePath, flags);
|
|
861
|
+
const { status } = syncRequest(buf);
|
|
862
|
+
if (status !== 0) throw statusToError(status, "rmdir", filePath);
|
|
863
|
+
}
|
|
864
|
+
async function rmdir(asyncRequest, filePath, options) {
|
|
865
|
+
const flags = options?.recursive ? 1 : 0;
|
|
866
|
+
const { status } = await asyncRequest(OP.RMDIR, filePath, flags);
|
|
867
|
+
if (status !== 0) throw statusToError(status, "rmdir", filePath);
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
// src/methods/rm.ts
|
|
871
|
+
function rmSync(syncRequest, filePath, options) {
|
|
872
|
+
const flags = (options?.recursive ? 1 : 0) | (options?.force ? 2 : 0);
|
|
873
|
+
const buf = encodeRequest(OP.UNLINK, filePath, flags);
|
|
874
|
+
const { status } = syncRequest(buf);
|
|
875
|
+
if (status === 3) {
|
|
876
|
+
const rmdirBuf = encodeRequest(OP.RMDIR, filePath, flags);
|
|
877
|
+
const rmdirResult = syncRequest(rmdirBuf);
|
|
878
|
+
if (rmdirResult.status !== 0) {
|
|
879
|
+
if (options?.force && rmdirResult.status === 1) return;
|
|
880
|
+
throw statusToError(rmdirResult.status, "rm", filePath);
|
|
881
|
+
}
|
|
882
|
+
return;
|
|
883
|
+
}
|
|
884
|
+
if (status !== 0) {
|
|
885
|
+
if (options?.force && status === 1) return;
|
|
886
|
+
throw statusToError(status, "rm", filePath);
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
async function rm(asyncRequest, filePath, options) {
|
|
890
|
+
const flags = (options?.recursive ? 1 : 0) | (options?.force ? 2 : 0);
|
|
891
|
+
const { status } = await asyncRequest(OP.UNLINK, filePath, flags);
|
|
892
|
+
if (status === 3) {
|
|
893
|
+
const { status: s2 } = await asyncRequest(OP.RMDIR, filePath, flags);
|
|
894
|
+
if (s2 !== 0) {
|
|
895
|
+
if (options?.force && s2 === 1) return;
|
|
896
|
+
throw statusToError(s2, "rm", filePath);
|
|
897
|
+
}
|
|
898
|
+
return;
|
|
899
|
+
}
|
|
900
|
+
if (status !== 0) {
|
|
901
|
+
if (options?.force && status === 1) return;
|
|
902
|
+
throw statusToError(status, "rm", filePath);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
// src/methods/unlink.ts
|
|
907
|
+
function unlinkSync(syncRequest, filePath) {
|
|
908
|
+
const buf = encodeRequest(OP.UNLINK, filePath);
|
|
909
|
+
const { status } = syncRequest(buf);
|
|
910
|
+
if (status !== 0) throw statusToError(status, "unlink", filePath);
|
|
911
|
+
}
|
|
912
|
+
async function unlink(asyncRequest, filePath) {
|
|
913
|
+
const { status } = await asyncRequest(OP.UNLINK, filePath);
|
|
914
|
+
if (status !== 0) throw statusToError(status, "unlink", filePath);
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
// src/methods/readdir.ts
|
|
918
|
+
function readdirBaseSync(syncRequest, filePath, withFileTypes) {
|
|
919
|
+
const flags = withFileTypes ? 1 : 0;
|
|
920
|
+
const buf = encodeRequest(OP.READDIR, filePath, flags);
|
|
921
|
+
const { status, data } = syncRequest(buf);
|
|
922
|
+
if (status !== 0) throw statusToError(status, "readdir", filePath);
|
|
923
|
+
if (!data) return [];
|
|
924
|
+
return withFileTypes ? decodeDirents(data, filePath) : decodeNames(data);
|
|
925
|
+
}
|
|
926
|
+
async function readdirBaseAsync(asyncRequest, filePath, withFileTypes) {
|
|
927
|
+
const flags = withFileTypes ? 1 : 0;
|
|
928
|
+
const { status, data } = await asyncRequest(OP.READDIR, filePath, flags);
|
|
929
|
+
if (status !== 0) throw statusToError(status, "readdir", filePath);
|
|
930
|
+
if (!data) return [];
|
|
931
|
+
return withFileTypes ? decodeDirents(data, filePath) : decodeNames(data);
|
|
932
|
+
}
|
|
933
|
+
function readdirRecursiveSync(syncRequest, basePath, prefix, withFileTypes) {
|
|
934
|
+
const entries = readdirBaseSync(syncRequest, basePath, true);
|
|
935
|
+
const results = [];
|
|
936
|
+
for (const entry of entries) {
|
|
937
|
+
const relativePath = prefix ? prefix + "/" + entry.name : entry.name;
|
|
938
|
+
if (withFileTypes) {
|
|
939
|
+
results.push({
|
|
940
|
+
name: relativePath,
|
|
941
|
+
isFile: entry.isFile,
|
|
942
|
+
isDirectory: entry.isDirectory,
|
|
943
|
+
isBlockDevice: entry.isBlockDevice,
|
|
944
|
+
isCharacterDevice: entry.isCharacterDevice,
|
|
945
|
+
isSymbolicLink: entry.isSymbolicLink,
|
|
946
|
+
isFIFO: entry.isFIFO,
|
|
947
|
+
isSocket: entry.isSocket
|
|
948
|
+
});
|
|
949
|
+
} else {
|
|
950
|
+
results.push(relativePath);
|
|
951
|
+
}
|
|
952
|
+
if (entry.isDirectory()) {
|
|
953
|
+
const childPath = basePath + "/" + entry.name;
|
|
954
|
+
results.push(
|
|
955
|
+
...readdirRecursiveSync(syncRequest, childPath, relativePath, withFileTypes)
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
return results;
|
|
960
|
+
}
|
|
961
|
+
async function readdirRecursiveAsync(asyncRequest, basePath, prefix, withFileTypes) {
|
|
962
|
+
const entries = await readdirBaseAsync(asyncRequest, basePath, true);
|
|
963
|
+
const results = [];
|
|
964
|
+
for (const entry of entries) {
|
|
965
|
+
const relativePath = prefix ? prefix + "/" + entry.name : entry.name;
|
|
966
|
+
if (withFileTypes) {
|
|
967
|
+
results.push({
|
|
968
|
+
name: relativePath,
|
|
969
|
+
isFile: entry.isFile,
|
|
970
|
+
isDirectory: entry.isDirectory,
|
|
971
|
+
isBlockDevice: entry.isBlockDevice,
|
|
972
|
+
isCharacterDevice: entry.isCharacterDevice,
|
|
973
|
+
isSymbolicLink: entry.isSymbolicLink,
|
|
974
|
+
isFIFO: entry.isFIFO,
|
|
975
|
+
isSocket: entry.isSocket
|
|
976
|
+
});
|
|
977
|
+
} else {
|
|
978
|
+
results.push(relativePath);
|
|
979
|
+
}
|
|
980
|
+
if (entry.isDirectory()) {
|
|
981
|
+
const childPath = basePath + "/" + entry.name;
|
|
982
|
+
const children = await readdirRecursiveAsync(
|
|
983
|
+
asyncRequest,
|
|
984
|
+
childPath,
|
|
985
|
+
relativePath,
|
|
986
|
+
withFileTypes
|
|
987
|
+
);
|
|
988
|
+
results.push(...children);
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
return results;
|
|
992
|
+
}
|
|
993
|
+
function readdirSync(syncRequest, filePath, options) {
|
|
994
|
+
const opts = typeof options === "string" ? { } : options;
|
|
995
|
+
if (opts?.recursive) {
|
|
996
|
+
return readdirRecursiveSync(
|
|
997
|
+
syncRequest,
|
|
998
|
+
filePath,
|
|
999
|
+
"",
|
|
1000
|
+
!!opts?.withFileTypes
|
|
1001
|
+
);
|
|
1002
|
+
}
|
|
1003
|
+
return readdirBaseSync(syncRequest, filePath, !!opts?.withFileTypes);
|
|
1004
|
+
}
|
|
1005
|
+
async function readdir(asyncRequest, filePath, options) {
|
|
1006
|
+
const opts = typeof options === "string" ? { } : options;
|
|
1007
|
+
if (opts?.recursive) {
|
|
1008
|
+
return readdirRecursiveAsync(
|
|
1009
|
+
asyncRequest,
|
|
1010
|
+
filePath,
|
|
1011
|
+
"",
|
|
1012
|
+
!!opts?.withFileTypes
|
|
1013
|
+
);
|
|
1014
|
+
}
|
|
1015
|
+
return readdirBaseAsync(asyncRequest, filePath, !!opts?.withFileTypes);
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
// src/methods/stat.ts
|
|
1019
|
+
function statSync(syncRequest, filePath, options) {
|
|
1020
|
+
const buf = encodeRequest(OP.STAT, filePath);
|
|
1021
|
+
const { status, data } = syncRequest(buf);
|
|
1022
|
+
if (status !== 0) throw statusToError(status, "stat", filePath);
|
|
1023
|
+
return options?.bigint ? decodeStatsBigInt(data) : decodeStats(data);
|
|
1024
|
+
}
|
|
1025
|
+
function lstatSync(syncRequest, filePath, options) {
|
|
1026
|
+
const buf = encodeRequest(OP.LSTAT, filePath);
|
|
1027
|
+
const { status, data } = syncRequest(buf);
|
|
1028
|
+
if (status !== 0) throw statusToError(status, "lstat", filePath);
|
|
1029
|
+
return options?.bigint ? decodeStatsBigInt(data) : decodeStats(data);
|
|
1030
|
+
}
|
|
1031
|
+
async function stat(asyncRequest, filePath, options) {
|
|
1032
|
+
const { status, data } = await asyncRequest(OP.STAT, filePath);
|
|
1033
|
+
if (status !== 0) throw statusToError(status, "stat", filePath);
|
|
1034
|
+
return options?.bigint ? decodeStatsBigInt(data) : decodeStats(data);
|
|
1035
|
+
}
|
|
1036
|
+
async function lstat(asyncRequest, filePath, options) {
|
|
1037
|
+
const { status, data } = await asyncRequest(OP.LSTAT, filePath);
|
|
1038
|
+
if (status !== 0) throw statusToError(status, "lstat", filePath);
|
|
1039
|
+
return options?.bigint ? decodeStatsBigInt(data) : decodeStats(data);
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
// src/methods/rename.ts
|
|
1043
|
+
var encoder5 = new TextEncoder();
|
|
1044
|
+
function renameSync(syncRequest, oldPath, newPath) {
|
|
1045
|
+
const buf = encodeTwoPathRequest(OP.RENAME, oldPath, newPath);
|
|
1046
|
+
const { status } = syncRequest(buf);
|
|
1047
|
+
if (status !== 0) throw statusToError(status, "rename", oldPath);
|
|
1048
|
+
}
|
|
1049
|
+
async function rename(asyncRequest, oldPath, newPath) {
|
|
1050
|
+
const path2Bytes = encoder5.encode(newPath);
|
|
1051
|
+
const payload = new Uint8Array(4 + path2Bytes.byteLength);
|
|
1052
|
+
new DataView(payload.buffer).setUint32(0, path2Bytes.byteLength, true);
|
|
1053
|
+
payload.set(path2Bytes, 4);
|
|
1054
|
+
const { status } = await asyncRequest(OP.RENAME, oldPath, 0, payload);
|
|
1055
|
+
if (status !== 0) throw statusToError(status, "rename", oldPath);
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
// src/methods/copyFile.ts
|
|
1059
|
+
var encoder6 = new TextEncoder();
|
|
1060
|
+
function copyFileSync(syncRequest, src, dest, mode) {
|
|
1061
|
+
const buf = encodeTwoPathRequest(OP.COPY, src, dest, mode ?? 0);
|
|
1062
|
+
const { status } = syncRequest(buf);
|
|
1063
|
+
if (status !== 0) throw statusToError(status, "copyFile", src);
|
|
1064
|
+
}
|
|
1065
|
+
async function copyFile(asyncRequest, src, dest, mode) {
|
|
1066
|
+
const path2Bytes = encoder6.encode(dest);
|
|
1067
|
+
const payload = new Uint8Array(4 + path2Bytes.byteLength);
|
|
1068
|
+
new DataView(payload.buffer).setUint32(0, path2Bytes.byteLength, true);
|
|
1069
|
+
payload.set(path2Bytes, 4);
|
|
1070
|
+
const { status } = await asyncRequest(OP.COPY, src, mode ?? 0, payload);
|
|
1071
|
+
if (status !== 0) throw statusToError(status, "copyFile", src);
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
// src/methods/truncate.ts
|
|
1075
|
+
function truncateSync(syncRequest, filePath, len = 0) {
|
|
1076
|
+
const lenBuf = new Uint8Array(8);
|
|
1077
|
+
new DataView(lenBuf.buffer).setFloat64(0, len, true);
|
|
1078
|
+
const buf = encodeRequest(OP.TRUNCATE, filePath, 0, lenBuf);
|
|
1079
|
+
const { status } = syncRequest(buf);
|
|
1080
|
+
if (status !== 0) throw statusToError(status, "truncate", filePath);
|
|
1081
|
+
}
|
|
1082
|
+
async function truncate(asyncRequest, filePath, len) {
|
|
1083
|
+
const lenBuf = new Uint8Array(8);
|
|
1084
|
+
new DataView(lenBuf.buffer).setFloat64(0, len ?? 0, true);
|
|
1085
|
+
const { status } = await asyncRequest(OP.TRUNCATE, filePath, 0, lenBuf);
|
|
1086
|
+
if (status !== 0) throw statusToError(status, "truncate", filePath);
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
// src/methods/access.ts
|
|
1090
|
+
function accessSync(syncRequest, filePath, mode = constants.F_OK) {
|
|
1091
|
+
const buf = encodeRequest(OP.ACCESS, filePath, mode);
|
|
1092
|
+
const { status } = syncRequest(buf);
|
|
1093
|
+
if (status !== 0) throw statusToError(status, "access", filePath);
|
|
1094
|
+
}
|
|
1095
|
+
async function access(asyncRequest, filePath, mode = constants.F_OK) {
|
|
1096
|
+
const { status } = await asyncRequest(OP.ACCESS, filePath, mode);
|
|
1097
|
+
if (status !== 0) throw statusToError(status, "access", filePath);
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
// src/methods/realpath.ts
|
|
1101
|
+
var decoder5 = new TextDecoder();
|
|
632
1102
|
function realpathSync(syncRequest, filePath) {
|
|
633
1103
|
const buf = encodeRequest(OP.REALPATH, filePath);
|
|
634
1104
|
const { status, data } = syncRequest(buf);
|
|
635
1105
|
if (status !== 0) throw statusToError(status, "realpath", filePath);
|
|
636
|
-
return
|
|
1106
|
+
return decoder5.decode(data);
|
|
637
1107
|
}
|
|
638
1108
|
async function realpath(asyncRequest, filePath) {
|
|
639
1109
|
const { status, data } = await asyncRequest(OP.REALPATH, filePath);
|
|
640
1110
|
if (status !== 0) throw statusToError(status, "realpath", filePath);
|
|
641
|
-
return
|
|
1111
|
+
return decoder5.decode(data);
|
|
642
1112
|
}
|
|
643
1113
|
|
|
644
1114
|
// src/methods/chmod.ts
|
|
@@ -693,212 +1163,65 @@ async function utimes(asyncRequest, filePath, atime, mtime) {
|
|
|
693
1163
|
const { status } = await asyncRequest(OP.UTIMES, filePath, 0, buf);
|
|
694
1164
|
if (status !== 0) throw statusToError(status, "utimes", filePath);
|
|
695
1165
|
}
|
|
696
|
-
|
|
697
|
-
// src/methods/symlink.ts
|
|
698
|
-
var
|
|
699
|
-
var
|
|
700
|
-
function symlinkSync(syncRequest, target, linkPath) {
|
|
701
|
-
const targetBytes =
|
|
702
|
-
const buf = encodeRequest(OP.SYMLINK, linkPath, 0, targetBytes);
|
|
703
|
-
const { status } = syncRequest(buf);
|
|
704
|
-
if (status !== 0) throw statusToError(status, "symlink", linkPath);
|
|
705
|
-
}
|
|
706
|
-
function readlinkSync(syncRequest, filePath) {
|
|
707
|
-
const buf = encodeRequest(OP.READLINK, filePath);
|
|
708
|
-
const { status, data } = syncRequest(buf);
|
|
709
|
-
if (status !== 0) throw statusToError(status, "readlink", filePath);
|
|
710
|
-
return decoder5.decode(data);
|
|
711
|
-
}
|
|
712
|
-
async function symlink(asyncRequest, target, linkPath) {
|
|
713
|
-
const targetBytes = encoder6.encode(target);
|
|
714
|
-
const { status } = await asyncRequest(OP.SYMLINK, linkPath, 0, targetBytes);
|
|
715
|
-
if (status !== 0) throw statusToError(status, "symlink", linkPath);
|
|
716
|
-
}
|
|
717
|
-
async function readlink(asyncRequest, filePath) {
|
|
718
|
-
const { status, data } = await asyncRequest(OP.READLINK, filePath);
|
|
719
|
-
if (status !== 0) throw statusToError(status, "readlink", filePath);
|
|
720
|
-
return decoder5.decode(data);
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
// src/methods/link.ts
|
|
724
|
-
var encoder7 = new TextEncoder();
|
|
725
|
-
function linkSync(syncRequest, existingPath, newPath) {
|
|
726
|
-
const buf = encodeTwoPathRequest(OP.LINK, existingPath, newPath);
|
|
727
|
-
const { status } = syncRequest(buf);
|
|
728
|
-
if (status !== 0) throw statusToError(status, "link", existingPath);
|
|
729
|
-
}
|
|
730
|
-
async function link(asyncRequest, existingPath, newPath) {
|
|
731
|
-
const path2Bytes = encoder7.encode(newPath);
|
|
732
|
-
const payload = new Uint8Array(4 + path2Bytes.byteLength);
|
|
733
|
-
new DataView(payload.buffer).setUint32(0, path2Bytes.byteLength, true);
|
|
734
|
-
payload.set(path2Bytes, 4);
|
|
735
|
-
const { status } = await asyncRequest(OP.LINK, existingPath, 0, payload);
|
|
736
|
-
if (status !== 0) throw statusToError(status, "link", existingPath);
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
// src/methods/mkdtemp.ts
|
|
740
|
-
var decoder6 = new TextDecoder();
|
|
741
|
-
function mkdtempSync(syncRequest, prefix) {
|
|
742
|
-
const buf = encodeRequest(OP.MKDTEMP, prefix);
|
|
743
|
-
const { status, data } = syncRequest(buf);
|
|
744
|
-
if (status !== 0) throw statusToError(status, "mkdtemp", prefix);
|
|
745
|
-
return decoder6.decode(data);
|
|
746
|
-
}
|
|
747
|
-
async function mkdtemp(asyncRequest, prefix) {
|
|
748
|
-
const { status, data } = await asyncRequest(OP.MKDTEMP, prefix);
|
|
749
|
-
if (status !== 0) throw statusToError(status, "mkdtemp", prefix);
|
|
750
|
-
return decoder6.decode(data);
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
// src/methods/open.ts
|
|
754
|
-
var encoder8 = new TextEncoder();
|
|
755
|
-
var decoder7 = new TextDecoder();
|
|
756
|
-
function parseFlags(flags) {
|
|
757
|
-
switch (flags) {
|
|
758
|
-
case "r":
|
|
759
|
-
return constants.O_RDONLY;
|
|
760
|
-
case "r+":
|
|
761
|
-
return constants.O_RDWR;
|
|
762
|
-
case "w":
|
|
763
|
-
return constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC;
|
|
764
|
-
case "w+":
|
|
765
|
-
return constants.O_RDWR | constants.O_CREAT | constants.O_TRUNC;
|
|
766
|
-
case "a":
|
|
767
|
-
return constants.O_WRONLY | constants.O_CREAT | constants.O_APPEND;
|
|
768
|
-
case "a+":
|
|
769
|
-
return constants.O_RDWR | constants.O_CREAT | constants.O_APPEND;
|
|
770
|
-
case "wx":
|
|
771
|
-
return constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC | constants.O_EXCL;
|
|
772
|
-
case "wx+":
|
|
773
|
-
return constants.O_RDWR | constants.O_CREAT | constants.O_TRUNC | constants.O_EXCL;
|
|
774
|
-
case "ax":
|
|
775
|
-
return constants.O_WRONLY | constants.O_CREAT | constants.O_APPEND | constants.O_EXCL;
|
|
776
|
-
case "ax+":
|
|
777
|
-
return constants.O_RDWR | constants.O_CREAT | constants.O_APPEND | constants.O_EXCL;
|
|
778
|
-
default:
|
|
779
|
-
return constants.O_RDONLY;
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
function openSync(syncRequest, filePath, flags = "r", _mode) {
|
|
783
|
-
const numFlags = typeof flags === "string" ? parseFlags(flags) : flags;
|
|
784
|
-
const buf = encodeRequest(OP.OPEN, filePath, numFlags);
|
|
785
|
-
const { status, data } = syncRequest(buf);
|
|
786
|
-
if (status !== 0) throw statusToError(status, "open", filePath);
|
|
787
|
-
return new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true);
|
|
788
|
-
}
|
|
789
|
-
function closeSync(syncRequest, fd) {
|
|
790
|
-
const fdBuf = new Uint8Array(4);
|
|
791
|
-
new DataView(fdBuf.buffer).setUint32(0, fd, true);
|
|
792
|
-
const buf = encodeRequest(OP.CLOSE, "", 0, fdBuf);
|
|
793
|
-
const { status } = syncRequest(buf);
|
|
794
|
-
if (status !== 0) throw statusToError(status, "close", String(fd));
|
|
795
|
-
}
|
|
796
|
-
function readSync(syncRequest, fd, buffer, offset = 0, length = buffer.byteLength, position = null) {
|
|
797
|
-
const fdBuf = new Uint8Array(12);
|
|
798
|
-
const dv = new DataView(fdBuf.buffer);
|
|
799
|
-
dv.setUint32(0, fd, true);
|
|
800
|
-
dv.setUint32(4, length, true);
|
|
801
|
-
dv.setInt32(8, position ?? -1, true);
|
|
802
|
-
const buf = encodeRequest(OP.FREAD, "", 0, fdBuf);
|
|
803
|
-
const { status, data } = syncRequest(buf);
|
|
804
|
-
if (status !== 0) throw statusToError(status, "read", String(fd));
|
|
805
|
-
if (data) {
|
|
806
|
-
buffer.set(data.subarray(0, Math.min(data.byteLength, length)), offset);
|
|
807
|
-
return data.byteLength;
|
|
808
|
-
}
|
|
809
|
-
return 0;
|
|
810
|
-
}
|
|
811
|
-
function writeSyncFd(syncRequest, fd, buffer, offset = 0, length = buffer.byteLength, position = null) {
|
|
812
|
-
const writeData = buffer.subarray(offset, offset + length);
|
|
813
|
-
const fdBuf = new Uint8Array(8 + writeData.byteLength);
|
|
814
|
-
const dv = new DataView(fdBuf.buffer);
|
|
815
|
-
dv.setUint32(0, fd, true);
|
|
816
|
-
dv.setInt32(4, position ?? -1, true);
|
|
817
|
-
fdBuf.set(writeData, 8);
|
|
818
|
-
const buf = encodeRequest(OP.FWRITE, "", 0, fdBuf);
|
|
819
|
-
const { status, data } = syncRequest(buf);
|
|
820
|
-
if (status !== 0) throw statusToError(status, "write", String(fd));
|
|
821
|
-
return data ? new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true) : 0;
|
|
1166
|
+
|
|
1167
|
+
// src/methods/symlink.ts
|
|
1168
|
+
var encoder7 = new TextEncoder();
|
|
1169
|
+
var decoder6 = new TextDecoder();
|
|
1170
|
+
function symlinkSync(syncRequest, target, linkPath, type) {
|
|
1171
|
+
const targetBytes = encoder7.encode(target);
|
|
1172
|
+
const buf = encodeRequest(OP.SYMLINK, linkPath, 0, targetBytes);
|
|
1173
|
+
const { status } = syncRequest(buf);
|
|
1174
|
+
if (status !== 0) throw statusToError(status, "symlink", linkPath);
|
|
822
1175
|
}
|
|
823
|
-
function
|
|
824
|
-
const
|
|
825
|
-
new DataView(fdBuf.buffer).setUint32(0, fd, true);
|
|
826
|
-
const buf = encodeRequest(OP.FSTAT, "", 0, fdBuf);
|
|
1176
|
+
function readlinkSync(syncRequest, filePath, options) {
|
|
1177
|
+
const buf = encodeRequest(OP.READLINK, filePath);
|
|
827
1178
|
const { status, data } = syncRequest(buf);
|
|
828
|
-
if (status !== 0) throw statusToError(status, "
|
|
829
|
-
|
|
1179
|
+
if (status !== 0) throw statusToError(status, "readlink", filePath);
|
|
1180
|
+
const encoding = typeof options === "string" ? options : options?.encoding;
|
|
1181
|
+
if (encoding === "buffer") return new Uint8Array(data);
|
|
1182
|
+
return decoder6.decode(data);
|
|
830
1183
|
}
|
|
831
|
-
function
|
|
832
|
-
const
|
|
833
|
-
const
|
|
834
|
-
|
|
835
|
-
dv.setUint32(4, len, true);
|
|
836
|
-
const buf = encodeRequest(OP.FTRUNCATE, "", 0, fdBuf);
|
|
837
|
-
const { status } = syncRequest(buf);
|
|
838
|
-
if (status !== 0) throw statusToError(status, "ftruncate", String(fd));
|
|
1184
|
+
async function symlink(asyncRequest, target, linkPath, type) {
|
|
1185
|
+
const targetBytes = encoder7.encode(target);
|
|
1186
|
+
const { status } = await asyncRequest(OP.SYMLINK, linkPath, 0, targetBytes);
|
|
1187
|
+
if (status !== 0) throw statusToError(status, "symlink", linkPath);
|
|
839
1188
|
}
|
|
840
|
-
function
|
|
841
|
-
const
|
|
1189
|
+
async function readlink(asyncRequest, filePath, options) {
|
|
1190
|
+
const { status, data } = await asyncRequest(OP.READLINK, filePath);
|
|
1191
|
+
if (status !== 0) throw statusToError(status, "readlink", filePath);
|
|
1192
|
+
const encoding = typeof options === "string" ? options : options?.encoding;
|
|
1193
|
+
if (encoding === "buffer") return new Uint8Array(data);
|
|
1194
|
+
return decoder6.decode(data);
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
// src/methods/link.ts
|
|
1198
|
+
var encoder8 = new TextEncoder();
|
|
1199
|
+
function linkSync(syncRequest, existingPath, newPath) {
|
|
1200
|
+
const buf = encodeTwoPathRequest(OP.LINK, existingPath, newPath);
|
|
842
1201
|
const { status } = syncRequest(buf);
|
|
843
|
-
if (status !== 0) throw statusToError(status, "
|
|
1202
|
+
if (status !== 0) throw statusToError(status, "link", existingPath);
|
|
844
1203
|
}
|
|
845
|
-
async function
|
|
846
|
-
const
|
|
847
|
-
const
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
1204
|
+
async function link(asyncRequest, existingPath, newPath) {
|
|
1205
|
+
const path2Bytes = encoder8.encode(newPath);
|
|
1206
|
+
const payload = new Uint8Array(4 + path2Bytes.byteLength);
|
|
1207
|
+
new DataView(payload.buffer).setUint32(0, path2Bytes.byteLength, true);
|
|
1208
|
+
payload.set(path2Bytes, 4);
|
|
1209
|
+
const { status } = await asyncRequest(OP.LINK, existingPath, 0, payload);
|
|
1210
|
+
if (status !== 0) throw statusToError(status, "link", existingPath);
|
|
851
1211
|
}
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
if (status !== 0) throw statusToError(status, "write", String(fd));
|
|
866
|
-
const bytesWritten = data ? new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true) : 0;
|
|
867
|
-
return { bytesWritten, buffer };
|
|
868
|
-
},
|
|
869
|
-
async readFile(options) {
|
|
870
|
-
const encoding = typeof options === "string" ? options : options?.encoding;
|
|
871
|
-
const { status, data } = await asyncRequest(OP.FREAD, "", 0, null, void 0, { fd, length: Number.MAX_SAFE_INTEGER, position: 0 });
|
|
872
|
-
if (status !== 0) throw statusToError(status, "read", String(fd));
|
|
873
|
-
const result = data ?? new Uint8Array(0);
|
|
874
|
-
if (encoding) return decoder7.decode(result);
|
|
875
|
-
return result;
|
|
876
|
-
},
|
|
877
|
-
async writeFile(data, _options) {
|
|
878
|
-
const encoded = typeof data === "string" ? encoder8.encode(data) : data;
|
|
879
|
-
const { status } = await asyncRequest(OP.FWRITE, "", 0, null, void 0, { fd, data: encoded, position: 0 });
|
|
880
|
-
if (status !== 0) throw statusToError(status, "write", String(fd));
|
|
881
|
-
},
|
|
882
|
-
async truncate(len = 0) {
|
|
883
|
-
const { status } = await asyncRequest(OP.FTRUNCATE, "", 0, null, void 0, { fd, length: len });
|
|
884
|
-
if (status !== 0) throw statusToError(status, "ftruncate", String(fd));
|
|
885
|
-
},
|
|
886
|
-
async stat() {
|
|
887
|
-
const { status, data } = await asyncRequest(OP.FSTAT, "", 0, null, void 0, { fd });
|
|
888
|
-
if (status !== 0) throw statusToError(status, "fstat", String(fd));
|
|
889
|
-
return decodeStats(data);
|
|
890
|
-
},
|
|
891
|
-
async sync() {
|
|
892
|
-
await asyncRequest(OP.FSYNC, "");
|
|
893
|
-
},
|
|
894
|
-
async datasync() {
|
|
895
|
-
await asyncRequest(OP.FSYNC, "");
|
|
896
|
-
},
|
|
897
|
-
async close() {
|
|
898
|
-
const { status } = await asyncRequest(OP.CLOSE, "", 0, null, void 0, { fd });
|
|
899
|
-
if (status !== 0) throw statusToError(status, "close", String(fd));
|
|
900
|
-
}
|
|
901
|
-
};
|
|
1212
|
+
|
|
1213
|
+
// src/methods/mkdtemp.ts
|
|
1214
|
+
var decoder7 = new TextDecoder();
|
|
1215
|
+
function mkdtempSync(syncRequest, prefix) {
|
|
1216
|
+
const buf = encodeRequest(OP.MKDTEMP, prefix);
|
|
1217
|
+
const { status, data } = syncRequest(buf);
|
|
1218
|
+
if (status !== 0) throw statusToError(status, "mkdtemp", prefix);
|
|
1219
|
+
return decoder7.decode(data);
|
|
1220
|
+
}
|
|
1221
|
+
async function mkdtemp(asyncRequest, prefix) {
|
|
1222
|
+
const { status, data } = await asyncRequest(OP.MKDTEMP, prefix);
|
|
1223
|
+
if (status !== 0) throw statusToError(status, "mkdtemp", prefix);
|
|
1224
|
+
return decoder7.decode(data);
|
|
902
1225
|
}
|
|
903
1226
|
|
|
904
1227
|
// src/methods/opendir.ts
|
|
@@ -1271,8 +1594,168 @@ async function* watchAsync(ns, _asyncRequest, filePath, options) {
|
|
|
1271
1594
|
}
|
|
1272
1595
|
}
|
|
1273
1596
|
|
|
1597
|
+
// src/methods/glob.ts
|
|
1598
|
+
function segmentToRegex(pattern) {
|
|
1599
|
+
let re = "^";
|
|
1600
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
1601
|
+
const ch = pattern[i];
|
|
1602
|
+
if (ch === "*") {
|
|
1603
|
+
re += "[^/]*";
|
|
1604
|
+
} else if (ch === "?") {
|
|
1605
|
+
re += "[^/]";
|
|
1606
|
+
} else if (".+^${}()|[]\\".includes(ch)) {
|
|
1607
|
+
re += "\\" + ch;
|
|
1608
|
+
} else {
|
|
1609
|
+
re += ch;
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
re += "$";
|
|
1613
|
+
return new RegExp(re);
|
|
1614
|
+
}
|
|
1615
|
+
function matchSegment(name, pattern) {
|
|
1616
|
+
return segmentToRegex(pattern).test(name);
|
|
1617
|
+
}
|
|
1618
|
+
function joinPath(base, name) {
|
|
1619
|
+
if (base === "/") return "/" + name;
|
|
1620
|
+
return base + "/" + name;
|
|
1621
|
+
}
|
|
1622
|
+
function globSync(syncRequest, pattern, options) {
|
|
1623
|
+
const cwd = options?.cwd ?? "/";
|
|
1624
|
+
const exclude = options?.exclude;
|
|
1625
|
+
const segments = pattern.split("/").filter((s) => s !== "");
|
|
1626
|
+
const results = [];
|
|
1627
|
+
function walk(dir, segIdx) {
|
|
1628
|
+
if (segIdx >= segments.length) return;
|
|
1629
|
+
const seg = segments[segIdx];
|
|
1630
|
+
const isLast = segIdx === segments.length - 1;
|
|
1631
|
+
if (seg === "**") {
|
|
1632
|
+
if (segIdx + 1 < segments.length) {
|
|
1633
|
+
walk(dir, segIdx + 1);
|
|
1634
|
+
}
|
|
1635
|
+
let entries2;
|
|
1636
|
+
try {
|
|
1637
|
+
entries2 = readdirSync(syncRequest, dir);
|
|
1638
|
+
} catch {
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1641
|
+
for (const entry of entries2) {
|
|
1642
|
+
const full = joinPath(dir, entry);
|
|
1643
|
+
if (exclude && exclude(full)) continue;
|
|
1644
|
+
let isDir;
|
|
1645
|
+
try {
|
|
1646
|
+
const s = statSync(syncRequest, full);
|
|
1647
|
+
isDir = s.isDirectory();
|
|
1648
|
+
} catch {
|
|
1649
|
+
continue;
|
|
1650
|
+
}
|
|
1651
|
+
if (isDir) {
|
|
1652
|
+
walk(full, segIdx);
|
|
1653
|
+
}
|
|
1654
|
+
if (isLast) {
|
|
1655
|
+
results.push(full);
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
return;
|
|
1659
|
+
}
|
|
1660
|
+
let entries;
|
|
1661
|
+
try {
|
|
1662
|
+
entries = readdirSync(syncRequest, dir);
|
|
1663
|
+
} catch {
|
|
1664
|
+
return;
|
|
1665
|
+
}
|
|
1666
|
+
for (const entry of entries) {
|
|
1667
|
+
if (!matchSegment(entry, seg)) continue;
|
|
1668
|
+
const full = joinPath(dir, entry);
|
|
1669
|
+
if (exclude && exclude(full)) continue;
|
|
1670
|
+
if (isLast) {
|
|
1671
|
+
results.push(full);
|
|
1672
|
+
} else {
|
|
1673
|
+
let isDir;
|
|
1674
|
+
try {
|
|
1675
|
+
const s = statSync(syncRequest, full);
|
|
1676
|
+
isDir = s.isDirectory();
|
|
1677
|
+
} catch {
|
|
1678
|
+
continue;
|
|
1679
|
+
}
|
|
1680
|
+
if (isDir) {
|
|
1681
|
+
walk(full, segIdx + 1);
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
walk(cwd, 0);
|
|
1687
|
+
return results;
|
|
1688
|
+
}
|
|
1689
|
+
async function glob(asyncRequest, pattern, options) {
|
|
1690
|
+
const cwd = options?.cwd ?? "/";
|
|
1691
|
+
const exclude = options?.exclude;
|
|
1692
|
+
const segments = pattern.split("/").filter((s) => s !== "");
|
|
1693
|
+
const results = [];
|
|
1694
|
+
async function walk(dir, segIdx) {
|
|
1695
|
+
if (segIdx >= segments.length) return;
|
|
1696
|
+
const seg = segments[segIdx];
|
|
1697
|
+
const isLast = segIdx === segments.length - 1;
|
|
1698
|
+
if (seg === "**") {
|
|
1699
|
+
if (segIdx + 1 < segments.length) {
|
|
1700
|
+
await walk(dir, segIdx + 1);
|
|
1701
|
+
}
|
|
1702
|
+
let entries2;
|
|
1703
|
+
try {
|
|
1704
|
+
entries2 = await readdir(asyncRequest, dir);
|
|
1705
|
+
} catch {
|
|
1706
|
+
return;
|
|
1707
|
+
}
|
|
1708
|
+
for (const entry of entries2) {
|
|
1709
|
+
const full = joinPath(dir, entry);
|
|
1710
|
+
if (exclude && exclude(full)) continue;
|
|
1711
|
+
let isDir;
|
|
1712
|
+
try {
|
|
1713
|
+
const s = await stat(asyncRequest, full);
|
|
1714
|
+
isDir = s.isDirectory();
|
|
1715
|
+
} catch {
|
|
1716
|
+
continue;
|
|
1717
|
+
}
|
|
1718
|
+
if (isDir) {
|
|
1719
|
+
await walk(full, segIdx);
|
|
1720
|
+
}
|
|
1721
|
+
if (isLast) {
|
|
1722
|
+
results.push(full);
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
return;
|
|
1726
|
+
}
|
|
1727
|
+
let entries;
|
|
1728
|
+
try {
|
|
1729
|
+
entries = await readdir(asyncRequest, dir);
|
|
1730
|
+
} catch {
|
|
1731
|
+
return;
|
|
1732
|
+
}
|
|
1733
|
+
for (const entry of entries) {
|
|
1734
|
+
if (!matchSegment(entry, seg)) continue;
|
|
1735
|
+
const full = joinPath(dir, entry);
|
|
1736
|
+
if (exclude && exclude(full)) continue;
|
|
1737
|
+
if (isLast) {
|
|
1738
|
+
results.push(full);
|
|
1739
|
+
} else {
|
|
1740
|
+
let isDir;
|
|
1741
|
+
try {
|
|
1742
|
+
const s = await stat(asyncRequest, full);
|
|
1743
|
+
isDir = s.isDirectory();
|
|
1744
|
+
} catch {
|
|
1745
|
+
continue;
|
|
1746
|
+
}
|
|
1747
|
+
if (isDir) {
|
|
1748
|
+
await walk(full, segIdx + 1);
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
await walk(cwd, 0);
|
|
1754
|
+
return results;
|
|
1755
|
+
}
|
|
1756
|
+
|
|
1274
1757
|
// src/filesystem.ts
|
|
1275
|
-
|
|
1758
|
+
new TextEncoder();
|
|
1276
1759
|
var DEFAULT_SAB_SIZE = 2 * 1024 * 1024;
|
|
1277
1760
|
var instanceRegistry = /* @__PURE__ */ new Map();
|
|
1278
1761
|
var HEADER_SIZE = SAB_OFFSETS.HEADER_SIZE;
|
|
@@ -1832,11 +2315,14 @@ var VFSFileSystem = class {
|
|
|
1832
2315
|
readdirSync(filePath, options) {
|
|
1833
2316
|
return readdirSync(this._sync, filePath, options);
|
|
1834
2317
|
}
|
|
1835
|
-
|
|
1836
|
-
return
|
|
2318
|
+
globSync(pattern, options) {
|
|
2319
|
+
return globSync(this._sync, pattern, options);
|
|
2320
|
+
}
|
|
2321
|
+
statSync(filePath, options) {
|
|
2322
|
+
return statSync(this._sync, filePath, options);
|
|
1837
2323
|
}
|
|
1838
|
-
lstatSync(filePath) {
|
|
1839
|
-
return lstatSync(this._sync, filePath);
|
|
2324
|
+
lstatSync(filePath, options) {
|
|
2325
|
+
return lstatSync(this._sync, filePath, options);
|
|
1840
2326
|
}
|
|
1841
2327
|
renameSync(oldPath, newPath) {
|
|
1842
2328
|
renameSync(this._sync, oldPath, newPath);
|
|
@@ -1844,6 +2330,112 @@ var VFSFileSystem = class {
|
|
|
1844
2330
|
copyFileSync(src, dest, mode) {
|
|
1845
2331
|
copyFileSync(this._sync, src, dest, mode);
|
|
1846
2332
|
}
|
|
2333
|
+
cpSync(src, dest, options) {
|
|
2334
|
+
const force = options?.force !== false;
|
|
2335
|
+
const errorOnExist = options?.errorOnExist ?? false;
|
|
2336
|
+
const dereference = options?.dereference ?? false;
|
|
2337
|
+
const preserveTimestamps = options?.preserveTimestamps ?? false;
|
|
2338
|
+
const srcStat = dereference ? this.statSync(src) : this.lstatSync(src);
|
|
2339
|
+
if (srcStat.isDirectory()) {
|
|
2340
|
+
if (!options?.recursive) {
|
|
2341
|
+
throw createError("EISDIR", "cp", src);
|
|
2342
|
+
}
|
|
2343
|
+
try {
|
|
2344
|
+
this.mkdirSync(dest, { recursive: true });
|
|
2345
|
+
} catch (e) {
|
|
2346
|
+
if (e.code !== "EEXIST") throw e;
|
|
2347
|
+
}
|
|
2348
|
+
const entries = this.readdirSync(src, { withFileTypes: true });
|
|
2349
|
+
for (const entry of entries) {
|
|
2350
|
+
const srcChild = join(src, entry.name);
|
|
2351
|
+
const destChild = join(dest, entry.name);
|
|
2352
|
+
this.cpSync(srcChild, destChild, options);
|
|
2353
|
+
}
|
|
2354
|
+
} else if (srcStat.isSymbolicLink() && !dereference) {
|
|
2355
|
+
const target = this.readlinkSync(src);
|
|
2356
|
+
let destExists = false;
|
|
2357
|
+
try {
|
|
2358
|
+
this.lstatSync(dest);
|
|
2359
|
+
destExists = true;
|
|
2360
|
+
} catch {
|
|
2361
|
+
}
|
|
2362
|
+
if (destExists) {
|
|
2363
|
+
if (errorOnExist) throw createError("EEXIST", "cp", dest);
|
|
2364
|
+
if (!force) return;
|
|
2365
|
+
this.unlinkSync(dest);
|
|
2366
|
+
}
|
|
2367
|
+
this.symlinkSync(target, dest);
|
|
2368
|
+
} else {
|
|
2369
|
+
let destExists = false;
|
|
2370
|
+
try {
|
|
2371
|
+
this.lstatSync(dest);
|
|
2372
|
+
destExists = true;
|
|
2373
|
+
} catch {
|
|
2374
|
+
}
|
|
2375
|
+
if (destExists) {
|
|
2376
|
+
if (errorOnExist) throw createError("EEXIST", "cp", dest);
|
|
2377
|
+
if (!force) return;
|
|
2378
|
+
}
|
|
2379
|
+
this.copyFileSync(src, dest, errorOnExist ? constants.COPYFILE_EXCL : 0);
|
|
2380
|
+
}
|
|
2381
|
+
if (preserveTimestamps) {
|
|
2382
|
+
const st = this.statSync(src);
|
|
2383
|
+
this.utimesSync(dest, st.atime, st.mtime);
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
async cp(src, dest, options) {
|
|
2387
|
+
const force = options?.force !== false;
|
|
2388
|
+
const errorOnExist = options?.errorOnExist ?? false;
|
|
2389
|
+
const dereference = options?.dereference ?? false;
|
|
2390
|
+
const preserveTimestamps = options?.preserveTimestamps ?? false;
|
|
2391
|
+
const srcStat = dereference ? await this.promises.stat(src) : await this.promises.lstat(src);
|
|
2392
|
+
if (srcStat.isDirectory()) {
|
|
2393
|
+
if (!options?.recursive) {
|
|
2394
|
+
throw createError("EISDIR", "cp", src);
|
|
2395
|
+
}
|
|
2396
|
+
try {
|
|
2397
|
+
await this.promises.mkdir(dest, { recursive: true });
|
|
2398
|
+
} catch (e) {
|
|
2399
|
+
if (e.code !== "EEXIST") throw e;
|
|
2400
|
+
}
|
|
2401
|
+
const entries = await this.promises.readdir(src, { withFileTypes: true });
|
|
2402
|
+
for (const entry of entries) {
|
|
2403
|
+
const srcChild = join(src, entry.name);
|
|
2404
|
+
const destChild = join(dest, entry.name);
|
|
2405
|
+
await this.cp(srcChild, destChild, options);
|
|
2406
|
+
}
|
|
2407
|
+
} else if (srcStat.isSymbolicLink() && !dereference) {
|
|
2408
|
+
const target = await this.promises.readlink(src);
|
|
2409
|
+
let destExists = false;
|
|
2410
|
+
try {
|
|
2411
|
+
await this.promises.lstat(dest);
|
|
2412
|
+
destExists = true;
|
|
2413
|
+
} catch {
|
|
2414
|
+
}
|
|
2415
|
+
if (destExists) {
|
|
2416
|
+
if (errorOnExist) throw createError("EEXIST", "cp", dest);
|
|
2417
|
+
if (!force) return;
|
|
2418
|
+
await this.promises.unlink(dest);
|
|
2419
|
+
}
|
|
2420
|
+
await this.promises.symlink(target, dest);
|
|
2421
|
+
} else {
|
|
2422
|
+
let destExists = false;
|
|
2423
|
+
try {
|
|
2424
|
+
await this.promises.lstat(dest);
|
|
2425
|
+
destExists = true;
|
|
2426
|
+
} catch {
|
|
2427
|
+
}
|
|
2428
|
+
if (destExists) {
|
|
2429
|
+
if (errorOnExist) throw createError("EEXIST", "cp", dest);
|
|
2430
|
+
if (!force) return;
|
|
2431
|
+
}
|
|
2432
|
+
await this.promises.copyFile(src, dest, errorOnExist ? constants.COPYFILE_EXCL : 0);
|
|
2433
|
+
}
|
|
2434
|
+
if (preserveTimestamps) {
|
|
2435
|
+
const st = await this.promises.stat(src);
|
|
2436
|
+
await this.promises.utimes(dest, st.atime, st.mtime);
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
1847
2439
|
truncateSync(filePath, len) {
|
|
1848
2440
|
truncateSync(this._sync, filePath, len);
|
|
1849
2441
|
}
|
|
@@ -1862,11 +2454,11 @@ var VFSFileSystem = class {
|
|
|
1862
2454
|
utimesSync(filePath, atime, mtime) {
|
|
1863
2455
|
utimesSync(this._sync, filePath, atime, mtime);
|
|
1864
2456
|
}
|
|
1865
|
-
symlinkSync(target, linkPath) {
|
|
2457
|
+
symlinkSync(target, linkPath, type) {
|
|
1866
2458
|
symlinkSync(this._sync, target, linkPath);
|
|
1867
2459
|
}
|
|
1868
|
-
readlinkSync(filePath) {
|
|
1869
|
-
return readlinkSync(this._sync, filePath);
|
|
2460
|
+
readlinkSync(filePath, options) {
|
|
2461
|
+
return readlinkSync(this._sync, filePath, options);
|
|
1870
2462
|
}
|
|
1871
2463
|
linkSync(existingPath, newPath) {
|
|
1872
2464
|
linkSync(this._sync, existingPath, newPath);
|
|
@@ -1884,8 +2476,8 @@ var VFSFileSystem = class {
|
|
|
1884
2476
|
readSync(fd, buffer, offset = 0, length = buffer.byteLength, position = null) {
|
|
1885
2477
|
return readSync(this._sync, fd, buffer, offset, length, position);
|
|
1886
2478
|
}
|
|
1887
|
-
writeSync(fd,
|
|
1888
|
-
return writeSyncFd(this._sync, fd,
|
|
2479
|
+
writeSync(fd, bufferOrString, offsetOrPosition, lengthOrEncoding, position) {
|
|
2480
|
+
return writeSyncFd(this._sync, fd, bufferOrString, offsetOrPosition, lengthOrEncoding, position);
|
|
1889
2481
|
}
|
|
1890
2482
|
fstatSync(fd) {
|
|
1891
2483
|
return fstatSync(this._sync, fd);
|
|
@@ -1896,6 +2488,31 @@ var VFSFileSystem = class {
|
|
|
1896
2488
|
fdatasyncSync(fd) {
|
|
1897
2489
|
fdatasyncSync(this._sync, fd);
|
|
1898
2490
|
}
|
|
2491
|
+
// ---- statfs methods ----
|
|
2492
|
+
statfsSync(_path) {
|
|
2493
|
+
return {
|
|
2494
|
+
type: 1447449377,
|
|
2495
|
+
// "VFS!"
|
|
2496
|
+
bsize: 4096,
|
|
2497
|
+
blocks: 1024 * 1024,
|
|
2498
|
+
// ~4GB virtual capacity
|
|
2499
|
+
bfree: 512 * 1024,
|
|
2500
|
+
// ~2GB free (estimate)
|
|
2501
|
+
bavail: 512 * 1024,
|
|
2502
|
+
files: 1e4,
|
|
2503
|
+
// default max inodes
|
|
2504
|
+
ffree: 5e3
|
|
2505
|
+
// estimate half free
|
|
2506
|
+
};
|
|
2507
|
+
}
|
|
2508
|
+
statfs(path, callback) {
|
|
2509
|
+
const result = this.statfsSync(path);
|
|
2510
|
+
if (callback) {
|
|
2511
|
+
callback(null, result);
|
|
2512
|
+
return;
|
|
2513
|
+
}
|
|
2514
|
+
return Promise.resolve(result);
|
|
2515
|
+
}
|
|
1899
2516
|
// ---- Watch methods ----
|
|
1900
2517
|
watch(filePath, options, listener) {
|
|
1901
2518
|
return watch(this.ns, filePath, options, listener);
|
|
@@ -1908,55 +2525,81 @@ var VFSFileSystem = class {
|
|
|
1908
2525
|
}
|
|
1909
2526
|
// ---- Stream methods ----
|
|
1910
2527
|
createReadStream(filePath, options) {
|
|
1911
|
-
const opts = typeof options === "string" ? { } : options;
|
|
2528
|
+
const opts = typeof options === "string" ? { encoding: options } : options;
|
|
1912
2529
|
const start = opts?.start ?? 0;
|
|
1913
2530
|
const end = opts?.end;
|
|
1914
2531
|
const highWaterMark = opts?.highWaterMark ?? 64 * 1024;
|
|
1915
2532
|
let position = start;
|
|
2533
|
+
let handle = null;
|
|
2534
|
+
const cleanup = async () => {
|
|
2535
|
+
if (handle) {
|
|
2536
|
+
try {
|
|
2537
|
+
await handle.close();
|
|
2538
|
+
} catch {
|
|
2539
|
+
}
|
|
2540
|
+
handle = null;
|
|
2541
|
+
}
|
|
2542
|
+
};
|
|
1916
2543
|
return new ReadableStream({
|
|
1917
2544
|
pull: async (controller) => {
|
|
1918
2545
|
try {
|
|
2546
|
+
if (!handle) {
|
|
2547
|
+
handle = await this.promises.open(filePath, opts?.flags ?? "r");
|
|
2548
|
+
}
|
|
1919
2549
|
const readLen = end !== void 0 ? Math.min(highWaterMark, end - position + 1) : highWaterMark;
|
|
1920
2550
|
if (readLen <= 0) {
|
|
2551
|
+
await cleanup();
|
|
1921
2552
|
controller.close();
|
|
1922
2553
|
return;
|
|
1923
2554
|
}
|
|
1924
|
-
const
|
|
1925
|
-
const
|
|
1926
|
-
|
|
1927
|
-
|
|
2555
|
+
const buffer = new Uint8Array(readLen);
|
|
2556
|
+
const { bytesRead } = await handle.read(buffer, 0, readLen, position);
|
|
2557
|
+
if (bytesRead === 0) {
|
|
2558
|
+
await cleanup();
|
|
1928
2559
|
controller.close();
|
|
1929
2560
|
return;
|
|
1930
2561
|
}
|
|
1931
|
-
controller.enqueue(
|
|
1932
|
-
position +=
|
|
2562
|
+
controller.enqueue(buffer.subarray(0, bytesRead));
|
|
2563
|
+
position += bytesRead;
|
|
1933
2564
|
if (end !== void 0 && position > end) {
|
|
2565
|
+
await cleanup();
|
|
1934
2566
|
controller.close();
|
|
1935
2567
|
}
|
|
1936
2568
|
} catch (err) {
|
|
2569
|
+
await cleanup();
|
|
1937
2570
|
controller.error(err);
|
|
1938
2571
|
}
|
|
2572
|
+
},
|
|
2573
|
+
cancel: async () => {
|
|
2574
|
+
await cleanup();
|
|
1939
2575
|
}
|
|
1940
2576
|
});
|
|
1941
2577
|
}
|
|
1942
2578
|
createWriteStream(filePath, options) {
|
|
1943
2579
|
const opts = typeof options === "string" ? { } : options;
|
|
1944
2580
|
let position = opts?.start ?? 0;
|
|
1945
|
-
let
|
|
2581
|
+
let handle = null;
|
|
1946
2582
|
return new WritableStream({
|
|
1947
2583
|
write: async (chunk) => {
|
|
1948
|
-
if (!
|
|
1949
|
-
|
|
1950
|
-
await this.promises.writeFile(filePath, new Uint8Array(0));
|
|
1951
|
-
}
|
|
1952
|
-
initialized = true;
|
|
2584
|
+
if (!handle) {
|
|
2585
|
+
handle = await this.promises.open(filePath, opts?.flags ?? "w");
|
|
1953
2586
|
}
|
|
1954
|
-
await
|
|
1955
|
-
position +=
|
|
2587
|
+
const { bytesWritten } = await handle.write(chunk, 0, chunk.byteLength, position);
|
|
2588
|
+
position += bytesWritten;
|
|
1956
2589
|
},
|
|
1957
2590
|
close: async () => {
|
|
1958
|
-
if (
|
|
1959
|
-
|
|
2591
|
+
if (handle) {
|
|
2592
|
+
if (opts?.flush) {
|
|
2593
|
+
await handle.sync();
|
|
2594
|
+
}
|
|
2595
|
+
await handle.close();
|
|
2596
|
+
handle = null;
|
|
2597
|
+
}
|
|
2598
|
+
},
|
|
2599
|
+
abort: async () => {
|
|
2600
|
+
if (handle) {
|
|
2601
|
+
await handle.close();
|
|
2602
|
+
handle = null;
|
|
1960
2603
|
}
|
|
1961
2604
|
}
|
|
1962
2605
|
});
|
|
@@ -2097,11 +2740,14 @@ var VFSPromises = class {
|
|
|
2097
2740
|
readdir(filePath, options) {
|
|
2098
2741
|
return readdir(this._async, filePath, options);
|
|
2099
2742
|
}
|
|
2100
|
-
|
|
2101
|
-
return
|
|
2743
|
+
glob(pattern, options) {
|
|
2744
|
+
return glob(this._async, pattern, options);
|
|
2102
2745
|
}
|
|
2103
|
-
|
|
2104
|
-
return
|
|
2746
|
+
stat(filePath, options) {
|
|
2747
|
+
return stat(this._async, filePath, options);
|
|
2748
|
+
}
|
|
2749
|
+
lstat(filePath, options) {
|
|
2750
|
+
return lstat(this._async, filePath, options);
|
|
2105
2751
|
}
|
|
2106
2752
|
access(filePath, mode) {
|
|
2107
2753
|
return access(this._async, filePath, mode);
|
|
@@ -2112,6 +2758,59 @@ var VFSPromises = class {
|
|
|
2112
2758
|
copyFile(src, dest, mode) {
|
|
2113
2759
|
return copyFile(this._async, src, dest, mode);
|
|
2114
2760
|
}
|
|
2761
|
+
async cp(src, dest, options) {
|
|
2762
|
+
const force = options?.force !== false;
|
|
2763
|
+
const errorOnExist = options?.errorOnExist ?? false;
|
|
2764
|
+
const dereference = options?.dereference ?? false;
|
|
2765
|
+
const preserveTimestamps = options?.preserveTimestamps ?? false;
|
|
2766
|
+
const srcStat = dereference ? await this.stat(src) : await this.lstat(src);
|
|
2767
|
+
if (srcStat.isDirectory()) {
|
|
2768
|
+
if (!options?.recursive) {
|
|
2769
|
+
throw createError("EISDIR", "cp", src);
|
|
2770
|
+
}
|
|
2771
|
+
try {
|
|
2772
|
+
await this.mkdir(dest, { recursive: true });
|
|
2773
|
+
} catch (e) {
|
|
2774
|
+
if (e.code !== "EEXIST") throw e;
|
|
2775
|
+
}
|
|
2776
|
+
const entries = await this.readdir(src, { withFileTypes: true });
|
|
2777
|
+
for (const entry of entries) {
|
|
2778
|
+
const srcChild = join(src, entry.name);
|
|
2779
|
+
const destChild = join(dest, entry.name);
|
|
2780
|
+
await this.cp(srcChild, destChild, options);
|
|
2781
|
+
}
|
|
2782
|
+
} else if (srcStat.isSymbolicLink() && !dereference) {
|
|
2783
|
+
const target = await this.readlink(src);
|
|
2784
|
+
let destExists = false;
|
|
2785
|
+
try {
|
|
2786
|
+
await this.lstat(dest);
|
|
2787
|
+
destExists = true;
|
|
2788
|
+
} catch {
|
|
2789
|
+
}
|
|
2790
|
+
if (destExists) {
|
|
2791
|
+
if (errorOnExist) throw createError("EEXIST", "cp", dest);
|
|
2792
|
+
if (!force) return;
|
|
2793
|
+
await this.unlink(dest);
|
|
2794
|
+
}
|
|
2795
|
+
await this.symlink(target, dest);
|
|
2796
|
+
} else {
|
|
2797
|
+
let destExists = false;
|
|
2798
|
+
try {
|
|
2799
|
+
await this.lstat(dest);
|
|
2800
|
+
destExists = true;
|
|
2801
|
+
} catch {
|
|
2802
|
+
}
|
|
2803
|
+
if (destExists) {
|
|
2804
|
+
if (errorOnExist) throw createError("EEXIST", "cp", dest);
|
|
2805
|
+
if (!force) return;
|
|
2806
|
+
}
|
|
2807
|
+
await this.copyFile(src, dest, errorOnExist ? constants.COPYFILE_EXCL : 0);
|
|
2808
|
+
}
|
|
2809
|
+
if (preserveTimestamps) {
|
|
2810
|
+
const st = await this.stat(src);
|
|
2811
|
+
await this.utimes(dest, st.atime, st.mtime);
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2115
2814
|
truncate(filePath, len) {
|
|
2116
2815
|
return truncate(this._async, filePath, len);
|
|
2117
2816
|
}
|
|
@@ -2130,11 +2829,11 @@ var VFSPromises = class {
|
|
|
2130
2829
|
utimes(filePath, atime, mtime) {
|
|
2131
2830
|
return utimes(this._async, filePath, atime, mtime);
|
|
2132
2831
|
}
|
|
2133
|
-
symlink(target, linkPath) {
|
|
2832
|
+
symlink(target, linkPath, type) {
|
|
2134
2833
|
return symlink(this._async, target, linkPath);
|
|
2135
2834
|
}
|
|
2136
|
-
readlink(filePath) {
|
|
2137
|
-
return readlink(this._async, filePath);
|
|
2835
|
+
readlink(filePath, options) {
|
|
2836
|
+
return readlink(this._async, filePath, options);
|
|
2138
2837
|
}
|
|
2139
2838
|
link(existingPath, newPath) {
|
|
2140
2839
|
return link(this._async, existingPath, newPath);
|
|
@@ -2148,6 +2847,22 @@ var VFSPromises = class {
|
|
|
2148
2847
|
mkdtemp(prefix) {
|
|
2149
2848
|
return mkdtemp(this._async, prefix);
|
|
2150
2849
|
}
|
|
2850
|
+
async statfs(path) {
|
|
2851
|
+
return {
|
|
2852
|
+
type: 1447449377,
|
|
2853
|
+
// "VFS!"
|
|
2854
|
+
bsize: 4096,
|
|
2855
|
+
blocks: 1024 * 1024,
|
|
2856
|
+
// ~4GB virtual capacity
|
|
2857
|
+
bfree: 512 * 1024,
|
|
2858
|
+
// ~2GB free (estimate)
|
|
2859
|
+
bavail: 512 * 1024,
|
|
2860
|
+
files: 1e4,
|
|
2861
|
+
// default max inodes
|
|
2862
|
+
ffree: 5e3
|
|
2863
|
+
// estimate half free
|
|
2864
|
+
};
|
|
2865
|
+
}
|
|
2151
2866
|
async *watch(filePath, options) {
|
|
2152
2867
|
yield* watchAsync(this._ns, this._async, filePath, options);
|
|
2153
2868
|
}
|
|
@@ -2461,6 +3176,7 @@ var VFSEngine = class {
|
|
|
2461
3176
|
type,
|
|
2462
3177
|
pathOffset,
|
|
2463
3178
|
pathLength,
|
|
3179
|
+
nlink: inodeView.getUint16(off + INODE.NLINK, true) || 1,
|
|
2464
3180
|
mode: inodeView.getUint32(off + INODE.MODE, true),
|
|
2465
3181
|
size,
|
|
2466
3182
|
firstBlock,
|
|
@@ -2495,6 +3211,7 @@ var VFSEngine = class {
|
|
|
2495
3211
|
type: v.getUint8(INODE.TYPE),
|
|
2496
3212
|
pathOffset: v.getUint32(INODE.PATH_OFFSET, true),
|
|
2497
3213
|
pathLength: v.getUint16(INODE.PATH_LENGTH, true),
|
|
3214
|
+
nlink: v.getUint16(INODE.NLINK, true) || 1,
|
|
2498
3215
|
mode: v.getUint32(INODE.MODE, true),
|
|
2499
3216
|
size: v.getFloat64(INODE.SIZE, true),
|
|
2500
3217
|
firstBlock: v.getUint32(INODE.FIRST_BLOCK, true),
|
|
@@ -2521,7 +3238,7 @@ var VFSEngine = class {
|
|
|
2521
3238
|
v.setUint8(INODE.FLAGS + 2, 0);
|
|
2522
3239
|
v.setUint32(INODE.PATH_OFFSET, inode.pathOffset, true);
|
|
2523
3240
|
v.setUint16(INODE.PATH_LENGTH, inode.pathLength, true);
|
|
2524
|
-
v.setUint16(INODE.
|
|
3241
|
+
v.setUint16(INODE.NLINK, inode.nlink, true);
|
|
2525
3242
|
v.setUint32(INODE.MODE, inode.mode, true);
|
|
2526
3243
|
v.setFloat64(INODE.SIZE, inode.size, true);
|
|
2527
3244
|
v.setUint32(INODE.FIRST_BLOCK, inode.firstBlock, true);
|
|
@@ -2763,6 +3480,7 @@ var VFSEngine = class {
|
|
|
2763
3480
|
type,
|
|
2764
3481
|
pathOffset: pathOff,
|
|
2765
3482
|
pathLength: pathLen,
|
|
3483
|
+
nlink: type === INODE_TYPE.DIRECTORY ? 2 : 1,
|
|
2766
3484
|
mode,
|
|
2767
3485
|
size,
|
|
2768
3486
|
firstBlock,
|
|
@@ -2915,6 +3633,7 @@ var VFSEngine = class {
|
|
|
2915
3633
|
if (idx === void 0) return { status: CODE_TO_STATUS.ENOENT };
|
|
2916
3634
|
const inode = this.readInode(idx);
|
|
2917
3635
|
if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };
|
|
3636
|
+
inode.nlink = Math.max(0, inode.nlink - 1);
|
|
2918
3637
|
this.freeBlockRange(inode.firstBlock, inode.blockCount);
|
|
2919
3638
|
inode.type = INODE_TYPE.FREE;
|
|
2920
3639
|
this.writeInode(idx, inode);
|
|
@@ -2939,7 +3658,21 @@ var VFSEngine = class {
|
|
|
2939
3658
|
}
|
|
2940
3659
|
encodeStatResponse(idx) {
|
|
2941
3660
|
const inode = this.readInode(idx);
|
|
2942
|
-
|
|
3661
|
+
let nlink = inode.nlink;
|
|
3662
|
+
if (inode.type === INODE_TYPE.DIRECTORY) {
|
|
3663
|
+
const path = this.readPath(inode.pathOffset, inode.pathLength);
|
|
3664
|
+
const children = this.getDirectChildren(path);
|
|
3665
|
+
let subdirCount = 0;
|
|
3666
|
+
for (const child of children) {
|
|
3667
|
+
const childIdx = this.pathIndex.get(child);
|
|
3668
|
+
if (childIdx !== void 0) {
|
|
3669
|
+
const childInode = this.readInode(childIdx);
|
|
3670
|
+
if (childInode.type === INODE_TYPE.DIRECTORY) subdirCount++;
|
|
3671
|
+
}
|
|
3672
|
+
}
|
|
3673
|
+
nlink = 2 + subdirCount;
|
|
3674
|
+
}
|
|
3675
|
+
const buf = new Uint8Array(53);
|
|
2943
3676
|
const view = new DataView(buf.buffer);
|
|
2944
3677
|
view.setUint8(0, inode.type);
|
|
2945
3678
|
view.setUint32(1, inode.mode, true);
|
|
@@ -2950,6 +3683,7 @@ var VFSEngine = class {
|
|
|
2950
3683
|
view.setUint32(37, inode.uid, true);
|
|
2951
3684
|
view.setUint32(41, inode.gid, true);
|
|
2952
3685
|
view.setUint32(45, idx, true);
|
|
3686
|
+
view.setUint32(49, nlink, true);
|
|
2953
3687
|
return { status: 0, data: buf };
|
|
2954
3688
|
}
|
|
2955
3689
|
// ---- MKDIR ----
|
|
@@ -3262,9 +3996,26 @@ var VFSEngine = class {
|
|
|
3262
3996
|
const target = this.readData(inode.firstBlock, inode.blockCount, inode.size);
|
|
3263
3997
|
return { status: 0, data: target };
|
|
3264
3998
|
}
|
|
3265
|
-
// ---- LINK (hard link — copies the file) ----
|
|
3999
|
+
// ---- LINK (hard link — copies the file data, tracks nlink) ----
|
|
3266
4000
|
link(existingPath, newPath) {
|
|
3267
|
-
|
|
4001
|
+
existingPath = this.normalizePath(existingPath);
|
|
4002
|
+
newPath = this.normalizePath(newPath);
|
|
4003
|
+
const srcIdx = this.resolvePathComponents(existingPath, true);
|
|
4004
|
+
if (srcIdx === void 0) return { status: CODE_TO_STATUS.ENOENT };
|
|
4005
|
+
const srcInode = this.readInode(srcIdx);
|
|
4006
|
+
if (srcInode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EPERM };
|
|
4007
|
+
if (this.pathIndex.has(newPath)) return { status: CODE_TO_STATUS.EEXIST };
|
|
4008
|
+
const result = this.copy(existingPath, newPath);
|
|
4009
|
+
if (result.status !== 0) return result;
|
|
4010
|
+
srcInode.nlink++;
|
|
4011
|
+
this.writeInode(srcIdx, srcInode);
|
|
4012
|
+
const destIdx = this.pathIndex.get(newPath);
|
|
4013
|
+
if (destIdx !== void 0) {
|
|
4014
|
+
const destInode = this.readInode(destIdx);
|
|
4015
|
+
destInode.nlink = srcInode.nlink;
|
|
4016
|
+
this.writeInode(destIdx, destInode);
|
|
4017
|
+
}
|
|
4018
|
+
return { status: 0 };
|
|
3268
4019
|
}
|
|
3269
4020
|
// ---- OPEN (file descriptor) ----
|
|
3270
4021
|
open(path, flags, tabId) {
|