New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@zenfs/core

Package Overview
Dependencies
Maintainers
0
Versions
165
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@zenfs/core - npm Package Compare versions

Comparing version 1.5.1 to 1.6.0

2

dist/config.d.ts
import type { Backend, BackendConfiguration, FilesystemOf, SharedConfig } from './backends/backend.js';
import { type Device, type DeviceDriver } from './devices.js';
/**

@@ -88,2 +89,3 @@ * Configuration for a specific mount point

export declare function configureSingle<T extends Backend>(configuration: MountConfiguration<T>): Promise<void>;
export declare function addDevice(driver: DeviceDriver, options?: object): Device;
/**

@@ -90,0 +92,0 @@ * Configures ZenFS with `configuration`

@@ -7,2 +7,3 @@ import { checkOptions, isBackend, isBackendConfig } from './backends/backend.js';

import * as fs from './emulation/index.js';
import { mounts } from './emulation/shared.js';
import { Errno, ErrnoError } from './error.js';

@@ -84,2 +85,8 @@ import { FileSystem } from './filesystem.js';

}
export function addDevice(driver, options) {
const devfs = mounts.get('/dev');
if (!(devfs instanceof DeviceFS))
throw new ErrnoError(Errno.ENOTSUP, '/dev does not exist or is not a device file system');
return devfs._createDevice(driver, options);
}
/**

@@ -86,0 +93,0 @@ * Configures ZenFS with `configuration`

53

dist/devices.d.ts

@@ -11,3 +11,3 @@ import type { FileReadResult } from 'node:fs/promises';

* @privateRemarks
* UUIDs were considered, however they don't make sense without an easy mechanism for persistance
* UUIDs were considered, however they don't make sense without an easy mechanism for persistence
*/

@@ -26,3 +26,2 @@ export interface Device<TData = any> {

* This is meant to be used by device drivers.
* @experimental
*/

@@ -32,3 +31,2 @@ data: TData;

* Major device number
* @experimental
*/

@@ -38,3 +36,2 @@ major: number;

* Minor device number
* @experimental
*/

@@ -52,2 +49,7 @@ minor: number;

/**
* If true, only a single device can exist per device FS.
* Note that if this is unset or false, auto-named devices will have a number suffix
*/
singleton?: boolean;
/**
* Whether the device is buffered (a "block" device) or unbuffered (a "character" device)

@@ -60,8 +62,8 @@ * @default false

* @returns `Device.data`
* @experimental
*/
init?(ino: bigint): {
init?(ino: bigint, options: object): {
data?: TData;
minor?: number;
major?: number;
name?: string;
};

@@ -72,3 +74,3 @@ /**

*/
read(file: DeviceFile, buffer: ArrayBufferView, offset?: number, length?: number, position?: number): number;
read(file: DeviceFile<TData>, buffer: ArrayBufferView, offset?: number, length?: number, position?: number): number;
/**

@@ -78,3 +80,3 @@ * Synchronously write to the device

*/
write(file: DeviceFile, buffer: Uint8Array, offset: number, length: number, position?: number): number;
write(file: DeviceFile<TData>, buffer: Uint8Array, offset: number, length: number, position?: number): number;
/**

@@ -84,3 +86,3 @@ * Sync the device

*/
sync?(file: DeviceFile): void;
sync?(file: DeviceFile<TData>): void;
/**

@@ -90,3 +92,3 @@ * Close the device

*/
close?(file: DeviceFile): void;
close?(file: DeviceFile<TData>): void;
}

@@ -99,8 +101,8 @@ /**

*/
export declare class DeviceFile extends File {
export declare class DeviceFile<TData = any> extends File {
fs: DeviceFS;
readonly device: Device;
readonly device: Device<TData>;
position: number;
constructor(fs: DeviceFS, path: string, device: Device);
get driver(): DeviceDriver;
constructor(fs: DeviceFS, path: string, device: Device<TData>);
get driver(): DeviceDriver<TData>;
protected get stats(): Partial<StatsLike>;

@@ -135,5 +137,11 @@ stat(): Promise<Stats>;

* Creates a new device at `path` relative to the `DeviceFS` root.
* @deprecated
*/
createDevice<TData = any>(path: string, driver: DeviceDriver<TData>): Device<TData | Record<string, never>>;
createDevice<TData = any>(path: string, driver: DeviceDriver<TData>, options?: object): Device<TData | Record<string, never>>;
protected devicesWithDriver(driver: DeviceDriver<unknown> | string, forceIdentity?: boolean): Device[];
/**
* @internal
*/
_createDevice<TData = any>(driver: DeviceDriver<TData>, options?: object): Device<TData | Record<string, never>>;
/**
* Adds default devices

@@ -168,3 +176,3 @@ */

* - Writes discard data, advancing the file position.
* @experimental
* @internal
*/

@@ -180,3 +188,3 @@ export declare const nullDevice: DeviceDriver;

* - Provides basic file metadata, treating it as a character device.
* @experimental
* @internal
*/

@@ -188,3 +196,3 @@ export declare const zeroDevice: DeviceDriver;

* - Writes always fail with ENOSPC (no space left on device).
* @experimental
* @internal
*/

@@ -196,3 +204,3 @@ export declare const fullDevice: DeviceDriver;

* - Writes discard data, advancing the file position.
* @experimental
* @internal
*/

@@ -202,5 +210,4 @@ export declare const randomDevice: DeviceDriver;

* Shortcuts for importing.
* @experimental
*/
declare const _default: {
export declare const devices: {
null: DeviceDriver<any>;

@@ -210,3 +217,5 @@ zero: DeviceDriver<any>;

random: DeviceDriver<any>;
console: DeviceDriver<{
output: (text: string) => unknown;
}>;
};
export default _default;

@@ -63,2 +63,3 @@ /*

import { basename, dirname } from './emulation/path.js';
import { decodeUTF8 } from './utils.js';
/**

@@ -158,4 +159,5 @@ * The base class for device files

* Creates a new device at `path` relative to the `DeviceFS` root.
* @deprecated
*/
createDevice(path, driver) {
createDevice(path, driver, options = {}) {
if (this.existsSync(path)) {

@@ -173,3 +175,3 @@ throw ErrnoError.With('EEXIST', path, 'mknod');

major: 0,
...driver.init?.(ino),
...driver.init?.(ino, options),
};

@@ -179,10 +181,47 @@ this.devices.set(path, dev);

}
devicesWithDriver(driver, forceIdentity) {
if (forceIdentity && typeof driver == 'string') {
throw new ErrnoError(Errno.EINVAL, 'Can not fetch devices using only a driver name');
}
const devs = [];
for (const device of this.devices.values()) {
if (forceIdentity && device.driver != driver)
continue;
const name = typeof driver == 'string' ? driver : driver.name;
if (name == device.driver.name)
devs.push(device);
}
return devs;
}
/**
* @internal
*/
_createDevice(driver, options = {}) {
let ino = 1n;
while (this.store.has(ino))
ino++;
const dev = {
driver,
ino,
data: {},
minor: 0,
major: 0,
...driver.init?.(ino, options),
};
const path = '/' + (dev.name || driver.name) + (driver.singleton ? '' : this.devicesWithDriver(driver).length);
if (this.existsSync(path)) {
throw ErrnoError.With('EEXIST', path, 'mknod');
}
this.devices.set(path, dev);
return dev;
}
/**
* Adds default devices
*/
addDefaults() {
this.createDevice('/null', nullDevice);
this.createDevice('/zero', zeroDevice);
this.createDevice('/full', fullDevice);
this.createDevice('/random', randomDevice);
this._createDevice(nullDevice);
this._createDevice(zeroDevice);
this._createDevice(fullDevice);
this._createDevice(randomDevice);
this._createDevice(consoleDevice);
}

@@ -358,6 +397,7 @@ constructor() {

* - Writes discard data, advancing the file position.
* @experimental
* @internal
*/
export const nullDevice = {
name: 'null',
singleton: true,
init() {

@@ -379,6 +419,7 @@ return { major: 1, minor: 3 };

* - Provides basic file metadata, treating it as a character device.
* @experimental
* @internal
*/
export const zeroDevice = {
name: 'zero',
singleton: true,
init() {

@@ -401,6 +442,7 @@ return { major: 1, minor: 5 };

* - Writes always fail with ENOSPC (no space left on device).
* @experimental
* @internal
*/
export const fullDevice = {
name: 'full',
singleton: true,
init() {

@@ -425,6 +467,7 @@ return { major: 1, minor: 7 };

* - Writes discard data, advancing the file position.
* @experimental
* @internal
*/
export const randomDevice = {
name: 'random',
singleton: true,
init() {

@@ -444,6 +487,25 @@ return { major: 1, minor: 8 };

/**
* Simulates the `/dev/console` device.
* @experimental @internal
*/
const consoleDevice = {
name: 'console',
singleton: true,
init(ino, { output = console.log } = {}) {
return { major: 5, minor: 1, data: { output } };
},
read() {
return 0;
},
write(file, buffer, offset, length) {
const text = decodeUTF8(buffer.slice(offset, offset + length));
file.device.data.output(text);
file.position += length;
return length;
},
};
/**
* Shortcuts for importing.
* @experimental
*/
export default {
export const devices = {
null: nullDevice,

@@ -453,2 +515,3 @@ zero: zeroDevice,

random: randomDevice,
console: consoleDevice,
};
import { Buffer } from 'buffer';
import type * as fs from 'node:fs';
import { ErrnoError } from '../error.js';
import type { FileContents } from '../filesystem.js';

@@ -312,2 +313,10 @@ import { BigIntStats, type Stats } from '../stats.js';

export declare function openAsBlob(this: V_Context, path: fs.PathLike, options?: fs.OpenAsBlobOptions): Promise<Blob>;
type GlobCallback<Args extends unknown[]> = (e: ErrnoError | null, ...args: Args) => unknown;
/**
* Retrieves the files matching the specified pattern.
*/
export declare function glob(this: V_Context, pattern: string | string[], callback: GlobCallback<[string[]]>): void;
export declare function glob(this: V_Context, pattern: string | string[], options: fs.GlobOptionsWithFileTypes, callback: GlobCallback<[Dirent[]]>): void;
export declare function glob(this: V_Context, pattern: string | string[], options: fs.GlobOptionsWithoutFileTypes, callback: GlobCallback<[string[]]>): void;
export declare function glob(this: V_Context, pattern: string | string[], options: fs.GlobOptions, callback: GlobCallback<[Dirent[] | string[]]>): void;
export {};

@@ -12,2 +12,12 @@ import { Buffer } from 'buffer';

/**
* Helper to collect an async iterator into an array
*/
async function collectAsyncIterator(it) {
const results = [];
for await (const result of it) {
results.push(result);
}
return results;
}
/**
* Asynchronous rename. No arguments other than a possible exception are given to the completion callback.

@@ -560,1 +570,9 @@ */

openAsBlob;
export function glob(pattern, options, callback = nop) {
callback = typeof options == 'function' ? options : callback;
const it = promises.glob.call(this, pattern, typeof options === 'function' ? undefined : options);
collectAsyncIterator(it)
.then(results => callback(null, results ?? []))
.catch((e) => callback(e));
}
glob;

@@ -7,3 +7,4 @@ export * from './async.js';

export * from './dir.js';
export { mountObject, mounts, mount, umount, _synced, chroot } from './shared.js';
export { mount, umount, chroot, mountObject } from './shared.js';
export { /** @deprecated security */ mounts } from './shared.js';
export { Stats, StatsFs, BigIntStatsFs } from '../stats.js';

@@ -7,3 +7,4 @@ export * from './async.js';

export * from './dir.js';
export { mountObject, mounts, mount, umount, _synced, chroot } from './shared.js';
export { mount, umount, chroot, mountObject } from './shared.js';
export { /** @deprecated security */ mounts } from './shared.js';
export { Stats, StatsFs, BigIntStatsFs } from '../stats.js';

@@ -13,4 +13,4 @@ import { Buffer } from 'buffer';

import { Dir, Dirent } from './dir.js';
import { type InternalOptions, type ReaddirOptions } from './shared.js';
import { ReadStream, WriteStream } from './streams.js';
import type { InternalOptions, NullEnc, ReaddirOptions, ReaddirOptsI, ReaddirOptsU } from './types.js';
export * as constants from './constants.js';

@@ -75,3 +75,5 @@ export declare class FileHandle implements promises.FileHandle {

*/
read<TBuffer extends NodeJS.ArrayBufferView>(buffer: TBuffer, offset?: number, length?: number, position?: number | null): Promise<promises.FileReadResult<TBuffer>>;
read<T extends NodeJS.ArrayBufferView>(buffer: T, offset?: number, length?: number, position?: number | null): Promise<promises.FileReadResult<T>>;
read<T extends NodeJS.ArrayBufferView = Buffer>(buffer: T, options?: promises.FileReadOptions<T>): Promise<promises.FileReadResult<T>>;
read<T extends NodeJS.ArrayBufferView = Buffer>(options?: promises.FileReadOptions<T>): Promise<promises.FileReadResult<T>>;
/**

@@ -95,5 +97,2 @@ * Asynchronously reads the entire contents of a file. The underlying file will _not_ be closed automatically.

* User code must still call the `fileHandle.close()` method.
*
* @since v17.0.0
* @experimental
*/

@@ -119,14 +118,10 @@ readableWebStream(options?: promises.ReadableWebStreamOptions): TReadableStream<Uint8Array>;

*/
write(data: FileContents, posOrOff?: number | null, lenOrEnc?: BufferEncoding | number, position?: number | null): Promise<{
write<T extends FileContents>(data: T, options?: number | null | {
offset?: number;
length?: number;
position?: number;
}, lenOrEnc?: BufferEncoding | number | null, position?: number | null): Promise<{
bytesWritten: number;
buffer: FileContents;
buffer: T;
}>;
write<TBuffer extends Uint8Array>(buffer: TBuffer, offset?: number, length?: number, position?: number): Promise<{
bytesWritten: number;
buffer: TBuffer;
}>;
write(data: string, position?: number, encoding?: BufferEncoding): Promise<{
bytesWritten: number;
buffer: string;
}>;
/**

@@ -263,15 +258,15 @@ * Asynchronously writes data to a file, replacing the file if it already exists. The underlying file will _not_ be closed automatically.

*/
export declare function readdir(this: V_Context, path: fs.PathLike, options?: (fs.ObjectEncodingOptions & ReaddirOptions & {
export declare function readdir(this: V_Context, path: fs.PathLike, options?: ReaddirOptsI<{
withFileTypes?: false;
}) | BufferEncoding | null): Promise<string[]>;
}> | NullEnc): Promise<string[]>;
export declare function readdir(this: V_Context, path: fs.PathLike, options: fs.BufferEncodingOption & ReaddirOptions & {
withFileTypes?: false;
}): Promise<Buffer[]>;
export declare function readdir(this: V_Context, path: fs.PathLike, options?: (fs.ObjectEncodingOptions & ReaddirOptions & {
export declare function readdir(this: V_Context, path: fs.PathLike, options?: ReaddirOptsI<{
withFileTypes?: false;
}) | BufferEncoding | null): Promise<string[] | Buffer[]>;
export declare function readdir(this: V_Context, path: fs.PathLike, options: fs.ObjectEncodingOptions & ReaddirOptions & {
}> | NullEnc): Promise<string[] | Buffer[]>;
export declare function readdir(this: V_Context, path: fs.PathLike, options: ReaddirOptsI<{
withFileTypes: true;
}): Promise<Dirent[]>;
export declare function readdir(this: V_Context, path: fs.PathLike, options?: (ReaddirOptions & (fs.ObjectEncodingOptions | fs.BufferEncodingOption)) | BufferEncoding | null): Promise<string[] | Dirent[] | Buffer[]>;
}>): Promise<Dirent[]>;
export declare function readdir(this: V_Context, path: fs.PathLike, options?: ReaddirOptsU<fs.BufferEncodingOption> | NullEnc): Promise<string[] | Dirent[] | Buffer[]>;
export declare function link(this: V_Context, targetPath: fs.PathLike, linkPath: fs.PathLike): Promise<void>;

@@ -365,1 +360,9 @@ /**

export declare function statfs(this: V_Context, path: fs.PathLike, opts?: fs.StatFsOptions): Promise<fs.StatsFs | fs.BigIntStatsFs>;
/**
* Retrieves the files matching the specified pattern.
* @todo Implement
*/
export declare function glob(this: V_Context, pattern: string | string[]): NodeJS.AsyncIterator<string>;
export declare function glob(this: V_Context, pattern: string | string[], opt: fs.GlobOptionsWithFileTypes): NodeJS.AsyncIterator<Dirent>;
export declare function glob(this: V_Context, pattern: string | string[], opt: fs.GlobOptionsWithoutFileTypes): NodeJS.AsyncIterator<string>;
export declare function glob(this: V_Context, pattern: string | string[], opt: fs.GlobOptions): NodeJS.AsyncIterator<Dirent | string>;

@@ -150,15 +150,19 @@ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {

}
/**
* Asynchronously reads data from the file.
* The `FileHandle` must have been opened for reading.
* @param buffer The buffer that the data will be written to.
* @param offset The offset in the buffer at which to start writing.
* @param length The number of bytes to read.
* @param position The offset from the beginning of the file from which data should be read. If `null`, data will be read from the current position.
*/
read(buffer, offset, length, position) {
async read(buffer, offset, length, position) {
if (typeof offset == 'object' && offset != null) {
position = offset.position;
length = offset.length;
offset = offset.offset;
}
if (!ArrayBuffer.isView(buffer) && typeof buffer == 'object') {
position = buffer.position;
length = buffer.length;
offset = buffer.offset;
buffer = buffer.buffer;
}
if (isNaN(+position)) {
position = this.file.position;
}
return this.file.read(buffer, offset, length, position);
buffer || (buffer = new Uint8Array((await this.file.stat()).size));
return this.file.read(buffer, offset ?? undefined, length ?? undefined, position ?? undefined);
}

@@ -184,5 +188,2 @@ async readFile(_options) {

* User code must still call the `fileHandle.close()` method.
*
* @since v17.0.0
* @experimental
*/

@@ -235,7 +236,17 @@ readableWebStream(options = {}) {

}
async write(data, posOrOff, lenOrEnc, position) {
/**
* Asynchronously writes `string` to the file.
* The `FileHandle` must have been opened for writing.
* It is unsafe to call `write()` multiple times on the same file without waiting for the `Promise`
* to be resolved (or rejected). For this scenario, `fs.createWriteStream` is strongly recommended.
*/
async write(data, options, lenOrEnc, position) {
let buffer, offset, length;
if (typeof options == 'object') {
lenOrEnc = options?.length;
position = options?.position;
options = options?.offset;
}
if (typeof data === 'string') {
// Signature 1: (fd, string, [position?, [encoding?]])
position = typeof posOrOff === 'number' ? posOrOff : null;
position = typeof options === 'number' ? options : null;
const encoding = typeof lenOrEnc === 'string' ? lenOrEnc : 'utf8';

@@ -247,5 +258,4 @@ offset = 0;

else {
// Signature 2: (fd, buffer, offset, length, position?)
buffer = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
offset = posOrOff;
offset = options;
length = lenOrEnc;

@@ -257,3 +267,3 @@ position = typeof position === 'number' ? position : null;

emitChange('change', this.file.path);
return { buffer, bytesWritten };
return { buffer: data, bytesWritten };
}

@@ -946,2 +956,5 @@ /**

throw: cleanup,
[Symbol.asyncDispose]() {
return Promise.resolve();
},
};

@@ -1097,1 +1110,33 @@ },

}
export function glob(pattern, opt) {
pattern = Array.isArray(pattern) ? pattern : [pattern];
const { cwd = '/', withFileTypes = false, exclude = () => false } = opt || {};
// Escape special characters in pattern
const regexPatterns = pattern.map(p => {
p = p
.replace(/([.?+^$(){}|[\]/])/g, '$1')
.replace(/\*\*/g, '.*')
.replace(/\*/g, '[^/]*')
.replace(/\?/g, '.');
return new RegExp(`^${p}$`);
});
async function* recursiveList(dir) {
const entries = await readdir(dir, { withFileTypes, encoding: 'utf8' });
for (const entry of entries) {
const fullPath = withFileTypes ? entry.path : dir + '/' + entry;
if (exclude((withFileTypes ? entry : fullPath)))
continue;
/**
* @todo it the pattern.source check correct?
*/
if ((await stat(fullPath)).isDirectory() && regexPatterns.some(pattern => pattern.source.includes('.*'))) {
yield* recursiveList(fullPath);
}
if (regexPatterns.some(pattern => pattern.test(fullPath.replace(/^\/+/g, '')))) {
yield withFileTypes ? entry : fullPath.replace(/^\/+/g, '');
}
}
}
return recursiveList(cwd);
}
glob;

@@ -1,2 +0,2 @@

import type { BigIntStatsFs, StatsFs } from 'node:fs';
import type * as fs from 'node:fs';
import { type BoundContext, type V_Context } from '../context.js';

@@ -52,8 +52,2 @@ import { ErrnoError } from '../error.js';

/**
* Wait for all file systems to be ready and synced.
* May be removed at some point.
* @experimental @internal
*/
export declare function _synced(): Promise<void>;
/**
* Reverse maps the paths in text from the mounted FileSystem to the global path

@@ -75,20 +69,4 @@ * @internal @hidden

*/
export declare function _statfs<const T extends boolean>(fs: FileSystem, bigint?: T): T extends true ? BigIntStatsFs : StatsFs;
export declare function _statfs<const T extends boolean>(fs: FileSystem, bigint?: T): T extends true ? fs.BigIntStatsFs : fs.StatsFs;
/**
* Options used for caching, among other things.
* @internal @hidden *UNSTABLE*
*/
export interface InternalOptions {
/**
* If true, then this readdir was called from another function.
* In this case, don't clear the cache when done.
* @internal *UNSTABLE*
*/
_isIndirect?: boolean;
}
export interface ReaddirOptions extends InternalOptions {
withFileTypes?: boolean;
recursive?: boolean;
}
/**
* Change the root path

@@ -95,0 +73,0 @@ * @param inPlace if true, this changes the root for the current context instead of creating a new one (if associated with a context).

@@ -89,11 +89,2 @@ // Utilities and shared data

/**
* Wait for all file systems to be ready and synced.
* May be removed at some point.
* @experimental @internal
*/
export async function _synced() {
await Promise.all([...mounts.values()].map(m => m.ready()));
return;
}
/**
* Reverse maps the paths in text from the mounted FileSystem to the global path

@@ -100,0 +91,0 @@ * @internal @hidden

@@ -5,3 +5,3 @@ import type * as Node from 'node:fs';

export declare class ReadStream extends Readable implements Node.ReadStream {
close(callback?: Callback): void;
close(callback?: Callback<[void], null>): void;
wrap(oldStream: NodeJS.ReadableStream): this;

@@ -13,3 +13,3 @@ bytesRead: number;

export declare class WriteStream extends Writable implements Node.WriteStream {
close(callback?: Callback): void;
close(callback?: Callback<[void], null>): void;
bytesWritten: number;

@@ -16,0 +16,0 @@ path: string | Buffer;

@@ -8,3 +8,3 @@ import { Readable, Writable } from 'readable-stream';

super.emit('close');
callback();
callback(null);
}

@@ -25,3 +25,3 @@ catch (err) {

super.emit('close');
callback();
callback(null);
}

@@ -28,0 +28,0 @@ catch (err) {

@@ -6,4 +6,4 @@ import { Buffer } from 'buffer';

import { Dir, Dirent } from './dir.js';
import { type InternalOptions, type ReaddirOptions } from './shared.js';
import type { V_Context } from '../context.js';
import type { ReaddirOptsI, ReaddirOptsU, InternalOptions, ReaddirOptions, NullEnc } from './types.js';
export declare function renameSync(this: V_Context, oldPath: fs.PathLike, newPath: fs.PathLike): void;

@@ -116,15 +116,15 @@ /**

export declare function mkdirSync(this: V_Context, path: fs.PathLike, options?: fs.Mode | fs.MakeDirectoryOptions | null): string | undefined;
export declare function readdirSync(this: V_Context, path: fs.PathLike, options?: (fs.ObjectEncodingOptions & ReaddirOptions & {
export declare function readdirSync(this: V_Context, path: fs.PathLike, options?: ReaddirOptsI<{
withFileTypes?: false;
}) | BufferEncoding | null): string[];
}> | NullEnc): string[];
export declare function readdirSync(this: V_Context, path: fs.PathLike, options: fs.BufferEncodingOption & ReaddirOptions & {
withFileTypes?: false;
}): Buffer[];
export declare function readdirSync(this: V_Context, path: fs.PathLike, options?: (fs.ObjectEncodingOptions & ReaddirOptions & {
export declare function readdirSync(this: V_Context, path: fs.PathLike, options?: ReaddirOptsI<{
withFileTypes?: false;
}) | BufferEncoding | null): string[] | Buffer[];
export declare function readdirSync(this: V_Context, path: fs.PathLike, options: fs.ObjectEncodingOptions & ReaddirOptions & {
}> | NullEnc): string[] | Buffer[];
export declare function readdirSync(this: V_Context, path: fs.PathLike, options: ReaddirOptsI<{
withFileTypes: true;
}): Dirent[];
export declare function readdirSync(this: V_Context, path: fs.PathLike, options?: (ReaddirOptions & (fs.ObjectEncodingOptions | fs.BufferEncodingOption)) | BufferEncoding | null): string[] | Dirent[] | Buffer[];
}>): Dirent[];
export declare function readdirSync(this: V_Context, path: fs.PathLike, options?: ReaddirOptsU<fs.BufferEncodingOption> | NullEnc): string[] | Dirent[] | Buffer[];
export declare function linkSync(this: V_Context, targetPath: fs.PathLike, linkPath: fs.PathLike): void;

@@ -224,1 +224,8 @@ /**

export declare function statfsSync(this: V_Context, path: fs.PathLike, options?: fs.StatFsOptions): fs.StatsFs | fs.BigIntStatsFs;
/**
* Retrieves the files matching the specified pattern.
*/
export declare function globSync(pattern: string | string[]): string[];
export declare function globSync(pattern: string | string[], options: fs.GlobOptionsWithFileTypes): Dirent[];
export declare function globSync(pattern: string | string[], options: fs.GlobOptionsWithoutFileTypes): string[];
export declare function globSync(pattern: string | string[], options: fs.GlobOptions): Dirent[] | string[];

@@ -799,1 +799,35 @@ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {

}
export function globSync(pattern, options = {}) {
pattern = Array.isArray(pattern) ? pattern : [pattern];
const { cwd = '/', withFileTypes = false, exclude = () => false } = options;
// Escape special characters in pattern
const regexPatterns = pattern.map(p => {
p = p
.replace(/([.?+^$(){}|[\]/])/g, '\\$1')
.replace(/\*\*/g, '.*')
.replace(/\*/g, '[^/]*')
.replace(/\?/g, '.');
return new RegExp(`^${p}$`);
});
const results = [];
function recursiveList(dir) {
const entries = readdirSync(dir, { withFileTypes, encoding: 'utf8' });
for (const entry of entries) {
const fullPath = withFileTypes ? entry.path : dir + '/' + entry;
if (exclude((withFileTypes ? entry : fullPath)))
continue;
/**
* @todo it the pattern.source check correct?
*/
if (statSync(fullPath).isDirectory() && regexPatterns.some(pattern => pattern.source.includes('.*'))) {
recursiveList(fullPath);
}
if (regexPatterns.some(pattern => pattern.test(fullPath.replace(/^\/+/g, '')))) {
results.push(withFileTypes ? entry.path : fullPath.replace(/^\/+/g, ''));
}
}
}
recursiveList(cwd);
return results;
}
globSync;

@@ -15,3 +15,2 @@ export * from './error.js';

export * from './devices.js';
export { default as devices } from './devices.js';
export * from './file.js';

@@ -18,0 +17,0 @@ export * from './filesystem.js';

@@ -15,3 +15,2 @@ export * from './error.js';

export * from './devices.js';
export { default as devices } from './devices.js';
export * from './file.js';

@@ -18,0 +17,0 @@ export * from './filesystem.js';

@@ -52,3 +52,3 @@ import type * as fs from 'node:fs';

export declare function encodeDirListing(data: Record<string, bigint>): Uint8Array;
export type Callback<Args extends unknown[] = []> = (e?: ErrnoError, ...args: OptionalTuple<Args>) => unknown;
export type Callback<Args extends unknown[] = [], NoError = undefined | void> = (e: ErrnoError | NoError, ...args: OptionalTuple<Args>) => unknown;
/**

@@ -55,0 +55,0 @@ * Normalizes a mode

{
"name": "@zenfs/core",
"version": "1.5.1",
"version": "1.6.0",
"description": "A filesystem, anywhere",

@@ -61,3 +61,4 @@ "funding": {

"dev": "npm run build -- --watch",
"prepublishOnly": "npm run build"
"prepublishOnly": "npm run build",
"postinstall": "patch-package"
},

@@ -70,3 +71,3 @@ "lint-staged": {

"dependencies": {
"@types/node": "^20.16.10",
"@types/node": "^22.10.1",
"@types/readable-stream": "^4.0.10",

@@ -88,2 +89,3 @@ "buffer": "^6.0.3",

"lint-staged": "^15.2.7",
"patch-package": "^8.0.0",
"prettier": "^3.2.5",

@@ -90,0 +92,0 @@ "tsx": "^4.19.1",

@@ -177,2 +177,5 @@ # ZenFS

name: 'custom_null',
// only 1 can exist per DeviceFS
singleton: true,
// optional if false
isBuffered: false,

@@ -182,3 +185,5 @@ read() {

},
write() {},
write() {
return 0;
},
};

@@ -189,17 +194,12 @@ ```

Finally, if you'd like to use your custom device with the file system, you can use so through the aptly named `DeviceFS`.
Finally, if you'd like to use your custom device with the file system:
```ts
const devfs = fs.mounts.get('/dev') as DeviceFS;
devfs.createDevice('/custom', customNullDevice);
import { addDevice, fs } from '@zenfs/core';
addDevice(customNullDevice);
fs.writeFileSync('/dev/custom', 'This gets discarded.');
```
In the above example, `createDevice` works relative to the `DeviceFS` mount point.
Additionally, a type assertion (` as ...`) is used since `fs.mounts` does not keep track of which file system type is mapped to which mount point. Doing so would create significant maintenance costs due to the complexity of implementing it.
If you would like to see a more intuitive way adding custom devices (e.g. `fs.mknod`), please feel free to open an issue for a feature request.
## Using with bundlers

@@ -206,0 +206,0 @@

@@ -16,4 +16,2 @@ import assert, { rejects } from 'node:assert';

await fs._synced();
suite('Dirent', () => {

@@ -20,0 +18,0 @@ test('name and parentPath getters', async () => {

@@ -21,4 +21,2 @@ import assert from 'node:assert';

await fs._synced();
suite('Directories', () => {

@@ -25,0 +23,0 @@ test('mkdir', async () => {

@@ -36,3 +36,3 @@ import assert from 'node:assert';

readStream.close(err => {
assert.strictEqual(err, undefined);
assert.equal(err, null);
assert(closed);

@@ -62,6 +62,6 @@ done();

readStream.close(err => {
assert.strictEqual(err, undefined);
assert.equal(err, null);
// Call close again
readStream.close(err2 => {
assert.strictEqual(err2, undefined);
assert.equal(err2, null);
done();

@@ -99,3 +99,3 @@ });

writeStream.close(err => {
assert.strictEqual(err, undefined);
assert.equal(err, null);
assert(closed);

@@ -125,6 +125,6 @@ done();

writeStream.close(err => {
assert.strictEqual(err, undefined);
assert.equal(err, null);
// Call close again
writeStream.close(err2 => {
assert.strictEqual(err2, undefined);
assert.equal(err2, null);
done();

@@ -131,0 +131,0 @@ });

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc