@zenfs/core 1.8.8 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/dist/backends/backend.d.ts +1 -1
  2. package/dist/backends/backend.js +7 -4
  3. package/dist/backends/fetch.d.ts +23 -32
  4. package/dist/backends/fetch.js +94 -134
  5. package/dist/backends/index.d.ts +1 -4
  6. package/dist/backends/index.js +1 -4
  7. package/dist/backends/memory.d.ts +7 -5
  8. package/dist/backends/memory.js +6 -4
  9. package/dist/backends/overlay.d.ts +4 -5
  10. package/dist/backends/overlay.js +16 -20
  11. package/dist/backends/passthrough.d.ts +3 -3
  12. package/dist/backends/passthrough.js +4 -6
  13. package/dist/backends/port/fs.d.ts +4 -5
  14. package/dist/backends/port/fs.js +7 -12
  15. package/dist/backends/port/rpc.d.ts +1 -1
  16. package/dist/backends/port/rpc.js +15 -13
  17. package/dist/backends/store/fs.d.ts +51 -40
  18. package/dist/backends/store/fs.js +347 -241
  19. package/dist/backends/store/map.d.ts +41 -0
  20. package/dist/backends/store/map.js +45 -0
  21. package/dist/backends/store/simple.d.ts +10 -58
  22. package/dist/backends/store/simple.js +8 -115
  23. package/dist/backends/store/store.d.ts +111 -44
  24. package/dist/backends/store/store.js +230 -38
  25. package/dist/config.d.ts +7 -3
  26. package/dist/config.js +17 -14
  27. package/dist/context.d.ts +1 -1
  28. package/dist/context.js +1 -1
  29. package/dist/index.d.ts +1 -5
  30. package/dist/index.js +1 -5
  31. package/dist/{devices.d.ts → internal/devices.d.ts} +4 -4
  32. package/dist/{devices.js → internal/devices.js} +18 -14
  33. package/dist/{file.d.ts → internal/file.d.ts} +3 -2
  34. package/dist/{file.js → internal/file.js} +17 -12
  35. package/dist/{backends/store → internal}/file_index.d.ts +13 -3
  36. package/dist/{backends/store → internal}/file_index.js +28 -5
  37. package/dist/{filesystem.d.ts → internal/filesystem.d.ts} +99 -32
  38. package/dist/internal/filesystem.js +83 -0
  39. package/dist/internal/index.d.ts +9 -0
  40. package/dist/internal/index.js +9 -0
  41. package/dist/internal/index_fs.d.ts +56 -0
  42. package/dist/internal/index_fs.js +184 -0
  43. package/dist/{backends/store → internal}/inode.d.ts +6 -1
  44. package/dist/{backends/store → internal}/inode.js +14 -6
  45. package/dist/internal/log.d.ts +132 -0
  46. package/dist/internal/log.js +177 -0
  47. package/dist/mixins/async.d.ts +2 -2
  48. package/dist/mixins/async.js +19 -16
  49. package/dist/mixins/mutexed.d.ts +9 -3
  50. package/dist/mixins/mutexed.js +22 -3
  51. package/dist/mixins/readonly.d.ts +2 -2
  52. package/dist/mixins/readonly.js +4 -3
  53. package/dist/mixins/shared.d.ts +1 -1
  54. package/dist/mixins/sync.d.ts +2 -2
  55. package/dist/stats.d.ts +2 -3
  56. package/dist/stats.js +7 -5
  57. package/dist/utils.d.ts +2 -15
  58. package/dist/utils.js +10 -47
  59. package/dist/vfs/async.d.ts +2 -2
  60. package/dist/vfs/async.js +3 -3
  61. package/dist/vfs/dir.js +1 -1
  62. package/dist/vfs/promises.d.ts +6 -6
  63. package/dist/vfs/promises.js +54 -49
  64. package/dist/vfs/shared.d.ts +3 -3
  65. package/dist/vfs/shared.js +16 -10
  66. package/dist/vfs/streams.js +1 -1
  67. package/dist/vfs/sync.d.ts +1 -2
  68. package/dist/vfs/sync.js +14 -15
  69. package/dist/vfs/types.d.ts +1 -0
  70. package/dist/vfs/watchers.d.ts +5 -1
  71. package/dist/vfs/watchers.js +16 -19
  72. package/package.json +3 -3
  73. package/readme.md +12 -12
  74. package/scripts/test.js +15 -3
  75. package/tests/backend/fetch.test.ts +49 -0
  76. package/tests/backend/port.test.ts +130 -0
  77. package/tests/common/context.test.ts +9 -4
  78. package/tests/common.ts +21 -3
  79. package/tests/data/image.jpg +0 -0
  80. package/tests/data/utf8.txt +1 -0
  81. package/tests/fetch/config.js +40 -0
  82. package/tests/fetch/fetch.ts +20 -0
  83. package/tests/fetch/run.sh +3 -3
  84. package/tests/fetch/{server.ts → server.js} +15 -11
  85. package/tests/fs/directory.test.ts +1 -1
  86. package/tests/fs/errors.test.ts +1 -1
  87. package/tests/fs/links.test.ts +1 -1
  88. package/tests/fs/open.test.ts +1 -1
  89. package/tests/fs/permissions.test.ts +2 -3
  90. package/tests/fs/rename.test.ts +1 -1
  91. package/tests/fs/stat.test.ts +1 -1
  92. package/tests/fs/times.test.ts +1 -1
  93. package/tests/fs/watch.test.ts +21 -22
  94. package/tests/fs/writeFile.test.ts +8 -7
  95. package/tests/readme.md +3 -3
  96. package/tests/setup/_overlay.ts +7 -0
  97. package/tests/setup/context.ts +2 -2
  98. package/tests/setup/index.ts +3 -3
  99. package/tests/setup/memory.ts +2 -2
  100. package/tests/setup/port.ts +2 -2
  101. package/tests/setup.ts +25 -5
  102. package/tests/tsconfig.json +3 -2
  103. package/dist/backends/store/index_fs.d.ts +0 -34
  104. package/dist/backends/store/index_fs.js +0 -67
  105. package/dist/filesystem.js +0 -52
  106. package/tests/fetch/cow+fetch.ts +0 -13
  107. package/tests/port/channel.test.ts +0 -39
  108. package/tests/port/config.test.ts +0 -30
  109. package/tests/port/remote.test.ts +0 -32
  110. package/tests/port/timeout.test.ts +0 -48
  111. /package/dist/{credentials.d.ts → internal/credentials.d.ts} +0 -0
  112. /package/dist/{credentials.js → internal/credentials.js} +0 -0
  113. /package/dist/{error.d.ts → internal/error.d.ts} +0 -0
  114. /package/dist/{error.js → internal/error.js} +0 -0
  115. /package/tests/{port → backend}/config.worker.js +0 -0
  116. /package/tests/{port → backend}/remote.worker.js +0 -0
@@ -37,8 +37,9 @@ var __setFunctionName = (this && this.__setFunctionName) || function (f, name, p
37
37
  return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
38
38
  };
39
39
  import { deserialize, pick, randomInt, sizeof, struct, types as t } from 'utilium';
40
- import { Stats } from '../../stats.js';
41
- import { size_max } from '../../vfs/constants.js';
40
+ import { Stats } from '../stats.js';
41
+ import { size_max } from '../vfs/constants.js';
42
+ import { crit, debug } from './log.js';
42
43
  /**
43
44
  * Root inode
44
45
  * @hidden
@@ -132,17 +133,21 @@ let Inode = (() => {
132
133
  return;
133
134
  }
134
135
  if (data.byteLength < 58) {
135
- throw new RangeError('Can not create an inode from a buffer less than 58 bytes');
136
+ throw crit(new RangeError('Can not create an inode from a buffer less than 58 bytes'));
136
137
  }
137
138
  // Expand the buffer so it is the right size
138
- if (data.byteLength < sz_inode) {
139
+ if (data.byteLength < __inode_sz) {
139
140
  const buf = ArrayBuffer.isView(data) ? data.buffer : data;
140
- const newBuffer = new Uint8Array(sz_inode);
141
+ const newBuffer = new Uint8Array(__inode_sz);
141
142
  newBuffer.set(new Uint8Array(buf));
143
+ debug('Extending undersized buffer for inode');
142
144
  data = newBuffer;
143
145
  }
144
146
  deserialize(this, data);
145
147
  }
148
+ toString() {
149
+ return `<Inode ${this.ino}>`;
150
+ }
146
151
  toJSON() {
147
152
  return pick(this, _inode_fields);
148
153
  }
@@ -221,4 +226,7 @@ let Inode = (() => {
221
226
  return Inode = _classThis;
222
227
  })();
223
228
  export { Inode };
224
- const sz_inode = sizeof(Inode);
229
+ /**
230
+ * @internal @hidden
231
+ */
232
+ export const __inode_sz = sizeof(Inode);
@@ -0,0 +1,132 @@
1
+ import { List } from 'utilium';
2
+ import { ErrnoError } from './error.js';
3
+ import type { FileSystem } from './filesystem.js';
4
+ export declare const enum Level {
5
+ /** Emergency */
6
+ EMERG = 0,
7
+ /** Alert */
8
+ ALERT = 1,
9
+ /** Critical */
10
+ CRIT = 2,
11
+ /** Error */
12
+ ERR = 3,
13
+ /** Warning */
14
+ WARN = 4,
15
+ /** Notice */
16
+ NOTICE = 5,
17
+ /** Informational */
18
+ INFO = 6,
19
+ /** Debug */
20
+ DEBUG = 7
21
+ }
22
+ /** An object mapping log levels to a textual representation of them */
23
+ export declare const levels: {
24
+ readonly 0: "emergency";
25
+ readonly 1: "alert";
26
+ readonly 2: "critical";
27
+ readonly 3: "error";
28
+ readonly 4: "warning";
29
+ readonly 5: "notice";
30
+ readonly 6: "info";
31
+ readonly 7: "debug";
32
+ };
33
+ export declare function levelOf(value: (typeof levels)[Level]): Level;
34
+ /** A log entry */
35
+ export interface Entry {
36
+ level: Level;
37
+ timestamp: Date;
38
+ elapsedMs: number;
39
+ message: string;
40
+ }
41
+ /** The list of log entries */
42
+ export declare const entries: List<Entry>;
43
+ export declare function log(level: Level, message: string): void;
44
+ interface LogShortcutOptions {
45
+ fs?: FileSystem;
46
+ }
47
+ /** Shortcut for logging emergencies */
48
+ export declare const emerg: <T extends {
49
+ toString(): string;
50
+ } | ErrnoError>(message: T, options?: LogShortcutOptions) => T;
51
+ /** Shortcut for logging alerts */
52
+ export declare const alert: <T extends {
53
+ toString(): string;
54
+ } | ErrnoError>(message: T, options?: LogShortcutOptions) => T;
55
+ /** Shortcut for logging critical errors */
56
+ export declare const crit: <T extends {
57
+ toString(): string;
58
+ } | ErrnoError>(message: T, options?: LogShortcutOptions) => T;
59
+ /** Shortcut for logging non-critical errors */
60
+ export declare const err: <T extends {
61
+ toString(): string;
62
+ } | ErrnoError>(message: T, options?: LogShortcutOptions) => T;
63
+ /** Shortcut for logging warnings */
64
+ export declare const warn: <T extends {
65
+ toString(): string;
66
+ } | ErrnoError>(message: T, options?: LogShortcutOptions) => T;
67
+ /** Shortcut for logging notices */
68
+ export declare const notice: <T extends {
69
+ toString(): string;
70
+ } | ErrnoError>(message: T, options?: LogShortcutOptions) => T;
71
+ /** Shortcut for logging informational messages */
72
+ export declare const info: <T extends {
73
+ toString(): string;
74
+ } | ErrnoError>(message: T, options?: LogShortcutOptions) => T;
75
+ /** Shortcut for logging debug messages */
76
+ export declare const debug: <T extends {
77
+ toString(): string;
78
+ } | ErrnoError>(message: T, options?: LogShortcutOptions) => T;
79
+ /**
80
+ * Shortcut for logging usage of deprecated functions at runtime
81
+ * @param symbol The thing that is deprecated
82
+ * @internal @hidden
83
+ */
84
+ export declare function log_deprecated(symbol: string): void;
85
+ /**
86
+ * Various format functions included to make using the logger easier.
87
+ * These are not the only formats you can use.
88
+ */
89
+ export declare const formats: {
90
+ /** Format with a timestamp and the level, colorized with ANSI escape codes */
91
+ readonly ansi_level: (this: void, entry: Entry) => string;
92
+ /**
93
+ * Format with a timestamp and colorize the message with ANSI escape codes.
94
+ * For EMERG and ALERT, the levels are included
95
+ */
96
+ readonly ansi_message: (this: void, entry: Entry) => string;
97
+ /** Uncolored format with a timestamp */
98
+ readonly default: (this: void, entry: Entry) => string;
99
+ };
100
+ export declare function format(entry: Entry): string;
101
+ /** Whether log entries are being recorded */
102
+ export declare let isEnabled: boolean;
103
+ export interface LogConfiguration {
104
+ /**
105
+ * If false, log messages will not be recorded or outputted
106
+ * @default false
107
+ */
108
+ enabled?: boolean;
109
+ /**
110
+ * The minimum level needed to output a message
111
+ * @default Level.ALERT
112
+ */
113
+ level?: Level | (typeof levels)[Level];
114
+ /**
115
+ * Formats a log entry into a string
116
+ * @default `[${ms / 1000}] ${message}`
117
+ */
118
+ format?(this: void, entry: Entry): string;
119
+ /**
120
+ * Outputs a log message
121
+ * @default console.error()
122
+ */
123
+ output?(this: void, message: string): unknown;
124
+ /**
125
+ * If set, output() all current entries after `configure` is done
126
+ * @default false
127
+ */
128
+ dumpBacklog?: boolean;
129
+ }
130
+ /** Configure logging behavior */
131
+ export declare function configure(options: LogConfiguration): void;
132
+ export {};
@@ -0,0 +1,177 @@
1
+ /* Logging utilities. The things in this file are named to work nicely when you import as a namespace. */
2
+ import { List } from 'utilium';
3
+ import { join } from '../vfs/path.js';
4
+ import { ErrnoError } from './error.js';
5
+ export var Level;
6
+ (function (Level) {
7
+ /** Emergency */
8
+ Level[Level["EMERG"] = 0] = "EMERG";
9
+ /** Alert */
10
+ Level[Level["ALERT"] = 1] = "ALERT";
11
+ /** Critical */
12
+ Level[Level["CRIT"] = 2] = "CRIT";
13
+ /** Error */
14
+ Level[Level["ERR"] = 3] = "ERR";
15
+ /** Warning */
16
+ Level[Level["WARN"] = 4] = "WARN";
17
+ /** Notice */
18
+ Level[Level["NOTICE"] = 5] = "NOTICE";
19
+ /** Informational */
20
+ Level[Level["INFO"] = 6] = "INFO";
21
+ /** Debug */
22
+ Level[Level["DEBUG"] = 7] = "DEBUG";
23
+ })(Level || (Level = {}));
24
+ /** An object mapping log levels to a textual representation of them */
25
+ export const levels = {
26
+ [Level.EMERG]: 'emergency',
27
+ [Level.ALERT]: 'alert',
28
+ [Level.CRIT]: 'critical',
29
+ [Level.ERR]: 'error',
30
+ [Level.WARN]: 'warning',
31
+ [Level.NOTICE]: 'notice',
32
+ [Level.INFO]: 'info',
33
+ [Level.DEBUG]: 'debug',
34
+ };
35
+ export function levelOf(value) {
36
+ return Object.values(levels).indexOf(value);
37
+ }
38
+ /** The list of log entries */
39
+ export const entries = new List();
40
+ export function log(level, message) {
41
+ if (!isEnabled)
42
+ return;
43
+ const entry = {
44
+ level,
45
+ message,
46
+ timestamp: new Date(),
47
+ elapsedMs: performance.now(),
48
+ };
49
+ entries.add(entry);
50
+ output(entry);
51
+ }
52
+ function _messageString(msg, options) {
53
+ var _a, _b;
54
+ if (!(msg instanceof ErrnoError))
55
+ return msg.toString();
56
+ const beforePath = msg.code + ': ' + msg.message;
57
+ if (!msg.path)
58
+ return beforePath;
59
+ const mountPoint = typeof options.fs == 'string' ? options.fs : ((_b = (_a = options.fs) === null || _a === void 0 ? void 0 : _a._mountPoint) !== null && _b !== void 0 ? _b : '<unknown>');
60
+ return beforePath + ': ' + join(mountPoint, msg.path);
61
+ }
62
+ function _shortcut(level) {
63
+ return function (message, options = {}) {
64
+ log(level, _messageString(message, options));
65
+ return message;
66
+ };
67
+ }
68
+ // Shortcuts
69
+ /** Shortcut for logging emergencies */
70
+ export const emerg = _shortcut(Level.EMERG);
71
+ /** Shortcut for logging alerts */
72
+ export const alert = _shortcut(Level.ALERT);
73
+ /** Shortcut for logging critical errors */
74
+ export const crit = _shortcut(Level.CRIT);
75
+ /** Shortcut for logging non-critical errors */
76
+ export const err = _shortcut(Level.ERR);
77
+ /** Shortcut for logging warnings */
78
+ export const warn = _shortcut(Level.WARN);
79
+ /** Shortcut for logging notices */
80
+ export const notice = _shortcut(Level.NOTICE);
81
+ /** Shortcut for logging informational messages */
82
+ export const info = _shortcut(Level.INFO);
83
+ /** Shortcut for logging debug messages */
84
+ export const debug = _shortcut(Level.DEBUG);
85
+ /**
86
+ * Shortcut for logging usage of deprecated functions at runtime
87
+ * @param symbol The thing that is deprecated
88
+ * @internal @hidden
89
+ */
90
+ export function log_deprecated(symbol) {
91
+ log(Level.WARN, symbol + ' is deprecated and should not be used.');
92
+ }
93
+ // Formatting and output
94
+ /**
95
+ * @internal @hidden
96
+ */
97
+ function ansi(text, format) {
98
+ return `\x1b[${format}m${text}\x1b[0m`;
99
+ }
100
+ function _prettyMs(entry, useANSI = false) {
101
+ const text = '[' + (entry.elapsedMs / 1000).toFixed(3).padStart(10) + '] ';
102
+ return useANSI ? ansi(text, '2;37') : text;
103
+ }
104
+ const _ansiLevelColor = {
105
+ [Level.EMERG]: '1;4;37;41',
106
+ [Level.ALERT]: '1;37;41',
107
+ [Level.CRIT]: '1;35',
108
+ [Level.ERR]: '1;31',
109
+ [Level.WARN]: '1;33',
110
+ [Level.NOTICE]: '1;36',
111
+ [Level.INFO]: '1;37',
112
+ [Level.DEBUG]: '0;2;37',
113
+ };
114
+ const _ansiMessageColor = {
115
+ [Level.EMERG]: '1;31',
116
+ [Level.ALERT]: '1;31',
117
+ [Level.CRIT]: '1;31',
118
+ [Level.ERR]: '31',
119
+ [Level.WARN]: '33',
120
+ [Level.NOTICE]: '1;37',
121
+ [Level.INFO]: '37',
122
+ [Level.DEBUG]: '2;37',
123
+ };
124
+ /**
125
+ * Various format functions included to make using the logger easier.
126
+ * These are not the only formats you can use.
127
+ */
128
+ export const formats = {
129
+ /** Format with a timestamp and the level, colorized with ANSI escape codes */
130
+ ansi_level(entry) {
131
+ const levelText = ansi(levels[entry.level].toUpperCase(), _ansiLevelColor[entry.level]);
132
+ return [_prettyMs(entry, true), levelText, entry.message].join(' ');
133
+ },
134
+ /**
135
+ * Format with a timestamp and colorize the message with ANSI escape codes.
136
+ * For EMERG and ALERT, the levels are included
137
+ */
138
+ ansi_message(entry) {
139
+ let msg = _prettyMs(entry, true);
140
+ const isImportant = entry.level < Level.CRIT;
141
+ if (isImportant)
142
+ msg += ansi(levels[entry.level].toUpperCase(), _ansiLevelColor[entry.level]) + ': ';
143
+ msg += ansi(entry.message, _ansiMessageColor[entry.level]);
144
+ return msg;
145
+ },
146
+ /** Uncolored format with a timestamp */
147
+ default(entry) {
148
+ return `[${_prettyMs(entry)}] ${entry.message}`;
149
+ },
150
+ };
151
+ let _format = formats.default;
152
+ export function format(entry) {
153
+ return _format(entry);
154
+ }
155
+ let _output = console.error;
156
+ function output(entry) {
157
+ if (entry.level > minLevel)
158
+ return;
159
+ _output(format(entry));
160
+ }
161
+ let minLevel = Level.ALERT;
162
+ // Configuration
163
+ /** Whether log entries are being recorded */
164
+ export let isEnabled = true;
165
+ /** Configure logging behavior */
166
+ export function configure(options) {
167
+ var _a, _b, _c, _d;
168
+ _format = (_a = options.format) !== null && _a !== void 0 ? _a : _format;
169
+ _output = (_b = options.output) !== null && _b !== void 0 ? _b : _output;
170
+ minLevel = typeof options.level == 'string' ? levelOf(options.level) : ((_c = options.level) !== null && _c !== void 0 ? _c : minLevel);
171
+ isEnabled = (_d = options.enabled) !== null && _d !== void 0 ? _d : isEnabled;
172
+ if (!options.dumpBacklog)
173
+ return;
174
+ for (const entry of entries) {
175
+ output(entry);
176
+ }
177
+ }
@@ -1,4 +1,4 @@
1
- import type { FileSystem } from '../filesystem.js';
1
+ import type { FileSystem } from '../internal/filesystem.js';
2
2
  import type { _SyncFSKeys, AsyncFSMethods, Mixin } from './shared.js';
3
3
  /** @internal */
4
4
  export type AsyncOperation = {
@@ -25,4 +25,4 @@ export interface AsyncMixin extends Pick<FileSystem, Exclude<_SyncFSKeys, 'exist
25
25
  * During loading, the contents of the async file system are preloaded into the synchronous store.
26
26
  *
27
27
  */
28
- export declare function Async<const T extends typeof FileSystem>(FS: T): Mixin<T, AsyncMixin>;
28
+ export declare function Async<const T extends abstract new (...args: any[]) => FileSystem>(FS: T): Mixin<T, AsyncMixin>;
@@ -51,8 +51,9 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
51
51
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
52
52
  });
53
53
  import { StoreFS } from '../backends/store/fs.js';
54
- import { Errno, ErrnoError } from '../error.js';
55
- import { LazyFile, parseFlag } from '../file.js';
54
+ import { Errno, ErrnoError } from '../internal/error.js';
55
+ import { LazyFile, parseFlag } from '../internal/file.js';
56
+ import { crit, err, notice } from '../internal/log.js';
56
57
  import { join } from '../vfs/path.js';
57
58
  /**
58
59
  * Async() implements synchronous methods on an asynchronous file system
@@ -73,29 +74,25 @@ export function Async(FS) {
73
74
  return this.done();
74
75
  }
75
76
  _async(promise) {
76
- if (!this._promise) {
77
- this._promise = promise;
78
- return;
79
- }
80
77
  this._promise = this._promise.then(() => promise);
81
78
  }
82
79
  constructor(...args) {
83
80
  super(...args);
81
+ this._promise = Promise.resolve();
84
82
  this._isInitialized = false;
85
83
  this._patchAsync();
86
84
  }
87
85
  async ready() {
88
86
  await super.ready();
89
87
  await this.queueDone();
90
- if (this._isInitialized || this._disableSync) {
88
+ if (this._isInitialized || this.attributes.has('no_async'))
91
89
  return;
92
- }
93
90
  this.checkSync();
94
91
  await this._sync.ready();
95
92
  // optimization: for 2 storeFS', we copy at a lower abstraction level.
96
93
  if (this._sync instanceof StoreFS && this instanceof StoreFS) {
97
- const sync = this._sync['store'].transaction();
98
- const async = this['store'].transaction();
94
+ const sync = this._sync.transaction();
95
+ const async = this.transaction();
99
96
  const promises = [];
100
97
  for (const key of await async.keys()) {
101
98
  promises.push(async.get(key).then(data => sync.setSync(key, data)));
@@ -110,15 +107,17 @@ export function Async(FS) {
110
107
  }
111
108
  catch (e) {
112
109
  this._isInitialized = false;
113
- throw e;
110
+ throw crit(e, { fs: this });
114
111
  }
115
112
  }
116
113
  checkSync(path, syscall) {
117
- if (this._disableSync) {
118
- throw new ErrnoError(Errno.ENOTSUP, 'Sync caching has been disabled for this async file system', path, syscall);
114
+ if (this.attributes.has('no_async')) {
115
+ throw crit(new ErrnoError(Errno.ENOTSUP, 'Sync preloading has been disabled for this async file system', path, syscall), {
116
+ fs: this,
117
+ });
119
118
  }
120
119
  if (!this._sync) {
121
- throw new ErrnoError(Errno.ENOTSUP, 'No sync cache is attached to this async file system', path, syscall);
120
+ throw crit(new ErrnoError(Errno.ENOTSUP, 'No sync cache is attached to this async file system', path, syscall), { fs: this });
122
121
  }
123
122
  }
124
123
  renameSync(oldPath, newPath) {
@@ -244,14 +243,18 @@ export function Async(FS) {
244
243
  this[key] = async (...args) => {
245
244
  var _a, _b;
246
245
  const result = await originalMethod.apply(this, args);
247
- if (new Error().stack.includes(`at <computed> [as ${key}]`) || !this._isInitialized)
246
+ if (new Error().stack.includes(`at <computed> [as ${key}]`))
248
247
  return result;
248
+ if (!this._isInitialized) {
249
+ notice('Skipping sync cache update for Async#' + key);
250
+ return result;
251
+ }
249
252
  try {
250
253
  // @ts-expect-error 2556
251
254
  (_b = (_a = this._sync) === null || _a === void 0 ? void 0 : _a[`${key}Sync`]) === null || _b === void 0 ? void 0 : _b.call(_a, ...args);
252
255
  }
253
256
  catch (e) {
254
- throw new ErrnoError(e.errno, e.message + ' (Out of sync!)', e.path, key);
257
+ throw err(new ErrnoError(e.errno, e.message + ' (Out of sync!)', e.path, key), { fs: this });
255
258
  }
256
259
  return result;
257
260
  };
@@ -1,9 +1,9 @@
1
- import type { File } from '../file.js';
2
- import type { CreationOptions, FileSystem, FileSystemMetadata } from '../filesystem.js';
1
+ import type { File } from '../internal/file.js';
2
+ import type { CreationOptions, FileSystem, FileSystemMetadata, UsageInfo } from '../internal/filesystem.js';
3
+ import type { InodeLike } from '../internal/inode.js';
3
4
  import type { Stats } from '../stats.js';
4
5
  import type { Concrete } from '../utils.js';
5
6
  import '../polyfills.js';
6
- import type { InodeLike } from '../backends/index.js';
7
7
  export declare class MutexLock {
8
8
  protected readonly previous?: MutexLock | undefined;
9
9
  protected current: PromiseWithResolvers<void>;
@@ -22,7 +22,13 @@ export declare class _MutexedFS<T extends FileSystem> implements FileSystem {
22
22
  * @internal
23
23
  */
24
24
  _fs: T;
25
+ get id(): number;
26
+ get name(): string;
27
+ get label(): string | undefined;
28
+ set label(value: string | undefined);
29
+ get attributes(): import("utilium").ConstMap<import("../internal/filesystem.js").FileSystemAttributes, keyof import("../internal/filesystem.js").FileSystemAttributes, void>;
25
30
  ready(): Promise<void>;
31
+ usage(): UsageInfo;
26
32
  metadata(): FileSystemMetadata;
27
33
  /**
28
34
  * The current locks
@@ -50,7 +50,8 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
50
50
  var e = new Error(message);
51
51
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
52
52
  });
53
- import { ErrnoError } from '../error.js';
53
+ import { ErrnoError } from '../internal/error.js';
54
+ import { err } from '../internal/log.js';
54
55
  import '../polyfills.js';
55
56
  export class MutexLock {
56
57
  get isLocked() {
@@ -78,9 +79,27 @@ export class MutexLock {
78
79
  * @hidden
79
80
  */
80
81
  export class _MutexedFS {
82
+ get id() {
83
+ return this._fs.id;
84
+ }
85
+ get name() {
86
+ return this._fs.name;
87
+ }
88
+ get label() {
89
+ return this._fs.label;
90
+ }
91
+ set label(value) {
92
+ this._fs.label = value;
93
+ }
94
+ get attributes() {
95
+ return this._fs.attributes;
96
+ }
81
97
  async ready() {
82
98
  return await this._fs.ready();
83
99
  }
100
+ usage() {
101
+ return this._fs.usage();
102
+ }
84
103
  metadata() {
85
104
  return this._fs.metadata();
86
105
  }
@@ -105,7 +124,7 @@ export class _MutexedFS {
105
124
  if (lock.isLocked) {
106
125
  const error = ErrnoError.With('EDEADLK', path, syscall);
107
126
  error.stack += stack === null || stack === void 0 ? void 0 : stack.slice('Error'.length);
108
- throw error;
127
+ throw err(error, { fs: this });
109
128
  }
110
129
  }, 5000);
111
130
  await (previous === null || previous === void 0 ? void 0 : previous.done());
@@ -119,7 +138,7 @@ export class _MutexedFS {
119
138
  lockSync(path, syscall) {
120
139
  var _a;
121
140
  if ((_a = this.currentLock) === null || _a === void 0 ? void 0 : _a.isLocked) {
122
- throw ErrnoError.With('EBUSY', path, syscall);
141
+ throw err(ErrnoError.With('EBUSY', path, syscall), { fs: this });
123
142
  }
124
143
  return this.addLock();
125
144
  }
@@ -1,4 +1,4 @@
1
- import type { FileSystem, FileSystemMetadata } from '../filesystem.js';
1
+ import type { FileSystem, FileSystemMetadata } from '../internal/filesystem.js';
2
2
  import type { StatsLike } from '../stats.js';
3
3
  import type { Mixin } from './shared.js';
4
4
  /**
@@ -26,4 +26,4 @@ export interface ReadonlyMixin {
26
26
  /**
27
27
  * Implements the non-readonly methods to throw `EROFS`
28
28
  */
29
- export declare function Readonly<T extends typeof FileSystem>(FS: T): Mixin<T, ReadonlyMixin>;
29
+ export declare function Readonly<T extends abstract new (...args: any[]) => FileSystem>(FS: T): Mixin<T, ReadonlyMixin>;
@@ -1,12 +1,13 @@
1
- import { Errno, ErrnoError } from '../error.js';
1
+ import { Errno, ErrnoError } from '../internal/error.js';
2
2
  /**
3
3
  * Implements the non-readonly methods to throw `EROFS`
4
4
  */
5
5
  /* eslint-disable @typescript-eslint/require-await */
6
6
  export function Readonly(FS) {
7
7
  class ReadonlyFS extends FS {
8
- metadata() {
9
- return { ...super.metadata(), readonly: true };
8
+ constructor(...args) {
9
+ super(...args);
10
+ this.attributes.set('no_write');
10
11
  }
11
12
  async rename() {
12
13
  throw new ErrnoError(Errno.EROFS);
@@ -1,5 +1,5 @@
1
1
  import type { ExtractProperties } from 'utilium';
2
- import type { FileSystem } from '../filesystem.js';
2
+ import type { FileSystem } from '../internal/filesystem.js';
3
3
  /**
4
4
  * `TBase` with `TMixin` mixed-in.
5
5
  * @internal
@@ -1,6 +1,6 @@
1
- import type { FileSystem } from '../filesystem.js';
1
+ import type { FileSystem } from '../internal/filesystem.js';
2
2
  import type { AsyncFSMethods, Mixin } from './shared.js';
3
3
  /**
4
4
  * Implements the asynchronous API in terms of the synchronous API.
5
5
  */
6
- export declare function Sync<T extends typeof FileSystem>(FS: T): Mixin<T, AsyncFSMethods>;
6
+ export declare function Sync<T extends abstract new (...args: any[]) => FileSystem>(FS: T): Mixin<T, AsyncFSMethods>;
package/dist/stats.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type * as Node from 'node:fs';
2
2
  import type { V_Context } from './context.js';
3
+ import type { InodeFields, InodeLike } from './internal/inode.js';
3
4
  import * as c from './vfs/constants.js';
4
- import type { InodeFields, InodeLike } from './backends/store/inode.js';
5
5
  /**
6
6
  * Indicates the type of a file. Applied to 'mode'.
7
7
  */
@@ -57,6 +57,7 @@ export declare abstract class StatsCommon<T extends number | bigint> implements
57
57
  protected abstract _isBigint: T extends bigint ? true : false;
58
58
  protected _convert(arg: number | bigint | string | boolean): T;
59
59
  get blocks(): T;
60
+ set blocks(value: T);
60
61
  /**
61
62
  * Unix-style file mode (e.g. 0o644) that includes the type of the item.
62
63
  * Type of the item can be FILE, DIRECTORY, SYMLINK, or SOCKET
@@ -150,14 +151,12 @@ export declare abstract class StatsCommon<T extends number | bigint> implements
150
151
  * Change the mode of the file.
151
152
  * We use this helper function to prevent messing up the type of the file.
152
153
  * @internal @deprecated
153
- * @todo [BREAKING] Remove
154
154
  */
155
155
  chmod(mode: number): void;
156
156
  /**
157
157
  * Change the owner user/group of the file.
158
158
  * This function makes sure it is a valid UID/GID (that is, a 32 unsigned int)
159
159
  * @internal @deprecated
160
- * @todo [BREAKING] Remove
161
160
  */
162
161
  chown(uid: number, gid: number): void;
163
162
  get atimeNs(): bigint;
package/dist/stats.js CHANGED
@@ -1,7 +1,8 @@
1
- import { credentials } from './credentials.js';
2
- import * as c from './vfs/constants.js';
3
1
  import { pick } from 'utilium';
4
- import { _inode_fields } from './backends/store/inode.js';
2
+ import { credentials } from './internal/credentials.js';
3
+ import { _inode_fields } from './internal/inode.js';
4
+ import { log_deprecated } from './internal/log.js';
5
+ import * as c from './vfs/constants.js';
5
6
  const n1000 = BigInt(1000);
6
7
  /**
7
8
  * Provides information about a particular entry in the file system.
@@ -14,6 +15,7 @@ export class StatsCommon {
14
15
  get blocks() {
15
16
  return this._convert(Math.ceil(Number(this.size) / 512));
16
17
  }
18
+ set blocks(value) { }
17
19
  get atime() {
18
20
  return new Date(Number(this.atimeMs));
19
21
  }
@@ -153,18 +155,18 @@ export class StatsCommon {
153
155
  * Change the mode of the file.
154
156
  * We use this helper function to prevent messing up the type of the file.
155
157
  * @internal @deprecated
156
- * @todo [BREAKING] Remove
157
158
  */
158
159
  chmod(mode) {
160
+ log_deprecated('StatsCommon#chmod');
159
161
  this.mode = this._convert((this.mode & c.S_IFMT) | mode);
160
162
  }
161
163
  /**
162
164
  * Change the owner user/group of the file.
163
165
  * This function makes sure it is a valid UID/GID (that is, a 32 unsigned int)
164
166
  * @internal @deprecated
165
- * @todo [BREAKING] Remove
166
167
  */
167
168
  chown(uid, gid) {
169
+ log_deprecated('StatsCommon#chown');
168
170
  uid = Number(uid);
169
171
  gid = Number(gid);
170
172
  if (!isNaN(uid) && 0 <= uid && uid < 2 ** 32) {