@zenfs/core 2.2.2 → 2.2.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.
- package/dist/backends/single_buffer.js +1 -0
- package/dist/internal/credentials.d.ts +6 -0
- package/dist/internal/credentials.js +10 -0
- package/dist/utils.d.ts +1 -2
- package/dist/vfs/dir.d.ts +4 -3
- package/dist/vfs/dir.js +4 -2
- package/dist/vfs/promises.d.ts +33 -25
- package/dist/vfs/promises.js +8 -8
- package/dist/vfs/shared.js +6 -5
- package/dist/vfs/sync.d.ts +22 -11
- package/dist/vfs/sync.js +1 -1
- package/dist/vfs/types.d.ts +3 -8
- package/package.json +2 -2
- package/tests/common/context.test.ts +14 -0
|
@@ -486,6 +486,7 @@ let SuperBlock = (() => {
|
|
|
486
486
|
* @returns the new metadata block
|
|
487
487
|
*/
|
|
488
488
|
rotateMetadata() {
|
|
489
|
+
this.used_bytes += this.used_bytes % BigInt(4);
|
|
489
490
|
const metadata = new MetadataBlock(this.buffer, Number(this.used_bytes));
|
|
490
491
|
metadata.previous_offset = this.metadata_offset;
|
|
491
492
|
this.metadata = metadata;
|
|
@@ -28,3 +28,9 @@ export interface CredentialsInit extends Partial<Credentials> {
|
|
|
28
28
|
* @category Internals
|
|
29
29
|
*/
|
|
30
30
|
export declare function createCredentials(source: CredentialsInit): Credentials;
|
|
31
|
+
/**
|
|
32
|
+
* Returns true if the credentials can be used for an operation that requires root privileges.
|
|
33
|
+
* @internal
|
|
34
|
+
* @category Internals
|
|
35
|
+
*/
|
|
36
|
+
export declare function credentialsAllowRoot(cred?: Credentials): boolean;
|
|
@@ -11,3 +11,13 @@ export function createCredentials(source) {
|
|
|
11
11
|
...source,
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Returns true if the credentials can be used for an operation that requires root privileges.
|
|
16
|
+
* @internal
|
|
17
|
+
* @category Internals
|
|
18
|
+
*/
|
|
19
|
+
export function credentialsAllowRoot(cred) {
|
|
20
|
+
if (!cred)
|
|
21
|
+
return false;
|
|
22
|
+
return !cred.uid || !cred.gid || !cred.euid || !cred.egid || cred.groups.some(gid => !gid);
|
|
23
|
+
}
|
package/dist/utils.d.ts
CHANGED
|
@@ -48,8 +48,7 @@ export declare function normalizePath(p: fs.PathLike, noResolve?: boolean): stri
|
|
|
48
48
|
*/
|
|
49
49
|
export declare function normalizeOptions(options: fs.WriteFileOptions | (fs.EncodingOption & {
|
|
50
50
|
flag?: fs.OpenMode;
|
|
51
|
-
}) | undefined, encoding: (BufferEncoding | null) | undefined, flag: string, mode?: number): {
|
|
52
|
-
encoding?: BufferEncoding | null;
|
|
51
|
+
}) | undefined, encoding: (BufferEncoding | null) | undefined, flag: string, mode?: number): fs.ObjectEncodingOptions & {
|
|
53
52
|
flag: string;
|
|
54
53
|
mode: number;
|
|
55
54
|
};
|
package/dist/vfs/dir.d.ts
CHANGED
|
@@ -2,11 +2,12 @@ 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 implements _Dirent {
|
|
5
|
+
export declare class Dirent<Name extends string | Buffer = string> implements _Dirent<Name> {
|
|
6
6
|
path: string;
|
|
7
7
|
protected stats: InodeLike;
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
protected readonly encoding?: (BufferEncoding | "buffer" | null) | undefined;
|
|
9
|
+
get name(): Name;
|
|
10
|
+
constructor(path: string, stats: InodeLike, encoding?: (BufferEncoding | "buffer" | null) | undefined);
|
|
10
11
|
get parentPath(): string;
|
|
11
12
|
isFile(): boolean;
|
|
12
13
|
isDirectory(): boolean;
|
package/dist/vfs/dir.js
CHANGED
|
@@ -5,11 +5,13 @@ import { readdir } from './promises.js';
|
|
|
5
5
|
import { readdirSync } from './sync.js';
|
|
6
6
|
export class Dirent {
|
|
7
7
|
get name() {
|
|
8
|
-
|
|
8
|
+
const name = Buffer.from(basename(this.path));
|
|
9
|
+
return (this.encoding == 'buffer' ? name : name.toString(this.encoding));
|
|
9
10
|
}
|
|
10
|
-
constructor(path, stats) {
|
|
11
|
+
constructor(path, stats, encoding) {
|
|
11
12
|
this.path = path;
|
|
12
13
|
this.stats = stats;
|
|
14
|
+
this.encoding = encoding;
|
|
13
15
|
}
|
|
14
16
|
get parentPath() {
|
|
15
17
|
return this.path;
|
package/dist/vfs/promises.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Abortable } from 'node:events';
|
|
1
2
|
import type * as fs from 'node:fs';
|
|
2
3
|
import type * as promises from 'node:fs/promises';
|
|
3
4
|
import type { Stream } from 'node:stream';
|
|
@@ -6,7 +7,7 @@ import type { V_Context } from '../context.js';
|
|
|
6
7
|
import type { FileSystem, StreamOptions } from '../internal/filesystem.js';
|
|
7
8
|
import type { InodeLike } from '../internal/inode.js';
|
|
8
9
|
import type { Interface as ReadlineInterface } from '../readline.js';
|
|
9
|
-
import type { FileContents,
|
|
10
|
+
import type { FileContents, ReaddirOptions } from './types.js';
|
|
10
11
|
import { Buffer } from 'buffer';
|
|
11
12
|
import '../polyfills.js';
|
|
12
13
|
import { Dir, Dirent } from './dir.js';
|
|
@@ -114,16 +115,13 @@ export declare class FileHandle implements promises.FileHandle {
|
|
|
114
115
|
read<T extends NodeJS.ArrayBufferView>(buffer: T, offset?: number, length?: number, position?: number | null): Promise<promises.FileReadResult<T>>;
|
|
115
116
|
read<T extends NodeJS.ArrayBufferView = Buffer>(buffer: T, options?: promises.FileReadOptions<T>): Promise<promises.FileReadResult<T>>;
|
|
116
117
|
read<T extends NodeJS.ArrayBufferView = Buffer>(options?: promises.FileReadOptions<T>): Promise<promises.FileReadResult<T>>;
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
readFile(_options?:
|
|
124
|
-
flag?: fs.OpenMode;
|
|
125
|
-
}): Promise<Buffer>;
|
|
126
|
-
readFile(_options: (fs.ObjectEncodingOptions & promises.FlagAndOpenMode) | BufferEncoding): Promise<string>;
|
|
118
|
+
readFile(options?: ({
|
|
119
|
+
encoding?: null;
|
|
120
|
+
} & Abortable) | null): Promise<Buffer>;
|
|
121
|
+
readFile(options: ({
|
|
122
|
+
encoding: BufferEncoding;
|
|
123
|
+
} & Abortable) | BufferEncoding): Promise<string>;
|
|
124
|
+
readFile(_options?: (fs.ObjectEncodingOptions & Abortable) | BufferEncoding | null): Promise<string | Buffer>;
|
|
127
125
|
/**
|
|
128
126
|
* Read file data using a `ReadableStream`.
|
|
129
127
|
* The handle will not be closed automatically.
|
|
@@ -254,15 +252,15 @@ export declare function open(this: V_Context, path: fs.PathLike, flag?: fs.OpenM
|
|
|
254
252
|
* @option flag Defaults to `'r'`.
|
|
255
253
|
* @returns the file data
|
|
256
254
|
*/
|
|
257
|
-
export declare function readFile(this: V_Context, path: fs.PathLike | promises.FileHandle, options?: {
|
|
255
|
+
export declare function readFile(this: V_Context, path: fs.PathLike | promises.FileHandle, options?: ({
|
|
258
256
|
encoding?: null;
|
|
259
257
|
flag?: fs.OpenMode;
|
|
260
|
-
} | null): Promise<Buffer>;
|
|
261
|
-
export declare function readFile(this: V_Context, path: fs.PathLike | promises.FileHandle, options: {
|
|
258
|
+
} & Abortable) | null): Promise<Buffer>;
|
|
259
|
+
export declare function readFile(this: V_Context, path: fs.PathLike | promises.FileHandle, options: ({
|
|
262
260
|
encoding: BufferEncoding;
|
|
263
261
|
flag?: fs.OpenMode;
|
|
264
|
-
} | BufferEncoding): Promise<string>;
|
|
265
|
-
export declare function readFile(this: V_Context, path: fs.PathLike | promises.FileHandle,
|
|
262
|
+
} & Abortable) | BufferEncoding): Promise<string>;
|
|
263
|
+
export declare function readFile(this: V_Context, path: fs.PathLike | promises.FileHandle, _options?: (fs.ObjectEncodingOptions & Abortable & {
|
|
266
264
|
flag?: fs.OpenMode;
|
|
267
265
|
}) | BufferEncoding | null): Promise<string | Buffer>;
|
|
268
266
|
/**
|
|
@@ -309,19 +307,29 @@ export declare function mkdir(this: V_Context, path: fs.PathLike, options?: fs.M
|
|
|
309
307
|
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
|
|
310
308
|
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'`.
|
|
311
309
|
*/
|
|
312
|
-
export declare function readdir(this: V_Context, path: fs.PathLike, options?:
|
|
310
|
+
export declare function readdir(this: V_Context, path: fs.PathLike, options?: (fs.ObjectEncodingOptions & {
|
|
313
311
|
withFileTypes?: false;
|
|
314
|
-
|
|
315
|
-
|
|
312
|
+
recursive?: boolean;
|
|
313
|
+
}) | BufferEncoding | null): Promise<string[]>;
|
|
314
|
+
export declare function readdir(this: V_Context, path: fs.PathLike, options: {
|
|
315
|
+
encoding: 'buffer';
|
|
316
316
|
withFileTypes?: false;
|
|
317
|
-
|
|
318
|
-
|
|
317
|
+
recursive?: boolean;
|
|
318
|
+
} | 'buffer'): Promise<Buffer[]>;
|
|
319
|
+
export declare function readdir(this: V_Context, path: fs.PathLike, options?: (fs.ObjectEncodingOptions & {
|
|
319
320
|
withFileTypes?: false;
|
|
320
|
-
|
|
321
|
-
|
|
321
|
+
recursive?: boolean;
|
|
322
|
+
}) | BufferEncoding | null): Promise<string[] | Buffer[]>;
|
|
323
|
+
export declare function readdir(this: V_Context, path: fs.PathLike, options: fs.ObjectEncodingOptions & {
|
|
324
|
+
withFileTypes: true;
|
|
325
|
+
recursive?: boolean;
|
|
326
|
+
}): Promise<Dirent[]>;
|
|
327
|
+
export declare function readdir(this: V_Context, path: fs.PathLike, options: {
|
|
328
|
+
encoding: 'buffer';
|
|
322
329
|
withFileTypes: true;
|
|
323
|
-
|
|
324
|
-
|
|
330
|
+
recursive?: boolean;
|
|
331
|
+
}): Promise<Dirent<Buffer>[]>;
|
|
332
|
+
export declare function readdir(this: V_Context, path: fs.PathLike, options?: ReaddirOptions): Promise<string[] | Dirent<any>[] | Buffer[]>;
|
|
325
333
|
export declare function link(this: V_Context, path: fs.PathLike, dest: fs.PathLike): Promise<void>;
|
|
326
334
|
/**
|
|
327
335
|
* `symlink`.
|
package/dist/vfs/promises.js
CHANGED
|
@@ -737,7 +737,7 @@ export async function mkdir(path, options) {
|
|
|
737
737
|
}
|
|
738
738
|
mkdir;
|
|
739
739
|
export async function readdir(path, options) {
|
|
740
|
-
|
|
740
|
+
const opt = typeof options === 'object' && options != null ? options : { encoding: options, withFileTypes: false, recursive: false };
|
|
741
741
|
path = await realpath.call(this, path);
|
|
742
742
|
const { fs, path: resolved } = resolveMount(path, this);
|
|
743
743
|
const $ex = { syscall: 'readdir', path };
|
|
@@ -752,7 +752,7 @@ export async function readdir(path, options) {
|
|
|
752
752
|
const values = [];
|
|
753
753
|
const addEntry = async (entry) => {
|
|
754
754
|
let entryStats;
|
|
755
|
-
if (
|
|
755
|
+
if (opt.recursive || opt.withFileTypes) {
|
|
756
756
|
entryStats = await fs.stat(join(resolved, entry)).catch((e) => {
|
|
757
757
|
if (e.code == 'ENOENT')
|
|
758
758
|
return;
|
|
@@ -761,18 +761,18 @@ export async function readdir(path, options) {
|
|
|
761
761
|
if (!entryStats)
|
|
762
762
|
return;
|
|
763
763
|
}
|
|
764
|
-
if (
|
|
765
|
-
values.push(new Dirent(entry, entryStats));
|
|
764
|
+
if (opt.withFileTypes) {
|
|
765
|
+
values.push(new Dirent(entry, entryStats, opt.encoding));
|
|
766
766
|
}
|
|
767
|
-
else if (
|
|
767
|
+
else if (opt.encoding == 'buffer') {
|
|
768
768
|
values.push(Buffer.from(entry));
|
|
769
769
|
}
|
|
770
770
|
else {
|
|
771
771
|
values.push(entry);
|
|
772
772
|
}
|
|
773
|
-
if (!
|
|
773
|
+
if (!opt.recursive || !isDirectory(entryStats))
|
|
774
774
|
return;
|
|
775
|
-
for (const subEntry of await readdir.call(this, join(path, entry),
|
|
775
|
+
for (const subEntry of await readdir.call(this, join(path, entry), opt)) {
|
|
776
776
|
if (subEntry instanceof Dirent) {
|
|
777
777
|
subEntry.path = join(entry, subEntry.path);
|
|
778
778
|
values.push(subEntry);
|
|
@@ -1102,7 +1102,7 @@ export async function rm(path, options) {
|
|
|
1102
1102
|
switch (stats.mode & constants.S_IFMT) {
|
|
1103
1103
|
case constants.S_IFDIR:
|
|
1104
1104
|
if (options === null || options === void 0 ? void 0 : options.recursive) {
|
|
1105
|
-
for (const entry of
|
|
1105
|
+
for (const entry of await readdir.call(this, path)) {
|
|
1106
1106
|
await rm.call(this, join(path, entry), options);
|
|
1107
1107
|
}
|
|
1108
1108
|
}
|
package/dist/vfs/shared.js
CHANGED
|
@@ -6,6 +6,7 @@ import { defaultContext } from '../internal/contexts.js';
|
|
|
6
6
|
import { join, resolve } from '../path.js';
|
|
7
7
|
import { normalizePath } from '../utils.js';
|
|
8
8
|
import { size_max } from './constants.js';
|
|
9
|
+
import { credentialsAllowRoot } from '../internal/credentials.js';
|
|
9
10
|
/**
|
|
10
11
|
* The map of mount points
|
|
11
12
|
* @category Backends and Configuration
|
|
@@ -59,7 +60,7 @@ export function resolveMount(path, ctx) {
|
|
|
59
60
|
continue;
|
|
60
61
|
path = path.slice(mountPoint.length > 1 ? mountPoint.length : 0); // Resolve the path relative to the mount point
|
|
61
62
|
if (path === '')
|
|
62
|
-
path =
|
|
63
|
+
path = '/';
|
|
63
64
|
const case_fold = fs.attributes.get('case_fold');
|
|
64
65
|
if (case_fold === 'lower')
|
|
65
66
|
path = path.toLowerCase();
|
|
@@ -90,13 +91,13 @@ export function _statfs(fs, bigint) {
|
|
|
90
91
|
* @category Backends and Configuration
|
|
91
92
|
*/
|
|
92
93
|
export function chroot(path) {
|
|
93
|
-
var _a, _b, _c
|
|
94
|
+
var _a, _b, _c;
|
|
94
95
|
const $ = this !== null && this !== void 0 ? this : defaultContext;
|
|
95
|
-
if ((
|
|
96
|
+
if (!credentialsAllowRoot($.credentials))
|
|
96
97
|
throw withErrno('EPERM', 'Can not chroot() as non-root user');
|
|
97
|
-
(
|
|
98
|
+
(_a = $.root) !== null && _a !== void 0 ? _a : ($.root = '/');
|
|
98
99
|
const newRoot = join($.root, path);
|
|
99
|
-
for (const handle of (
|
|
100
|
+
for (const handle of (_c = (_b = $.descriptors) === null || _b === void 0 ? void 0 : _b.values()) !== null && _c !== void 0 ? _c : []) {
|
|
100
101
|
if (!handle.path.startsWith($.root))
|
|
101
102
|
throw UV('EBUSY', 'chroot', handle.path);
|
|
102
103
|
handle.path = handle.path.slice($.root.length);
|
package/dist/vfs/sync.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type * as fs from 'node:fs';
|
|
2
2
|
import type { V_Context } from '../context.js';
|
|
3
|
-
import type { FileContents,
|
|
3
|
+
import type { FileContents, ReaddirOptions } from './types.js';
|
|
4
4
|
import { Buffer } from 'buffer';
|
|
5
5
|
import { Dir, Dirent } from './dir.js';
|
|
6
6
|
import { BigIntStats, Stats } from './stats.js';
|
|
@@ -47,7 +47,7 @@ export declare function lopenSync(this: V_Context, path: fs.PathLike, flag: stri
|
|
|
47
47
|
*/
|
|
48
48
|
export declare function readFileSync(this: V_Context, path: fs.PathOrFileDescriptor, options?: {
|
|
49
49
|
flag?: string;
|
|
50
|
-
} | null):
|
|
50
|
+
} | null): NonSharedBuffer;
|
|
51
51
|
export declare function readFileSync(this: V_Context, path: fs.PathOrFileDescriptor, options?: (fs.EncodingOption & {
|
|
52
52
|
flag?: string;
|
|
53
53
|
}) | BufferEncoding | null): string;
|
|
@@ -112,19 +112,30 @@ export declare function mkdirSync(this: V_Context, path: fs.PathLike, options?:
|
|
|
112
112
|
recursive?: false;
|
|
113
113
|
}) | null): void;
|
|
114
114
|
export declare function mkdirSync(this: V_Context, path: fs.PathLike, options?: fs.Mode | fs.MakeDirectoryOptions | null): string | undefined;
|
|
115
|
-
export declare function readdirSync(this: V_Context, path: fs.PathLike, options?:
|
|
115
|
+
export declare function readdirSync(this: V_Context, path: fs.PathLike, options?: {
|
|
116
|
+
encoding: BufferEncoding | null;
|
|
116
117
|
withFileTypes?: false;
|
|
117
|
-
|
|
118
|
-
|
|
118
|
+
recursive?: boolean;
|
|
119
|
+
} | BufferEncoding | null): string[];
|
|
120
|
+
export declare function readdirSync(this: V_Context, path: fs.PathLike, options: {
|
|
121
|
+
encoding: 'buffer';
|
|
119
122
|
withFileTypes?: false;
|
|
120
|
-
|
|
121
|
-
|
|
123
|
+
recursive?: boolean;
|
|
124
|
+
} | 'buffer'): Buffer[];
|
|
125
|
+
export declare function readdirSync(this: V_Context, path: fs.PathLike, options?: (fs.ObjectEncodingOptions & {
|
|
122
126
|
withFileTypes?: false;
|
|
123
|
-
|
|
124
|
-
|
|
127
|
+
recursive?: boolean;
|
|
128
|
+
}) | BufferEncoding | null): string[] | Buffer[];
|
|
129
|
+
export declare function readdirSync(this: V_Context, path: fs.PathLike, options: fs.ObjectEncodingOptions & {
|
|
125
130
|
withFileTypes: true;
|
|
126
|
-
|
|
127
|
-
|
|
131
|
+
recursive?: boolean;
|
|
132
|
+
}): Dirent[];
|
|
133
|
+
export declare function readdirSync(this: V_Context, path: fs.PathLike, options: {
|
|
134
|
+
encoding: 'buffer';
|
|
135
|
+
withFileTypes: true;
|
|
136
|
+
recursive?: boolean;
|
|
137
|
+
}): Dirent<Buffer>[];
|
|
138
|
+
export declare function readdirSync(this: V_Context, path: fs.PathLike, options?: ReaddirOptions): string[] | Dirent<any>[] | Buffer[];
|
|
128
139
|
export declare function linkSync(this: V_Context, targetPath: fs.PathLike, linkPath: fs.PathLike): void;
|
|
129
140
|
/**
|
|
130
141
|
* Synchronous `symlink`.
|
package/dist/vfs/sync.js
CHANGED
|
@@ -496,7 +496,7 @@ export function readdirSync(path, options) {
|
|
|
496
496
|
continue;
|
|
497
497
|
}
|
|
498
498
|
if (options === null || options === void 0 ? void 0 : options.withFileTypes) {
|
|
499
|
-
values.push(new Dirent(entry, entryStat));
|
|
499
|
+
values.push(new Dirent(entry, entryStat, options.encoding));
|
|
500
500
|
}
|
|
501
501
|
else if ((options === null || options === void 0 ? void 0 : options.encoding) == 'buffer') {
|
|
502
502
|
values.push(Buffer.from(entry));
|
package/dist/vfs/types.d.ts
CHANGED
|
@@ -15,15 +15,10 @@ export interface OpenOptions {
|
|
|
15
15
|
*/
|
|
16
16
|
allowDirectory?: boolean;
|
|
17
17
|
}
|
|
18
|
-
export
|
|
18
|
+
export type ReaddirOptions = {
|
|
19
19
|
withFileTypes?: boolean;
|
|
20
20
|
recursive?: boolean;
|
|
21
|
-
|
|
21
|
+
encoding?: BufferEncoding | 'buffer' | null;
|
|
22
|
+
} | BufferEncoding | 'buffer' | null;
|
|
22
23
|
/** Helper union @hidden */
|
|
23
24
|
export type GlobOptionsU = fs.GlobOptionsWithFileTypes | fs.GlobOptionsWithoutFileTypes | fs.GlobOptions;
|
|
24
|
-
/** Helper with union @hidden */
|
|
25
|
-
export type ReaddirOptsU<T> = (ReaddirOptions & (fs.ObjectEncodingOptions | T)) | NullEnc;
|
|
26
|
-
/** Helper with intersection @hidden */
|
|
27
|
-
export type ReaddirOptsI<T> = ReaddirOptions & fs.ObjectEncodingOptions & T;
|
|
28
|
-
/** @hidden */
|
|
29
|
-
export type NullEnc = BufferEncoding | null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenfs/core",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.3",
|
|
4
4
|
"description": "A filesystem, anywhere",
|
|
5
5
|
"funding": {
|
|
6
6
|
"type": "individual",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"buffer": "^6.0.3",
|
|
72
72
|
"eventemitter3": "^5.0.1",
|
|
73
73
|
"kerium": "^1.3.4",
|
|
74
|
-
"memium": "^0.2.
|
|
74
|
+
"memium": "^0.2.1",
|
|
75
75
|
"readable-stream": "^4.5.2",
|
|
76
76
|
"utilium": "^2.3.3"
|
|
77
77
|
},
|
|
@@ -3,6 +3,7 @@ import { suite, test } from 'node:test';
|
|
|
3
3
|
import { canary } from 'utilium';
|
|
4
4
|
import { bindContext } from '../../dist/context.js';
|
|
5
5
|
import * as fs from '../../dist/vfs/index.js';
|
|
6
|
+
import { configure, InMemory } from '../../dist/index.js';
|
|
6
7
|
|
|
7
8
|
fs.mkdirSync('/ctx');
|
|
8
9
|
const { fs: ctx } = bindContext({ root: '/ctx' });
|
|
@@ -58,4 +59,17 @@ suite('Context', () => {
|
|
|
58
59
|
await watcher.return!();
|
|
59
60
|
await promise;
|
|
60
61
|
});
|
|
62
|
+
|
|
63
|
+
test('Path resolution of / with context root and mount point being the same', async () => {
|
|
64
|
+
// @zenfs/core#226
|
|
65
|
+
await configure({
|
|
66
|
+
mounts: { '/bananas': InMemory },
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const bananas = bindContext({ root: '/bananas' });
|
|
70
|
+
|
|
71
|
+
fs.writeFileSync('/bananas/yellow', 'true');
|
|
72
|
+
|
|
73
|
+
assert.deepEqual(bananas.fs.readdirSync('/'), ['yellow']);
|
|
74
|
+
});
|
|
61
75
|
});
|