@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
@@ -13,8 +13,7 @@ export declare const version = 1;
13
13
  * An index of files
14
14
  * @internal
15
15
  */
16
- export declare class Index extends Map<string, Readonly<Inode>> {
17
- protected _directories?: Map<string, Record<string, number>>;
16
+ export declare class Index extends Map<string, Inode> {
18
17
  /**
19
18
  * Converts the index to JSON
20
19
  */
@@ -23,7 +22,18 @@ export declare class Index extends Map<string, Readonly<Inode>> {
23
22
  * Converts the index to a string
24
23
  */
25
24
  toString(): string;
25
+ pathOf(id: number): string | undefined;
26
+ getByID(id: number): Inode | undefined;
27
+ entryByID(id: number): {
28
+ path: string;
29
+ inode: Inode;
30
+ } | undefined;
26
31
  directoryEntries(path: string): Record<string, number>;
32
+ /**
33
+ * Get the next available ID in the index
34
+ * @internal
35
+ */
36
+ _alloc(): number;
27
37
  /**
28
38
  * Gets a list of entries for each directory in the index.
29
39
  * Use
@@ -32,7 +42,7 @@ export declare class Index extends Map<string, Readonly<Inode>> {
32
42
  /**
33
43
  * Loads the index from JSON data
34
44
  */
35
- fromJSON(json: IndexData): void;
45
+ fromJSON(json: IndexData): this;
36
46
  /**
37
47
  * Parses an index from a string
38
48
  */
@@ -1,8 +1,8 @@
1
1
  /* Note: this file is named file_index.ts because Typescript has special behavior regarding index.ts which can't be disabled. */
2
2
  import { isJSON, randomInt } from 'utilium';
3
- import { Errno, ErrnoError } from '../../error.js';
4
- import { S_IFDIR, S_IFMT, size_max } from '../../vfs/constants.js';
5
- import { basename, dirname } from '../../vfs/path.js';
3
+ import { S_IFDIR, S_IFMT, size_max } from '../vfs/constants.js';
4
+ import { basename, dirname } from '../vfs/path.js';
5
+ import { Errno, ErrnoError } from './error.js';
6
6
  import { Inode } from './inode.js';
7
7
  export const version = 1;
8
8
  /**
@@ -25,6 +25,22 @@ export class Index extends Map {
25
25
  toString() {
26
26
  return JSON.stringify(this.toJSON());
27
27
  }
28
+ pathOf(id) {
29
+ for (const [path, inode] of this) {
30
+ if (inode.ino == id || inode.data == id)
31
+ return path;
32
+ }
33
+ }
34
+ getByID(id) {
35
+ var _a;
36
+ return (_a = this.entryByID(id)) === null || _a === void 0 ? void 0 : _a.inode;
37
+ }
38
+ entryByID(id) {
39
+ for (const [path, inode] of this) {
40
+ if (inode.ino == id || inode.data == id)
41
+ return { path, inode };
42
+ }
43
+ }
28
44
  directoryEntries(path) {
29
45
  const node = this.get(path);
30
46
  if (!node)
@@ -39,6 +55,13 @@ export class Index extends Map {
39
55
  }
40
56
  return entries;
41
57
  }
58
+ /**
59
+ * Get the next available ID in the index
60
+ * @internal
61
+ */
62
+ _alloc() {
63
+ return Math.max(...[...this.values()].flatMap(i => [i.ino, i.data])) + 1;
64
+ }
42
65
  /**
43
66
  * Gets a list of entries for each directory in the index.
44
67
  * Use
@@ -72,14 +95,14 @@ export class Index extends Map {
72
95
  node.ino = 0;
73
96
  this.set(path, new Inode(node));
74
97
  }
98
+ return this;
75
99
  }
76
100
  /**
77
101
  * Parses an index from a string
78
102
  */
79
103
  static parse(data) {
80
- if (!isJSON(data)) {
104
+ if (!isJSON(data))
81
105
  throw new ErrnoError(Errno.EINVAL, 'Invalid JSON');
82
- }
83
106
  const json = JSON.parse(data);
84
107
  const index = new Index();
85
108
  index.fromJSON(json);
@@ -1,29 +1,51 @@
1
+ import type { ConstMap } from 'utilium';
2
+ import type { Stats, StatsLike } from '../stats.js';
1
3
  import type { File } from './file.js';
2
- import type { Stats, StatsLike } from './stats.js';
3
- export type FileContents = ArrayBufferView | string;
4
+ /**
5
+ * Usage information about a file system
6
+ */
7
+ export interface UsageInfo {
8
+ /**
9
+ * The total space
10
+ */
11
+ totalSpace: number;
12
+ /**
13
+ * The available space
14
+ */
15
+ freeSpace: number;
16
+ /**
17
+ * The optimal block size to use with the file system
18
+ * @default 4096
19
+ */
20
+ blockSize?: number;
21
+ /**
22
+ * Total number of nodes available
23
+ */
24
+ totalNodes?: number;
25
+ /**
26
+ * Number of free nodes available
27
+ */
28
+ freeNodes?: number;
29
+ }
4
30
  /**
5
31
  * Metadata about a FileSystem
32
+ * @deprecated
6
33
  */
7
- export interface FileSystemMetadata {
34
+ export interface FileSystemMetadata extends UsageInfo {
8
35
  /**
9
36
  * The name of the FS
37
+ * @deprecated Use `FileSystem#name`
10
38
  */
11
39
  name: string;
12
40
  /**
13
41
  * Whether the FS is readonly or not
42
+ * @deprecated Use `FileSystem#attributes
14
43
  */
15
44
  readonly: boolean;
16
- /**
17
- * The total space
18
- */
19
- totalSpace: number;
20
- /**
21
- * The available space
22
- */
23
- freeSpace: number;
24
45
  /**
25
46
  * If set, disables File from using a resizable array buffer.
26
47
  * @default false
48
+ * @deprecated Use `FileSystem#attributes`
27
49
  */
28
50
  noResizableBuffers: boolean;
29
51
  /**
@@ -31,32 +53,45 @@ export interface FileSystemMetadata {
31
53
  * This means *sync operations will not work*.
32
54
  * It has no affect on sync file systems.
33
55
  * @default false
56
+ * @deprecated Use `FileSystem#attributes
34
57
  */
35
58
  noAsyncCache: boolean;
36
59
  /**
37
- * The optimal block size to use with the file system
38
- * @default 4096
60
+ * The type of the FS
39
61
  */
40
- blockSize?: number;
62
+ type: number;
41
63
  /**
42
- * Total number of (file) nodes available
64
+ * Various features the file system supports.
65
+ * @deprecated Use `FileSystem#attributes`
43
66
  */
44
- totalNodes?: number;
45
- /**
46
- * Number of free (file) nodes available
67
+ features?: unknown[];
68
+ }
69
+ /**
70
+ * Attributes that control how the file system interacts with the VFS.
71
+ * No options are set by default.
72
+ */
73
+ export type FileSystemAttributes = {
74
+ /** The FS supports setuid and setgid when creating files and directories. */
75
+ setid: void;
76
+ /** If set, disables `PreloadFile` from using a resizable array buffer. */
77
+ no_buffer_resize: void;
78
+ /**
79
+ * If set disables async file systems from preloading their contents.
80
+ * This means *sync operations will not work* (unless the contents are cached)
81
+ * It has no affect on sync file systems.
47
82
  */
48
- freeNodes?: number;
83
+ no_async: void;
49
84
  /**
50
- * The type of the FS
85
+ * Currently unused. In the future, this will disable caching.
86
+ * Not recommended due to performance impact.
51
87
  */
52
- type: number;
88
+ no_cache: void;
53
89
  /**
54
- * Various features the file system supports.
55
- * These are used by the VFS for optimizations.
56
- * - setid: The FS supports setuid and setgid when creating files and directories.
90
+ * If set, the file system should not be written to.
91
+ * This should be set for read-only file systems.
57
92
  */
58
- features?: ('setid' | '')[];
59
- }
93
+ no_write: void;
94
+ };
60
95
  /**
61
96
  * Options used when creating files and directories.
62
97
  * This weird naming and such is to preserve backward compatibility.
@@ -96,16 +131,48 @@ export interface PureCreationOptions extends CreationOptions {
96
131
  */
97
132
  export declare abstract class FileSystem {
98
133
  /**
99
- * Get metadata about the current file system
134
+ * A unique ID for this kind of file system.
135
+ * Currently unused internally, but could be used for partition tables or something
100
136
  */
101
- metadata(): FileSystemMetadata;
137
+ readonly id: number;
138
+ /**
139
+ * The name for this file system.
140
+ * For example, tmpfs for an in memory one
141
+ */
142
+ readonly name: string;
143
+ label?: string;
102
144
  /**
103
- * Whether the sync cache should be disabled.
104
- * Only affects async things.
145
+ * The last place this file system was mounted
105
146
  * @internal @protected
106
147
  */
107
- _disableSync?: boolean;
108
- constructor(...args: any[]);
148
+ _mountPoint?: string;
149
+ /**
150
+ * @see FileSystemAttributes
151
+ */
152
+ readonly attributes: ConstMap<FileSystemAttributes>;
153
+ constructor(
154
+ /**
155
+ * A unique ID for this kind of file system.
156
+ * Currently unused internally, but could be used for partition tables or something
157
+ */
158
+ id: number,
159
+ /**
160
+ * The name for this file system.
161
+ * For example, tmpfs for an in memory one
162
+ */
163
+ name: string);
164
+ toString(): string;
165
+ /**
166
+ * Default implementation.
167
+ * @todo Implement
168
+ * @experimental
169
+ */
170
+ usage(): UsageInfo;
171
+ /**
172
+ * Get metadata about the current file system
173
+ * @deprecated
174
+ */
175
+ metadata(): FileSystemMetadata;
109
176
  ready(): Promise<void>;
110
177
  abstract rename(oldPath: string, newPath: string): Promise<void>;
111
178
  abstract renameSync(oldPath: string, newPath: string): void;
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Provides a consistent and easy to use internal API.
3
+ * Default implementations for `exists` and `existsSync` are included.
4
+ * If you are extending this class, note that every path is an absolute path and all arguments are present.
5
+ * @internal
6
+ */
7
+ export class FileSystem {
8
+ constructor(
9
+ /**
10
+ * A unique ID for this kind of file system.
11
+ * Currently unused internally, but could be used for partition tables or something
12
+ */
13
+ id,
14
+ /**
15
+ * The name for this file system.
16
+ * For example, tmpfs for an in memory one
17
+ */
18
+ name) {
19
+ this.id = id;
20
+ this.name = name;
21
+ /**
22
+ * @see FileSystemAttributes
23
+ */
24
+ this.attributes = new Map();
25
+ }
26
+ toString() {
27
+ var _a;
28
+ return `${this.name} ${(_a = this.label) !== null && _a !== void 0 ? _a : ''} (${this._mountPoint ? 'mounted on ' + this._mountPoint : 'unmounted'})`;
29
+ }
30
+ /**
31
+ * Default implementation.
32
+ * @todo Implement
33
+ * @experimental
34
+ */
35
+ usage() {
36
+ return {
37
+ totalSpace: 0,
38
+ freeSpace: 0,
39
+ };
40
+ }
41
+ /* node:coverage disable */
42
+ /**
43
+ * Get metadata about the current file system
44
+ * @deprecated
45
+ */
46
+ metadata() {
47
+ return {
48
+ ...this.usage(),
49
+ name: this.name,
50
+ readonly: this.attributes.has('no_write'),
51
+ noResizableBuffers: this.attributes.has('no_buffer_resize'),
52
+ noAsyncCache: this.attributes.has('no_async'),
53
+ features: Array.from(this.attributes.keys()),
54
+ type: this.id,
55
+ };
56
+ }
57
+ /* node:coverage enable */
58
+ async ready() { }
59
+ /**
60
+ * Test whether or not `path` exists.
61
+ */
62
+ async exists(path) {
63
+ try {
64
+ await this.stat(path);
65
+ return true;
66
+ }
67
+ catch (e) {
68
+ return e.code != 'ENOENT';
69
+ }
70
+ }
71
+ /**
72
+ * Test whether or not `path` exists.
73
+ */
74
+ existsSync(path) {
75
+ try {
76
+ this.statSync(path);
77
+ return true;
78
+ }
79
+ catch (e) {
80
+ return e.code != 'ENOENT';
81
+ }
82
+ }
83
+ }
@@ -0,0 +1,9 @@
1
+ export * from './credentials.js';
2
+ export * from './devices.js';
3
+ export * from './error.js';
4
+ export * from './file_index.js';
5
+ export * from './file.js';
6
+ export * from './filesystem.js';
7
+ export * from './index_fs.js';
8
+ export * from './inode.js';
9
+ export * as log from './log.js';
@@ -0,0 +1,9 @@
1
+ export * from './credentials.js';
2
+ export * from './devices.js';
3
+ export * from './error.js';
4
+ export * from './file_index.js';
5
+ export * from './file.js';
6
+ export * from './filesystem.js';
7
+ export * from './index_fs.js';
8
+ export * from './inode.js';
9
+ export * as log from './log.js';
@@ -0,0 +1,56 @@
1
+ import { Stats } from '../stats.js';
2
+ import { type File } from './file.js';
3
+ import { Index } from './file_index.js';
4
+ import { FileSystem, type CreationOptions, type PureCreationOptions } from './filesystem.js';
5
+ import { Inode, type InodeLike } from './inode.js';
6
+ /**
7
+ * Uses an `Index` for metadata.
8
+ */
9
+ export declare abstract class IndexFS extends FileSystem {
10
+ readonly index: Index;
11
+ constructor(id: number, name: string, index?: Index);
12
+ /**
13
+ * @deprecated
14
+ */
15
+ reloadFiles(): never;
16
+ /**
17
+ * @deprecated
18
+ */
19
+ reloadFilesSync(): never;
20
+ /**
21
+ * Finds all the paths in the index that need to be moved for a rename
22
+ */
23
+ private pathsForRename;
24
+ rename(oldPath: string, newPath: string): Promise<void>;
25
+ renameSync(oldPath: string, newPath: string): void;
26
+ stat(path: string): Promise<Stats>;
27
+ statSync(path: string): Stats;
28
+ openFile(path: string, flag: string): Promise<File>;
29
+ openFileSync(path: string, flag: string): File;
30
+ protected _remove(path: string, isUnlink: boolean): void;
31
+ protected abstract remove(path: string): Promise<void>;
32
+ protected abstract removeSync(path: string): void;
33
+ unlink(path: string): Promise<void>;
34
+ unlinkSync(path: string): void;
35
+ rmdir(path: string): Promise<void>;
36
+ rmdirSync(path: string): void;
37
+ protected create(path: string, options: PureCreationOptions): Inode;
38
+ createFile(path: string, flag: string, mode: number, options: CreationOptions): Promise<File>;
39
+ createFileSync(path: string, flag: string, mode: number, options: CreationOptions): File;
40
+ mkdir(path: string, mode: number, options: CreationOptions): Promise<void>;
41
+ mkdirSync(path: string, mode: number, options: CreationOptions): void;
42
+ link(target: string, link: string): Promise<void>;
43
+ linkSync(target: string, link: string): void;
44
+ readdir(path: string): Promise<string[]>;
45
+ readdirSync(path: string): string[];
46
+ /**
47
+ * Optional hook for implementations to support updating metadata
48
+ */
49
+ protected syncMetadata?(path: string, metadata: Readonly<InodeLike>): Promise<void>;
50
+ sync(path: string, data?: Uint8Array, stats?: Readonly<InodeLike>): Promise<void>;
51
+ /**
52
+ * Optional hook for implementations to support updating metadata
53
+ */
54
+ protected syncMetadataSync?(path: string, metadata: Readonly<InodeLike>): void;
55
+ syncSync(path: string, data?: Uint8Array, stats?: Readonly<InodeLike>): void;
56
+ }
@@ -0,0 +1,188 @@
1
+ /* eslint-disable @typescript-eslint/require-await */
2
+ import { _throw } from 'utilium';
3
+ import { Stats } from '../stats.js';
4
+ 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
+ import { Index } from './file_index.js';
9
+ import { FileSystem } from './filesystem.js';
10
+ import { Inode } from './inode.js';
11
+ /**
12
+ * Uses an `Index` for metadata.
13
+ */
14
+ export class IndexFS extends FileSystem {
15
+ constructor(id, name, index = new Index()) {
16
+ super(id, name);
17
+ this.index = index;
18
+ }
19
+ /* node:coverage disable */
20
+ /**
21
+ * @deprecated
22
+ */
23
+ reloadFiles() {
24
+ throw ErrnoError.With('ENOTSUP');
25
+ }
26
+ /**
27
+ * @deprecated
28
+ */
29
+ reloadFilesSync() {
30
+ throw ErrnoError.With('ENOTSUP');
31
+ }
32
+ /* node:coverage enable */
33
+ /**
34
+ * Finds all the paths in the index that need to be moved for a rename
35
+ */
36
+ pathsForRename(oldPath, newPath) {
37
+ if (newPath === oldPath)
38
+ return [];
39
+ if (!this.index.has(oldPath))
40
+ throw ErrnoError.With('ENOENT', oldPath, 'rename');
41
+ if ((dirname(newPath) + '/').startsWith(oldPath + '/'))
42
+ throw ErrnoError.With('EBUSY', dirname(oldPath), 'rename');
43
+ const toRename = [];
44
+ for (const [from, inode] of this.index.entries()) {
45
+ const rel = relative(oldPath, from);
46
+ if (rel.startsWith('..'))
47
+ continue;
48
+ let to = join(newPath, rel);
49
+ if (to.endsWith('/'))
50
+ to = to.slice(0, -1);
51
+ toRename.push({ from, to, inode });
52
+ }
53
+ return toRename;
54
+ }
55
+ async rename(oldPath, newPath) {
56
+ for (const { from, to, inode } of this.pathsForRename(oldPath, newPath)) {
57
+ const data = new Uint8Array(inode.size);
58
+ await this.read(from, data, 0, inode.size);
59
+ this.index.delete(from);
60
+ this.index.set(to, inode);
61
+ await this.write(to, data, 0);
62
+ }
63
+ }
64
+ renameSync(oldPath, newPath) {
65
+ for (const { from, to, inode } of this.pathsForRename(oldPath, newPath)) {
66
+ const data = new Uint8Array(inode.size);
67
+ this.readSync(from, data, 0, inode.size);
68
+ this.index.delete(from);
69
+ this.index.set(to, inode);
70
+ this.writeSync(to, data, 0);
71
+ }
72
+ }
73
+ async stat(path) {
74
+ const inode = this.index.get(path);
75
+ if (!inode)
76
+ throw ErrnoError.With('ENOENT', path, 'stat');
77
+ return new Stats(inode);
78
+ }
79
+ statSync(path) {
80
+ const inode = this.index.get(path);
81
+ if (!inode)
82
+ throw ErrnoError.With('ENOENT', path, 'stat');
83
+ return new Stats(inode);
84
+ }
85
+ async openFile(path, flag) {
86
+ var _a;
87
+ const stats = (_a = this.index.get(path)) !== null && _a !== void 0 ? _a : _throw(ErrnoError.With('ENOENT', path, 'openFile'));
88
+ return new LazyFile(this, path, flag, stats);
89
+ }
90
+ openFileSync(path, flag) {
91
+ var _a;
92
+ const stats = (_a = this.index.get(path)) !== null && _a !== void 0 ? _a : _throw(ErrnoError.With('ENOENT', path, 'openFile'));
93
+ return new LazyFile(this, path, flag, stats);
94
+ }
95
+ _remove(path, isUnlink) {
96
+ const syscall = isUnlink ? 'unlink' : 'rmdir';
97
+ const inode = this.index.get(path);
98
+ if (!inode)
99
+ throw ErrnoError.With('ENOENT', path, syscall);
100
+ const isDir = (inode.mode & S_IFMT) == S_IFDIR;
101
+ if (!isDir && !isUnlink)
102
+ throw ErrnoError.With('ENOTDIR', path, syscall);
103
+ if (isDir && isUnlink)
104
+ throw ErrnoError.With('EISDIR', path, syscall);
105
+ this.index.delete(path);
106
+ }
107
+ async unlink(path) {
108
+ this._remove(path, true);
109
+ await this.remove(path);
110
+ }
111
+ unlinkSync(path) {
112
+ this._remove(path, true);
113
+ this.removeSync(path);
114
+ }
115
+ async rmdir(path) {
116
+ this._remove(path, false);
117
+ await this.remove(path);
118
+ }
119
+ rmdirSync(path) {
120
+ this._remove(path, false);
121
+ this.removeSync(path);
122
+ }
123
+ create(path, options) {
124
+ const syscall = (options.mode & S_IFMT) == S_IFDIR ? 'mkdir' : 'createFile';
125
+ if (this.index.has(path))
126
+ throw ErrnoError.With('EEXIST', path, syscall);
127
+ const parent = this.index.get(dirname(path));
128
+ if (!parent)
129
+ throw ErrnoError.With('ENOENT', dirname(path), syscall);
130
+ const id = this.index._alloc();
131
+ const inode = new Inode({
132
+ ino: id,
133
+ data: id + 1,
134
+ mode: options.mode,
135
+ size: 0,
136
+ uid: parent.mode & S_ISUID ? parent.uid : options.uid,
137
+ gid: parent.mode & S_ISGID ? parent.gid : options.gid,
138
+ });
139
+ this.index.set(path, inode);
140
+ return inode;
141
+ }
142
+ async createFile(path, flag, mode, options) {
143
+ const node = this.create(path, { mode: mode | S_IFREG, ...options });
144
+ return new LazyFile(this, path, flag, node.toStats());
145
+ }
146
+ createFileSync(path, flag, mode, options) {
147
+ const node = this.create(path, { mode: mode | S_IFREG, ...options });
148
+ return new LazyFile(this, path, flag, node.toStats());
149
+ }
150
+ async mkdir(path, mode, options) {
151
+ this.create(path, { mode: mode | S_IFDIR, ...options });
152
+ }
153
+ mkdirSync(path, mode, options) {
154
+ this.create(path, { mode: mode | S_IFDIR, ...options });
155
+ }
156
+ link(target, link) {
157
+ throw ErrnoError.With('ENOSYS', link, 'link');
158
+ }
159
+ linkSync(target, link) {
160
+ throw ErrnoError.With('ENOSYS', link, 'link');
161
+ }
162
+ async readdir(path) {
163
+ return Object.keys(this.index.directoryEntries(path));
164
+ }
165
+ readdirSync(path) {
166
+ return Object.keys(this.index.directoryEntries(path));
167
+ }
168
+ async sync(path, data, stats) {
169
+ var _a;
170
+ const inode = this.index.get(path);
171
+ if (!inode)
172
+ throw ErrnoError.With('ENOENT', path, 'sync');
173
+ if (inode.update(stats))
174
+ await ((_a = this.syncMetadata) === null || _a === void 0 ? void 0 : _a.call(this, path, stats));
175
+ if (data)
176
+ await this.write(path, data, 0);
177
+ }
178
+ syncSync(path, data, stats) {
179
+ var _a;
180
+ const inode = this.index.get(path);
181
+ if (!inode)
182
+ throw ErrnoError.With('ENOENT', path, 'sync');
183
+ if (inode.update(stats))
184
+ (_a = this.syncMetadataSync) === null || _a === void 0 ? void 0 : _a.call(this, path, stats);
185
+ if (data)
186
+ this.writeSync(path, data, 0);
187
+ }
188
+ }
@@ -1,4 +1,4 @@
1
- import { Stats, type StatsLike } from '../../stats.js';
1
+ import { Stats, type StatsLike } from '../stats.js';
2
2
  /**
3
3
  * Root inode
4
4
  * @hidden
@@ -39,6 +39,7 @@ export declare class Inode implements InodeLike {
39
39
  flags: number;
40
40
  /** For future use */
41
41
  __padding: number;
42
+ toString(): string;
42
43
  toJSON(): InodeLike;
43
44
  /**
44
45
  * Handy function that converts the Inode to a Node Stats object.
@@ -56,3 +57,7 @@ export declare class Inode implements InodeLike {
56
57
  */
57
58
  update(data?: Partial<Readonly<InodeLike>>): boolean;
58
59
  }
60
+ /**
61
+ * @internal @hidden
62
+ */
63
+ export declare const __inode_sz: number;