@zenfs/core 1.1.6 → 1.2.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 (58) hide show
  1. package/dist/backends/file_index.js +0 -3
  2. package/dist/backends/overlay.js +0 -8
  3. package/dist/backends/store/fs.js +4 -17
  4. package/dist/config.d.ts +14 -0
  5. package/dist/config.js +4 -0
  6. package/dist/devices.js +0 -12
  7. package/dist/emulation/cache.d.ts +21 -0
  8. package/dist/emulation/cache.js +36 -0
  9. package/dist/emulation/promises.d.ts +9 -14
  10. package/dist/emulation/promises.js +71 -48
  11. package/dist/emulation/shared.d.ts +22 -0
  12. package/dist/emulation/shared.js +6 -0
  13. package/dist/emulation/sync.d.ts +11 -20
  14. package/dist/emulation/sync.js +44 -23
  15. package/package.json +4 -2
  16. package/scripts/test.js +14 -1
  17. package/src/backends/backend.ts +160 -0
  18. package/src/backends/fetch.ts +180 -0
  19. package/src/backends/file_index.ts +206 -0
  20. package/src/backends/memory.ts +50 -0
  21. package/src/backends/overlay.ts +560 -0
  22. package/src/backends/port/fs.ts +335 -0
  23. package/src/backends/port/readme.md +54 -0
  24. package/src/backends/port/rpc.ts +167 -0
  25. package/src/backends/readme.md +3 -0
  26. package/src/backends/store/fs.ts +700 -0
  27. package/src/backends/store/readme.md +9 -0
  28. package/src/backends/store/simple.ts +146 -0
  29. package/src/backends/store/store.ts +173 -0
  30. package/src/config.ts +173 -0
  31. package/src/credentials.ts +31 -0
  32. package/src/devices.ts +459 -0
  33. package/src/emulation/async.ts +834 -0
  34. package/src/emulation/cache.ts +44 -0
  35. package/src/emulation/constants.ts +182 -0
  36. package/src/emulation/dir.ts +138 -0
  37. package/src/emulation/index.ts +8 -0
  38. package/src/emulation/path.ts +440 -0
  39. package/src/emulation/promises.ts +1133 -0
  40. package/src/emulation/shared.ts +160 -0
  41. package/src/emulation/streams.ts +34 -0
  42. package/src/emulation/sync.ts +867 -0
  43. package/src/emulation/watchers.ts +193 -0
  44. package/src/error.ts +307 -0
  45. package/src/file.ts +661 -0
  46. package/src/filesystem.ts +174 -0
  47. package/src/index.ts +25 -0
  48. package/src/inode.ts +132 -0
  49. package/src/mixins/async.ts +208 -0
  50. package/src/mixins/index.ts +5 -0
  51. package/src/mixins/mutexed.ts +257 -0
  52. package/src/mixins/readonly.ts +96 -0
  53. package/src/mixins/shared.ts +25 -0
  54. package/src/mixins/sync.ts +58 -0
  55. package/src/polyfills.ts +21 -0
  56. package/src/stats.ts +363 -0
  57. package/src/utils.ts +288 -0
  58. package/tests/fs/readdir.test.ts +3 -3
@@ -0,0 +1,160 @@
1
+ // Utilities and shared data
2
+
3
+ import type { BigIntStatsFs, StatsFs } from 'node:fs';
4
+ import { InMemory } from '../backends/memory.js';
5
+ import { Errno, ErrnoError } from '../error.js';
6
+ import type { File } from '../file.js';
7
+ import type { FileSystem } from '../filesystem.js';
8
+ import { normalizePath } from '../utils.js';
9
+ import { resolve, type AbsolutePath } from './path.js';
10
+ import { size_max } from './constants.js';
11
+
12
+ // descriptors
13
+ export const fdMap: Map<number, File> = new Map();
14
+ let nextFd = 100;
15
+ export function file2fd(file: File): number {
16
+ const fd = nextFd++;
17
+ fdMap.set(fd, file);
18
+ return fd;
19
+ }
20
+ export function fd2file(fd: number): File {
21
+ if (!fdMap.has(fd)) {
22
+ throw new ErrnoError(Errno.EBADF);
23
+ }
24
+ return fdMap.get(fd)!;
25
+ }
26
+
27
+ export type MountObject = Record<AbsolutePath, FileSystem>;
28
+
29
+ /**
30
+ * The map of mount points
31
+ * @internal
32
+ */
33
+ export const mounts: Map<string, FileSystem> = new Map();
34
+
35
+ // Set a default root.
36
+ mount('/', InMemory.create({ name: 'root' }));
37
+
38
+ /**
39
+ * Mounts the file system at `mountPoint`.
40
+ */
41
+ export function mount(mountPoint: string, fs: FileSystem): void {
42
+ if (mountPoint[0] !== '/') {
43
+ mountPoint = '/' + mountPoint;
44
+ }
45
+ mountPoint = resolve(mountPoint);
46
+ if (mounts.has(mountPoint)) {
47
+ throw new ErrnoError(Errno.EINVAL, 'Mount point ' + mountPoint + ' is already in use.');
48
+ }
49
+ mounts.set(mountPoint, fs);
50
+ }
51
+
52
+ /**
53
+ * Unmounts the file system at `mountPoint`.
54
+ */
55
+ export function umount(mountPoint: string): void {
56
+ if (mountPoint[0] !== '/') {
57
+ mountPoint = `/${mountPoint}`;
58
+ }
59
+ mountPoint = resolve(mountPoint);
60
+ if (!mounts.has(mountPoint)) {
61
+ throw new ErrnoError(Errno.EINVAL, 'Mount point ' + mountPoint + ' is already unmounted.');
62
+ }
63
+ mounts.delete(mountPoint);
64
+ }
65
+
66
+ /**
67
+ * Gets the internal FileSystem for the path, then returns it along with the path relative to the FS' root
68
+ */
69
+ export function resolveMount(path: string): { fs: FileSystem; path: string; mountPoint: string } {
70
+ path = normalizePath(path);
71
+ // Maybe do something for devices here
72
+ const sortedMounts = [...mounts].sort((a, b) => (a[0].length > b[0].length ? -1 : 1)); // descending order of the string length
73
+ for (const [mountPoint, fs] of sortedMounts) {
74
+ // We know path is normalized, so it would be a substring of the mount point.
75
+ if (mountPoint.length <= path.length && path.startsWith(mountPoint)) {
76
+ path = path.slice(mountPoint.length > 1 ? mountPoint.length : 0); // Resolve the path relative to the mount point
77
+ if (path === '') {
78
+ path = '/';
79
+ }
80
+ return { fs, path, mountPoint };
81
+ }
82
+ }
83
+
84
+ throw new ErrnoError(Errno.EIO, 'ZenFS not initialized with a file system');
85
+ }
86
+
87
+ /**
88
+ * Reverse maps the paths in text from the mounted FileSystem to the global path
89
+ * @hidden
90
+ */
91
+ export function fixPaths(text: string, paths: Record<string, string>): string {
92
+ for (const [from, to] of Object.entries(paths)) {
93
+ text = text?.replaceAll(from, to);
94
+ }
95
+ return text;
96
+ }
97
+
98
+ /**
99
+ * Fix paths in error stacks
100
+ * @hidden
101
+ */
102
+ export function fixError<E extends ErrnoError>(e: E, paths: Record<string, string>): E {
103
+ if (typeof e.stack == 'string') {
104
+ e.stack = fixPaths(e.stack, paths);
105
+ }
106
+ e.message = fixPaths(e.message, paths);
107
+ return e;
108
+ }
109
+
110
+ export function mountObject(mounts: MountObject): void {
111
+ if ('/' in mounts) {
112
+ umount('/');
113
+ }
114
+ for (const [point, fs] of Object.entries(mounts)) {
115
+ mount(point, fs);
116
+ }
117
+ }
118
+
119
+ /**
120
+ * @hidden
121
+ */
122
+ export function _statfs<const T extends boolean>(fs: FileSystem, bigint?: T): T extends true ? BigIntStatsFs : StatsFs {
123
+ const md = fs.metadata();
124
+ const bs = md.blockSize || 4096;
125
+
126
+ return {
127
+ type: (bigint ? BigInt : Number)(md.type),
128
+ bsize: (bigint ? BigInt : Number)(bs),
129
+ ffree: (bigint ? BigInt : Number)(md.freeNodes || size_max),
130
+ files: (bigint ? BigInt : Number)(md.totalNodes || size_max),
131
+ bavail: (bigint ? BigInt : Number)(md.freeSpace / bs),
132
+ bfree: (bigint ? BigInt : Number)(md.freeSpace / bs),
133
+ blocks: (bigint ? BigInt : Number)(md.totalSpace / bs),
134
+ } as T extends true ? BigIntStatsFs : StatsFs;
135
+ }
136
+
137
+ export const config = {
138
+ /**
139
+ * Whether to perform access checks
140
+ */
141
+ checkAccess: true,
142
+ };
143
+
144
+ /**
145
+ * Options used for caching, among other things.
146
+ * @internal *UNSTABLE*
147
+ */
148
+ export interface InternalOptions {
149
+ /**
150
+ * If true, then this readdir was called from another function.
151
+ * In this case, don't clear the cache when done.
152
+ * @internal *UNSTABLE*
153
+ */
154
+ _isIndirect?: boolean;
155
+ }
156
+
157
+ export interface ReaddirOptions extends InternalOptions {
158
+ withFileTypes?: boolean;
159
+ recursive?: boolean;
160
+ }
@@ -0,0 +1,34 @@
1
+ import type * as Node from 'node:fs';
2
+ import { Readable, Writable } from 'readable-stream';
3
+ import type { Callback } from '../utils.js';
4
+ import { ErrnoError, Errno } from '../error.js';
5
+
6
+ export class ReadStream extends Readable implements Node.ReadStream {
7
+ close(callback: Callback = () => null): void {
8
+ try {
9
+ super.destroy();
10
+ super.emit('close');
11
+ callback();
12
+ } catch (err) {
13
+ callback(new ErrnoError(Errno.EIO, (err as Error).toString()));
14
+ }
15
+ }
16
+ declare bytesRead: number;
17
+ declare path: string | Buffer;
18
+ declare pending: boolean;
19
+ }
20
+
21
+ export class WriteStream extends Writable implements Node.WriteStream {
22
+ close(callback: Callback = () => null): void {
23
+ try {
24
+ super.destroy();
25
+ super.emit('close');
26
+ callback();
27
+ } catch (err) {
28
+ callback(new ErrnoError(Errno.EIO, (err as Error).toString()));
29
+ }
30
+ }
31
+ declare bytesWritten: number;
32
+ declare path: string | Buffer;
33
+ declare pending: boolean;
34
+ }