@zenfs/core 1.11.4 → 2.1.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 (135) hide show
  1. package/dist/backends/backend.d.ts +19 -15
  2. package/dist/backends/backend.js +36 -19
  3. package/dist/backends/cow.d.ts +20 -30
  4. package/dist/backends/cow.js +83 -192
  5. package/dist/backends/fetch.d.ts +1 -0
  6. package/dist/backends/fetch.js +30 -30
  7. package/dist/backends/index.d.ts +1 -1
  8. package/dist/backends/index.js +1 -1
  9. package/dist/backends/memory.d.ts +5 -7
  10. package/dist/backends/memory.js +2 -3
  11. package/dist/backends/passthrough.d.ts +19 -23
  12. package/dist/backends/passthrough.js +98 -288
  13. package/dist/backends/port.d.ts +220 -0
  14. package/dist/backends/port.js +328 -0
  15. package/dist/backends/single_buffer.d.ts +59 -47
  16. package/dist/backends/single_buffer.js +468 -219
  17. package/dist/backends/store/fs.d.ts +25 -35
  18. package/dist/backends/store/fs.js +276 -315
  19. package/dist/backends/store/store.d.ts +10 -15
  20. package/dist/backends/store/store.js +11 -10
  21. package/dist/config.d.ts +3 -12
  22. package/dist/config.js +17 -19
  23. package/dist/context.d.ts +8 -21
  24. package/dist/context.js +33 -10
  25. package/dist/index.d.ts +2 -1
  26. package/dist/index.js +2 -1
  27. package/dist/internal/contexts.d.ts +63 -0
  28. package/dist/internal/contexts.js +15 -0
  29. package/dist/internal/credentials.d.ts +2 -11
  30. package/dist/internal/credentials.js +0 -19
  31. package/dist/internal/devices.d.ts +18 -80
  32. package/dist/internal/devices.js +103 -316
  33. package/dist/internal/error.d.ts +9 -204
  34. package/dist/internal/error.js +19 -288
  35. package/dist/internal/file_index.d.ts +1 -1
  36. package/dist/internal/file_index.js +11 -11
  37. package/dist/internal/filesystem.d.ts +51 -94
  38. package/dist/internal/filesystem.js +21 -20
  39. package/dist/internal/index.d.ts +1 -2
  40. package/dist/internal/index.js +1 -2
  41. package/dist/internal/index_fs.d.ts +12 -30
  42. package/dist/internal/index_fs.js +37 -69
  43. package/dist/internal/inode.d.ts +140 -24
  44. package/dist/internal/inode.js +515 -66
  45. package/dist/mixins/async.js +52 -112
  46. package/dist/mixins/mutexed.d.ts +19 -18
  47. package/dist/mixins/mutexed.js +62 -64
  48. package/dist/mixins/readonly.d.ts +7 -6
  49. package/dist/mixins/readonly.js +24 -18
  50. package/dist/mixins/sync.js +8 -8
  51. package/dist/{vfs/path.d.ts → path.d.ts} +3 -4
  52. package/dist/{vfs/path.js → path.js} +6 -9
  53. package/dist/polyfills.js +1 -1
  54. package/dist/readline.d.ts +134 -0
  55. package/dist/readline.js +623 -0
  56. package/dist/utils.d.ts +9 -37
  57. package/dist/utils.js +17 -85
  58. package/dist/vfs/acl.d.ts +42 -0
  59. package/dist/vfs/acl.js +268 -0
  60. package/dist/vfs/async.d.ts +9 -23
  61. package/dist/vfs/async.js +25 -27
  62. package/dist/vfs/config.d.ts +6 -18
  63. package/dist/vfs/config.js +8 -18
  64. package/dist/vfs/dir.d.ts +3 -3
  65. package/dist/vfs/dir.js +12 -12
  66. package/dist/vfs/file.d.ts +106 -0
  67. package/dist/vfs/file.js +244 -0
  68. package/dist/vfs/flags.d.ts +19 -0
  69. package/dist/vfs/flags.js +62 -0
  70. package/dist/vfs/index.d.ts +4 -10
  71. package/dist/vfs/index.js +4 -13
  72. package/dist/vfs/ioctl.d.ts +88 -0
  73. package/dist/vfs/ioctl.js +409 -0
  74. package/dist/vfs/promises.d.ts +81 -19
  75. package/dist/vfs/promises.js +404 -288
  76. package/dist/vfs/shared.d.ts +7 -37
  77. package/dist/vfs/shared.js +29 -85
  78. package/dist/{stats.d.ts → vfs/stats.d.ts} +14 -28
  79. package/dist/{stats.js → vfs/stats.js} +11 -66
  80. package/dist/vfs/streams.d.ts +1 -0
  81. package/dist/vfs/streams.js +32 -27
  82. package/dist/vfs/sync.d.ts +3 -3
  83. package/dist/vfs/sync.js +263 -260
  84. package/dist/vfs/watchers.d.ts +2 -2
  85. package/dist/vfs/watchers.js +12 -12
  86. package/dist/vfs/xattr.d.ts +116 -0
  87. package/dist/vfs/xattr.js +201 -0
  88. package/package.json +5 -3
  89. package/readme.md +1 -1
  90. package/scripts/test.js +2 -2
  91. package/tests/assignment.ts +1 -1
  92. package/tests/backend/config.worker.js +4 -1
  93. package/tests/backend/fetch.test.ts +3 -0
  94. package/tests/backend/port.test.ts +19 -33
  95. package/tests/backend/remote.worker.js +4 -1
  96. package/tests/backend/single-buffer.test.ts +53 -0
  97. package/tests/backend/single-buffer.worker.js +30 -0
  98. package/tests/common/context.test.ts +3 -3
  99. package/tests/common/handle.test.ts +17 -12
  100. package/tests/common/mutex.test.ts +9 -9
  101. package/tests/common/path.test.ts +1 -1
  102. package/tests/common/readline.test.ts +104 -0
  103. package/tests/common.ts +4 -19
  104. package/tests/fetch/fetch.ts +2 -2
  105. package/tests/fs/append.test.ts +4 -4
  106. package/tests/fs/directory.test.ts +25 -25
  107. package/tests/fs/errors.test.ts +15 -19
  108. package/tests/fs/links.test.ts +4 -3
  109. package/tests/fs/open.test.ts +4 -21
  110. package/tests/fs/permissions.test.ts +14 -18
  111. package/tests/fs/read.test.ts +10 -9
  112. package/tests/fs/readFile.test.ts +10 -26
  113. package/tests/fs/rename.test.ts +4 -9
  114. package/tests/fs/stat.test.ts +8 -8
  115. package/tests/fs/streams.test.ts +2 -11
  116. package/tests/fs/times.test.ts +7 -7
  117. package/tests/fs/truncate.test.ts +8 -36
  118. package/tests/fs/watch.test.ts +10 -10
  119. package/tests/fs/write.test.ts +77 -13
  120. package/tests/fs/xattr.test.ts +85 -0
  121. package/tests/logs.js +22 -0
  122. package/tests/setup/context.ts +1 -1
  123. package/tests/setup/index.ts +3 -3
  124. package/tests/setup/port.ts +7 -1
  125. package/dist/backends/port/fs.d.ts +0 -84
  126. package/dist/backends/port/fs.js +0 -151
  127. package/dist/backends/port/rpc.d.ts +0 -77
  128. package/dist/backends/port/rpc.js +0 -100
  129. package/dist/backends/store/simple.d.ts +0 -20
  130. package/dist/backends/store/simple.js +0 -13
  131. package/dist/internal/file.d.ts +0 -359
  132. package/dist/internal/file.js +0 -751
  133. package/dist/internal/log.d.ts +0 -133
  134. package/dist/internal/log.js +0 -218
  135. package/tests/fs/writeFile.test.ts +0 -70
@@ -1,6 +1,6 @@
1
+ import type { UUID } from 'node:crypto';
1
2
  import type { ConstMap } from 'utilium';
2
- import type { Stats, StatsLike } from '../stats.js';
3
- import type { File } from './file.js';
3
+ import type { InodeLike } from './inode.js';
4
4
  /**
5
5
  * Usage information about a file system
6
6
  * @category Internals
@@ -29,46 +29,6 @@ export interface UsageInfo {
29
29
  */
30
30
  freeNodes?: number;
31
31
  }
32
- /**
33
- * Metadata about a FileSystem
34
- * @category Internals
35
- * @deprecated
36
- */
37
- export interface FileSystemMetadata extends UsageInfo {
38
- /**
39
- * The name of the FS
40
- * @deprecated Use `FileSystem#name`
41
- */
42
- name: string;
43
- /**
44
- * Whether the FS is readonly or not
45
- * @deprecated Use `FileSystem#attributes
46
- */
47
- readonly: boolean;
48
- /**
49
- * If set, disables File from using a resizable array buffer.
50
- * @default false
51
- * @deprecated Use `FileSystem#attributes`
52
- */
53
- noResizableBuffers: boolean;
54
- /**
55
- * If set, disables caching on async file systems.
56
- * This means *sync operations will not work*.
57
- * It has no affect on sync file systems.
58
- * @default false
59
- * @deprecated Use `FileSystem#attributes
60
- */
61
- noAsyncCache: boolean;
62
- /**
63
- * The type of the FS
64
- */
65
- type: number;
66
- /**
67
- * Various features the file system supports.
68
- * @deprecated Use `FileSystem#attributes`
69
- */
70
- features?: unknown[];
71
- }
72
32
  /**
73
33
  * Attributes that control how the file system interacts with the VFS.
74
34
  * No options are set by default.
@@ -76,24 +36,22 @@ export interface FileSystemMetadata extends UsageInfo {
76
36
  * @internal
77
37
  */
78
38
  export type FileSystemAttributes = {
79
- /** The FS supports setuid and setgid when creating files and directories. */
80
- setid: void;
81
- /** If set, disables `PreloadFile` from using a resizable array buffer. */
82
- no_buffer_resize: void;
83
39
  /**
84
40
  * If set disables async file systems from preloading their contents.
85
41
  * This means *sync operations will not work* (unless the contents are cached)
86
42
  * It has no affect on sync file systems.
87
43
  */
88
- no_async: void;
44
+ no_async_preload: void;
89
45
  /**
90
46
  * Currently unused. In the future, this will disable caching.
91
- * Not recommended due to performance impact.
47
+ * Analogous to `S_DAX` on every file.
92
48
  */
93
49
  no_cache: void;
94
50
  /**
95
51
  * If set, the file system should not be written to.
96
52
  * This should be set for read-only file systems.
53
+ * Note this does NOT trigger EROFS errors;
54
+ * writes will silently be dropped.
97
55
  */
98
56
  no_write: void;
99
57
  /**
@@ -106,15 +64,29 @@ export type FileSystemAttributes = {
106
64
  * @internal
107
65
  */
108
66
  default_stream_write: void;
67
+ /**
68
+ * Do not update access times.
69
+ */
70
+ no_atime: void;
71
+ /**
72
+ * Ignore suid and sgid bits.
73
+ * @todo Implement
74
+ * @experimental
75
+ */
76
+ no_suid: void;
77
+ /**
78
+ * Writes are synced at once
79
+ * @experimental
80
+ */
81
+ sync: void;
109
82
  };
110
83
  /**
111
84
  * Options used when creating files and directories.
112
85
  * This weird naming and such is to preserve backward compatibility.
113
- * @todo [BREAKING] Move the `mode` parameter of `createFile` and `mkdir` into this
114
86
  * @category Internals
115
87
  * @internal
116
88
  */
117
- export interface CreationOptions {
89
+ export interface CreationOptions extends Partial<InodeLike> {
118
90
  /**
119
91
  * The uid to create the file.
120
92
  * This is ignored if the FS supports setuid and the setuid bit is set
@@ -125,23 +97,14 @@ export interface CreationOptions {
125
97
  * This is ignored if the FS supports setgid and the setgid bit is set
126
98
  */
127
99
  gid: number;
128
- /**
129
- * The mode to create the file with.
130
- */
131
- mode?: number;
132
- }
133
- /**
134
- * This is the correct type that will be used when the API is updated in a breaking release
135
- * @category Internals
136
- * @internal
137
- */
138
- export interface PureCreationOptions extends CreationOptions {
139
100
  /**
140
101
  * The mode to create the file with.
141
102
  */
142
103
  mode: number;
143
104
  }
144
105
  /**
106
+ * Options for streaming operations
107
+ * @category Internals
145
108
  * @internal
146
109
  */
147
110
  export interface StreamOptions {
@@ -160,7 +123,7 @@ export declare abstract class FileSystem {
160
123
  * A unique ID for this kind of file system.
161
124
  * Currently unused internally, but could be used for partition tables or something
162
125
  */
163
- readonly id: number;
126
+ readonly type: number;
164
127
  /**
165
128
  * The name for this file system.
166
129
  * For example, tmpfs for an in memory one
@@ -172,6 +135,13 @@ export declare abstract class FileSystem {
172
135
  * @internal @protected
173
136
  */
174
137
  _mountPoint?: string;
138
+ /**
139
+ * The UUID of the file system.
140
+ * @privateRemarks This is only used by `ioctl`
141
+ * @internal @protected
142
+ */
143
+ _uuid: UUID;
144
+ get uuid(): UUID;
175
145
  /**
176
146
  * @see FileSystemAttributes
177
147
  */
@@ -181,7 +151,7 @@ export declare abstract class FileSystem {
181
151
  * A unique ID for this kind of file system.
182
152
  * Currently unused internally, but could be used for partition tables or something
183
153
  */
184
- id: number,
154
+ type: number,
185
155
  /**
186
156
  * The name for this file system.
187
157
  * For example, tmpfs for an in memory one
@@ -194,42 +164,29 @@ export declare abstract class FileSystem {
194
164
  * @experimental
195
165
  */
196
166
  usage(): UsageInfo;
197
- /**
198
- * Get metadata about the current file system
199
- * @deprecated
200
- */
201
- metadata(): FileSystemMetadata;
202
167
  ready(): Promise<void>;
203
168
  abstract rename(oldPath: string, newPath: string): Promise<void>;
204
169
  abstract renameSync(oldPath: string, newPath: string): void;
205
- abstract stat(path: string): Promise<Stats>;
206
- abstract statSync(path: string): Stats;
207
- /**
208
- * Opens the file at `path` with `flag`. The file must exist.
209
- * @param path The path to open.
210
- * @param flag The flag to use when opening the file.
211
- */
212
- abstract openFile(path: string, flag: string): Promise<File>;
213
- /**
214
- * Opens the file at `path` with `flag`. The file must exist.
215
- * @param path The path to open.
216
- * @param flag The flag to use when opening the file.
217
- */
218
- abstract openFileSync(path: string, flag: string): File;
170
+ abstract stat(path: string): Promise<InodeLike>;
171
+ abstract statSync(path: string): InodeLike;
172
+ /** Modify metadata. */
173
+ abstract touch(path: string, metadata: Partial<InodeLike>): Promise<void>;
174
+ /** Modify metadata. */
175
+ abstract touchSync(path: string, metadata: Partial<InodeLike>): void;
219
176
  /**
220
- * Create the file at `path` with the given options. Then, open it with `flag`.
177
+ * Create the file at `path` with the given options.
221
178
  */
222
- abstract createFile(path: string, flag: string, mode: number, options: CreationOptions): Promise<File>;
179
+ abstract createFile(path: string, options: CreationOptions): Promise<InodeLike>;
223
180
  /**
224
- * Create the file at `path` with the given options. Then, open it with `flag`.
181
+ * Create the file at `path` with the given options.
225
182
  */
226
- abstract createFileSync(path: string, flag: string, mode: number, options: CreationOptions): File;
183
+ abstract createFileSync(path: string, options: CreationOptions): InodeLike;
227
184
  abstract unlink(path: string): Promise<void>;
228
185
  abstract unlinkSync(path: string): void;
229
186
  abstract rmdir(path: string): Promise<void>;
230
187
  abstract rmdirSync(path: string): void;
231
- abstract mkdir(path: string, mode: number, options: CreationOptions): Promise<void>;
232
- abstract mkdirSync(path: string, mode: number, options: CreationOptions): void;
188
+ abstract mkdir(path: string, options: CreationOptions): Promise<InodeLike>;
189
+ abstract mkdirSync(path: string, options: CreationOptions): InodeLike;
233
190
  abstract readdir(path: string): Promise<string[]>;
234
191
  abstract readdirSync(path: string): string[];
235
192
  /**
@@ -242,22 +199,22 @@ export declare abstract class FileSystem {
242
199
  existsSync(path: string): boolean;
243
200
  abstract link(target: string, link: string): Promise<void>;
244
201
  abstract linkSync(target: string, link: string): void;
245
- abstract sync(path: string, data?: Uint8Array, stats?: Readonly<Partial<StatsLike>>): Promise<void>;
246
- abstract syncSync(path: string, data?: Uint8Array, stats?: Readonly<Partial<StatsLike>>): void;
202
+ abstract sync(): Promise<void>;
203
+ abstract syncSync(): void;
247
204
  /**
248
205
  * Reads into a buffer
249
206
  * @param buffer The buffer to read into. You must set the `byteOffset` and `byteLength` appropriately!
250
- * @param offset The offset into the file to start reading from
207
+ * @param start The offset into the file to start reading from
251
208
  * @param end The position in the file to stop reading
252
209
  */
253
- abstract read(path: string, buffer: Uint8Array, offset: number, end: number): Promise<void>;
210
+ abstract read(path: string, buffer: Uint8Array, start: number, end: number): Promise<void>;
254
211
  /**
255
212
  * Reads into a buffer
256
213
  * @param buffer The buffer to read into. You must set the `byteOffset` and `byteLength` appropriately!
257
- * @param offset The offset into the file to start reading from
214
+ * @param start The offset into the file to start reading from
258
215
  * @param end The position in the file to stop reading
259
216
  */
260
- abstract readSync(path: string, buffer: Uint8Array, offset: number, end: number): void;
217
+ abstract readSync(path: string, buffer: Uint8Array, start: number, end: number): void;
261
218
  /**
262
219
  * Writes a buffer to a file
263
220
  * @param buffer The buffer to write. You must set the `byteOffset` and `byteLength` appropriately!
@@ -7,19 +7,28 @@ const _chunkSize = 0x1000;
7
7
  * @internal
8
8
  */
9
9
  export class FileSystem {
10
+ get uuid() {
11
+ return this._uuid;
12
+ }
10
13
  constructor(
11
14
  /**
12
15
  * A unique ID for this kind of file system.
13
16
  * Currently unused internally, but could be used for partition tables or something
14
17
  */
15
- id,
18
+ type,
16
19
  /**
17
20
  * The name for this file system.
18
21
  * For example, tmpfs for an in memory one
19
22
  */
20
23
  name) {
21
- this.id = id;
24
+ this.type = type;
22
25
  this.name = name;
26
+ /**
27
+ * The UUID of the file system.
28
+ * @privateRemarks This is only used by `ioctl`
29
+ * @internal @protected
30
+ */
31
+ this._uuid = crypto.randomUUID();
23
32
  /**
24
33
  * @see FileSystemAttributes
25
34
  */
@@ -44,23 +53,6 @@ export class FileSystem {
44
53
  freeSpace: 0,
45
54
  };
46
55
  }
47
- /* node:coverage disable */
48
- /**
49
- * Get metadata about the current file system
50
- * @deprecated
51
- */
52
- metadata() {
53
- return {
54
- ...this.usage(),
55
- name: this.name,
56
- readonly: this.attributes.has('no_write'),
57
- noResizableBuffers: this.attributes.has('no_buffer_resize'),
58
- noAsyncCache: this.attributes.has('no_async'),
59
- features: Array.from(this.attributes.keys()),
60
- type: this.id,
61
- };
62
- }
63
- /* node:coverage enable */
64
56
  async ready() { }
65
57
  /**
66
58
  * Test whether or not `path` exists.
@@ -115,8 +107,17 @@ export class FileSystem {
115
107
  let position = (_a = options.start) !== null && _a !== void 0 ? _a : 0;
116
108
  return new WritableStream({
117
109
  write: async (chunk, controller) => {
118
- await this.write(path, chunk, position).catch(controller.error.bind(controller));
110
+ let err = false;
111
+ const _err = (ex) => {
112
+ err = true;
113
+ controller.error(ex);
114
+ };
115
+ const { size } = await this.stat(path);
116
+ await this.write(path, chunk, position).catch(_err);
117
+ if (err)
118
+ return;
119
119
  position += chunk.byteLength;
120
+ await this.touch(path, { mtimeMs: Date.now(), size: Math.max(size, position) }).catch(_err);
120
121
  },
121
122
  });
122
123
  }
@@ -1,9 +1,8 @@
1
+ export { log } from 'kerium';
1
2
  export * from './credentials.js';
2
3
  export * from './devices.js';
3
4
  export * from './error.js';
4
5
  export * from './file_index.js';
5
- export * from './file.js';
6
6
  export * from './filesystem.js';
7
7
  export * from './index_fs.js';
8
8
  export * from './inode.js';
9
- export * as log from './log.js';
@@ -1,9 +1,8 @@
1
+ export { log } from 'kerium'; // DO NOT USE
1
2
  export * from './credentials.js';
2
3
  export * from './devices.js';
3
4
  export * from './error.js';
4
5
  export * from './file_index.js';
5
- export * from './file.js';
6
6
  export * from './filesystem.js';
7
7
  export * from './index_fs.js';
8
8
  export * from './inode.js';
9
- export * as log from './log.js';
@@ -1,7 +1,5 @@
1
- import { Stats } from '../stats.js';
2
- import { type File } from './file.js';
3
1
  import { Index } from './file_index.js';
4
- import { FileSystem, type CreationOptions, type PureCreationOptions, type UsageInfo } from './filesystem.js';
2
+ import { FileSystem, type CreationOptions, type UsageInfo } from './filesystem.js';
5
3
  import { Inode, type InodeLike } from './inode.js';
6
4
  /**
7
5
  * A file system that uses an `Index` for metadata.
@@ -12,24 +10,16 @@ export declare abstract class IndexFS extends FileSystem {
12
10
  readonly index: Index;
13
11
  constructor(id: number, name: string, index?: Index);
14
12
  usage(): UsageInfo;
15
- /**
16
- * @deprecated
17
- */
18
- reloadFiles(): never;
19
- /**
20
- * @deprecated
21
- */
22
- reloadFilesSync(): never;
23
13
  /**
24
14
  * Finds all the paths in the index that need to be moved for a rename
25
15
  */
26
16
  private pathsForRename;
27
17
  rename(oldPath: string, newPath: string): Promise<void>;
28
18
  renameSync(oldPath: string, newPath: string): void;
29
- stat(path: string): Promise<Stats>;
30
- statSync(path: string): Stats;
31
- openFile(path: string, flag: string): Promise<File>;
32
- openFileSync(path: string, flag: string): File;
19
+ stat(path: string): Promise<Inode>;
20
+ statSync(path: string): Inode;
21
+ touch(path: string, metadata: InodeLike): Promise<void>;
22
+ touchSync(path: string, metadata: InodeLike): void;
33
23
  protected _remove(path: string, isUnlink: boolean): void;
34
24
  protected abstract remove(path: string): Promise<void>;
35
25
  protected abstract removeSync(path: string): void;
@@ -37,23 +27,15 @@ export declare abstract class IndexFS extends FileSystem {
37
27
  unlinkSync(path: string): void;
38
28
  rmdir(path: string): Promise<void>;
39
29
  rmdirSync(path: string): void;
40
- protected create(path: string, options: PureCreationOptions): Inode;
41
- createFile(path: string, flag: string, mode: number, options: CreationOptions): Promise<File>;
42
- createFileSync(path: string, flag: string, mode: number, options: CreationOptions): File;
43
- mkdir(path: string, mode: number, options: CreationOptions): Promise<void>;
44
- mkdirSync(path: string, mode: number, options: CreationOptions): void;
30
+ protected create(path: string, options: CreationOptions): Inode;
31
+ createFile(path: string, options: CreationOptions): Promise<InodeLike>;
32
+ createFileSync(path: string, options: CreationOptions): InodeLike;
33
+ mkdir(path: string, options: CreationOptions): Promise<InodeLike>;
34
+ mkdirSync(path: string, options: CreationOptions): InodeLike;
45
35
  link(target: string, link: string): Promise<void>;
46
36
  linkSync(target: string, link: string): void;
47
37
  readdir(path: string): Promise<string[]>;
48
38
  readdirSync(path: string): string[];
49
- /**
50
- * Optional hook for implementations to support updating metadata
51
- */
52
- protected syncMetadata?(path: string, metadata: Readonly<InodeLike>): Promise<void>;
53
- sync(path: string, data?: Uint8Array, stats?: Readonly<InodeLike>): Promise<void>;
54
- /**
55
- * Optional hook for implementations to support updating metadata
56
- */
57
- protected syncMetadataSync?(path: string, metadata: Readonly<InodeLike>): void;
58
- syncSync(path: string, data?: Uint8Array, stats?: Readonly<InodeLike>): void;
39
+ sync(): Promise<void>;
40
+ syncSync(): void;
59
41
  }
@@ -1,10 +1,8 @@
1
1
  /* eslint-disable @typescript-eslint/require-await */
2
+ import { withErrno } from 'kerium';
2
3
  import { _throw } from 'utilium';
3
- import { Stats } from '../stats.js';
4
+ import { dirname, join, relative } from '../path.js';
4
5
  import { S_IFDIR, S_IFMT, S_IFREG, S_ISGID, S_ISUID } from '../vfs/constants.js';
5
- import { dirname, join, relative } from '../vfs/path.js';
6
- import { ErrnoError } from './error.js';
7
- import { LazyFile } from './file.js';
8
6
  import { Index } from './file_index.js';
9
7
  import { FileSystem } from './filesystem.js';
10
8
  import { Inode } from './inode.js';
@@ -21,28 +19,14 @@ export class IndexFS extends FileSystem {
21
19
  usage() {
22
20
  return this.index.usage();
23
21
  }
24
- /* node:coverage disable */
25
- /**
26
- * @deprecated
27
- */
28
- reloadFiles() {
29
- throw ErrnoError.With('ENOTSUP');
30
- }
31
- /**
32
- * @deprecated
33
- */
34
- reloadFilesSync() {
35
- throw ErrnoError.With('ENOTSUP');
36
- }
37
- /* node:coverage enable */
38
22
  /**
39
23
  * Finds all the paths in the index that need to be moved for a rename
40
24
  */
41
25
  pathsForRename(oldPath, newPath) {
42
26
  if (!this.index.has(oldPath))
43
- throw ErrnoError.With('ENOENT', oldPath, 'rename');
27
+ throw withErrno('ENOENT');
44
28
  if ((dirname(newPath) + '/').startsWith(oldPath + '/'))
45
- throw ErrnoError.With('EBUSY', dirname(oldPath), 'rename');
29
+ throw withErrno('EBUSY');
46
30
  const toRename = [];
47
31
  for (const [from, inode] of this.index.entries()) {
48
32
  const rel = relative(oldPath, from);
@@ -82,35 +66,36 @@ export class IndexFS extends FileSystem {
82
66
  async stat(path) {
83
67
  const inode = this.index.get(path);
84
68
  if (!inode)
85
- throw ErrnoError.With('ENOENT', path, 'stat');
86
- return new Stats(inode);
69
+ throw withErrno('ENOENT');
70
+ return inode;
87
71
  }
88
72
  statSync(path) {
89
73
  const inode = this.index.get(path);
90
74
  if (!inode)
91
- throw ErrnoError.With('ENOENT', path, 'stat');
92
- return new Stats(inode);
75
+ throw withErrno('ENOENT');
76
+ return inode;
93
77
  }
94
- async openFile(path, flag) {
78
+ async touch(path, metadata) {
95
79
  var _a;
96
- const stats = (_a = this.index.get(path)) !== null && _a !== void 0 ? _a : _throw(ErrnoError.With('ENOENT', path, 'openFile'));
97
- return new LazyFile(this, path, flag, stats);
80
+ const inode = (_a = this.index.get(path)) !== null && _a !== void 0 ? _a : _throw(withErrno('ENOENT'));
81
+ inode.update(metadata);
98
82
  }
99
- openFileSync(path, flag) {
83
+ touchSync(path, metadata) {
100
84
  var _a;
101
- const stats = (_a = this.index.get(path)) !== null && _a !== void 0 ? _a : _throw(ErrnoError.With('ENOENT', path, 'openFile'));
102
- return new LazyFile(this, path, flag, stats);
85
+ const inode = (_a = this.index.get(path)) !== null && _a !== void 0 ? _a : _throw(withErrno('ENOENT'));
86
+ inode.update(metadata);
103
87
  }
104
88
  _remove(path, isUnlink) {
105
- const syscall = isUnlink ? 'unlink' : 'rmdir';
106
89
  const inode = this.index.get(path);
107
90
  if (!inode)
108
- throw ErrnoError.With('ENOENT', path, syscall);
91
+ throw withErrno('ENOENT');
109
92
  const isDir = (inode.mode & S_IFMT) == S_IFDIR;
110
93
  if (!isDir && !isUnlink)
111
- throw ErrnoError.With('ENOTDIR', path, syscall);
94
+ throw withErrno('ENOTDIR');
112
95
  if (isDir && isUnlink)
113
- throw ErrnoError.With('EISDIR', path, syscall);
96
+ throw withErrno('EISDIR');
97
+ if (isDir && this.readdirSync(path).length)
98
+ throw withErrno('ENOTEMPTY');
114
99
  this.index.delete(path);
115
100
  }
116
101
  async unlink(path) {
@@ -130,12 +115,11 @@ export class IndexFS extends FileSystem {
130
115
  this.removeSync(path);
131
116
  }
132
117
  create(path, options) {
133
- const syscall = (options.mode & S_IFMT) == S_IFDIR ? 'mkdir' : 'createFile';
134
118
  if (this.index.has(path))
135
- throw ErrnoError.With('EEXIST', path, syscall);
119
+ throw withErrno('EEXIST');
136
120
  const parent = this.index.get(dirname(path));
137
121
  if (!parent)
138
- throw ErrnoError.With('ENOENT', dirname(path), syscall);
122
+ throw withErrno('ENOENT');
139
123
  const id = this.index._alloc();
140
124
  const inode = new Inode({
141
125
  ino: id,
@@ -148,25 +132,27 @@ export class IndexFS extends FileSystem {
148
132
  this.index.set(path, inode);
149
133
  return inode;
150
134
  }
151
- async createFile(path, flag, mode, options) {
152
- const node = this.create(path, { mode: mode | S_IFREG, ...options });
153
- return new LazyFile(this, path, flag, node.toStats());
135
+ async createFile(path, options) {
136
+ options.mode |= S_IFREG;
137
+ return this.create(path, options);
154
138
  }
155
- createFileSync(path, flag, mode, options) {
156
- const node = this.create(path, { mode: mode | S_IFREG, ...options });
157
- return new LazyFile(this, path, flag, node.toStats());
139
+ createFileSync(path, options) {
140
+ options.mode |= S_IFREG;
141
+ return this.create(path, options);
158
142
  }
159
- async mkdir(path, mode, options) {
160
- this.create(path, { mode: mode | S_IFDIR, ...options });
143
+ async mkdir(path, options) {
144
+ options.mode |= S_IFDIR;
145
+ return this.create(path, options);
161
146
  }
162
- mkdirSync(path, mode, options) {
163
- this.create(path, { mode: mode | S_IFDIR, ...options });
147
+ mkdirSync(path, options) {
148
+ options.mode |= S_IFDIR;
149
+ return this.create(path, options);
164
150
  }
165
151
  link(target, link) {
166
- throw ErrnoError.With('ENOSYS', link, 'link');
152
+ throw withErrno('ENOSYS');
167
153
  }
168
154
  linkSync(target, link) {
169
- throw ErrnoError.With('ENOSYS', link, 'link');
155
+ throw withErrno('ENOSYS');
170
156
  }
171
157
  async readdir(path) {
172
158
  return Object.keys(this.index.directoryEntries(path));
@@ -174,24 +160,6 @@ export class IndexFS extends FileSystem {
174
160
  readdirSync(path) {
175
161
  return Object.keys(this.index.directoryEntries(path));
176
162
  }
177
- async sync(path, data, stats) {
178
- var _a;
179
- const inode = this.index.get(path);
180
- if (!inode)
181
- throw ErrnoError.With('ENOENT', path, 'sync');
182
- if (inode.update(stats))
183
- await ((_a = this.syncMetadata) === null || _a === void 0 ? void 0 : _a.call(this, path, stats));
184
- if (data)
185
- await this.write(path, data, 0);
186
- }
187
- syncSync(path, data, stats) {
188
- var _a;
189
- const inode = this.index.get(path);
190
- if (!inode)
191
- throw ErrnoError.With('ENOENT', path, 'sync');
192
- if (inode.update(stats))
193
- (_a = this.syncMetadataSync) === null || _a === void 0 ? void 0 : _a.call(this, path, stats);
194
- if (data)
195
- this.writeSync(path, data, 0);
196
- }
163
+ async sync() { }
164
+ syncSync() { }
197
165
  }