@zenfs/core 0.12.10 → 0.14.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.
@@ -18,6 +18,7 @@ import { BigIntStats, type Stats } from '../stats.js';
18
18
  import { Dir, Dirent } from './dir.js';
19
19
  import { ReadStream, WriteStream } from './streams.js';
20
20
  export * as constants from './constants.js';
21
+ import '../symbol-dispose.js';
21
22
  export declare class FileHandle implements promises.FileHandle {
22
23
  /**
23
24
  * The file descriptor for this file handle.
@@ -1,3 +1,48 @@
1
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2
+ if (value !== null && value !== void 0) {
3
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
4
+ var dispose;
5
+ if (async) {
6
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
7
+ dispose = value[Symbol.asyncDispose];
8
+ }
9
+ if (dispose === void 0) {
10
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
11
+ dispose = value[Symbol.dispose];
12
+ }
13
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
14
+ env.stack.push({ value: value, dispose: dispose, async: async });
15
+ }
16
+ else if (async) {
17
+ env.stack.push({ async: true });
18
+ }
19
+ return value;
20
+ };
21
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
22
+ return function (env) {
23
+ function fail(e) {
24
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
25
+ env.hasError = true;
26
+ }
27
+ function next() {
28
+ while (env.stack.length) {
29
+ var rec = env.stack.pop();
30
+ try {
31
+ var result = rec.dispose && rec.dispose.call(rec.value);
32
+ if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
33
+ }
34
+ catch (e) {
35
+ fail(e);
36
+ }
37
+ }
38
+ if (env.hasError) throw env.error;
39
+ }
40
+ return next();
41
+ };
42
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
43
+ var e = new Error(message);
44
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
45
+ });
1
46
  import { Buffer } from 'buffer';
2
47
  import { Errno, ErrnoError } from '../error.js';
3
48
  import { isAppendable, isExclusive, isReadable, isTruncating, isWriteable, parseFlag } from '../file.js';
@@ -9,6 +54,7 @@ import { dirname, join, parse } from './path.js';
9
54
  import { _statfs, cred, fd2file, fdMap, file2fd, fixError, mounts, resolveMount } from './shared.js';
10
55
  import { ReadStream, WriteStream } from './streams.js';
11
56
  export * as constants from './constants.js';
57
+ import '../symbol-dispose.js';
12
58
  export class FileHandle {
13
59
  constructor(fdOrFile) {
14
60
  const isFile = typeof fdOrFile != 'number';
@@ -353,12 +399,19 @@ lstat;
353
399
  * @param len
354
400
  */
355
401
  export async function truncate(path, len = 0) {
356
- const handle = await open(path, 'r+');
402
+ const env_1 = { stack: [], error: void 0, hasError: false };
357
403
  try {
404
+ const handle = __addDisposableResource(env_1, await open(path, 'r+'), true);
358
405
  await handle.truncate(len);
359
406
  }
407
+ catch (e_1) {
408
+ env_1.error = e_1;
409
+ env_1.hasError = true;
410
+ }
360
411
  finally {
361
- await handle.close();
412
+ const result_1 = __disposeResources(env_1);
413
+ if (result_1)
414
+ await result_1;
362
415
  }
363
416
  }
364
417
  truncate;
@@ -425,13 +478,20 @@ export async function open(path, flag = 'r', mode = 0o644) {
425
478
  }
426
479
  open;
427
480
  export async function readFile(path, _options) {
428
- const options = normalizeOptions(_options, null, 'r', 0o644);
429
- const handle = typeof path == 'object' && 'fd' in path ? path : await open(path, options.flag, options.mode);
481
+ const env_2 = { stack: [], error: void 0, hasError: false };
430
482
  try {
483
+ const options = normalizeOptions(_options, null, 'r', 0o644);
484
+ const handle = __addDisposableResource(env_2, typeof path == 'object' && 'fd' in path ? path : await open(path, options.flag, options.mode), true);
431
485
  return await handle.readFile(options);
432
486
  }
487
+ catch (e_2) {
488
+ env_2.error = e_2;
489
+ env_2.hasError = true;
490
+ }
433
491
  finally {
434
- await handle.close();
492
+ const result_2 = __disposeResources(env_2);
493
+ if (result_2)
494
+ await result_2;
435
495
  }
436
496
  }
437
497
  readFile;
@@ -447,17 +507,24 @@ readFile;
447
507
  * @option options flag Defaults to `'w'`.
448
508
  */
449
509
  export async function writeFile(path, data, _options) {
450
- const options = normalizeOptions(_options, 'utf8', 'w+', 0o644);
451
- const handle = path instanceof FileHandle ? path : await open(path.toString(), options.flag, options.mode);
510
+ const env_3 = { stack: [], error: void 0, hasError: false };
452
511
  try {
512
+ const options = normalizeOptions(_options, 'utf8', 'w+', 0o644);
513
+ const handle = __addDisposableResource(env_3, path instanceof FileHandle ? path : await open(path.toString(), options.flag, options.mode), true);
453
514
  const _data = typeof data == 'string' ? data : data;
454
515
  if (typeof _data != 'string' && !(_data instanceof Uint8Array)) {
455
516
  throw new ErrnoError(Errno.EINVAL, 'Iterables and streams not supported', handle.file.path, 'writeFile');
456
517
  }
457
518
  await handle.writeFile(_data, options);
458
519
  }
520
+ catch (e_3) {
521
+ env_3.error = e_3;
522
+ env_3.hasError = true;
523
+ }
459
524
  finally {
460
- await handle.close();
525
+ const result_3 = __disposeResources(env_3);
526
+ if (result_3)
527
+ await result_3;
461
528
  }
462
529
  }
463
530
  writeFile;
@@ -472,21 +539,28 @@ writeFile;
472
539
  * @option options flag Defaults to `'a'`.
473
540
  */
474
541
  export async function appendFile(path, data, _options) {
475
- const options = normalizeOptions(_options, 'utf8', 'a', 0o644);
476
- const flag = parseFlag(options.flag);
477
- if (!isAppendable(flag)) {
478
- throw new ErrnoError(Errno.EINVAL, 'Flag passed to appendFile must allow for appending.');
479
- }
480
- if (typeof data != 'string' && !options.encoding) {
481
- throw new ErrnoError(Errno.EINVAL, 'Encoding not specified');
482
- }
483
- const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
484
- const handle = typeof path == 'object' && 'fd' in path ? path : await open(path, options.flag, options.mode);
542
+ const env_4 = { stack: [], error: void 0, hasError: false };
485
543
  try {
544
+ const options = normalizeOptions(_options, 'utf8', 'a', 0o644);
545
+ const flag = parseFlag(options.flag);
546
+ if (!isAppendable(flag)) {
547
+ throw new ErrnoError(Errno.EINVAL, 'Flag passed to appendFile must allow for appending.');
548
+ }
549
+ if (typeof data != 'string' && !options.encoding) {
550
+ throw new ErrnoError(Errno.EINVAL, 'Encoding not specified');
551
+ }
552
+ const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
553
+ const handle = __addDisposableResource(env_4, typeof path == 'object' && 'fd' in path ? path : await open(path, options.flag, options.mode), true);
486
554
  await handle.appendFile(encodedData, options);
487
555
  }
556
+ catch (e_4) {
557
+ env_4.error = e_4;
558
+ env_4.hasError = true;
559
+ }
488
560
  finally {
489
- await handle.close();
561
+ const result_4 = __disposeResources(env_4);
562
+ if (result_4)
563
+ await result_4;
490
564
  }
491
565
  }
492
566
  appendFile;
@@ -508,14 +582,28 @@ export async function rmdir(path) {
508
582
  }
509
583
  rmdir;
510
584
  export async function mkdir(path, options) {
585
+ options = typeof options === 'object' ? options : { mode: options };
586
+ const mode = normalizeMode(options?.mode, 0o777);
511
587
  path = normalizePath(path);
512
588
  path = (await exists(path)) ? await realpath(path) : path;
513
589
  const { fs, path: resolved } = resolveMount(path);
590
+ const errorPaths = { [resolved]: path };
514
591
  try {
515
- await fs.mkdir(resolved, normalizeMode(typeof options == 'object' ? options?.mode : options, 0o777), cred);
592
+ if (!options?.recursive) {
593
+ await fs.mkdir(resolved, mode, cred);
594
+ }
595
+ const dirs = [];
596
+ for (let dir = resolved, origDir = path; !(await fs.exists(dir, cred)); dir = dirname(dir), origDir = dirname(origDir)) {
597
+ dirs.unshift(dir);
598
+ errorPaths[dir] = origDir;
599
+ }
600
+ for (const dir of dirs) {
601
+ await fs.mkdir(dir, mode, cred);
602
+ }
603
+ return dirs[0];
516
604
  }
517
605
  catch (e) {
518
- throw fixError(e, { [resolved]: path });
606
+ throw fixError(e, errorPaths);
519
607
  }
520
608
  }
521
609
  mkdir;
@@ -584,14 +672,21 @@ export async function symlink(target, path, type = 'file') {
584
672
  }
585
673
  symlink;
586
674
  export async function readlink(path, options) {
587
- const handle = await _open(normalizePath(path), 'r', 0o644, false);
675
+ const env_5 = { stack: [], error: void 0, hasError: false };
588
676
  try {
677
+ const handle = __addDisposableResource(env_5, await _open(normalizePath(path), 'r', 0o644, false), true);
589
678
  const value = await handle.readFile();
590
679
  const encoding = typeof options == 'object' ? options?.encoding : options;
591
680
  return encoding == 'buffer' ? value : value.toString(encoding);
592
681
  }
682
+ catch (e_5) {
683
+ env_5.error = e_5;
684
+ env_5.hasError = true;
685
+ }
593
686
  finally {
594
- await handle.close();
687
+ const result_5 = __disposeResources(env_5);
688
+ if (result_5)
689
+ await result_5;
595
690
  }
596
691
  }
597
692
  readlink;
@@ -603,12 +698,19 @@ readlink;
603
698
  * @param gid
604
699
  */
605
700
  export async function chown(path, uid, gid) {
606
- const handle = await open(path, 'r+');
701
+ const env_6 = { stack: [], error: void 0, hasError: false };
607
702
  try {
703
+ const handle = __addDisposableResource(env_6, await open(path, 'r+'), true);
608
704
  await handle.chown(uid, gid);
609
705
  }
706
+ catch (e_6) {
707
+ env_6.error = e_6;
708
+ env_6.hasError = true;
709
+ }
610
710
  finally {
611
- await handle.close();
711
+ const result_6 = __disposeResources(env_6);
712
+ if (result_6)
713
+ await result_6;
612
714
  }
613
715
  }
614
716
  chown;
@@ -619,12 +721,19 @@ chown;
619
721
  * @param gid
620
722
  */
621
723
  export async function lchown(path, uid, gid) {
622
- const handle = await _open(path, 'r+', 0o644, false);
724
+ const env_7 = { stack: [], error: void 0, hasError: false };
623
725
  try {
726
+ const handle = __addDisposableResource(env_7, await _open(path, 'r+', 0o644, false), true);
624
727
  await handle.chown(uid, gid);
625
728
  }
729
+ catch (e_7) {
730
+ env_7.error = e_7;
731
+ env_7.hasError = true;
732
+ }
626
733
  finally {
627
- await handle.close();
734
+ const result_7 = __disposeResources(env_7);
735
+ if (result_7)
736
+ await result_7;
628
737
  }
629
738
  }
630
739
  lchown;
@@ -634,12 +743,19 @@ lchown;
634
743
  * @param mode
635
744
  */
636
745
  export async function chmod(path, mode) {
637
- const handle = await open(path, 'r+');
746
+ const env_8 = { stack: [], error: void 0, hasError: false };
638
747
  try {
748
+ const handle = __addDisposableResource(env_8, await open(path, 'r+'), true);
639
749
  await handle.chmod(mode);
640
750
  }
751
+ catch (e_8) {
752
+ env_8.error = e_8;
753
+ env_8.hasError = true;
754
+ }
641
755
  finally {
642
- await handle.close();
756
+ const result_8 = __disposeResources(env_8);
757
+ if (result_8)
758
+ await result_8;
643
759
  }
644
760
  }
645
761
  chmod;
@@ -649,12 +765,19 @@ chmod;
649
765
  * @param mode
650
766
  */
651
767
  export async function lchmod(path, mode) {
652
- const handle = await _open(path, 'r+', 0o644, false);
768
+ const env_9 = { stack: [], error: void 0, hasError: false };
653
769
  try {
770
+ const handle = __addDisposableResource(env_9, await _open(path, 'r+', 0o644, false), true);
654
771
  await handle.chmod(mode);
655
772
  }
773
+ catch (e_9) {
774
+ env_9.error = e_9;
775
+ env_9.hasError = true;
776
+ }
656
777
  finally {
657
- await handle.close();
778
+ const result_9 = __disposeResources(env_9);
779
+ if (result_9)
780
+ await result_9;
658
781
  }
659
782
  }
660
783
  lchmod;
@@ -665,12 +788,19 @@ lchmod;
665
788
  * @param mtime
666
789
  */
667
790
  export async function utimes(path, atime, mtime) {
668
- const handle = await open(path, 'r+');
791
+ const env_10 = { stack: [], error: void 0, hasError: false };
669
792
  try {
793
+ const handle = __addDisposableResource(env_10, await open(path, 'r+'), true);
670
794
  await handle.utimes(atime, mtime);
671
795
  }
796
+ catch (e_10) {
797
+ env_10.error = e_10;
798
+ env_10.hasError = true;
799
+ }
672
800
  finally {
673
- await handle.close();
801
+ const result_10 = __disposeResources(env_10);
802
+ if (result_10)
803
+ await result_10;
674
804
  }
675
805
  }
676
806
  utimes;
@@ -681,12 +811,19 @@ utimes;
681
811
  * @param mtime
682
812
  */
683
813
  export async function lutimes(path, atime, mtime) {
684
- const handle = await _open(path, 'r+', 0o644, false);
814
+ const env_11 = { stack: [], error: void 0, hasError: false };
685
815
  try {
816
+ const handle = __addDisposableResource(env_11, await _open(path, 'r+', 0o644, false), true);
686
817
  await handle.utimes(new Date(atime), new Date(mtime));
687
818
  }
819
+ catch (e_11) {
820
+ env_11.error = e_11;
821
+ env_11.hasError = true;
822
+ }
688
823
  finally {
689
- await handle.close();
824
+ const result_11 = __disposeResources(env_11);
825
+ if (result_11)
826
+ await result_11;
690
827
  }
691
828
  }
692
829
  lutimes;
@@ -1,3 +1,48 @@
1
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2
+ if (value !== null && value !== void 0) {
3
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
4
+ var dispose;
5
+ if (async) {
6
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
7
+ dispose = value[Symbol.asyncDispose];
8
+ }
9
+ if (dispose === void 0) {
10
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
11
+ dispose = value[Symbol.dispose];
12
+ }
13
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
14
+ env.stack.push({ value: value, dispose: dispose, async: async });
15
+ }
16
+ else if (async) {
17
+ env.stack.push({ async: true });
18
+ }
19
+ return value;
20
+ };
21
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
22
+ return function (env) {
23
+ function fail(e) {
24
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
25
+ env.hasError = true;
26
+ }
27
+ function next() {
28
+ while (env.stack.length) {
29
+ var rec = env.stack.pop();
30
+ try {
31
+ var result = rec.dispose && rec.dispose.call(rec.value);
32
+ if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
33
+ }
34
+ catch (e) {
35
+ fail(e);
36
+ }
37
+ }
38
+ if (env.hasError) throw env.error;
39
+ }
40
+ return next();
41
+ };
42
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
43
+ var e = new Error(message);
44
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
45
+ });
1
46
  import { Buffer } from 'buffer';
2
47
  import { Errno, ErrnoError } from '../error.js';
3
48
  import { isAppendable, isExclusive, isReadable, isTruncating, isWriteable, parseFlag } from '../file.js';
@@ -78,12 +123,21 @@ lstatSync;
78
123
  * @param len
79
124
  */
80
125
  export function truncateSync(path, len = 0) {
81
- const fd = openSync(path, 'r+');
126
+ const env_1 = { stack: [], error: void 0, hasError: false };
82
127
  try {
83
- ftruncateSync(fd, len);
128
+ const file = __addDisposableResource(env_1, _openSync(path, 'r+'), false);
129
+ len || (len = 0);
130
+ if (len < 0) {
131
+ throw new ErrnoError(Errno.EINVAL);
132
+ }
133
+ file.truncateSync(len);
134
+ }
135
+ catch (e_1) {
136
+ env_1.error = e_1;
137
+ env_1.hasError = true;
84
138
  }
85
139
  finally {
86
- closeSync(fd);
140
+ __disposeResources(env_1);
87
141
  }
88
142
  }
89
143
  truncateSync;
@@ -161,9 +215,10 @@ export function lopenSync(path, flag, mode) {
161
215
  * Synchronously reads the entire contents of a file.
162
216
  */
163
217
  function _readFileSync(fname, flag, resolveSymlinks) {
164
- // Get file.
165
- const file = _openSync(fname, flag, 0o644, resolveSymlinks);
218
+ const env_2 = { stack: [], error: void 0, hasError: false };
166
219
  try {
220
+ // Get file.
221
+ const file = __addDisposableResource(env_2, _openSync(fname, flag, 0o644, resolveSymlinks), false);
167
222
  const stat = file.statSync();
168
223
  // Allocate buffer.
169
224
  const data = new Uint8Array(stat.size);
@@ -171,8 +226,12 @@ function _readFileSync(fname, flag, resolveSymlinks) {
171
226
  file.closeSync();
172
227
  return data;
173
228
  }
229
+ catch (e_2) {
230
+ env_2.error = e_2;
231
+ env_2.hasError = true;
232
+ }
174
233
  finally {
175
- file.closeSync();
234
+ __disposeResources(env_2);
176
235
  }
177
236
  }
178
237
  export function readFileSync(path, _options = {}) {
@@ -186,24 +245,29 @@ export function readFileSync(path, _options = {}) {
186
245
  }
187
246
  readFileSync;
188
247
  export function writeFileSync(path, data, _options = {}) {
189
- const options = normalizeOptions(_options, 'utf8', 'w+', 0o644);
190
- const flag = parseFlag(options.flag);
191
- if (!isWriteable(flag)) {
192
- throw new ErrnoError(Errno.EINVAL, 'Flag passed to writeFile must allow for writing.');
193
- }
194
- if (typeof data != 'string' && !options.encoding) {
195
- throw new ErrnoError(Errno.EINVAL, 'Encoding not specified');
196
- }
197
- const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
198
- if (!encodedData) {
199
- throw new ErrnoError(Errno.EINVAL, 'Data not specified');
200
- }
201
- const file = _openSync(typeof path == 'number' ? fd2file(path).path : path.toString(), flag, options.mode, true);
248
+ const env_3 = { stack: [], error: void 0, hasError: false };
202
249
  try {
250
+ const options = normalizeOptions(_options, 'utf8', 'w+', 0o644);
251
+ const flag = parseFlag(options.flag);
252
+ if (!isWriteable(flag)) {
253
+ throw new ErrnoError(Errno.EINVAL, 'Flag passed to writeFile must allow for writing.');
254
+ }
255
+ if (typeof data != 'string' && !options.encoding) {
256
+ throw new ErrnoError(Errno.EINVAL, 'Encoding not specified');
257
+ }
258
+ const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
259
+ if (!encodedData) {
260
+ throw new ErrnoError(Errno.EINVAL, 'Data not specified');
261
+ }
262
+ const file = __addDisposableResource(env_3, _openSync(typeof path == 'number' ? fd2file(path).path : path.toString(), flag, options.mode, true), false);
203
263
  file.writeSync(encodedData, 0, encodedData.byteLength, 0);
204
264
  }
265
+ catch (e_3) {
266
+ env_3.error = e_3;
267
+ env_3.hasError = true;
268
+ }
205
269
  finally {
206
- file.closeSync();
270
+ __disposeResources(env_3);
207
271
  }
208
272
  }
209
273
  writeFileSync;
@@ -219,21 +283,26 @@ writeFileSync;
219
283
  * @option options flag Defaults to `'a'`.
220
284
  */
221
285
  export function appendFileSync(filename, data, _options = {}) {
222
- const options = normalizeOptions(_options, 'utf8', 'a', 0o644);
223
- const flag = parseFlag(options.flag);
224
- if (!isAppendable(flag)) {
225
- throw new ErrnoError(Errno.EINVAL, 'Flag passed to appendFile must allow for appending.');
226
- }
227
- if (typeof data != 'string' && !options.encoding) {
228
- throw new ErrnoError(Errno.EINVAL, 'Encoding not specified');
229
- }
230
- const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
231
- const file = _openSync(typeof filename == 'number' ? fd2file(filename).path : filename.toString(), flag, options.mode, true);
286
+ const env_4 = { stack: [], error: void 0, hasError: false };
232
287
  try {
288
+ const options = normalizeOptions(_options, 'utf8', 'a', 0o644);
289
+ const flag = parseFlag(options.flag);
290
+ if (!isAppendable(flag)) {
291
+ throw new ErrnoError(Errno.EINVAL, 'Flag passed to appendFile must allow for appending.');
292
+ }
293
+ if (typeof data != 'string' && !options.encoding) {
294
+ throw new ErrnoError(Errno.EINVAL, 'Encoding not specified');
295
+ }
296
+ const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
297
+ const file = __addDisposableResource(env_4, _openSync(typeof filename == 'number' ? fd2file(filename).path : filename.toString(), flag, options.mode, true), false);
233
298
  file.writeSync(encodedData, 0, encodedData.byteLength);
234
299
  }
300
+ catch (e_4) {
301
+ env_4.error = e_4;
302
+ env_4.hasError = true;
303
+ }
235
304
  finally {
236
- file.closeSync();
305
+ __disposeResources(env_4);
237
306
  }
238
307
  }
239
308
  appendFileSync;
@@ -366,15 +435,28 @@ export function rmdirSync(path) {
366
435
  }
367
436
  rmdirSync;
368
437
  export function mkdirSync(path, options) {
369
- const mode = normalizeMode(typeof options == 'number' || typeof options == 'string' ? options : options?.mode, 0o777);
370
- const recursive = typeof options == 'object' && options?.recursive;
438
+ options = typeof options === 'object' ? options : { mode: options };
439
+ const mode = normalizeMode(options?.mode, 0o777);
371
440
  path = normalizePath(path);
372
- const { fs, path: resolved } = resolveMount(existsSync(path) ? realpathSync(path) : path);
441
+ path = existsSync(path) ? realpathSync(path) : path;
442
+ const { fs, path: resolved } = resolveMount(path);
443
+ const errorPaths = { [resolved]: path };
373
444
  try {
374
- return fs.mkdirSync(resolved, mode, cred);
445
+ if (!options?.recursive) {
446
+ return fs.mkdirSync(resolved, mode, cred);
447
+ }
448
+ const dirs = [];
449
+ for (let dir = resolved, original = path; !fs.existsSync(dir, cred); dir = dirname(dir), original = dirname(original)) {
450
+ dirs.unshift(dir);
451
+ errorPaths[dir] = original;
452
+ }
453
+ for (const dir of dirs) {
454
+ fs.mkdirSync(dir, mode, cred);
455
+ }
456
+ return dirs[0];
375
457
  }
376
458
  catch (e) {
377
- throw fixError(e, { [resolved]: path });
459
+ throw fixError(e, errorPaths);
378
460
  }
379
461
  }
380
462
  mkdirSync;
package/dist/file.d.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  import type { FileReadResult } from 'node:fs/promises';
4
4
  import type { FileSystem } from './filesystem.js';
5
5
  import { Stats, type FileType } from './stats.js';
6
+ import './symbol-dispose.js';
6
7
  declare global {
7
8
  interface ArrayBuffer {
8
9
  readonly resizable: boolean;
package/dist/file.js CHANGED
@@ -2,6 +2,7 @@ import { O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY,
2
2
  import { Errno, ErrnoError } from './error.js';
3
3
  import { size_max } from './inode.js';
4
4
  import { Stats } from './stats.js';
5
+ import './symbol-dispose.js';
5
6
  const validFlags = ['r', 'r+', 'rs', 'rs+', 'w', 'wx', 'w+', 'wx+', 'a', 'ax', 'a+', 'ax+'];
6
7
  export function parseFlag(flag) {
7
8
  if (typeof flag === 'number') {