@zenfs/core 2.7.5 → 2.7.6

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 (45) hide show
  1. package/dist/backends/backend.js +0 -2
  2. package/dist/backends/cow.d.ts +2 -2
  3. package/dist/backends/cow.js +6 -14
  4. package/dist/backends/passthrough.d.ts +0 -54
  5. package/dist/backends/passthrough.js +0 -54
  6. package/dist/backends/port.d.ts +2 -6
  7. package/dist/backends/port.js +3 -11
  8. package/dist/backends/store/fs.d.ts +0 -9
  9. package/dist/backends/store/fs.js +1 -21
  10. package/dist/backends/store/store.d.ts +1 -1
  11. package/dist/backends/store/store.js +1 -5
  12. package/dist/internal/contexts.d.ts +1 -2
  13. package/dist/internal/credentials.d.ts +0 -3
  14. package/dist/internal/file_index.js +0 -1
  15. package/dist/internal/index_fs.d.ts +2 -2
  16. package/dist/internal/index_fs.js +2 -2
  17. package/dist/internal/inode.d.ts +21 -43
  18. package/dist/internal/rpc.d.ts +16 -7
  19. package/dist/internal/rpc.js +2 -11
  20. package/dist/mixins/mutexed.d.ts +6 -41
  21. package/dist/mixins/mutexed.js +36 -109
  22. package/dist/mixins/sync.js +0 -2
  23. package/dist/node/async.js +2 -12
  24. package/dist/node/index.d.ts +1 -1
  25. package/dist/node/promises.d.ts +1 -6
  26. package/dist/node/promises.js +1 -1
  27. package/dist/node/stats.d.ts +25 -99
  28. package/dist/node/stats.js +18 -55
  29. package/dist/node/streams.d.ts +1 -37
  30. package/dist/node/sync.d.ts +1 -6
  31. package/dist/node/sync.js +2 -2
  32. package/dist/polyfills.js +9 -0
  33. package/dist/utils.d.ts +0 -4
  34. package/dist/vfs/acl.d.ts +1 -3
  35. package/dist/vfs/acl.js +1 -3
  36. package/dist/vfs/async.js +0 -5
  37. package/dist/vfs/dir.d.ts +3 -0
  38. package/dist/vfs/dir.js +4 -1
  39. package/dist/vfs/file.d.ts +1 -8
  40. package/dist/vfs/file.js +1 -3
  41. package/dist/vfs/sync.js +0 -1
  42. package/dist/vfs/vcache.js +0 -1
  43. package/package.json +1 -2
  44. package/tests/common/context.test.ts +1 -1
  45. package/tests/common/mutex.test.ts +0 -61
@@ -55,9 +55,7 @@ export function checkOptions(backend, options) {
55
55
  : typeof value === type || value?.constructor?.name === type;
56
56
  if (Array.isArray(opt.type) ? opt.type.some(v => isType(v)) : isType(opt.type))
57
57
  continue;
58
- // The type of the value as a string
59
58
  const type = typeof value == 'object' && 'constructor' in value ? value.constructor.name : typeof value;
60
- // The expected type (as a string)
61
59
  const name = (type) => (typeof type == 'function' ? (type.name != 'type' ? type.name : type.toString()) : type);
62
60
  const expected = Array.isArray(opt.type) ? `one of ${opt.type.map(name).join(', ')}` : name(opt.type);
63
61
  throw err(withErrno('EINVAL', `Incorrect type for "${optName}": ${type} (expected ${expected})`));
@@ -162,14 +162,14 @@ declare const _CopyOnWrite: {
162
162
  };
163
163
  type _CopyOnWrite = typeof _CopyOnWrite;
164
164
  /**
165
- * Overlay makes a read-only filesystem writable by storing writes on a second, writable file system.
165
+ * Makes a read-only filesystem writable by storing writes on a second, writable file system.
166
166
  * Deletes are persisted via metadata stored on the writable file system.
167
167
  * @category Backends and Configuration
168
168
  */
169
169
  export interface CopyOnWrite extends _CopyOnWrite {
170
170
  }
171
171
  /**
172
- * Overlay makes a read-only filesystem writable by storing writes on a second, writable file system.
172
+ * Makes a read-only filesystem writable by storing writes on a second, writable file system.
173
173
  * Deletes are persisted via metadata stored on the writable file system.
174
174
  * @category Backends and Configuration
175
175
  * @internal
@@ -141,7 +141,7 @@ export class CopyOnWriteFS extends FileSystem {
141
141
  }
142
142
  /* Note the layer's inode is not mutated, since it may be a persistent object.
143
143
  `Inode` fields are accessors, so a copy must be explicit rather than a spread. */
144
- return { ...pick(inode, _inode_fields), attributes: inode.attributes, ino };
144
+ return Object.assign(pick(inode, _inode_fields), { attributes: inode.attributes, ino });
145
145
  }
146
146
  /**
147
147
  * @todo Consider trying to track information on the writable as well
@@ -252,25 +252,19 @@ export class CopyOnWriteFS extends FileSystem {
252
252
  async unlink(path) {
253
253
  if (!(await this.exists(path)))
254
254
  throw withErrno('ENOENT');
255
- if (await this.writable.exists(path)) {
255
+ if (await this.writable.exists(path))
256
256
  await this.writable.unlink(path);
257
- }
258
- // if it still exists add to the delete log
259
- if (await this.exists(path)) {
257
+ if (await this.exists(path))
260
258
  this.journal.add('delete', path);
261
- }
262
259
  this.inos.delete(path);
263
260
  }
264
261
  unlinkSync(path) {
265
262
  if (!this.existsSync(path))
266
263
  throw withErrno('ENOENT');
267
- if (this.writable.existsSync(path)) {
264
+ if (this.writable.existsSync(path))
268
265
  this.writable.unlinkSync(path);
269
- }
270
- // if it still exists add to the delete log
271
- if (this.existsSync(path)) {
266
+ if (this.existsSync(path))
272
267
  this.journal.add('delete', path);
273
- }
274
268
  this.inos.delete(path);
275
269
  }
276
270
  async rmdir(path) {
@@ -283,7 +277,6 @@ export class CopyOnWriteFS extends FileSystem {
283
277
  this.inos.delete(path);
284
278
  return;
285
279
  }
286
- // Check if directory is empty.
287
280
  if ((await this.readdir(path)).length)
288
281
  throw withErrno('ENOTEMPTY');
289
282
  this.journal.add('delete', path);
@@ -299,7 +292,6 @@ export class CopyOnWriteFS extends FileSystem {
299
292
  this.inos.delete(path);
300
293
  return;
301
294
  }
302
- // Check if directory is empty.
303
295
  if (this.readdirSync(path).length)
304
296
  throw withErrno('ENOTEMPTY');
305
297
  this.journal.add('delete', path);
@@ -488,7 +480,7 @@ const _CopyOnWrite = {
488
480
  },
489
481
  };
490
482
  /**
491
- * Overlay makes a read-only filesystem writable by storing writes on a second, writable file system.
483
+ * Makes a read-only filesystem writable by storing writes on a second, writable file system.
492
484
  * Deletes are persisted via metadata stored on the writable file system.
493
485
  * @category Backends and Configuration
494
486
  * @internal
@@ -16,21 +16,9 @@ export declare class PassthroughFS extends FileSystem {
16
16
  constructor(nodeFS: NodeFS, prefix: string);
17
17
  usage(): UsageInfo;
18
18
  path(path: string): string;
19
- /**
20
- * Rename a file or directory.
21
- */
22
19
  rename(oldPath: string, newPath: string): Promise<void>;
23
- /**
24
- * Rename a file or directory synchronously.
25
- */
26
20
  renameSync(oldPath: string, newPath: string): void;
27
- /**
28
- * Get file statistics.
29
- */
30
21
  stat(path: string): Promise<InodeLike>;
31
- /**
32
- * Get file statistics synchronously.
33
- */
34
22
  statSync(path: string): InodeLike;
35
23
  /**
36
24
  * @privateRemarks
@@ -42,61 +30,19 @@ export declare class PassthroughFS extends FileSystem {
42
30
  * Timestamps should be updated by the underlying file system.
43
31
  */
44
32
  touchSync(path: string, metadata: InodeLike): void;
45
- /**
46
- * Unlink (delete) a file.
47
- */
48
33
  unlink(path: string): Promise<void>;
49
- /**
50
- * Unlink (delete) a file synchronously.
51
- */
52
34
  unlinkSync(path: string): void;
53
- /**
54
- * Create a directory.
55
- */
56
35
  mkdir(path: string, options: CreationOptions): Promise<InodeLike>;
57
- /**
58
- * Create a directory synchronously.
59
- */
60
36
  mkdirSync(path: string, options: CreationOptions): InodeLike;
61
- /**
62
- * Read the contents of a directory.
63
- */
64
37
  readdir(path: string): Promise<string[]>;
65
- /**
66
- * Read the contents of a directory synchronously.
67
- */
68
38
  readdirSync(path: string): string[];
69
- /**
70
- * Create a file.
71
- */
72
39
  createFile(path: string, options: CreationOptions): Promise<InodeLike>;
73
- /**
74
- * Create a file synchronously.
75
- */
76
40
  createFileSync(path: string, options: CreationOptions): InodeLike;
77
- /**
78
- * Remove a directory.
79
- */
80
41
  rmdir(path: string): Promise<void>;
81
- /**
82
- * Remove a directory synchronously.
83
- */
84
42
  rmdirSync(path: string): void;
85
- /**
86
- * Synchronize data to the file system.
87
- */
88
43
  sync(): Promise<void>;
89
- /**
90
- * Synchronize data to the file system synchronously.
91
- */
92
44
  syncSync(): void;
93
- /**
94
- * Create a hard link.
95
- */
96
45
  link(target: string, link: string): Promise<void>;
97
- /**
98
- * Create a hard link synchronously.
99
- */
100
46
  linkSync(target: string, link: string): void;
101
47
  read(path: string, buffer: Uint8Array, offset: number, end: number): Promise<void>;
102
48
  readSync(path: string, buffer: Uint8Array, offset: number, end: number): void;
@@ -72,27 +72,15 @@ export class PassthroughFS extends FileSystem {
72
72
  path(path) {
73
73
  return this.prefix + path;
74
74
  }
75
- /**
76
- * Rename a file or directory.
77
- */
78
75
  async rename(oldPath, newPath) {
79
76
  await this.nodeFS.promises.rename(this.path(oldPath), this.path(newPath));
80
77
  }
81
- /**
82
- * Rename a file or directory synchronously.
83
- */
84
78
  renameSync(oldPath, newPath) {
85
79
  this.nodeFS.renameSync(this.path(oldPath), this.path(newPath));
86
80
  }
87
- /**
88
- * Get file statistics.
89
- */
90
81
  async stat(path) {
91
82
  return await this.nodeFS.promises.stat(this.path(path));
92
83
  }
93
- /**
94
- * Get file statistics synchronously.
95
- */
96
84
  statSync(path) {
97
85
  return this.nodeFS.statSync(this.path(path));
98
86
  }
@@ -135,47 +123,26 @@ export class PassthroughFS extends FileSystem {
135
123
  err('Failed to chown passthrough file: ' + error.message);
136
124
  }
137
125
  }
138
- /**
139
- * Unlink (delete) a file.
140
- */
141
126
  async unlink(path) {
142
127
  await this.nodeFS.promises.unlink(this.path(path));
143
128
  }
144
- /**
145
- * Unlink (delete) a file synchronously.
146
- */
147
129
  unlinkSync(path) {
148
130
  this.nodeFS.unlinkSync(this.path(path));
149
131
  }
150
- /**
151
- * Create a directory.
152
- */
153
132
  async mkdir(path, options) {
154
133
  await this.nodeFS.promises.mkdir(this.path(path), options);
155
134
  return await this.nodeFS.promises.stat(this.path(path));
156
135
  }
157
- /**
158
- * Create a directory synchronously.
159
- */
160
136
  mkdirSync(path, options) {
161
137
  this.nodeFS.mkdirSync(this.path(path), options);
162
138
  return this.nodeFS.statSync(this.path(path));
163
139
  }
164
- /**
165
- * Read the contents of a directory.
166
- */
167
140
  async readdir(path) {
168
141
  return await this.nodeFS.promises.readdir(this.path(path));
169
142
  }
170
- /**
171
- * Read the contents of a directory synchronously.
172
- */
173
143
  readdirSync(path) {
174
144
  return this.nodeFS.readdirSync(this.path(path));
175
145
  }
176
- /**
177
- * Create a file.
178
- */
179
146
  async createFile(path, options) {
180
147
  if (isDirectory(options)) {
181
148
  await this.nodeFS.promises.mkdir(this.path(path), { mode: options.mode });
@@ -198,9 +165,6 @@ export class PassthroughFS extends FileSystem {
198
165
  }
199
166
  return await this.nodeFS.promises.stat(this.path(path));
200
167
  }
201
- /**
202
- * Create a file synchronously.
203
- */
204
168
  createFileSync(path, options) {
205
169
  if (isDirectory(options)) {
206
170
  this.nodeFS.mkdirSync(this.path(path), { mode: options.mode });
@@ -211,39 +175,21 @@ export class PassthroughFS extends FileSystem {
211
175
  }
212
176
  return this.nodeFS.statSync(this.path(path));
213
177
  }
214
- /**
215
- * Remove a directory.
216
- */
217
178
  async rmdir(path) {
218
179
  await this.nodeFS.promises.rmdir(this.path(path));
219
180
  }
220
- /**
221
- * Remove a directory synchronously.
222
- */
223
181
  rmdirSync(path) {
224
182
  this.nodeFS.rmdirSync(this.path(path));
225
183
  }
226
- /**
227
- * Synchronize data to the file system.
228
- */
229
184
  async sync() {
230
185
  warn('Sync on passthrough is unnecessary');
231
186
  }
232
- /**
233
- * Synchronize data to the file system synchronously.
234
- */
235
187
  syncSync() {
236
188
  warn('Sync on passthrough is unnecessary');
237
189
  }
238
- /**
239
- * Create a hard link.
240
- */
241
190
  async link(target, link) {
242
191
  await this.nodeFS.promises.link(this.path(target), this.path(link));
243
192
  }
244
- /**
245
- * Create a hard link synchronously.
246
- */
247
193
  linkSync(target, link) {
248
194
  this.nodeFS.linkSync(this.path(target), this.path(link));
249
195
  }
@@ -33,13 +33,9 @@ export declare class PortFS<T extends RPC.Channel = RPC.Channel> extends PortFS_
33
33
  readonly channel: T;
34
34
  readonly timeout: number;
35
35
  readonly port: RPC.Port<T>;
36
- /**
37
- * @hidden
38
- */
36
+ /** @hidden */
39
37
  _sync: import("./index.js").StoreFS<import("./memory.js").InMemoryStore>;
40
- /**
41
- * Constructs a new PortFS instance that connects with the FS running on `options.port`.
42
- */
38
+ /** Constructs a new PortFS instance that connects with the FS running on `options.port`. */
43
39
  constructor(channel: T, timeout?: number);
44
40
  protected rpc<const T extends RPC.Method>(method: T, ...args: Parameters<RPC.Methods[T]>): Promise<Awaited<ReturnType<RPC.Methods[T]>>>;
45
41
  ready(): Promise<void>;
@@ -19,13 +19,9 @@ export class PortFS extends Async(FileSystem) {
19
19
  channel;
20
20
  timeout;
21
21
  port;
22
- /**
23
- * @hidden
24
- */
22
+ /** @hidden */
25
23
  _sync = InMemory.create({ label: 'tmpfs:port' });
26
- /**
27
- * Constructs a new PortFS instance that connects with the FS running on `options.port`.
28
- */
24
+ /** Constructs a new PortFS instance that connects with the FS running on `options.port`. */
29
25
  constructor(channel, timeout = 250) {
30
26
  super(0x706f7274, 'portfs');
31
27
  this.channel = channel;
@@ -34,11 +30,7 @@ export class PortFS extends Async(FileSystem) {
34
30
  RPC.attach(this.port, RPC.handleResponse);
35
31
  }
36
32
  rpc(method, ...args) {
37
- return RPC.request({ method, args }, {
38
- port: this.port,
39
- timeout: this.timeout,
40
- fs: this,
41
- });
33
+ return RPC.request({ method, args }, { port: this.port, timeout: this.timeout, fs: this });
42
34
  }
43
35
  async ready() {
44
36
  await this.rpc('ready');
@@ -42,9 +42,6 @@ export declare class StoreFS<T extends Store = Store> extends FileSystem {
42
42
  ready(): Promise<void>;
43
43
  readySync(): void;
44
44
  constructor(store: T);
45
- /**
46
- * @experimental
47
- */
48
45
  usage(): UsageInfo;
49
46
  /**
50
47
  * Load an index into the StoreFS.
@@ -77,13 +74,7 @@ export declare class StoreFS<T extends Store = Store> extends FileSystem {
77
74
  mkdirSync(path: string, options: CreationOptions): Inode;
78
75
  readdir(path: string): Promise<string[]>;
79
76
  readdirSync(path: string): string[];
80
- /**
81
- * Updated the inode and data node at `path`
82
- */
83
77
  sync(): Promise<void>;
84
- /**
85
- * Updated the inode and data node at `path`
86
- */
87
78
  syncSync(): void;
88
79
  link(target: string, link: string): Promise<void>;
89
80
  linkSync(target: string, link: string): void;
@@ -162,9 +162,6 @@ export class StoreFS extends FileSystem {
162
162
  this.label = store.label;
163
163
  debug(this.name + ': supports features: ' + this.store.flags?.join(', '));
164
164
  }
165
- /**
166
- * @experimental
167
- */
168
165
  usage() {
169
166
  return (this.store.usage?.() || {
170
167
  totalSpace: 0,
@@ -525,13 +522,7 @@ export class StoreFS extends FileSystem {
525
522
  __disposeResources(env_12);
526
523
  }
527
524
  }
528
- /**
529
- * Updated the inode and data node at `path`
530
- */
531
525
  async sync() { }
532
- /**
533
- * Updated the inode and data node at `path`
534
- */
535
526
  syncSync() { }
536
527
  async link(target, link) {
537
528
  const env_13 = { stack: [], error: void 0, hasError: false };
@@ -758,16 +749,13 @@ export class StoreFS extends FileSystem {
758
749
  crit('Store contains an invalid root inode. Refusing to populate tables');
759
750
  return;
760
751
  }
761
- // Keep track of directories we have already traversed to avoid loops
762
752
  const visitedDirectories = new Set();
763
753
  let i = 0;
764
- // Start BFS from root
765
754
  const queue = [['/', rootIno]];
766
755
  while (queue.length > 0) {
767
756
  i++;
768
757
  const [path, ino] = queue.shift();
769
758
  this._add(ino, path);
770
- // Get the inode data from the store
771
759
  const inodeData = await tx.get(ino);
772
760
  if (!inodeData) {
773
761
  warn('Store is missing data for inode: ' + ino);
@@ -777,14 +765,10 @@ export class StoreFS extends FileSystem {
777
765
  warn(`Invalid inode size for ino ${ino}: ${inodeData.length}`);
778
766
  continue;
779
767
  }
780
- // Parse the raw data into our Inode object
781
768
  const inode = new Inode(inodeData);
782
- // If it is a directory and not yet visited, read its directory listing
783
- if (!isDirectory(inode) || visitedDirectories.has(ino)) {
769
+ if (!isDirectory(inode) || visitedDirectories.has(ino))
784
770
  continue;
785
- }
786
771
  visitedDirectories.add(ino);
787
- // Grab the directory listing from the store
788
772
  const dirData = await tx.get(inode.data);
789
773
  if (!dirData) {
790
774
  warn('Store is missing directory data: ' + inode.data);
@@ -963,11 +947,9 @@ export class StoreFS extends FileSystem {
963
947
  const { dir: parentPath, base: fname } = parse(path);
964
948
  const parent = await this.findInode(tx, parentPath);
965
949
  const listing = decodeDirListing((await tx.get(parent.data)) ?? _throw(withErrno('ENOENT')));
966
- // Check if file already exists.
967
950
  if (listing[fname])
968
951
  throw withErrno('EEXIST');
969
952
  const id = this.allocNew(path);
970
- // Commit data.
971
953
  const inode = new Inode({
972
954
  ...options,
973
955
  ino: id,
@@ -977,7 +959,6 @@ export class StoreFS extends FileSystem {
977
959
  });
978
960
  await tx.set(inode.ino, inode);
979
961
  await tx.set(inode.data, data);
980
- // Update and commit parent directory listing.
981
962
  listing[fname] = inode.ino;
982
963
  await tx.set(parent.data, encodeDirListing(listing));
983
964
  await tx.commit();
@@ -1025,7 +1006,6 @@ export class StoreFS extends FileSystem {
1025
1006
  size: data.byteLength,
1026
1007
  nlink: 1,
1027
1008
  });
1028
- // Update and commit parent directory listing.
1029
1009
  tx.setSync(inode.ino, inode);
1030
1010
  tx.setSync(inode.data, data);
1031
1011
  listing[fname] = inode.ino;
@@ -162,7 +162,7 @@ export declare class WrappedTransaction<T extends Store = Store> {
162
162
  data?: Uint8Array;
163
163
  offset: number;
164
164
  }[]>;
165
- /**TransactionEntry
165
+ /**
166
166
  * List of keys modified in this transaction, if any.
167
167
  */
168
168
  protected modifiedKeys: Set<number>;
@@ -109,7 +109,7 @@ export class WrappedTransaction {
109
109
  * Allows us to roll back commits.
110
110
  */
111
111
  originalData = new Map();
112
- /**TransactionEntry
112
+ /**
113
113
  * List of keys modified in this transaction, if any.
114
114
  */
115
115
  modifiedKeys = new Set();
@@ -154,11 +154,9 @@ export class WrappedTransaction {
154
154
  async abort() {
155
155
  if (this.done)
156
156
  return;
157
- // Rollback old values.
158
157
  for (const [id, entries] of this.originalData) {
159
158
  if (!this.modifiedKeys.has(id))
160
159
  continue;
161
- // Key didn't exist.
162
160
  if (entries.some(ent => !ent.data)) {
163
161
  await this.raw.remove(id);
164
162
  this.fs._remove(id);
@@ -173,11 +171,9 @@ export class WrappedTransaction {
173
171
  abortSync() {
174
172
  if (this.done)
175
173
  return;
176
- // Rollback old values.
177
174
  for (const [id, entries] of this.originalData) {
178
175
  if (!this.modifiedKeys.has(id))
179
176
  continue;
180
- // Key didn't exist.
181
177
  if (entries.some(ent => !ent.data)) {
182
178
  this.raw.removeSync(id);
183
179
  this.fs._remove(id);
@@ -20,8 +20,7 @@ export interface FSContext {
20
20
  /** The unique ID of the context */
21
21
  readonly id: number;
22
22
  /**
23
- * The absolute root path of the context
24
- *
23
+ * The absolute root path of the context.
25
24
  * Note the parent's root is not considered
26
25
  */
27
26
  root: string;
@@ -11,9 +11,6 @@ export interface Credentials {
11
11
  sgid: number;
12
12
  euid: number;
13
13
  egid: number;
14
- /**
15
- * List of group IDs.
16
- */
17
14
  groups: number[];
18
15
  }
19
16
  /**
@@ -1,5 +1,4 @@
1
1
  // SPDX-License-Identifier: LGPL-3.0-or-later
2
- /* Note: this file is named file_index.ts because Typescript has special behavior regarding index.ts which can't be disabled. */
3
2
  import { withErrno } from 'kerium';
4
3
  import { sizeof } from 'memium';
5
4
  import { isJSON, randomInt } from 'utilium';
@@ -40,8 +40,8 @@ export declare abstract class IndexFS extends FileSystem {
40
40
  protected _mkdirSync?(path: string, options: CreationOptions): void;
41
41
  mkdir(path: string, options: CreationOptions): Promise<Inode>;
42
42
  mkdirSync(path: string, options: CreationOptions): Inode;
43
- link(target: string, link: string): Promise<void>;
44
- linkSync(target: string, link: string): void;
43
+ link(): Promise<void>;
44
+ linkSync(): void;
45
45
  readdir(path: string): Promise<string[]>;
46
46
  readdirSync(path: string): string[];
47
47
  sync(): Promise<void>;
@@ -200,10 +200,10 @@ export class IndexFS extends FileSystem {
200
200
  this._mkdirSync?.(path, options);
201
201
  return inode;
202
202
  }
203
- link(target, link) {
203
+ link() {
204
204
  throw withErrno('ENOSYS');
205
205
  }
206
- linkSync(target, link) {
206
+ linkSync() {
207
207
  throw withErrno('ENOSYS');
208
208
  }
209
209
  async readdir(path) {
@@ -32,61 +32,39 @@ export interface InodeFields {
32
32
  data?: number;
33
33
  flags?: number;
34
34
  version?: number;
35
+ /** Extended attributes */
36
+ attributes?: Attributes;
35
37
  }
36
- /**
37
- * @category Internals
38
- * @internal
39
- */
40
- export interface InodeLike<T extends number | bigint = number> extends InodeFields {
41
- /**
42
- * Size of the item in bytes.
43
- * For directories/symlinks, this is normally the size of the struct that represents the item.
44
- */
38
+ export interface StatsLike<T extends number | bigint = number | bigint> {
39
+ /** Size of the item in bytes. For directories/symlinks, this may be the size of the struct that represents the item. */
45
40
  size: T;
46
- /**
47
- * Unix-style file mode (e.g. 0o644) that includes the item type
48
- */
41
+ /** Unix-style file mode (e.g. 0o644) that includes the item type */
49
42
  mode: T;
50
- /**
51
- * Time of last access, since epoch
52
- */
43
+ /** Time of last access, since epoch */
53
44
  atimeMs: T;
54
- /**
55
- * Time of last modification, since epoch
56
- */
45
+ /** Time of last modification, since epoch */
57
46
  mtimeMs: T;
58
- /**
59
- * Time of last time file status was changed, since epoch
60
- */
47
+ /** Time of last time file status was changed, since epoch */
61
48
  ctimeMs: T;
62
- /**
63
- * Time of file creation, since epoch
64
- */
49
+ /** Time of file creation, since epoch */
65
50
  birthtimeMs: T;
66
- /**
67
- * The id of the user that owns the file
68
- */
51
+ /** The id of the user that owns the file */
69
52
  uid: T;
70
- /**
71
- * The id of the group that owns the file
72
- */
53
+ /** The id of the group that owns the file */
73
54
  gid: T;
74
- /**
75
- * Inode number
76
- */
55
+ /** Inode number */
77
56
  ino: T;
78
- /**
79
- * Number of hard links
80
- */
57
+ /** Number of hard links */
81
58
  nlink: T;
82
- /**
83
- * Device ID for special files
84
- */
59
+ /** Device ID for special files */
85
60
  rdev: T;
86
- /**
87
- * Extended attributes
88
- */
89
- attributes?: Attributes;
61
+ }
62
+ /**
63
+ * @category Internals
64
+ * @internal
65
+ * @todo [breaking] switch fully to using bigints
66
+ */
67
+ export interface InodeLike<T extends number | bigint = number> extends InodeFields, StatsLike<T> {
90
68
  }
91
69
  /**
92
70
  * @internal @hidden
@@ -100,15 +100,24 @@ export interface Message {
100
100
  method: Method;
101
101
  stack: string;
102
102
  }
103
- export interface Request<TMethod extends Method = Method> extends Message {
103
+ export interface RequestInit<TMethod extends Method = Method> {
104
104
  method: TMethod;
105
105
  args: Parameters<Methods[TMethod]>;
106
106
  }
107
- export interface Response<TMethod extends Method = Method> extends Message {
108
- error?: WithOptional<ExceptionJSON, 'code' | 'errno'>;
109
- method: TMethod;
110
- value: ReturnType<Methods[TMethod]>;
111
- }
107
+ export type Request<TMethod extends Method = Method> = {
108
+ [K in Method]: Message & RequestInit<K>;
109
+ }[TMethod];
110
+ export type Response<TMethod extends Method = Method> = {
111
+ [K in Method]: Message & {
112
+ error?: WithOptional<ExceptionJSON, 'code' | 'errno'>;
113
+ method: K;
114
+ /**
115
+ * This is undefined if an error occurs, and we check it at runtime.
116
+ * We don't do the type stuff because Typescript gets confused
117
+ */
118
+ value: ReturnType<Methods[K]>;
119
+ };
120
+ }[TMethod];
112
121
  /**
113
122
  * Encode a RPC message as a string using JSON.
114
123
  * This is only done when structured cloning is not available.
@@ -130,7 +139,7 @@ export interface Executor extends PromiseWithResolvers<any> {
130
139
  fs: PortFS;
131
140
  timeout: ReturnType<typeof setTimeout>;
132
141
  }
133
- export declare function request<const TRequest extends Request, TValue>(request: Omit<TRequest, 'id' | 'stack' | '_zenfs'>, { port, timeout: ms, fs }: Partial<Options> & {
142
+ export declare function request<const Init extends RequestInit, TValue>(request: Init, { port, timeout: ms, fs }: Partial<Options> & {
134
143
  fs: PortFS;
135
144
  }): Promise<TValue>;
136
145
  export declare function handleResponse<const TMethod extends Method>(response: Response<TMethod>): void;