@zenfs/core 1.8.8 → 1.9.1

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 +188 -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
@@ -1,4 +1,6 @@
1
- import { ErrnoError } from '../../error.js';
1
+ import { Resource } from 'utilium/cache.js';
2
+ import { ErrnoError } from '../../internal/error.js';
3
+ import { err, warn } from '../../internal/log.js';
2
4
  import '../../polyfills.js';
3
5
  /**
4
6
  * A transaction for a store.
@@ -6,20 +8,6 @@ import '../../polyfills.js';
6
8
  export class Transaction {
7
9
  constructor(store) {
8
10
  this.store = store;
9
- /**
10
- * Whether the transaction was committed or aborted
11
- */
12
- this.done = false;
13
- }
14
- async [Symbol.asyncDispose]() {
15
- if (this.done)
16
- return;
17
- await this.abort();
18
- }
19
- [Symbol.dispose]() {
20
- if (this.done)
21
- return;
22
- this.abortSync();
23
11
  }
24
12
  }
25
13
  /**
@@ -27,45 +15,249 @@ export class Transaction {
27
15
  */
28
16
  export class SyncTransaction extends Transaction {
29
17
  /* eslint-disable @typescript-eslint/require-await */
30
- async keys() {
31
- return this.keysSync();
32
- }
33
- async get(id) {
34
- return this.getSync(id);
18
+ async get(id, offset, end) {
19
+ return this.getSync(id, offset, end);
35
20
  }
36
- async set(id, data, isMetadata) {
37
- return this.setSync(id, data, isMetadata);
21
+ async set(id, data, offset) {
22
+ return this.setSync(id, data, offset);
38
23
  }
39
24
  async remove(id) {
40
25
  return this.removeSync(id);
41
26
  }
42
- async commit() {
43
- return this.commitSync();
27
+ }
28
+ /**
29
+ * Transaction that implements synchronous operations with a cache
30
+ * @implementors You *must* update the cache and wait for `store.asyncDone` in your asynchronous methods.
31
+ * @todo Make sure we handle abortions correctly, especially since the cache is shared between transactions.
32
+ */
33
+ export class AsyncTransaction extends Transaction {
34
+ constructor() {
35
+ super(...arguments);
36
+ this.asyncDone = Promise.resolve();
44
37
  }
45
- async abort() {
46
- return this.abortSync();
38
+ /**
39
+ * Run a asynchronous operation from a sync context. Not magic and subject to (race) conditions.
40
+ * @internal
41
+ */
42
+ async(promise) {
43
+ this.asyncDone = this.asyncDone.then(() => promise);
44
+ }
45
+ /**
46
+ * Gets a cache resource
47
+ * If `info` is set and the resource doesn't exist, it will be created
48
+ * @internal
49
+ */
50
+ _cached(id, info) {
51
+ var _a;
52
+ var _b;
53
+ (_a = (_b = this.store).cache) !== null && _a !== void 0 ? _a : (_b.cache = new Map());
54
+ const resource = this.store.cache.get(id);
55
+ if (!resource)
56
+ return !info ? undefined : new Resource(id, info.size, {}, this.store.cache);
57
+ if (info)
58
+ resource.size = info.size;
59
+ return resource;
60
+ }
61
+ getSync(id, offset, end) {
62
+ var _a;
63
+ const resource = this._cached(id);
64
+ if (!resource)
65
+ return;
66
+ end !== null && end !== void 0 ? end : (end = resource.size);
67
+ const missing = resource.missing(offset, end);
68
+ for (const { start, end } of missing) {
69
+ this.async(this.get(id, start, end));
70
+ }
71
+ if (missing.length)
72
+ throw err(ErrnoError.With('EAGAIN', (_a = this.store._fs) === null || _a === void 0 ? void 0 : _a._path(id)));
73
+ const region = resource.regionAt(offset);
74
+ if (!region) {
75
+ warn('Missing cache region for ' + id);
76
+ return;
77
+ }
78
+ return region.data.subarray(offset - region.offset, end - region.offset);
79
+ }
80
+ setSync(id, data, offset) {
81
+ this.async(this.set(id, data, offset));
82
+ }
83
+ removeSync(id) {
84
+ var _a;
85
+ this.async(this.remove(id));
86
+ (_a = this.store.cache) === null || _a === void 0 ? void 0 : _a.delete(id);
47
87
  }
48
88
  }
49
89
  /**
50
- * Transaction that only supports asynchronous operations
90
+ * Wraps a transaction with the ability to roll-back changes, among other things.
91
+ * This is used by `StoreFS`
92
+ * @internal @hidden
51
93
  */
52
- export class AsyncTransaction extends Transaction {
53
- keysSync() {
54
- throw ErrnoError.With('ENOSYS', undefined, 'AsyncTransaction.keysSync');
94
+ export class WrappedTransaction {
95
+ flag(flag) {
96
+ var _a, _b;
97
+ return (_b = (_a = this.raw.store.flags) === null || _a === void 0 ? void 0 : _a.includes(flag)) !== null && _b !== void 0 ? _b : false;
98
+ }
99
+ constructor(raw, fs) {
100
+ this.raw = raw;
101
+ this.fs = fs;
102
+ /**
103
+ * Whether the transaction was committed or aborted
104
+ */
105
+ this.done = false;
106
+ /**
107
+ * Stores data in the keys we modify prior to modifying them.
108
+ * Allows us to roll back commits.
109
+ */
110
+ this.originalData = new Map();
111
+ /**TransactionEntry
112
+ * List of keys modified in this transaction, if any.
113
+ */
114
+ this.modifiedKeys = new Set();
115
+ }
116
+ keys() {
117
+ return this.raw.keys();
55
118
  }
56
- getSync() {
57
- throw ErrnoError.With('ENOSYS', undefined, 'AsyncTransaction.getSync');
119
+ async get(id, offset = 0, end) {
120
+ const data = await this.raw.get(id, offset, end);
121
+ this.stash(id);
122
+ return data;
58
123
  }
59
- setSync() {
60
- throw ErrnoError.With('ENOSYS', undefined, 'AsyncTransaction.setSync');
124
+ getSync(id, offset = 0, end) {
125
+ const data = this.raw.getSync(id, offset, end);
126
+ this.stash(id);
127
+ return data;
61
128
  }
62
- removeSync() {
63
- throw ErrnoError.With('ENOSYS', undefined, 'AsyncTransaction.removeSync');
129
+ async set(id, data, offset = 0) {
130
+ await this.markModified(id, offset, data.byteLength);
131
+ await this.raw.set(id, data, offset);
132
+ }
133
+ setSync(id, data, offset = 0) {
134
+ this.markModifiedSync(id, offset, data.byteLength);
135
+ this.raw.setSync(id, data, offset);
136
+ }
137
+ async remove(id) {
138
+ await this.markModified(id, 0, undefined);
139
+ await this.raw.remove(id);
140
+ }
141
+ removeSync(id) {
142
+ this.markModifiedSync(id, 0, undefined);
143
+ this.raw.removeSync(id);
144
+ }
145
+ commit() {
146
+ this.done = true;
147
+ return Promise.resolve();
64
148
  }
65
149
  commitSync() {
66
- throw ErrnoError.With('ENOSYS', undefined, 'AsyncTransaction.commitSync');
150
+ this.done = true;
151
+ }
152
+ async abort() {
153
+ if (this.done)
154
+ return;
155
+ // Rollback old values.
156
+ for (const [id, entries] of this.originalData) {
157
+ if (!this.modifiedKeys.has(id))
158
+ continue;
159
+ // Key didn't exist.
160
+ if (entries.some(ent => !ent.data)) {
161
+ await this.raw.remove(id);
162
+ this.fs._remove(id);
163
+ continue;
164
+ }
165
+ for (const entry of entries.reverse()) {
166
+ await this.raw.set(id, entry.data, entry.offset);
167
+ }
168
+ }
169
+ this.done = true;
67
170
  }
68
171
  abortSync() {
69
- throw ErrnoError.With('ENOSYS', undefined, 'AsyncTransaction.abortSync');
172
+ if (this.done)
173
+ return;
174
+ // Rollback old values.
175
+ for (const [id, entries] of this.originalData) {
176
+ if (!this.modifiedKeys.has(id))
177
+ continue;
178
+ // Key didn't exist.
179
+ if (entries.some(ent => !ent.data)) {
180
+ this.raw.removeSync(id);
181
+ this.fs._remove(id);
182
+ continue;
183
+ }
184
+ for (const entry of entries.reverse()) {
185
+ this.raw.setSync(id, entry.data, entry.offset);
186
+ }
187
+ }
188
+ this.done = true;
189
+ }
190
+ async [Symbol.asyncDispose]() {
191
+ if (this.done)
192
+ return;
193
+ await this.abort();
194
+ }
195
+ [Symbol.dispose]() {
196
+ if (this.done)
197
+ return;
198
+ this.abortSync();
199
+ }
200
+ /**
201
+ * Stashes given key value pair into `originalData` if it doesn't already exist.
202
+ * Allows us to stash values the program is requesting anyway to
203
+ * prevent needless `get` requests if the program modifies the data later
204
+ * on during the transaction.
205
+ */
206
+ stash(id, data, offset = 0) {
207
+ if (!this.originalData.has(id))
208
+ this.originalData.set(id, []);
209
+ this.originalData.get(id).push({ data, offset });
210
+ }
211
+ /**
212
+ * Marks an id as modified, and stashes its value if it has not been stashed already.
213
+ */
214
+ async markModified(id, offset, length) {
215
+ this.modifiedKeys.add(id);
216
+ const end = length ? offset + length : undefined;
217
+ try {
218
+ this.stash(id, await this.raw.get(id, offset, end), offset);
219
+ }
220
+ catch (e) {
221
+ if (!(this.raw instanceof AsyncTransaction))
222
+ throw e;
223
+ /*
224
+ async transaction has a quirk:
225
+ setting the buffer to a larger size doesn't work correctly due to cache ranges
226
+ so, we cache the existing sub-ranges
227
+ */
228
+ const tx = this.raw;
229
+ const resource = tx._cached(id);
230
+ if (!resource)
231
+ throw e;
232
+ for (const range of resource.cached(offset, end !== null && end !== void 0 ? end : offset)) {
233
+ this.stash(id, await this.raw.get(id, range.start, range.end), range.start);
234
+ }
235
+ }
236
+ }
237
+ /**
238
+ * Marks an id as modified, and stashes its value if it has not been stashed already.
239
+ */
240
+ markModifiedSync(id, offset, length) {
241
+ this.modifiedKeys.add(id);
242
+ const end = length ? offset + length : undefined;
243
+ try {
244
+ this.stash(id, this.raw.getSync(id, offset, end), offset);
245
+ }
246
+ catch (e) {
247
+ if (!(this.raw instanceof AsyncTransaction))
248
+ throw e;
249
+ /*
250
+ async transaction has a quirk:
251
+ setting the buffer to a larger size doesn't work correctly due to cache ranges
252
+ so, we cache the existing sub-ranges
253
+ */
254
+ const tx = this.raw;
255
+ const resource = tx._cached(id);
256
+ if (!resource)
257
+ throw e;
258
+ for (const range of resource.cached(offset, end !== null && end !== void 0 ? end : offset)) {
259
+ this.stash(id, this.raw.getSync(id, range.start, range.end), range.start);
260
+ }
261
+ }
70
262
  }
71
263
  }
package/dist/config.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { Backend, BackendConfiguration, FilesystemOf, SharedConfig } from './backends/backend.js';
2
- import type { Device, DeviceDriver } from './devices.js';
2
+ import type { Device, DeviceDriver } from './internal/devices.js';
3
+ import type { LogConfiguration } from './internal/log.js';
3
4
  /**
4
5
  * Configuration for a specific mount point
5
6
  */
@@ -37,7 +38,6 @@ export interface Configuration<T extends ConfigMounts> extends SharedConfig {
37
38
  gid: number;
38
39
  /**
39
40
  * Whether to automatically add normal Linux devices
40
- * @experimental
41
41
  * @default false
42
42
  */
43
43
  addDevices: boolean;
@@ -60,7 +60,6 @@ export interface Configuration<T extends ConfigMounts> extends SharedConfig {
60
60
  * If true, disables *all* permissions checking.
61
61
  *
62
62
  * This can increase performance.
63
- * @experimental
64
63
  * @default false
65
64
  */
66
65
  disableAccessChecks: boolean;
@@ -81,6 +80,11 @@ export interface Configuration<T extends ConfigMounts> extends SharedConfig {
81
80
  * @default false
82
81
  */
83
82
  onlySyncOnClose: boolean;
83
+ /**
84
+ * Configurations options for the log.
85
+ * @experimental
86
+ */
87
+ log: LogConfiguration;
84
88
  }
85
89
  /**
86
90
  * Configures ZenFS with single mount point /
package/dist/config.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import { checkOptions, isBackend, isBackendConfig } from './backends/backend.js';
2
- import { useCredentials } from './credentials.js';
3
- import { DeviceFS } from './devices.js';
4
- import { Errno, ErrnoError } from './error.js';
5
- import { FileSystem } from './filesystem.js';
2
+ import { useCredentials } from './internal/credentials.js';
3
+ import { DeviceFS } from './internal/devices.js';
4
+ import { Errno, ErrnoError } from './internal/error.js';
5
+ import { FileSystem } from './internal/filesystem.js';
6
+ import { configure as configureLog, crit, err, info } from './internal/log.js';
6
7
  import * as cache from './vfs/cache.js';
7
8
  import { config } from './vfs/config.js';
8
9
  import * as fs from './vfs/index.js';
@@ -16,10 +17,10 @@ function isMountConfig(arg) {
16
17
  */
17
18
  export async function resolveMountConfig(configuration, _depth = 0) {
18
19
  if (typeof configuration !== 'object' || configuration == null) {
19
- throw new ErrnoError(Errno.EINVAL, 'Invalid options on mount configuration');
20
+ throw err(new ErrnoError(Errno.EINVAL, 'Invalid options on mount configuration'));
20
21
  }
21
22
  if (!isMountConfig(configuration)) {
22
- throw new ErrnoError(Errno.EINVAL, 'Invalid mount configuration');
23
+ throw err(new ErrnoError(Errno.EINVAL, 'Invalid mount configuration'));
23
24
  }
24
25
  if (configuration instanceof FileSystem) {
25
26
  await configuration.ready();
@@ -29,24 +30,24 @@ export async function resolveMountConfig(configuration, _depth = 0) {
29
30
  configuration = { backend: configuration };
30
31
  }
31
32
  for (const [key, value] of Object.entries(configuration)) {
32
- if (key == 'backend') {
33
+ if (key == 'backend')
33
34
  continue;
34
- }
35
- if (!isMountConfig(value)) {
35
+ if (!isMountConfig(value))
36
36
  continue;
37
- }
37
+ info('Resolving nested mount configuration: ' + key);
38
38
  if (_depth > 10) {
39
- throw new ErrnoError(Errno.EINVAL, 'Invalid configuration, too deep and possibly infinite');
39
+ throw err(new ErrnoError(Errno.EINVAL, 'Invalid configuration, too deep and possibly infinite'));
40
40
  }
41
41
  configuration[key] = await resolveMountConfig(value, ++_depth);
42
42
  }
43
43
  const { backend } = configuration;
44
44
  if (typeof backend.isAvailable == 'function' && !(await backend.isAvailable())) {
45
- throw new ErrnoError(Errno.EPERM, 'Backend not available: ' + backend.name);
45
+ throw err(new ErrnoError(Errno.EPERM, 'Backend not available: ' + backend.name));
46
46
  }
47
47
  await checkOptions(backend, configuration);
48
48
  const mount = (await backend.create(configuration));
49
- mount._disableSync = configuration.disableAsyncCache || false;
49
+ if (configuration.disableAsyncCache)
50
+ mount.attributes.set('no_async');
50
51
  await mount.ready();
51
52
  return mount;
52
53
  }
@@ -84,7 +85,7 @@ async function mount(path, mount) {
84
85
  export function addDevice(driver, options) {
85
86
  const devfs = mounts.get('/dev');
86
87
  if (!(devfs instanceof DeviceFS))
87
- throw new ErrnoError(Errno.ENOTSUP, '/dev does not exist or is not a device file system');
88
+ throw crit(new ErrnoError(Errno.ENOTSUP, '/dev does not exist or is not a device file system'));
88
89
  return devfs._createDevice(driver, options);
89
90
  }
90
91
  /**
@@ -101,6 +102,8 @@ export async function configure(configuration) {
101
102
  config.checkAccess = !configuration.disableAccessChecks;
102
103
  config.updateOnRead = !configuration.disableUpdateOnRead;
103
104
  config.syncImmediately = !configuration.onlySyncOnClose;
105
+ if (configuration.log)
106
+ configureLog(configuration.log);
104
107
  if (configuration.mounts) {
105
108
  // sort to make sure any root replacement is done first
106
109
  for (const [_point, mountConfig] of Object.entries(configuration.mounts).sort(([a], [b]) => (a.length > b.length ? 1 : -1))) {
package/dist/context.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { CredentialInit, Credentials } from './credentials.js';
1
+ import type { CredentialInit, Credentials } from './internal/credentials.js';
2
2
  import * as fs from './vfs/index.js';
3
3
  /**
4
4
  * Represents some context used for FS operations
package/dist/context.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createCredentials, credentials as defaultCredentials } from './credentials.js';
1
+ import { createCredentials, credentials as defaultCredentials } from './internal/credentials.js';
2
2
  import * as fs from './vfs/index.js';
3
3
  /**
4
4
  * Binds a this value for all of the functions in an object (not recursive)
package/dist/index.d.ts CHANGED
@@ -1,11 +1,7 @@
1
1
  export * from './backends/index.js';
2
2
  export * from './config.js';
3
3
  export * from './context.js';
4
- export * from './credentials.js';
5
- export * from './devices.js';
6
- export * from './error.js';
7
- export * from './file.js';
8
- export * from './filesystem.js';
4
+ export * from './internal/index.js';
9
5
  export * from './mixins/index.js';
10
6
  export * from './stats.js';
11
7
  export * from './utils.js';
package/dist/index.js CHANGED
@@ -1,11 +1,7 @@
1
1
  export * from './backends/index.js';
2
2
  export * from './config.js';
3
3
  export * from './context.js';
4
- export * from './credentials.js';
5
- export * from './devices.js';
6
- export * from './error.js';
7
- export * from './file.js';
8
- export * from './filesystem.js';
4
+ export * from './internal/index.js';
9
5
  export * from './mixins/index.js';
10
6
  export * from './stats.js';
11
7
  export * from './utils.js';
@@ -1,10 +1,10 @@
1
- import { Inode } from './backends/index.js';
2
- import { InMemoryStore } from './backends/memory.js';
3
- import { StoreFS } from './backends/store/fs.js';
1
+ import { InMemoryStore } from '../backends/memory.js';
2
+ import { StoreFS } from '../backends/store/fs.js';
3
+ import { Stats } from '../stats.js';
4
4
  import type { FileReadResult } from './file.js';
5
5
  import { File } from './file.js';
6
6
  import type { CreationOptions } from './filesystem.js';
7
- import { Stats } from './stats.js';
7
+ import { Inode } from './inode.js';
8
8
  /**
9
9
  * A device
10
10
  * @todo Maybe add some other device information, like a UUID?
@@ -53,15 +53,17 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
53
53
  var e = new Error(message);
54
54
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
55
55
  });
56
- import { Inode } from './backends/index.js';
57
- import { InMemoryStore } from './backends/memory.js';
58
- import { StoreFS } from './backends/store/fs.js';
56
+ import { canary } from 'utilium';
57
+ import { InMemoryStore } from '../backends/memory.js';
58
+ import { StoreFS } from '../backends/store/fs.js';
59
+ import { Stats } from '../stats.js';
60
+ import { decodeUTF8 } from '../utils.js';
61
+ import { S_IFBLK, S_IFCHR } from '../vfs/constants.js';
62
+ import { basename, dirname } from '../vfs/path.js';
59
63
  import { Errno, ErrnoError } from './error.js';
60
64
  import { File } from './file.js';
61
- import { Stats } from './stats.js';
62
- import { canary, decodeUTF8 } from './utils.js';
63
- import { S_IFBLK, S_IFCHR } from './vfs/constants.js';
64
- import { basename, dirname } from './vfs/path.js';
65
+ import { Inode } from './inode.js';
66
+ import { alert, debug, err, info, log_deprecated } from './log.js';
65
67
  /**
66
68
  * The base class for device files
67
69
  * This class only does some simple things:
@@ -162,18 +164,19 @@ export class DeviceFile extends File {
162
164
  * A temporary file system that manages and interfaces with devices
163
165
  */
164
166
  export class DeviceFS extends StoreFS {
167
+ /* node:coverage disable */
165
168
  /**
166
169
  * Creates a new device at `path` relative to the `DeviceFS` root.
167
170
  * @deprecated
168
171
  */
169
- /* node:coverage disable */
170
172
  createDevice(path, driver, options = {}) {
171
173
  var _a;
174
+ log_deprecated('DeviceFS#createDevice');
172
175
  if (this.existsSync(path)) {
173
176
  throw ErrnoError.With('EEXIST', path, 'mknod');
174
177
  }
175
178
  let ino = 1;
176
- const silence = canary(path, 'mknod');
179
+ const silence = canary(ErrnoError.With('EDEADLK', path, 'mknod'));
177
180
  while (this.store.has(ino))
178
181
  ino++;
179
182
  silence();
@@ -191,7 +194,7 @@ export class DeviceFS extends StoreFS {
191
194
  /* node:coverage enable */
192
195
  devicesWithDriver(driver, forceIdentity) {
193
196
  if (forceIdentity && typeof driver == 'string') {
194
- throw new ErrnoError(Errno.EINVAL, 'Can not fetch devices using only a driver name');
197
+ throw err(new ErrnoError(Errno.EINVAL, 'Can not fetch devices using only a driver name'), { fs: this });
195
198
  }
196
199
  const devs = [];
197
200
  for (const device of this.devices.values()) {
@@ -220,10 +223,10 @@ export class DeviceFS extends StoreFS {
220
223
  ...(_a = driver.init) === null || _a === void 0 ? void 0 : _a.call(driver, ino, options),
221
224
  };
222
225
  const path = '/' + (dev.name || driver.name) + (driver.singleton ? '' : this.devicesWithDriver(driver).length);
223
- if (this.existsSync(path)) {
226
+ if (this.existsSync(path))
224
227
  throw ErrnoError.With('EEXIST', path, 'mknod');
225
- }
226
228
  this.devices.set(path, dev);
229
+ info('Initialized device: ' + this._mountPoint + path);
227
230
  return dev;
228
231
  }
229
232
  /**
@@ -235,6 +238,7 @@ export class DeviceFS extends StoreFS {
235
238
  this._createDevice(fullDevice);
236
239
  this._createDevice(randomDevice);
237
240
  this._createDevice(consoleDevice);
241
+ debug('Added default devices.');
238
242
  }
239
243
  constructor() {
240
244
  super(new InMemoryStore('devfs'));
@@ -386,13 +390,13 @@ export class DeviceFS extends StoreFS {
386
390
  }
387
391
  async sync(path, data, stats) {
388
392
  if (this.devices.has(path)) {
389
- throw new ErrnoError(Errno.EINVAL, 'Attempted to sync a device incorrectly (bug)', path, 'sync');
393
+ throw alert(new ErrnoError(Errno.EINVAL, 'Attempted to sync a device incorrectly (bug)', path, 'sync'), { fs: this });
390
394
  }
391
395
  return super.sync(path, data, stats);
392
396
  }
393
397
  syncSync(path, data, stats) {
394
398
  if (this.devices.has(path)) {
395
- throw new ErrnoError(Errno.EINVAL, 'Attempted to sync a device incorrectly (bug)', path, 'sync');
399
+ throw alert(new ErrnoError(Errno.EINVAL, 'Attempted to sync a device incorrectly (bug)', path, 'sync'), { fs: this });
396
400
  }
397
401
  return super.syncSync(path, data, stats);
398
402
  }
@@ -1,6 +1,6 @@
1
+ import { Stats, type StatsLike } from '../stats.js';
1
2
  import type { FileSystem } from './filesystem.js';
2
- import './polyfills.js';
3
- import { Stats, type StatsLike } from './stats.js';
3
+ import '../polyfills.js';
4
4
  export declare function parseFlag(flag: string | number): string;
5
5
  export declare function flagToString(flag: number): string;
6
6
  export declare function flagToNumber(flag: string): number;
@@ -220,6 +220,7 @@ export declare class PreloadFile<FS extends FileSystem> extends File<FS> {
220
220
  * @deprecated
221
221
  */
222
222
  export declare class NoSyncFile<T extends FileSystem> extends PreloadFile<T> {
223
+ constructor(...args: ConstructorParameters<typeof PreloadFile<T>>);
223
224
  sync(): Promise<void>;
224
225
  syncSync(): void;
225
226
  close(): Promise<void>;
@@ -1,9 +1,10 @@
1
+ import { extendBuffer } from 'utilium/buffer.js';
2
+ import { _chown, Stats } from '../stats.js';
3
+ import { config } from '../vfs/config.js';
4
+ import * as c from '../vfs/constants.js';
1
5
  import { Errno, ErrnoError } from './error.js';
2
- import './polyfills.js';
3
- import { _chown, Stats } from './stats.js';
4
- import { growBuffer } from './utils.js';
5
- import { config } from './vfs/config.js';
6
- import * as c from './vfs/constants.js';
6
+ import { log_deprecated } from './log.js';
7
+ import '../polyfills.js';
7
8
  const maxByteLength = 0x100000; // 1 MiB
8
9
  const validFlags = ['r', 'r+', 'rs', 'rs+', 'w', 'wx', 'w+', 'wx+', 'a', 'ax', 'a+', 'ax+'];
9
10
  export function parseFlag(flag) {
@@ -148,7 +149,7 @@ export class PreloadFile extends File {
148
149
  /**
149
150
  * A buffer containing the entire contents of the file.
150
151
  */
151
- _buffer = new Uint8Array(new ArrayBuffer(0, fs.metadata().noResizableBuffers ? {} : { maxByteLength }))) {
152
+ _buffer = new Uint8Array(new ArrayBuffer(0, fs.attributes.has('no_buffer_resize') ? {} : { maxByteLength }))) {
152
153
  super(fs, path);
153
154
  this.flag = flag;
154
155
  this.stats = stats;
@@ -208,7 +209,7 @@ export class PreloadFile extends File {
208
209
  throw ErrnoError.With('EBADF', this.path, 'sync');
209
210
  if (!this.dirty)
210
211
  return;
211
- if (!this.fs.metadata().readonly)
212
+ if (!this.fs.attributes.has('no_write'))
212
213
  await this.fs.sync(this.path, this._buffer, this.stats);
213
214
  this.dirty = false;
214
215
  }
@@ -217,7 +218,7 @@ export class PreloadFile extends File {
217
218
  throw ErrnoError.With('EBADF', this.path, 'sync');
218
219
  if (!this.dirty)
219
220
  return;
220
- if (!this.fs.metadata().readonly)
221
+ if (!this.fs.attributes.has('no_write'))
221
222
  this.fs.syncSync(this.path, this._buffer, this.stats);
222
223
  this.dirty = false;
223
224
  }
@@ -291,7 +292,7 @@ export class PreloadFile extends File {
291
292
  this.dirty = true;
292
293
  const end = position + length;
293
294
  const slice = buffer.subarray(offset, offset + length);
294
- this._buffer = growBuffer(this._buffer, end);
295
+ this._buffer = extendBuffer(this._buffer, end);
295
296
  if (end > this.stats.size)
296
297
  this.stats.size = end;
297
298
  this._buffer.set(slice, position);
@@ -433,12 +434,16 @@ export class PreloadFile extends File {
433
434
  this.syncSync();
434
435
  }
435
436
  }
437
+ /* node:coverage disable */
436
438
  /**
437
439
  * For the file systems which do not sync to anything.
438
440
  * @deprecated
439
441
  */
440
- /* node:coverage disable */
441
442
  export class NoSyncFile extends PreloadFile {
443
+ constructor(...args) {
444
+ log_deprecated('NoSyncFile');
445
+ super(...args);
446
+ }
442
447
  sync() {
443
448
  return Promise.resolve();
444
449
  }
@@ -495,7 +500,7 @@ export class LazyFile extends File {
495
500
  throw ErrnoError.With('EBADF', this.path, 'sync');
496
501
  if (!this.dirty)
497
502
  return;
498
- if (!this.fs.metadata().readonly)
503
+ if (!this.fs.attributes.has('no_write'))
499
504
  await this.fs.sync(this.path, undefined, this.stats);
500
505
  this.dirty = false;
501
506
  }
@@ -504,7 +509,7 @@ export class LazyFile extends File {
504
509
  throw ErrnoError.With('EBADF', this.path, 'sync');
505
510
  if (!this.dirty)
506
511
  return;
507
- if (!this.fs.metadata().readonly)
512
+ if (!this.fs.attributes.has('no_write'))
508
513
  this.fs.syncSync(this.path, undefined, this.stats);
509
514
  this.dirty = false;
510
515
  }