@zenfs/core 0.9.7 → 0.10.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 (71) hide show
  1. package/dist/backends/AsyncStore.js +29 -29
  2. package/dist/backends/Fetch.d.ts +84 -0
  3. package/dist/backends/Fetch.js +171 -0
  4. package/dist/backends/Index.js +19 -19
  5. package/dist/backends/Locked.d.ts +11 -11
  6. package/dist/backends/Locked.js +50 -49
  7. package/dist/backends/Overlay.js +21 -21
  8. package/dist/backends/SyncStore.js +27 -27
  9. package/dist/backends/backend.js +4 -4
  10. package/dist/backends/port/fs.d.ts +124 -0
  11. package/dist/backends/port/fs.js +241 -0
  12. package/dist/backends/port/rpc.d.ts +60 -0
  13. package/dist/backends/port/rpc.js +71 -0
  14. package/dist/backends/port/store.d.ts +30 -0
  15. package/dist/backends/port/store.js +142 -0
  16. package/dist/browser.min.js +4 -4
  17. package/dist/browser.min.js.map +4 -4
  18. package/dist/config.d.ts +8 -10
  19. package/dist/config.js +11 -11
  20. package/dist/emulation/async.js +6 -6
  21. package/dist/emulation/dir.js +2 -2
  22. package/dist/emulation/index.d.ts +1 -1
  23. package/dist/emulation/index.js +1 -1
  24. package/dist/emulation/path.d.ts +3 -2
  25. package/dist/emulation/path.js +19 -45
  26. package/dist/emulation/promises.d.ts +7 -12
  27. package/dist/emulation/promises.js +144 -146
  28. package/dist/emulation/shared.d.ts +5 -10
  29. package/dist/emulation/shared.js +8 -8
  30. package/dist/emulation/streams.js +3 -3
  31. package/dist/emulation/sync.js +25 -25
  32. package/dist/{ApiError.d.ts → error.d.ts} +13 -14
  33. package/dist/error.js +292 -0
  34. package/dist/file.d.ts +2 -0
  35. package/dist/file.js +10 -4
  36. package/dist/filesystem.js +15 -15
  37. package/dist/index.d.ts +4 -1
  38. package/dist/index.js +4 -1
  39. package/dist/mutex.js +2 -1
  40. package/dist/utils.d.ts +8 -7
  41. package/dist/utils.js +11 -12
  42. package/package.json +3 -3
  43. package/readme.md +17 -9
  44. package/src/backends/AsyncStore.ts +29 -29
  45. package/src/backends/Fetch.ts +230 -0
  46. package/src/backends/Index.ts +19 -19
  47. package/src/backends/Locked.ts +50 -49
  48. package/src/backends/Overlay.ts +23 -23
  49. package/src/backends/SyncStore.ts +27 -27
  50. package/src/backends/backend.ts +6 -6
  51. package/src/backends/port/fs.ts +308 -0
  52. package/src/backends/port/readme.md +59 -0
  53. package/src/backends/port/rpc.ts +144 -0
  54. package/src/backends/port/store.ts +187 -0
  55. package/src/config.ts +20 -24
  56. package/src/emulation/async.ts +6 -6
  57. package/src/emulation/dir.ts +2 -2
  58. package/src/emulation/index.ts +1 -1
  59. package/src/emulation/path.ts +25 -49
  60. package/src/emulation/promises.ts +150 -159
  61. package/src/emulation/shared.ts +12 -14
  62. package/src/emulation/streams.ts +3 -3
  63. package/src/emulation/sync.ts +28 -28
  64. package/src/{ApiError.ts → error.ts} +89 -89
  65. package/src/file.ts +12 -4
  66. package/src/filesystem.ts +15 -15
  67. package/src/index.ts +4 -1
  68. package/src/mutex.ts +3 -1
  69. package/src/utils.ts +16 -18
  70. package/tsconfig.json +2 -2
  71. package/dist/ApiError.js +0 -292
package/dist/config.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { Backend, BackendConfiguration } from './backends/backend.js';
2
2
  import { FileSystem } from './filesystem.js';
3
+ import type { AbsolutePath } from './emulation/path.js';
3
4
  /**
4
5
  * Configuration for a specific mount point
5
6
  */
@@ -10,18 +11,15 @@ export type MountConfiguration<FS extends FileSystem = FileSystem, TOptions exte
10
11
  */
11
12
  export declare function resolveMountConfig<FS extends FileSystem, TOptions extends object = object>(config: MountConfiguration<FS, TOptions>, _depth?: number): Promise<FS>;
12
13
  /**
13
- *A mapping of mount points to their configurations
14
+ * Configuration
14
15
  */
15
- export type MappingConfiguration = Partial<{
16
- uid: number;
17
- gid: number;
18
- }> & Record<string, FileSystem | BackendConfiguration | Backend>;
19
- /**
20
- * Configuration for the file systems
21
- */
22
- export type Configuration = MountConfiguration | MappingConfiguration;
16
+ export interface Configuration {
17
+ mounts: Record<AbsolutePath, MountConfiguration>;
18
+ uid?: number;
19
+ gid?: number;
20
+ }
23
21
  /**
24
22
  * Creates filesystems with the given configuration, and initializes ZenFS with it.
25
23
  * @see Configuration for more info on the configuration object.
26
24
  */
27
- export declare function configure(config: Configuration): Promise<void>;
25
+ export declare function configure(config: MountConfiguration | Configuration): Promise<void>;
package/dist/config.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ApiError, ErrorCode } from './ApiError.js';
1
+ import { ErrnoError, Errno } from './error.js';
2
2
  import { checkOptions, isBackend, isBackendConfig } from './backends/backend.js';
3
3
  import * as fs from './emulation/index.js';
4
4
  import { setCred } from './emulation/shared.js';
@@ -12,10 +12,10 @@ function isMountConfig(arg) {
12
12
  */
13
13
  export async function resolveMountConfig(config, _depth = 0) {
14
14
  if (typeof config !== 'object' || config == null) {
15
- throw new ApiError(ErrorCode.EINVAL, 'Invalid options on mount configuration');
15
+ throw new ErrnoError(Errno.EINVAL, 'Invalid options on mount configuration');
16
16
  }
17
17
  if (!isMountConfig(config)) {
18
- throw new ApiError(ErrorCode.EINVAL, 'Invalid mount configuration');
18
+ throw new ErrnoError(Errno.EINVAL, 'Invalid mount configuration');
19
19
  }
20
20
  if (config instanceof FileSystem) {
21
21
  return config;
@@ -31,13 +31,13 @@ export async function resolveMountConfig(config, _depth = 0) {
31
31
  continue;
32
32
  }
33
33
  if (_depth > 10) {
34
- throw new ApiError(ErrorCode.EINVAL, 'Invalid configuration, too deep and possibly infinite');
34
+ throw new ErrnoError(Errno.EINVAL, 'Invalid configuration, too deep and possibly infinite');
35
35
  }
36
36
  config[key] = await resolveMountConfig(value, ++_depth);
37
37
  }
38
38
  const { backend } = config;
39
39
  if (!(await backend.isAvailable())) {
40
- throw new ApiError(ErrorCode.EPERM, 'Backend not available: ' + backend);
40
+ throw new ErrnoError(Errno.EPERM, 'Backend not available: ' + backend);
41
41
  }
42
42
  checkOptions(backend, config);
43
43
  const mount = backend.create(config);
@@ -53,14 +53,14 @@ export async function configure(config) {
53
53
  const gid = 'gid' in config ? config.gid || 0 : 0;
54
54
  if (isMountConfig(config)) {
55
55
  // single FS
56
- config = { '/': config };
56
+ config = { mounts: { '/': config } };
57
57
  }
58
- for (const [point, value] of Object.entries(config)) {
59
- if (point == 'uid' || point == 'gid' || typeof value == 'number') {
60
- continue;
58
+ for (const [point, value] of Object.entries(config.mounts)) {
59
+ if (!point.startsWith('/')) {
60
+ throw new ErrnoError(Errno.EINVAL, 'Mount points must have absolute paths');
61
61
  }
62
- config[point] = await resolveMountConfig(value);
62
+ config.mounts[point] = await resolveMountConfig(value);
63
63
  }
64
- fs.mountMapping(config);
64
+ fs.mountObject(config.mounts);
65
65
  setCred({ uid, gid, suid: uid, sgid: gid, euid: uid, egid: gid });
66
66
  }
@@ -1,4 +1,4 @@
1
- import { ApiError, ErrorCode } from '../ApiError.js';
1
+ import { ErrnoError, Errno } from '../error.js';
2
2
  import { BigIntStats } from '../stats.js';
3
3
  import { nop, normalizeMode } from '../utils.js';
4
4
  import { R_OK } from './constants.js';
@@ -128,7 +128,7 @@ export function ftruncate(fd, lenOrCB, cb = nop) {
128
128
  cb = typeof lenOrCB === 'function' ? lenOrCB : cb;
129
129
  const file = fd2file(fd);
130
130
  if (length < 0) {
131
- throw new ApiError(ErrorCode.EINVAL);
131
+ throw new ErrnoError(Errno.EINVAL);
132
132
  }
133
133
  file.truncate(length)
134
134
  .then(() => cb())
@@ -179,7 +179,7 @@ export function write(fd, data, cbPosOff, cbLenEnc, cbPos, cb = nop) {
179
179
  default:
180
180
  // ...try to find the callback and get out of here!
181
181
  cb = typeof cbLenEnc === 'function' ? cbLenEnc : typeof cbPos === 'function' ? cbPos : cb;
182
- cb(new ApiError(ErrorCode.EINVAL, 'Invalid arguments.'));
182
+ cb(new ErrnoError(Errno.EINVAL, 'Invalid arguments.'));
183
183
  return;
184
184
  }
185
185
  buffer = Buffer.from(data);
@@ -431,18 +431,18 @@ export function access(path, cbMode, cb = nop) {
431
431
  }
432
432
  access;
433
433
  export function watchFile(path, optsListener, listener = nop) {
434
- throw ApiError.With('ENOSYS', path.toString(), 'watchFile');
434
+ throw ErrnoError.With('ENOSYS', path.toString(), 'watchFile');
435
435
  }
436
436
  watchFile;
437
437
  /**
438
438
  * @todo Implement
439
439
  */
440
440
  export function unwatchFile(path, listener = nop) {
441
- throw ApiError.With('ENOSYS', path.toString(), 'unwatchFile');
441
+ throw ErrnoError.With('ENOSYS', path.toString(), 'unwatchFile');
442
442
  }
443
443
  unwatchFile;
444
444
  export function watch(path, options, listener = nop) {
445
- throw ApiError.With('ENOSYS', path.toString(), 'watch');
445
+ throw ErrnoError.With('ENOSYS', path.toString(), 'watch');
446
446
  }
447
447
  watch;
448
448
  /**
@@ -1,5 +1,5 @@
1
1
  import { readdir } from './promises.js';
2
- import { ApiError, ErrorCode } from '../ApiError.js';
2
+ import { ErrnoError, Errno } from '../error.js';
3
3
  import { readdirSync } from './sync.js';
4
4
  import { basename } from './path.js';
5
5
  export class Dirent {
@@ -38,7 +38,7 @@ export class Dirent {
38
38
  export class Dir {
39
39
  checkClosed() {
40
40
  if (this.closed) {
41
- throw new ApiError(ErrorCode.EBADF, 'Can not use closed Dir');
41
+ throw new ErrnoError(Errno.EBADF, 'Can not use closed Dir');
42
42
  }
43
43
  }
44
44
  constructor(path) {
@@ -4,5 +4,5 @@ export * as promises from './promises.js';
4
4
  export * as constants from './constants.js';
5
5
  export * from './streams.js';
6
6
  export * from './dir.js';
7
- export { mountMapping, mounts, mount, umount } from './shared.js';
7
+ export { mountObject, mounts, mount, umount } from './shared.js';
8
8
  export { Stats, BigIntStats, StatsFs } from '../stats.js';
@@ -4,5 +4,5 @@ export * as promises from './promises.js';
4
4
  export * as constants from './constants.js';
5
5
  export * from './streams.js';
6
6
  export * from './dir.js';
7
- export { mountMapping, mounts, mount, umount } from './shared.js';
7
+ export { mountObject, mounts, mount, umount } from './shared.js';
8
8
  export { Stats, BigIntStats, StatsFs } from '../stats.js';
@@ -1,14 +1,15 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
2
  import type { ParsedPath } from 'node:path';
3
+ export type AbsolutePath = `/${string}`;
3
4
  export declare let cwd: string;
4
5
  export declare function cd(path: string): void;
5
6
  export declare const sep = "/";
6
7
  export declare function normalizeString(path: string, allowAboveRoot: boolean): string;
7
8
  export declare function formatExt(ext: string): string;
8
- export declare function resolve(...args: string[]): string;
9
+ export declare function resolve(...parts: string[]): AbsolutePath;
9
10
  export declare function normalize(path: string): string;
10
11
  export declare function isAbsolute(path: string): boolean;
11
- export declare function join(...args: string[]): string;
12
+ export declare function join(...parts: string[]): string;
12
13
  export declare function relative(from: string, to: string): string;
13
14
  export declare function dirname(path: string): string;
14
15
  export declare function basename(path: string, suffix?: string): string;
@@ -25,11 +25,6 @@ export function cd(path) {
25
25
  cwd = resolve(cwd, path);
26
26
  }
27
27
  export const sep = '/';
28
- function validateString(str, name) {
29
- if (typeof str != 'string') {
30
- throw new TypeError(`"${name}" is not a string`);
31
- }
32
- }
33
28
  function validateObject(str, name) {
34
29
  if (typeof str != 'object') {
35
30
  throw new TypeError(`"${name}" is not an object`);
@@ -107,19 +102,18 @@ export function normalizeString(path, allowAboveRoot) {
107
102
  export function formatExt(ext) {
108
103
  return ext ? `${ext[0] === '.' ? '' : '.'}${ext}` : '';
109
104
  }
110
- export function resolve(...args) {
105
+ export function resolve(...parts) {
111
106
  let resolved = '';
112
- let absolute = false;
113
- for (let i = args.length - 1; i >= -1 && !absolute; i--) {
114
- const path = i >= 0 ? args[i] : cwd;
115
- validateString(path, `paths[${i}]`);
116
- // Skip empty entries
117
- if (!path.length) {
107
+ for (const part of [...parts.reverse(), cwd]) {
108
+ if (!part.length) {
118
109
  continue;
119
110
  }
120
- resolved = `${path}/${resolved}`;
121
- absolute = path[0] == '/';
111
+ resolved = `${part}/${resolved}`;
112
+ if (part.startsWith('/')) {
113
+ break;
114
+ }
122
115
  }
116
+ const absolute = resolved.startsWith('/');
123
117
  // At this point the path should be resolved to a full absolute path, but
124
118
  // handle relative paths to be safe (might happen when cwd fails)
125
119
  // Normalize the path
@@ -127,17 +121,16 @@ export function resolve(...args) {
127
121
  if (absolute) {
128
122
  return `/${resolved}`;
129
123
  }
130
- return resolved.length > 0 ? resolved : '/';
124
+ return resolved.length ? resolved : '/';
131
125
  }
132
126
  export function normalize(path) {
133
- validateString(path, 'path');
134
- if (path.length === 0)
127
+ if (!path.length)
135
128
  return '.';
136
- const isAbsolute = path[0] === '/';
137
- const trailingSeparator = path.at(-1) === '/';
129
+ const isAbsolute = path.startsWith('/');
130
+ const trailingSeparator = path.endsWith('/');
138
131
  // Normalize the path
139
132
  path = normalizeString(path, !isAbsolute);
140
- if (path.length === 0) {
133
+ if (!path.length) {
141
134
  if (isAbsolute)
142
135
  return '/';
143
136
  return trailingSeparator ? './' : '.';
@@ -147,30 +140,17 @@ export function normalize(path) {
147
140
  return isAbsolute ? `/${path}` : path;
148
141
  }
149
142
  export function isAbsolute(path) {
150
- validateString(path, 'path');
151
- return path.length > 0 && path[0] === '/';
143
+ return path.startsWith('/');
152
144
  }
153
- export function join(...args) {
154
- if (args.length === 0)
145
+ export function join(...parts) {
146
+ if (!parts.length)
155
147
  return '.';
156
- let joined;
157
- for (let i = 0; i < args.length; ++i) {
158
- const arg = args[i];
159
- validateString(arg, 'path');
160
- if (arg.length > 0) {
161
- if (joined === undefined)
162
- joined = arg;
163
- else
164
- joined += `/${arg}`;
165
- }
166
- }
167
- if (joined === undefined)
148
+ const joined = parts.join('/');
149
+ if (!joined?.length)
168
150
  return '.';
169
151
  return normalize(joined);
170
152
  }
171
153
  export function relative(from, to) {
172
- validateString(from, 'from');
173
- validateString(to, 'to');
174
154
  if (from === to)
175
155
  return '';
176
156
  // Trim leading forward slashes.
@@ -233,7 +213,6 @@ export function relative(from, to) {
233
213
  return `${out}${to.slice(toStart + lastCommonSep)}`;
234
214
  }
235
215
  export function dirname(path) {
236
- validateString(path, 'path');
237
216
  if (path.length === 0)
238
217
  return '.';
239
218
  const hasRoot = path[0] === '/';
@@ -258,9 +237,6 @@ export function dirname(path) {
258
237
  return path.slice(0, end);
259
238
  }
260
239
  export function basename(path, suffix) {
261
- if (suffix !== undefined)
262
- validateString(suffix, 'ext');
263
- validateString(path, 'path');
264
240
  let start = 0;
265
241
  let end = -1;
266
242
  let matchedSlash = true;
@@ -330,7 +306,6 @@ export function basename(path, suffix) {
330
306
  return path.slice(start, end);
331
307
  }
332
308
  export function extname(path) {
333
- validateString(path, 'path');
334
309
  let startDot = -1;
335
310
  let startPart = 0;
336
311
  let end = -1;
@@ -387,8 +362,7 @@ export function format(pathObject) {
387
362
  return dir === pathObject.root ? `${dir}${base}` : `${dir}/${base}`;
388
363
  }
389
364
  export function parse(path) {
390
- validateString(path, 'path');
391
- const isAbsolute = path[0] === '/';
365
+ const isAbsolute = path.startsWith('/');
392
366
  const ret = { root: isAbsolute ? '/' : '', dir: '', base: '', ext: '', name: '' };
393
367
  if (path.length === 0)
394
368
  return ret;
@@ -13,25 +13,22 @@ import type { Stream } from 'node:stream';
13
13
  import type { ReadableStream as TReadableStream } from 'node:stream/web';
14
14
  import type { Interface as ReadlineInterface } from 'readline';
15
15
  import { File } from '../file.js';
16
- import { FileContents } from '../filesystem.js';
16
+ import type { FileContents } from '../filesystem.js';
17
17
  import { BigIntStats, type BigIntStatsFs, type Stats, type StatsFs } from '../stats.js';
18
18
  import { Dir, Dirent } from './dir.js';
19
19
  import { ReadStream, WriteStream } from './streams.js';
20
20
  export * as constants from './constants.js';
21
21
  export declare class FileHandle implements promises.FileHandle {
22
22
  /**
23
- * Gets the file descriptor for this file handle.
23
+ * The file descriptor for this file handle.
24
24
  */
25
25
  readonly fd: number;
26
- constructor(
27
- /**
28
- * Gets the file descriptor for this file handle.
29
- */
30
- fd: number);
31
26
  /**
32
27
  * @internal
28
+ * The file for this file handle
33
29
  */
34
- get file(): File;
30
+ readonly file: File;
31
+ constructor(fdOrFile: number | File);
35
32
  /**
36
33
  * Asynchronous fchown(2) - Change ownership of a file.
37
34
  */
@@ -182,9 +179,9 @@ export declare class FileHandle implements promises.FileHandle {
182
179
  export declare function rename(oldPath: fs.PathLike, newPath: fs.PathLike): Promise<void>;
183
180
  /**
184
181
  * Test whether or not the given path exists by checking with the file system.
185
- * @param _path
182
+ * @param path
186
183
  */
187
- export declare function exists(_path: fs.PathLike): Promise<boolean>;
184
+ export declare function exists(path: fs.PathLike): Promise<boolean>;
188
185
  /**
189
186
  * `stat`.
190
187
  * @param path
@@ -378,8 +375,6 @@ export declare function lutimes(path: fs.PathLike, atime: fs.TimeLike, mtime: fs
378
375
  * Asynchronous realpath(3) - return the canonicalized absolute pathname.
379
376
  * @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
380
377
  * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
381
- *
382
- * Note: This *Can not* use doOp since doOp depends on it
383
378
  */
384
379
  export declare function realpath(path: fs.PathLike, options: fs.BufferEncodingOption): Promise<Buffer>;
385
380
  export declare function realpath(path: fs.PathLike, options?: fs.EncodingOption | BufferEncoding): Promise<string>;