@zenfs/core 2.3.2 → 2.3.3

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.
@@ -102,7 +102,7 @@ const { format } = new Intl.NumberFormat('en-US', {
102
102
  });
103
103
  let MetadataEntry = (() => {
104
104
  var _a, _b, _c, _d;
105
- let _classDecorators = [struct(packed)];
105
+ let _classDecorators = [struct(packed, { name: 'MetadataEntry' })];
106
106
  let _classDescriptor;
107
107
  let _classExtraInitializers = [];
108
108
  let _classThis;
@@ -49,7 +49,7 @@ export const rootIno = 0;
49
49
  const maxDynamicData = 3968;
50
50
  let Attribute = (() => {
51
51
  var _a, _b;
52
- let _classDecorators = [struct(packed)];
52
+ let _classDecorators = [struct(packed, { name: 'Attribute' })];
53
53
  let _classDescriptor;
54
54
  let _classExtraInitializers = [];
55
55
  let _classThis;
package/dist/vfs/dir.d.ts CHANGED
@@ -2,13 +2,56 @@ import type { Dir as _Dir, Dirent as _Dirent } from 'node:fs';
2
2
  import type { V_Context } from '../context.js';
3
3
  import type { InodeLike } from '../internal/inode.js';
4
4
  import type { Callback } from '../utils.js';
5
- export declare class Dirent<Name extends string | Buffer = string> implements _Dirent<Name> {
6
- path: string;
7
- protected stats: InodeLike;
8
- protected readonly encoding?: (BufferEncoding | "buffer" | null) | undefined;
5
+ import { Buffer } from 'buffer';
6
+ import { BufferView } from 'utilium/buffer.js';
7
+ /**
8
+ * @see `DT_*` in `dirent.h`
9
+ */
10
+ export declare enum DirType {
11
+ UNKNOWN = 0,
12
+ FIFO = 1,
13
+ CHR = 2,
14
+ DIR = 4,
15
+ BLK = 6,
16
+ REG = 8,
17
+ LNK = 10,
18
+ SOCK = 12,
19
+ WHT = 14
20
+ }
21
+ /**
22
+ * Converts a file mode to a directory type.
23
+ * @see `IFTODT` in `dirent.h`
24
+ */
25
+ export declare function ifToDt(mode: number): DirType;
26
+ /**
27
+ * Converts a directory type to a file mode.
28
+ * @see `DTTOIF` in `dirent.h`
29
+ */
30
+ export declare function dtToIf(dt: DirType): number;
31
+ export declare class Dirent<Name extends string | Buffer = string, TArrayBuffer extends ArrayBufferLike = ArrayBufferLike> extends BufferView<TArrayBuffer> implements _Dirent<Name> {
32
+ protected accessor ino: number;
33
+ /** Reserved for 64-bit inodes */
34
+ private accessor _ino;
35
+ protected accessor type: DirType;
36
+ protected accessor _name: Uint8Array;
9
37
  get name(): Name;
10
- constructor(path: string, stats: InodeLike, encoding?: (BufferEncoding | "buffer" | null) | undefined);
38
+ /**
39
+ * @internal @protected
40
+ */
41
+ _encoding?: BufferEncoding | 'buffer' | null;
42
+ /**
43
+ * @internal @protected
44
+ */
45
+ _parentPath: string;
11
46
  get parentPath(): string;
47
+ /**
48
+ * @deprecated Removed in Node v24, use `parentPath` instead.
49
+ */
50
+ get path(): string;
51
+ /**
52
+ * @internal
53
+ */
54
+ static from(path: string, stats: InodeLike, encoding?: BufferEncoding | 'buffer' | null): Dirent;
12
55
  isFile(): boolean;
13
56
  isDirectory(): boolean;
14
57
  isBlockDevice(): boolean;
package/dist/vfs/dir.js CHANGED
@@ -1,46 +1,184 @@
1
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
2
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
3
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
4
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
5
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
6
+ var _, done = false;
7
+ for (var i = decorators.length - 1; i >= 0; i--) {
8
+ var context = {};
9
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
10
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
11
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
12
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
13
+ if (kind === "accessor") {
14
+ if (result === void 0) continue;
15
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
16
+ if (_ = accept(result.get)) descriptor.get = _;
17
+ if (_ = accept(result.set)) descriptor.set = _;
18
+ if (_ = accept(result.init)) initializers.unshift(_);
19
+ }
20
+ else if (_ = accept(result)) {
21
+ if (kind === "field") initializers.unshift(_);
22
+ else descriptor[key] = _;
23
+ }
24
+ }
25
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
26
+ done = true;
27
+ };
28
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
29
+ var useValue = arguments.length > 2;
30
+ for (var i = 0; i < initializers.length; i++) {
31
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
32
+ }
33
+ return useValue ? value : void 0;
34
+ };
35
+ import { Buffer } from 'buffer';
1
36
  import { withErrno } from 'kerium';
2
- import { isBlockDevice, isCharacterDevice, isDirectory, isFIFO, isFile, isSocket, isSymbolicLink } from '../internal/inode.js';
3
- import { basename } from '../path.js';
37
+ import { packed, sizeof, struct, types as t } from 'memium';
38
+ import { warn } from 'kerium/log';
39
+ import { encodeUTF8 } from 'utilium';
40
+ import { BufferView } from 'utilium/buffer.js';
41
+ import { basename, dirname } from '../path.js';
4
42
  import { readdir } from './promises.js';
5
43
  import { readdirSync } from './sync.js';
6
- export class Dirent {
7
- path;
8
- stats;
9
- encoding;
10
- get name() {
11
- const name = Buffer.from(basename(this.path));
12
- return (this.encoding == 'buffer' ? name : name.toString(this.encoding));
13
- }
14
- constructor(path, stats, encoding) {
15
- this.path = path;
16
- this.stats = stats;
17
- this.encoding = encoding;
18
- }
19
- get parentPath() {
20
- return this.path;
21
- }
22
- isFile() {
23
- return isFile(this.stats);
24
- }
25
- isDirectory() {
26
- return isDirectory(this.stats);
27
- }
28
- isBlockDevice() {
29
- return isBlockDevice(this.stats);
30
- }
31
- isCharacterDevice() {
32
- return isCharacterDevice(this.stats);
33
- }
34
- isSymbolicLink() {
35
- return isSymbolicLink(this.stats);
36
- }
37
- isFIFO() {
38
- return isFIFO(this.stats);
39
- }
40
- isSocket() {
41
- return isSocket(this.stats);
42
- }
44
+ /**
45
+ * @see `DT_*` in `dirent.h`
46
+ */
47
+ export var DirType;
48
+ (function (DirType) {
49
+ DirType[DirType["UNKNOWN"] = 0] = "UNKNOWN";
50
+ DirType[DirType["FIFO"] = 1] = "FIFO";
51
+ DirType[DirType["CHR"] = 2] = "CHR";
52
+ DirType[DirType["DIR"] = 4] = "DIR";
53
+ DirType[DirType["BLK"] = 6] = "BLK";
54
+ DirType[DirType["REG"] = 8] = "REG";
55
+ DirType[DirType["LNK"] = 10] = "LNK";
56
+ DirType[DirType["SOCK"] = 12] = "SOCK";
57
+ DirType[DirType["WHT"] = 14] = "WHT";
58
+ })(DirType || (DirType = {}));
59
+ /**
60
+ * Converts a file mode to a directory type.
61
+ * @see `IFTODT` in `dirent.h`
62
+ */
63
+ export function ifToDt(mode) {
64
+ return ((mode & 0o170000) >> 12);
65
+ }
66
+ /**
67
+ * Converts a directory type to a file mode.
68
+ * @see `DTTOIF` in `dirent.h`
69
+ */
70
+ export function dtToIf(dt) {
71
+ return dt << 12;
43
72
  }
73
+ let Dirent = (() => {
74
+ var _a, _b, _c;
75
+ let _classDecorators = [struct(packed, { name: 'Dirent' })];
76
+ let _classDescriptor;
77
+ let _classExtraInitializers = [];
78
+ let _classThis;
79
+ let _classSuper = BufferView;
80
+ let _ino_decorators;
81
+ let _ino_initializers = [];
82
+ let _ino_extraInitializers = [];
83
+ let __ino_decorators;
84
+ let __ino_initializers = [];
85
+ let __ino_extraInitializers = [];
86
+ let _type_decorators;
87
+ let _type_initializers = [];
88
+ let _type_extraInitializers = [];
89
+ let __name_decorators;
90
+ let __name_initializers = [];
91
+ let __name_extraInitializers = [];
92
+ var Dirent = class extends _classSuper {
93
+ static { _classThis = this; }
94
+ static {
95
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
96
+ _ino_decorators = [(_a = t).uint32.bind(_a)];
97
+ __ino_decorators = [(_b = t).uint32.bind(_b)];
98
+ _type_decorators = [(_c = t).uint8.bind(_c)];
99
+ __name_decorators = [t.char(256)];
100
+ __esDecorate(this, null, _ino_decorators, { kind: "accessor", name: "ino", static: false, private: false, access: { has: obj => "ino" in obj, get: obj => obj.ino, set: (obj, value) => { obj.ino = value; } }, metadata: _metadata }, _ino_initializers, _ino_extraInitializers);
101
+ __esDecorate(this, null, __ino_decorators, { kind: "accessor", name: "_ino", static: false, private: false, access: { has: obj => "_ino" in obj, get: obj => obj._ino, set: (obj, value) => { obj._ino = value; } }, metadata: _metadata }, __ino_initializers, __ino_extraInitializers);
102
+ __esDecorate(this, null, _type_decorators, { kind: "accessor", name: "type", static: false, private: false, access: { has: obj => "type" in obj, get: obj => obj.type, set: (obj, value) => { obj.type = value; } }, metadata: _metadata }, _type_initializers, _type_extraInitializers);
103
+ __esDecorate(this, null, __name_decorators, { kind: "accessor", name: "_name", static: false, private: false, access: { has: obj => "_name" in obj, get: obj => obj._name, set: (obj, value) => { obj._name = value; } }, metadata: _metadata }, __name_initializers, __name_extraInitializers);
104
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
105
+ Dirent = _classThis = _classDescriptor.value;
106
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
107
+ __runInitializers(_classThis, _classExtraInitializers);
108
+ }
109
+ #ino_accessor_storage = __runInitializers(this, _ino_initializers, void 0);
110
+ get ino() { return this.#ino_accessor_storage; }
111
+ set ino(value) { this.#ino_accessor_storage = value; }
112
+ #_ino_accessor_storage = (__runInitializers(this, _ino_extraInitializers), __runInitializers(this, __ino_initializers, void 0));
113
+ /** Reserved for 64-bit inodes */
114
+ get _ino() { return this.#_ino_accessor_storage; }
115
+ set _ino(value) { this.#_ino_accessor_storage = value; }
116
+ #type_accessor_storage = (__runInitializers(this, __ino_extraInitializers), __runInitializers(this, _type_initializers, void 0));
117
+ get type() { return this.#type_accessor_storage; }
118
+ set type(value) { this.#type_accessor_storage = value; }
119
+ #_name_accessor_storage = (__runInitializers(this, _type_extraInitializers), __runInitializers(this, __name_initializers, void 0));
120
+ get _name() { return this.#_name_accessor_storage; }
121
+ set _name(value) { this.#_name_accessor_storage = value; }
122
+ get name() {
123
+ const end = (this._name.indexOf(0) + 1 || 256) - 1;
124
+ const name = Buffer.from(this._name.subarray(0, end));
125
+ return (this._encoding == 'buffer' ? name : name.toString(this._encoding));
126
+ }
127
+ /**
128
+ * @internal @protected
129
+ */
130
+ _encoding = __runInitializers(this, __name_extraInitializers);
131
+ /**
132
+ * @internal @protected
133
+ */
134
+ _parentPath;
135
+ get parentPath() {
136
+ return this._parentPath;
137
+ }
138
+ /**
139
+ * @deprecated Removed in Node v24, use `parentPath` instead.
140
+ */
141
+ get path() {
142
+ warn('Dirent.path was removed in Node v24, use parentPath instead');
143
+ return this._parentPath;
144
+ }
145
+ /**
146
+ * @internal
147
+ */
148
+ static from(path, stats, encoding) {
149
+ const dirent = new Dirent(new ArrayBuffer(sizeof(Dirent) + 1));
150
+ dirent._parentPath = dirname(path);
151
+ dirent._name = encodeUTF8(basename(path));
152
+ dirent.ino = stats.ino;
153
+ dirent.type = ifToDt(stats.mode);
154
+ dirent._encoding = encoding;
155
+ return dirent;
156
+ }
157
+ isFile() {
158
+ return this.type === DirType.REG;
159
+ }
160
+ isDirectory() {
161
+ return this.type === DirType.DIR;
162
+ }
163
+ isBlockDevice() {
164
+ return this.type === DirType.BLK;
165
+ }
166
+ isCharacterDevice() {
167
+ return this.type === DirType.CHR;
168
+ }
169
+ isSymbolicLink() {
170
+ return this.type === DirType.LNK;
171
+ }
172
+ isFIFO() {
173
+ return this.type === DirType.FIFO;
174
+ }
175
+ isSocket() {
176
+ return this.type === DirType.SOCK;
177
+ }
178
+ };
179
+ return Dirent = _classThis;
180
+ })();
181
+ export { Dirent };
44
182
  /**
45
183
  * A class representing a directory stream.
46
184
  */
package/dist/vfs/ioctl.js CHANGED
@@ -87,7 +87,7 @@ var XFlag;
87
87
  })(XFlag || (XFlag = {}));
88
88
  let fsxattr = (() => {
89
89
  var _a, _b, _c, _d, _e;
90
- let _classDecorators = [struct()];
90
+ let _classDecorators = [struct({ name: 'fsxattr' })];
91
91
  let _classDescriptor;
92
92
  let _classExtraInitializers = [];
93
93
  let _classThis;
@@ -52,10 +52,9 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
52
52
  });
53
53
  import { Buffer } from 'buffer';
54
54
  import { Exception, rethrow, setUVMessage, UV } from 'kerium';
55
- import { decodeUTF8 } from 'utilium';
56
55
  import { defaultContext } from '../internal/contexts.js';
57
56
  import { hasAccess, InodeFlags, isBlockDevice, isCharacterDevice, isDirectory, isSymbolicLink } from '../internal/inode.js';
58
- import { dirname, join, matchesGlob, parse, resolve } from '../path.js';
57
+ import { basename, dirname, join, matchesGlob, parse, resolve } from '../path.js';
59
58
  import '../polyfills.js';
60
59
  import { createInterface } from '../readline.js';
61
60
  import { __assertType, globToRegex, normalizeMode, normalizeOptions, normalizePath, normalizeTime } from '../utils.js';
@@ -540,8 +539,9 @@ export async function stat(path, options) {
540
539
  stat;
541
540
  export async function lstat(path, options) {
542
541
  path = normalizePath(path);
543
- const { fs, path: resolved } = resolveMount(path, this);
544
542
  const $ex = { syscall: 'lstat', path };
543
+ path = join(await realpath.call(this, dirname(path)), basename(path));
544
+ const { fs, path: resolved } = resolveMount(path, this);
545
545
  const stats = await fs.stat(resolved).catch(rethrow($ex));
546
546
  if (checkAccess && !hasAccess(this, stats, constants.R_OK))
547
547
  throw UV('EACCES', $ex);
@@ -753,9 +753,9 @@ export async function mkdir(path, options) {
753
753
  return dirs[0][0];
754
754
  }
755
755
  mkdir;
756
- export async function readdir(path, options) {
756
+ export async function readdir(_path, options) {
757
757
  const opt = typeof options === 'object' && options != null ? options : { encoding: options, withFileTypes: false, recursive: false };
758
- path = await realpath.call(this, path);
758
+ const path = await realpath.call(this, _path);
759
759
  const { fs, path: resolved } = resolveMount(path, this);
760
760
  const $ex = { syscall: 'readdir', path };
761
761
  const stats = await fs.stat(resolved).catch(rethrow({ syscall: 'stat', path }));
@@ -779,7 +779,7 @@ export async function readdir(path, options) {
779
779
  return;
780
780
  }
781
781
  if (opt.withFileTypes) {
782
- values.push(new Dirent(entry, entryStats, opt.encoding));
782
+ values.push(Dirent.from(join(_path.toString(), entry), entryStats, opt.encoding));
783
783
  }
784
784
  else if (opt.encoding == 'buffer') {
785
785
  values.push(Buffer.from(entry));
@@ -789,19 +789,9 @@ export async function readdir(path, options) {
789
789
  }
790
790
  if (!opt.recursive || !isDirectory(entryStats))
791
791
  return;
792
- for (const subEntry of await readdir.call(this, join(path, entry), opt)) {
793
- if (subEntry instanceof Dirent) {
794
- subEntry.path = join(entry, subEntry.path);
795
- values.push(subEntry);
796
- }
797
- else if (Buffer.isBuffer(subEntry)) {
798
- // Convert Buffer to string, prefix with the full path
799
- values.push(Buffer.from(join(entry, decodeUTF8(subEntry))));
800
- }
801
- else {
802
- values.push(join(entry, subEntry));
803
- }
804
- }
792
+ const children = await fs.readdir(join(resolved, entry)).catch(rethrow({ syscall: 'readdir', path: join(path, entry) }));
793
+ for (const child of children)
794
+ await addEntry(join(entry, child));
805
795
  };
806
796
  await Promise.all(entries.map(addEntry));
807
797
  return values;
@@ -1238,7 +1228,7 @@ export function glob(pattern, opt) {
1238
1228
  async function* recursiveList(dir) {
1239
1229
  const entries = await readdir(dir, { withFileTypes, encoding: 'utf8' });
1240
1230
  for (const entry of entries) {
1241
- const fullPath = withFileTypes ? entry.path : dir + '/' + entry;
1231
+ const fullPath = withFileTypes ? join(entry.parentPath, entry.name) : dir + '/' + entry;
1242
1232
  if (typeof exclude != 'function' ? exclude.some(p => matchesGlob(p, fullPath)) : exclude((withFileTypes ? entry : fullPath)))
1243
1233
  continue;
1244
1234
  /**
package/dist/vfs/sync.js CHANGED
@@ -52,11 +52,11 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
52
52
  });
53
53
  import { Buffer } from 'buffer';
54
54
  import { Errno, Exception, setUVMessage, UV } from 'kerium';
55
- import { decodeUTF8, encodeUTF8 } from 'utilium';
55
+ import { encodeUTF8 } from 'utilium';
56
56
  import { defaultContext } from '../internal/contexts.js';
57
57
  import { wrap } from '../internal/error.js';
58
58
  import { hasAccess, isDirectory, isSymbolicLink } from '../internal/inode.js';
59
- import { dirname, join, matchesGlob, parse, resolve } from '../path.js';
59
+ import { basename, dirname, join, matchesGlob, parse, resolve } from '../path.js';
60
60
  import { __assertType, globToRegex, normalizeMode, normalizeOptions, normalizePath, normalizeTime } from '../utils.js';
61
61
  import { checkAccess } from './config.js';
62
62
  import * as constants from './constants.js';
@@ -139,7 +139,8 @@ export function statSync(path, options) {
139
139
  statSync;
140
140
  export function lstatSync(path, options) {
141
141
  path = normalizePath(path);
142
- const { fs, path: resolved } = resolveMount(path, this);
142
+ const real = join(realpathSync.call(this, dirname(path)), basename(path));
143
+ const { fs, path: resolved } = resolveMount(real, this);
143
144
  const stats = wrap(fs, 'statSync', path)(resolved);
144
145
  if (checkAccess && !hasAccess(this, stats, constants.R_OK))
145
146
  throw UV('EACCES', { syscall: 'lstat', path });
@@ -485,16 +486,18 @@ export function readdirSync(path, options) {
485
486
  const entries = wrap(fs, 'readdirSync', path)(resolved);
486
487
  // Iterate over entries and handle recursive case if needed
487
488
  const values = [];
488
- for (const entry of entries) {
489
+ const addEntry = (entry) => {
489
490
  let entryStat;
490
491
  try {
491
492
  entryStat = fs.statSync(join(resolved, entry));
492
493
  }
493
- catch {
494
- continue;
494
+ catch (e) {
495
+ if (e.code == 'ENOENT')
496
+ return;
497
+ throw setUVMessage(Object.assign(e, { syscall: 'stat', path: join(path, entry) }));
495
498
  }
496
499
  if (options?.withFileTypes) {
497
- values.push(new Dirent(entry, entryStat, options.encoding));
500
+ values.push(Dirent.from(entry, entryStat, options.encoding));
498
501
  }
499
502
  else if (options?.encoding == 'buffer') {
500
503
  values.push(Buffer.from(entry));
@@ -503,20 +506,13 @@ export function readdirSync(path, options) {
503
506
  values.push(entry);
504
507
  }
505
508
  if (!isDirectory(entryStat) || !options?.recursive)
506
- continue;
507
- for (const subEntry of readdirSync.call(this, join(path, entry), options)) {
508
- if (subEntry instanceof Dirent) {
509
- subEntry.path = join(entry, subEntry.path);
510
- values.push(subEntry);
511
- }
512
- else if (Buffer.isBuffer(subEntry)) {
513
- values.push(Buffer.from(join(entry, decodeUTF8(subEntry))));
514
- }
515
- else {
516
- values.push(join(entry, subEntry));
517
- }
518
- }
519
- }
509
+ return;
510
+ const children = wrap(fs, 'readdirSync', join(path, entry))(join(resolved, entry));
511
+ for (const child of children)
512
+ addEntry(join(entry, child));
513
+ };
514
+ for (const entry of entries)
515
+ addEntry(entry);
520
516
  return values;
521
517
  }
522
518
  readdirSync;
@@ -862,7 +858,7 @@ export function globSync(pattern, options = {}) {
862
858
  function recursiveList(dir) {
863
859
  const entries = readdirSync(dir, { withFileTypes, encoding: 'utf8' });
864
860
  for (const entry of entries) {
865
- const fullPath = withFileTypes ? entry.path : dir + '/' + entry;
861
+ const fullPath = withFileTypes ? join(entry.parentPath, entry.name) : dir + '/' + entry;
866
862
  if (typeof exclude != 'function' ? exclude.some(p => matchesGlob(p, fullPath)) : exclude((withFileTypes ? entry : fullPath)))
867
863
  continue;
868
864
  /**
@@ -872,7 +868,7 @@ export function globSync(pattern, options = {}) {
872
868
  recursiveList(fullPath);
873
869
  }
874
870
  if (regexPatterns.some(pattern => pattern.test(fullPath.replace(/^\/+/g, '')))) {
875
- results.push(withFileTypes ? entry.path : fullPath.replace(/^\/+/g, ''));
871
+ results.push(withFileTypes ? entry : fullPath.replace(/^\/+/g, ''));
876
872
  }
877
873
  }
878
874
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenfs/core",
3
- "version": "2.3.2",
3
+ "version": "2.3.3",
4
4
  "description": "A filesystem, anywhere",
5
5
  "funding": {
6
6
  "type": "individual",
package/scripts/test.js CHANGED
@@ -212,7 +212,7 @@ for (const setupFile of positionals) {
212
212
  execSync(
213
213
  [
214
214
  'tsx --trace-deprecation',
215
- options.inspect ? 'inspect' : '',
215
+ options.inspect ? '--inspect' : '',
216
216
  '--test --experimental-test-coverage',
217
217
  options.force ? '--test-force-exit' : '',
218
218
  options.skip ? `--test-skip-pattern=${options.skip}` : '',
@@ -16,15 +16,15 @@ for (const file of testFiles) {
16
16
  suite('Dirent', () => {
17
17
  test('name and parentPath getters', async () => {
18
18
  const stats = await fs.promises.lstat(testFile);
19
- const dirent = new fs.Dirent(testFile, stats);
19
+ const dirent = fs.Dirent.from(testFile, stats);
20
20
 
21
21
  assert.equal(dirent.name, testFile);
22
- assert.equal(dirent.parentPath, testFile);
22
+ assert.equal(dirent.parentPath, '.');
23
23
  });
24
24
 
25
25
  test('isFile', async () => {
26
26
  const fileStats = await fs.promises.lstat(testFile);
27
- const fileDirent = new fs.Dirent(testFile, fileStats);
27
+ const fileDirent = fs.Dirent.from(testFile, fileStats);
28
28
 
29
29
  assert(fileDirent.isFile());
30
30
  assert(!fileDirent.isDirectory());
@@ -32,7 +32,7 @@ suite('Dirent', () => {
32
32
 
33
33
  test('isDirectory', async () => {
34
34
  const dirStats = await fs.promises.lstat('test-directory');
35
- const dirDirent = new fs.Dirent('test-directory', dirStats);
35
+ const dirDirent = fs.Dirent.from('test-directory', dirStats);
36
36
 
37
37
  assert(!dirDirent.isFile());
38
38
  assert(dirDirent.isDirectory());
@@ -40,14 +40,14 @@ suite('Dirent', () => {
40
40
 
41
41
  test('isSymbolicLink', async () => {
42
42
  const symlinkStats = await fs.promises.lstat('test-symlink');
43
- const symlinkDirent = new fs.Dirent('test-symlink', symlinkStats);
43
+ const symlinkDirent = fs.Dirent.from('test-symlink', symlinkStats);
44
44
 
45
45
  assert(symlinkDirent.isSymbolicLink());
46
46
  });
47
47
 
48
48
  test('other methods return false', async () => {
49
49
  const fileStats = await fs.promises.lstat(testFile);
50
- const fileDirent = new fs.Dirent(testFile, fileStats);
50
+ const fileDirent = fs.Dirent.from(testFile, fileStats);
51
51
 
52
52
  assert(!fileDirent.isBlockDevice());
53
53
  assert(!fileDirent.isCharacterDevice());
@@ -1,4 +1,5 @@
1
1
  import assert from 'node:assert/strict';
2
+ import { join } from 'node:path/posix';
2
3
  import { suite, test } from 'node:test';
3
4
  import { fs } from '../common.js';
4
5
 
@@ -143,10 +144,12 @@ suite('Directories', () => {
143
144
 
144
145
  test('readdir returns Dirent recursively', async () => {
145
146
  const entries = await fs.promises.readdir(testDir, { recursive: true, withFileTypes: true });
146
- const paths = entries.map(entry => entry.path).sort();
147
- assert.equal(paths[0], 'file1.txt');
148
- assert.equal(paths[4], 'subdir1/file4.txt');
149
- assert.equal(paths[8], 'subdir2/file5.txt');
147
+ entries.sort((a, b) => join(a.parentPath, a.name).localeCompare(join(b.parentPath, b.name)));
148
+ const values = entries.map(entry => [entry.parentPath, entry.name]);
149
+
150
+ assert.deepEqual(values[0], [testDir, 'file1.txt']);
151
+ assert.deepEqual(values[4], [join(testDir, 'subdir1'), 'file4.txt']);
152
+ assert.deepEqual(values[8], [join(testDir, 'subdir2'), 'file5.txt']);
150
153
  });
151
154
 
152
155
  test('readdirSync returns files recursively', () => {
@@ -18,6 +18,16 @@ suite('Links', () => {
18
18
  assert(stats.isSymbolicLink());
19
19
  });
20
20
 
21
+ test('lstat file inside symlinked directory', async () => {
22
+ // @zenfs/core#241
23
+ await fs.promises.mkdir('/a');
24
+ await fs.promises.writeFile('/a/hello.txt', 'hello world');
25
+ await fs.promises.symlink('/a', '/b');
26
+
27
+ const stat = await fs.promises.lstat('/b/hello.txt');
28
+ assert(stat.isFile());
29
+ });
30
+
21
31
  test('readlink', async () => {
22
32
  const destination = await fs.promises.readlink(symlink);
23
33
  assert.equal(destination, target);