@zenfs/core 1.6.8 → 1.6.10

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.
@@ -1,6 +1,6 @@
1
1
  import type { RequiredKeys } from 'utilium';
2
2
  import type { FileSystem } from '../filesystem.js';
3
- type OptionType = 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function';
3
+ type OptionType = 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | (abstract new (...args: any[]) => any);
4
4
  /**
5
5
  * Resolves the type of Backend.options from the options interface
6
6
  */
@@ -1,5 +1,4 @@
1
1
  import { ErrnoError, Errno } from '../error.js';
2
- import { levenshtein } from '../utils.js';
3
2
  /** @internal */
4
3
  export function isBackend(arg) {
5
4
  return arg != null && typeof arg == 'object' && 'create' in arg && typeof arg.create == 'function';
@@ -14,30 +13,24 @@ export async function checkOptions(backend, options) {
14
13
  }
15
14
  // Check for required options.
16
15
  for (const [optName, opt] of Object.entries(backend.options)) {
17
- const providedValue = options?.[optName];
18
- if (providedValue === undefined || providedValue === null) {
16
+ const value = options?.[optName];
17
+ if (value === undefined || value === null) {
19
18
  if (!opt.required) {
20
19
  continue;
21
20
  }
22
- /* Required option not provided.
23
- if any incorrect options provided, which ones are close to the provided one?
24
- (edit distance 5 === close)*/
25
- const incorrectOptions = Object.keys(options)
26
- .filter(o => !(o in backend.options))
27
- .map((a) => {
28
- return { str: a, distance: levenshtein(optName, a) };
29
- })
30
- .filter(o => o.distance < 5)
31
- .sort((a, b) => a.distance - b.distance);
32
- throw new ErrnoError(Errno.EINVAL, `${backend.name}: Required option '${optName}' not provided.${incorrectOptions.length > 0 ? ` You provided '${incorrectOptions[0].str}', did you mean '${optName}'.` : ''}`);
21
+ throw new ErrnoError(Errno.EINVAL, 'Missing required option: ' + optName);
33
22
  }
34
- // Option provided, check type.
35
- const typeMatches = Array.isArray(opt.type) ? opt.type.indexOf(typeof providedValue) != -1 : typeof providedValue == opt.type;
36
- if (!typeMatches) {
37
- throw new ErrnoError(Errno.EINVAL, `${backend.name}: Value provided for option ${optName} is not the proper type. Expected ${Array.isArray(opt.type) ? `one of {${opt.type.join(', ')}}` : opt.type}, but received ${typeof providedValue}`);
23
+ const isType = (value) => (typeof opt.type == 'function' ? value instanceof opt.type : typeof value === opt.type);
24
+ if (Array.isArray(opt.type) ? !opt.type.some(isType) : !isType(value)) {
25
+ // The type of the value as a string
26
+ const type = typeof value == 'object' && 'constructor' in value ? value.constructor.name : typeof value;
27
+ // The expected type (as a string)
28
+ const name = (type) => (typeof type == 'function' ? type.name : type);
29
+ const expected = Array.isArray(opt.type) ? `one of ${opt.type.map(name).join(', ')}` : name(opt.type);
30
+ throw new ErrnoError(Errno.EINVAL, `Incorrect type for "${optName}": ${type} (expected ${expected})`);
38
31
  }
39
32
  if (opt.validator) {
40
- await opt.validator(providedValue);
33
+ await opt.validator(value);
41
34
  }
42
35
  // Otherwise: All good!
43
36
  }
@@ -773,7 +773,8 @@ export async function readlink(path, options) {
773
773
  const handle = __addDisposableResource(env_6, await _open.call(this, normalizePath(path), 'r', 0o644, false), true);
774
774
  const value = await handle.readFile();
775
775
  const encoding = typeof options == 'object' ? options?.encoding : options;
776
- return encoding == 'buffer' ? value : value.toString(encoding);
776
+ // always defaults to utf-8 to avoid wrangler (cloudflare) worker "unknown encoding" exception
777
+ return encoding == 'buffer' ? value : value.toString((encoding ?? 'utf-8'));
777
778
  }
778
779
  catch (e_6) {
779
780
  env_6.error = e_6;
@@ -1,10 +1,10 @@
1
1
  import { Buffer } from 'buffer';
2
2
  import type * as fs from 'node:fs';
3
+ import type { V_Context } from '../context.js';
3
4
  import type { FileContents } from '../filesystem.js';
4
5
  import { BigIntStats, type Stats } from '../stats.js';
5
6
  import { Dir, Dirent } from './dir.js';
6
- import type { V_Context } from '../context.js';
7
- import type { ReaddirOptsI, ReaddirOptsU, InternalOptions, ReaddirOptions, NullEnc } from './types.js';
7
+ import type { InternalOptions, NullEnc, ReaddirOptions, ReaddirOptsI, ReaddirOptsU } from './types.js';
8
8
  export declare function renameSync(this: V_Context, oldPath: fs.PathLike, newPath: fs.PathLike): void;
9
9
  /**
10
10
  * Test whether or not `path` exists by checking with the file system.
@@ -549,7 +549,8 @@ export function readlinkSync(path, options) {
549
549
  if (encoding == 'buffer') {
550
550
  return value;
551
551
  }
552
- return value.toString(encoding);
552
+ // always defaults to utf-8 to avoid wrangler (cloudflare) worker "unknown encoding" exception
553
+ return value.toString(encoding ?? 'utf-8');
553
554
  }
554
555
  readlinkSync;
555
556
  export function chownSync(path, uid, gid) {
package/dist/utils.d.ts CHANGED
@@ -2,21 +2,10 @@ import type * as fs from 'node:fs';
2
2
  import { type ClassLike, type OptionalTuple } from 'utilium';
3
3
  import { type AbsolutePath } from './emulation/path.js';
4
4
  import { ErrnoError } from './error.js';
5
- import type { FileSystem } from './filesystem.js';
6
5
  declare global {
7
6
  function atob(data: string): string;
8
7
  function btoa(data: string): string;
9
8
  }
10
- /**
11
- * Synchronous recursive makedir.
12
- * @hidden
13
- */
14
- export declare function mkdirpSync(path: string, mode: number, fs: FileSystem): void;
15
- /**
16
- * Calculates levenshtein distance.
17
- * @hidden
18
- */
19
- export declare function levenshtein(a: string, b: string): number;
20
9
  /**
21
10
  * Encodes a string into a buffer
22
11
  * @internal
package/dist/utils.js CHANGED
@@ -1,89 +1,6 @@
1
1
  import { randomHex } from 'utilium';
2
- import { dirname, resolve } from './emulation/path.js';
2
+ import { resolve } from './emulation/path.js';
3
3
  import { Errno, ErrnoError } from './error.js';
4
- /**
5
- * Synchronous recursive makedir.
6
- * @hidden
7
- */
8
- export function mkdirpSync(path, mode, fs) {
9
- if (!fs.existsSync(path)) {
10
- mkdirpSync(dirname(path), mode, fs);
11
- fs.mkdirSync(path, mode);
12
- }
13
- }
14
- function _min(d0, d1, d2, bx, ay) {
15
- return Math.min(d0 + 1, d1 + 1, d2 + 1, bx === ay ? d1 : d1 + 1);
16
- }
17
- /**
18
- * Calculates levenshtein distance.
19
- * @hidden
20
- */
21
- export function levenshtein(a, b) {
22
- if (a === b) {
23
- return 0;
24
- }
25
- if (a.length > b.length) {
26
- [a, b] = [b, a]; // Swap a and b
27
- }
28
- let la = a.length;
29
- let lb = b.length;
30
- // Trim common suffix
31
- while (la > 0 && a.charCodeAt(la - 1) === b.charCodeAt(lb - 1)) {
32
- la--;
33
- lb--;
34
- }
35
- let offset = 0;
36
- // Trim common prefix
37
- while (offset < la && a.charCodeAt(offset) === b.charCodeAt(offset)) {
38
- offset++;
39
- }
40
- la -= offset;
41
- lb -= offset;
42
- if (la === 0 || lb === 1) {
43
- return lb;
44
- }
45
- const vector = new Array(la << 1);
46
- for (let y = 0; y < la;) {
47
- vector[la + y] = a.charCodeAt(offset + y);
48
- vector[y] = ++y;
49
- }
50
- let x;
51
- let d0;
52
- let d1;
53
- let d2;
54
- let d3;
55
- for (x = 0; x + 3 < lb;) {
56
- const bx0 = b.charCodeAt(offset + (d0 = x));
57
- const bx1 = b.charCodeAt(offset + (d1 = x + 1));
58
- const bx2 = b.charCodeAt(offset + (d2 = x + 2));
59
- const bx3 = b.charCodeAt(offset + (d3 = x + 3));
60
- let dd = (x += 4);
61
- for (let y = 0; y < la;) {
62
- const ay = vector[la + y];
63
- const dy = vector[y];
64
- d0 = _min(dy, d0, d1, bx0, ay);
65
- d1 = _min(d0, d1, d2, bx1, ay);
66
- d2 = _min(d1, d2, d3, bx2, ay);
67
- dd = _min(d2, d3, dd, bx3, ay);
68
- vector[y++] = dd;
69
- d3 = d2;
70
- d2 = d1;
71
- d1 = d0;
72
- d0 = dy;
73
- }
74
- }
75
- let dd = 0;
76
- for (; x < lb;) {
77
- const bx0 = b.charCodeAt(offset + (d0 = x));
78
- dd = ++x;
79
- for (let y = 0; y < la; y++) {
80
- const dy = vector[y];
81
- vector[y] = dd = dy < d0 || dd < d0 ? (dy > dd ? dd + 1 : dy + 1) : bx0 === vector[la + y] ? d0 : d0 + 1;
82
- d0 = dy;
83
- }
84
- }
85
- return dd;
86
- }
87
4
  /**
88
5
  * Encodes a string into a buffer
89
6
  * @internal
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenfs/core",
3
- "version": "1.6.8",
3
+ "version": "1.6.10",
4
4
  "description": "A filesystem, anywhere",
5
5
  "funding": {
6
6
  "type": "individual",
@@ -44,7 +44,6 @@
44
44
  ".": "./dist/index.js",
45
45
  "./*": "./dist/*",
46
46
  "./promises": "./dist/emulation/promises.js",
47
- "./mixins": "./dist/mixins/index.js",
48
47
  "./path": "./dist/emulation/path.js",
49
48
  "./eslint": "./eslint.shared.js",
50
49
  "./tests/*": "./tests/*"
package/readme.md CHANGED
@@ -147,9 +147,6 @@ fs.umount('/mnt/zip'); // finished using the zip
147
147
 
148
148
  ### Devices and device files
149
149
 
150
- > [!WARNING]
151
- > This is an **experimental** feature. Breaking changes may occur during non-major releases. Using this feature is the fastest way to make it stable.
152
-
153
150
  ZenFS includes experimental support for device files. These are designed to follow Linux's device file behavior, for consistency and ease of use. You can automatically add some normal devices with the `addDevices` configuration option:
154
151
 
155
152
  ```ts