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
1
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 0.12.2 to 0.12.3

2

dist/backends/backend.d.ts
import type { RequiredKeys } from 'utilium';
import { FileSystem } from '../filesystem.js';
import type { FileSystem } from '../filesystem.js';
type OptionType = 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function';

@@ -4,0 +4,0 @@ /**

import type { FileSystemMetadata } from '../filesystem.js';
import { Stats } from '../stats.js';
import type { Stats } from '../stats.js';
import { IndexFS } from './index/fs.js';

@@ -4,0 +4,0 @@ import type { IndexData } from './index/index.js';

@@ -5,3 +5,4 @@ import type { Cred } from '../../cred.js';

import type { Stats } from '../../stats.js';
import { Index, IndexData } from './index.js';
import type { IndexData } from './index.js';
import { Index } from './index.js';
declare const IndexFS_base: (abstract new (...args: any[]) => {

@@ -23,3 +24,2 @@ metadata(): import("../../filesystem.js").FileSystemMetadata;

syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
_type?: number | undefined;
ready(): Promise<void>;

@@ -26,0 +26,0 @@ stat(path: string, cred: Cred): Promise<Stats>;

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

import { Stats, StatsLike } from '../../stats.js';
import type { StatsLike } from '../../stats.js';
import { Stats } from '../../stats.js';
/**

@@ -3,0 +4,0 @@ * An Index in JSON form

@@ -1,6 +0,7 @@

import { FileSystem, FileSystemMetadata } from '../filesystem.js';
import { File } from '../file.js';
import type { FileSystemMetadata } from '../filesystem.js';
import { FileSystem } from '../filesystem.js';
import type { File } from '../file.js';
import { Stats } from '../stats.js';
import { LockedFS } from './locked.js';
import { Cred } from '../cred.js';
import type { Cred } from '../cred.js';
/**

@@ -7,0 +8,0 @@ * Configuration options for OverlayFS instances.

@@ -19,2 +19,3 @@ /// <reference types="node" resolution-mode="require"/>

rpc<const T extends FileMethod & string>(method: T, ...args: Parameters<FileMethods[T]>): Promise<Awaited<ReturnType<FileMethods[T]>>>;
protected _throwNoSync(syscall: string): never;
stat(): Promise<Stats>;

@@ -59,3 +60,2 @@ statSync(): Stats;

syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
_type?: number | undefined;
rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;

@@ -67,3 +67,6 @@ stat(path: string, cred: Cred): Promise<Stats>;

rmdir(path: string, cred: Cred): Promise<void>;
mkdir(path: string, mode: number, cred: Cred): Promise<void>;
mkdir(path: string, mode: number, cred: Cred): Promise<void>; /**
* Constructs a new PortFS instance that connects with ZenFS running on
* the specified port.
*/
readdir(path: string, cred: Cred): Promise<string[]>;

@@ -70,0 +73,0 @@ exists(path: string, cred: Cred): Promise<boolean>;

@@ -23,2 +23,5 @@ import { Errno, ErrnoError } from '../../error.js';

}
_throwNoSync(syscall) {
throw new ErrnoError(Errno.ENOTSUP, 'Syncrohnous operations not support on PortFile', this.path, syscall);
}
stat() {

@@ -28,3 +31,3 @@ return this.rpc('stat');

statSync() {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.stat');
this._throwNoSync('stat');
}

@@ -35,3 +38,3 @@ truncate(len) {

truncateSync() {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.truncate');
this._throwNoSync('truncate');
}

@@ -42,3 +45,3 @@ write(buffer, offset, length, position) {

writeSync() {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.write');
this._throwNoSync('write');
}

@@ -50,3 +53,3 @@ async read(buffer, offset, length, position) {

readSync() {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.read');
this._throwNoSync('read');
}

@@ -57,3 +60,3 @@ chown(uid, gid) {

chownSync() {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.chown');
this._throwNoSync('chown');
}

@@ -64,3 +67,3 @@ chmod(mode) {

chmodSync() {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.chmod');
this._throwNoSync('chmod');
}

@@ -71,3 +74,3 @@ utimes(atime, mtime) {

utimesSync() {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.utimes');
this._throwNoSync('utimes');
}

@@ -78,3 +81,3 @@ _setType(type) {

_setTypeSync() {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile._setType');
this._throwNoSync('_setType');
}

@@ -85,3 +88,3 @@ close() {

closeSync() {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.close');
this._throwNoSync('close');
}

@@ -92,3 +95,3 @@ sync() {

syncSync() {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.sync');
this._throwNoSync('sync');
}

@@ -95,0 +98,0 @@ }

@@ -9,3 +9,3 @@ import type { Backend, BackendConfiguration, FilesystemOf } from './backends/backend.js';

* Retrieve a file system with the given configuration.
* @param config A BackendConfig object.
* @see MountConfiguration
*/

@@ -12,0 +12,0 @@ export declare function resolveMountConfig<T extends Backend>(config: MountConfiguration<T>, _depth?: number): Promise<FilesystemOf<T>>;

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

* Retrieve a file system with the given configuration.
* @param config A BackendConfig object.
* @see MountConfiguration
*/

@@ -14,0 +14,0 @@ export async function resolveMountConfig(config, _depth = 0) {

/**
* Credentials used for various operations.
* Similar to Linux's cred struct. See https://github.com/torvalds/linux/blob/master/include/linux/cred.h
* Similar to Linux's cred struct.
* @see https://github.com/torvalds/linux/blob/master/include/linux/cred.h
*/

@@ -5,0 +6,0 @@ export interface Cred {

@@ -9,3 +9,4 @@ /// <reference types="node" resolution-mode="require"/>

import { type Callback } from '../utils.js';
import { Dirent, type Dir } from './dir.js';
import type { Dirent } from './dir.js';
import { type Dir } from './dir.js';
import * as promises from './promises.js';

@@ -12,0 +13,0 @@ import { ReadStream, WriteStream } from './streams.js';

@@ -15,3 +15,3 @@ /// <reference types="node" resolution-mode="require"/>

import type { Interface as ReadlineInterface } from 'readline';
import { File } from '../file.js';
import type { File } from '../file.js';
import type { FileContents } from '../filesystem.js';

@@ -18,0 +18,0 @@ import { BigIntStats, type Stats } from '../stats.js';

import { Buffer } from 'buffer';
import { Errno, ErrnoError } from '../error.js';
import { ActionType, isAppendable, isReadable, isWriteable, parseFlag, pathExistsAction, pathNotExistsAction } from '../file.js';
import { isAppendable, isExclusive, isReadable, isTruncating, isWriteable, parseFlag } from '../file.js';
import { BigIntStats, FileType } from '../stats.js';

@@ -86,3 +86,3 @@ import { normalizeMode, normalizeOptions, normalizePath, normalizeTime } from '../utils.js';

const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding) : data;
await this.file.write(encodedData, 0, encodedData.length, null);
await this.file.write(encodedData, 0, encodedData.length);
}

@@ -391,36 +391,28 @@ /**

if (!(await fs.exists(path, cred))) {
switch (pathNotExistsAction(flag)) {
case ActionType.CREATE:
// Ensure parent exists.
const parentStats = await fs.stat(dirname(resolved), cred);
if (parentStats && !parentStats.isDirectory()) {
throw ErrnoError.With('ENOTDIR', dirname(path), '_open');
}
return new FileHandle(await fs.createFile(resolved, flag, mode, cred));
case ActionType.THROW:
throw ErrnoError.With('ENOENT', path, '_open');
default:
throw new ErrnoError(Errno.EINVAL, 'Invalid file flag');
if ((!isWriteable(flag) && !isAppendable(flag)) || flag == 'r+') {
throw ErrnoError.With('ENOENT', path, '_open');
}
// Create the file
const parentStats = await fs.stat(dirname(resolved), cred);
if (parentStats && !parentStats.isDirectory()) {
throw ErrnoError.With('ENOTDIR', dirname(path), '_open');
}
return new FileHandle(await fs.createFile(resolved, flag, mode, cred));
}
switch (pathExistsAction(flag)) {
case ActionType.THROW:
throw ErrnoError.With('EEXIST', path, '_open');
case ActionType.TRUNCATE:
/*
In a previous implementation, we deleted the file and
re-created it. However, this created a race condition if another
asynchronous request was trying to read the file, as the file
would not exist for a small period of time.
*/
const file = await fs.openFile(resolved, flag, cred);
await file.truncate(0);
await file.sync();
return new FileHandle(file);
case ActionType.NOP:
// Must await so thrown errors are caught by the catch below
return new FileHandle(await fs.openFile(resolved, flag, cred));
default:
throw new ErrnoError(Errno.EINVAL, 'Invalid file flag');
if (isExclusive(flag)) {
throw ErrnoError.With('EEXIST', path, '_open');
}
if (!isTruncating(flag)) {
return new FileHandle(await fs.openFile(resolved, flag, cred));
}
/*
In a previous implementation, we deleted the file and
re-created it. However, this created a race condition if another
asynchronous request was trying to read the file, as the file
would not exist for a small period of time.
*/
const file = await fs.openFile(resolved, flag, cred);
await file.truncate(0);
await file.sync();
return new FileHandle(file);
}

@@ -427,0 +419,0 @@ /**

/// <reference types="node" resolution-mode="require"/>
import type { BigIntStatsFs, StatsFs } from 'node:fs';
import { Cred } from '../cred.js';
import type { Cred } from '../cred.js';
import type { File } from '../file.js';
import { FileSystem } from '../filesystem.js';
import type { FileSystem } from '../filesystem.js';
import { type AbsolutePath } from './path.js';

@@ -7,0 +7,0 @@ export declare let cred: Cred;

@@ -6,3 +6,2 @@ // Utilities and shared data

import { size_max } from '../inode.js';
import { ZenFsType } from '../stats.js';
import { normalizePath } from '../utils.js';

@@ -113,3 +112,3 @@ import { resolve } from './path.js';

return {
type: (bigint ? BigInt : Number)(md.type || ZenFsType),
type: (bigint ? BigInt : Number)(md.type),
bsize: (bigint ? BigInt : Number)(bs),

@@ -116,0 +115,0 @@ ffree: (bigint ? BigInt : Number)(md.freeNodes || size_max),

@@ -5,3 +5,3 @@ /// <reference types="node" resolution-mode="require"/>

import { Readable, Writable } from 'readable-stream';
import { Callback } from '../utils.js';
import type { Callback } from '../utils.js';
export declare class ReadStream extends Readable implements Node.ReadStream {

@@ -8,0 +8,0 @@ close(callback?: Callback): void;

@@ -6,3 +6,3 @@ /// <reference types="node" resolution-mode="require"/>

import type * as fs from 'node:fs';
import { FileContents } from '../filesystem.js';
import type { FileContents } from '../filesystem.js';
import { BigIntStats, type Stats } from '../stats.js';

@@ -9,0 +9,0 @@ import { Dir, Dirent } from './dir.js';

import { Buffer } from 'buffer';
import { Errno, ErrnoError } from '../error.js';
import { ActionType, isAppendable, isReadable, isWriteable, parseFlag, pathExistsAction, pathNotExistsAction } from '../file.js';
import { isAppendable, isExclusive, isReadable, isTruncating, isWriteable, parseFlag } from '../file.js';
import { BigIntStats, FileType } from '../stats.js';

@@ -111,15 +111,11 @@ import { normalizeMode, normalizeOptions, normalizePath, normalizeTime } from '../utils.js';

if (!fs.existsSync(resolved, cred)) {
switch (pathNotExistsAction(flag)) {
case ActionType.CREATE:
// Ensure parent exists.
const parentStats = fs.statSync(dirname(resolved), cred);
if (!parentStats.isDirectory()) {
throw ErrnoError.With('ENOTDIR', dirname(path), '_open');
}
return fs.createFileSync(resolved, flag, mode, cred);
case ActionType.THROW:
throw ErrnoError.With('ENOENT', path, '_open');
default:
throw new ErrnoError(Errno.EINVAL, 'Invalid FileFlag object.');
if ((!isWriteable(flag) && !isAppendable(flag)) || flag == 'r+') {
throw ErrnoError.With('ENOENT', path, '_open');
}
// Create the file
const parentStats = fs.statSync(dirname(resolved), cred);
if (!parentStats.isDirectory()) {
throw ErrnoError.With('ENOTDIR', dirname(path), '_open');
}
return fs.createFileSync(resolved, flag, mode, cred);
}

@@ -130,21 +126,17 @@ const stats = fs.statSync(resolved, cred);

}
// File exists.
switch (pathExistsAction(flag)) {
case ActionType.THROW:
throw ErrnoError.With('EEXIST', path, '_open');
case ActionType.TRUNCATE:
// Delete file.
fs.unlinkSync(resolved, cred);
/*
Create file. Use the same mode as the old file.
Node itself modifies the ctime when this occurs, so this action
will preserve that behavior if the underlying file system
supports those properties.
*/
return fs.createFileSync(resolved, flag, stats.mode, cred);
case ActionType.NOP:
return fs.openFileSync(resolved, flag, cred);
default:
throw new ErrnoError(Errno.EINVAL, 'Invalid FileFlag object.');
if (isExclusive(flag)) {
throw ErrnoError.With('EEXIST', path, '_open');
}
if (!isTruncating(flag)) {
return fs.openFileSync(resolved, flag, cred);
}
// Delete file.
fs.unlinkSync(resolved, cred);
/*
Create file. Use the same mode as the old file.
Node itself modifies the ctime when this occurs, so this action
will preserve that behavior if the underlying file system
supports those properties.
*/
return fs.createFileSync(resolved, flag, stats.mode, cred);
}

@@ -243,3 +235,3 @@ /**

try {
file.writeSync(encodedData, 0, encodedData.byteLength, null);
file.writeSync(encodedData, 0, encodedData.byteLength);
}

@@ -246,0 +238,0 @@ finally {

@@ -5,3 +5,3 @@ /// <reference types="node" resolution-mode="require"/>

* needed.
* @url https://en.wikipedia.org/wiki/Errno.h
* @see https://en.wikipedia.org/wiki/Errno.h
*/

@@ -8,0 +8,0 @@ export declare enum Errno {

/**
* Standard libc error codes. More will be added to this enum and error strings as they are
* needed.
* @url https://en.wikipedia.org/wiki/Errno.h
* @see https://en.wikipedia.org/wiki/Errno.h
*/

@@ -6,0 +6,0 @@ export var Errno;

@@ -23,11 +23,2 @@ /// <reference types="node" resolution-mode="require"/>

}
/**
* @hidden
*/
export declare enum ActionType {
NOP = 0,
THROW = 1,
TRUNCATE = 2,
CREATE = 3
}
export declare function parseFlag(flag: string | number): string;

@@ -47,4 +38,2 @@ export declare function flagToString(flag: number): string;

export declare function isExclusive(flag: string): boolean;
export declare function pathExistsAction(flag: string): ActionType;
export declare function pathNotExistsAction(flag: string): ActionType;
export declare abstract class File {

@@ -106,3 +95,3 @@ /**

*/
abstract write(buffer: Uint8Array, offset?: number, length?: number, position?: number | null): Promise<number>;
abstract write(buffer: Uint8Array, offset?: number, length?: number, position?: number): Promise<number>;
/**

@@ -120,3 +109,3 @@ * Write buffer to the file.

*/
abstract writeSync(buffer: Uint8Array, offset?: number, length?: number, position?: number | null): number;
abstract writeSync(buffer: Uint8Array, offset?: number, length?: number, position?: number): number;
/**

@@ -123,0 +112,0 @@ * Read data from the file.

@@ -1,19 +0,5 @@

import { ErrnoError, Errno } from './error.js';
import { O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY, S_IFMT } from './emulation/constants.js';
import { Errno, ErrnoError } from './error.js';
import { size_max } from './inode.js';
import { Stats } from './stats.js';
/**
* @hidden
*/
export var ActionType;
(function (ActionType) {
// Indicates that the code should not do anything.
ActionType[ActionType["NOP"] = 0] = "NOP";
// Indicates that the code should throw an exception.
ActionType[ActionType["THROW"] = 1] = "THROW";
// Indicates that the code should truncate the file, but only if it is a file.
ActionType[ActionType["TRUNCATE"] = 2] = "TRUNCATE";
// Indicates that the code should create the file.
ActionType[ActionType["CREATE"] = 3] = "CREATE";
})(ActionType || (ActionType = {}));
const validFlags = ['r', 'r+', 'rs', 'rs+', 'w', 'wx', 'w+', 'wx+', 'a', 'ax', 'a+', 'ax+'];

@@ -120,17 +106,2 @@ export function parseFlag(flag) {

}
export function pathExistsAction(flag) {
if (isExclusive(flag)) {
return ActionType.THROW;
}
if (isTruncating(flag)) {
return ActionType.TRUNCATE;
}
return ActionType.NOP;
}
export function pathNotExistsAction(flag) {
if ((isWriteable(flag) || isAppendable(flag)) && flag !== 'r+') {
return ActionType.CREATE;
}
return ActionType.THROW;
}
export class File {

@@ -310,3 +281,3 @@ [Symbol.asyncDispose]() {

*/
async write(buffer, offset = 0, length = this.stats.size, position = 0) {
async write(buffer, offset = 0, length = this.stats.size, position = this.position) {
const bytesWritten = this.writeSync(buffer, offset, length, position);

@@ -329,5 +300,4 @@ await this.sync();

*/
writeSync(buffer, offset = 0, length = this.stats.size, position = 0) {
writeSync(buffer, offset = 0, length = this.stats.size, position = this.position) {
this.dirty = true;
position ?? (position = this.position);
if (!isWriteable(this.flag)) {

@@ -334,0 +304,0 @@ throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode.');

import { type Cred } from './cred.js';
import { type File } from './file.js';
import type { Stats } from './stats.js';
import { type Stats } from './stats.js';
export type FileContents = ArrayBufferView | string;

@@ -53,3 +53,3 @@ /**

*/
type?: number;
type: number;
}

@@ -59,16 +59,8 @@ /**

*
* This class includes some default implementations
* This class includes default implementations for `exists` and `existsSync`
*
* Assume the following about arguments passed to each API method:
*
* - Every path is an absolute path. `.`, `..`, and other items are resolved into an absolute form.
* - All arguments are present. Any optional arguments at the Node API level have been passed in with their default values.
* If you are extending this class, note that every path is an absolute path and all arguments are present.
*/
export declare abstract class FileSystem {
/**
* Numeric type, used for statfs
* @internal @protected
*/
_type?: number;
/**
* Get metadata about the current file system

@@ -80,4 +72,3 @@ */

/**
* Asynchronous rename. No arguments other than a possible exception
* are given to the completion callback.
* Asynchronous rename.
*/

@@ -98,4 +89,4 @@ abstract rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;

/**
* Opens the file at path p with the given flag. The file must exist.
* @param p The path to open.
* Opens the file at `path` with the given flag. The file must exist.
* @param path The path to open.
* @param flag The flag to use when opening the file.

@@ -105,4 +96,4 @@ */

/**
* Opens the file at path p with the given flag. The file must exist.
* @param p The path to open.
* Opens the file at `path` with the given flag. The file must exist.
* @param path The path to open.
* @param flag The flag to use when opening the file.

@@ -113,9 +104,7 @@ * @return A File object corresponding to the opened file.

/**
* Create the file at path p with the given mode. Then, open it with the given
* flag.
* Create the file at `path` with the given mode. Then, open it with the given flag.
*/
abstract createFile(path: string, flag: string, mode: number, cred: Cred): Promise<File>;
/**
* Create the file at path p with the given mode. Then, open it with the given
* flag.
* Create the file at `path` with the given mode. Then, open it with the given flag.
*/

@@ -141,4 +130,3 @@ abstract createFileSync(path: string, flag: string, mode: number, cred: Cred): File;

* Asynchronous `mkdir`.
* @param mode Mode to make the directory using. Can be ignored if
* the filesystem doesn't support permissions.
* @param mode Mode to make the directory using.
*/

@@ -148,4 +136,3 @@ abstract mkdir(path: string, mode: number, cred: Cred): Promise<void>;

* Synchronous `mkdir`.
* @param mode Mode to make the directory using. Can be ignored if
* the filesystem doesn't support permissions.
* @param mode Mode to make the directory using.
*/

@@ -155,5 +142,2 @@ abstract mkdirSync(path: string, mode: number, cred: Cred): void;

* Asynchronous `readdir`. Reads the contents of a directory.
*
* The callback gets two arguments `(err, files)` where `files` is an array of
* the names of the files in the directory excluding `'.'` and `'..'`.
*/

@@ -245,10 +229,8 @@ abstract readdir(path: string, cred: Cred): Promise<string[]>;

*
* Implementing classes must define a protected _sync property for the synchronous file system used as a cache.
* by:
* Implementing classes must define `_sync` for the synchronous file system used as a cache.
* Synchronous methods on an asynchronous FS are implemented by:
* - Performing operations over the in-memory copy,
* while asynchronously pipelining them to the backing store.
* - During loading, the contents of the async file system are eloaded into the synchronous store.
*
* - Performing operations over the in-memory copy, while asynchronously pipelining them
* to the backing store.
* - During application loading, the contents of the async file system can be reloaded into
* the synchronous store, if desired.
*
*/

@@ -255,0 +237,0 @@ export declare function Async<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => AsyncFS) & T;

@@ -5,11 +5,9 @@ import { ErrnoError, Errno } from './error.js';

import { PreloadFile, parseFlag } from './file.js';
import { ZenFsType } from './stats.js';
/**
* Structure for a filesystem. All ZenFS backends must extend this.
*
* This class includes some default implementations
* This class includes default implementations for `exists` and `existsSync`
*
* Assume the following about arguments passed to each API method:
*
* - Every path is an absolute path. `.`, `..`, and other items are resolved into an absolute form.
* - All arguments are present. Any optional arguments at the Node API level have been passed in with their default values.
* If you are extending this class, note that every path is an absolute path and all arguments are present.
*/

@@ -28,3 +26,3 @@ export class FileSystem {

noAsyncCache: false,
type: this._type,
type: ZenFsType,
};

@@ -104,10 +102,8 @@ }

*
* Implementing classes must define a protected _sync property for the synchronous file system used as a cache.
* by:
* Implementing classes must define `_sync` for the synchronous file system used as a cache.
* Synchronous methods on an asynchronous FS are implemented by:
* - Performing operations over the in-memory copy,
* while asynchronously pipelining them to the backing store.
* - During loading, the contents of the async file system are eloaded into the synchronous store.
*
* - Performing operations over the in-memory copy, while asynchronously pipelining them
* to the backing store.
* - During application loading, the contents of the async file system can be reloaded into
* the synchronous store, if desired.
*
*/

@@ -114,0 +110,0 @@ // eslint-disable-next-line @typescript-eslint/no-explicit-any

/// <reference types="node" resolution-mode="require"/>
import type * as Node from 'fs';
import { Cred } from './cred.js';
import type { Cred } from './cred.js';
/**

@@ -5,0 +5,0 @@ * Indicates the type of the given file. Applied to 'mode'.

@@ -5,5 +5,5 @@ /// <reference types="node" resolution-mode="require"/>

import { ErrnoError } from './error.js';
import { Cred } from './cred.js';
import type { Cred } from './cred.js';
import { type AbsolutePath } from './emulation/path.js';
import { FileSystem } from './filesystem.js';
import type { FileSystem } from './filesystem.js';
import type * as fs from 'node:fs';

@@ -10,0 +10,0 @@ declare global {

@@ -1,4 +0,4 @@

Copyright (c) 2023-2024 James P. and other ZenFS contributors.
Copyright (c) James P. and other ZenFS contributors.
Copyright (c) 2013-2023 John Vilk and other BrowserFS contributors.
Copyright (c) Joyent, Inc. and other Node contributors for `test/fixtures/node`.

@@ -22,25 +22,1 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of

SOFTWARE.
This license applies to all parts of ZenFS, except for the following items:
- The test fixtures located in `test/fixtures/node`. Their license follows:
"""
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
"""
{
"name": "@zenfs/core",
"version": "0.12.2",
"version": "0.12.3",
"description": "A filesystem in your browser",

@@ -41,3 +41,3 @@ "main": "dist/index.js",

"format:check": "prettier --check .",
"lint": "eslint src tests && tsc -p tsconfig.json --noEmit",
"lint": "tsc -p tsconfig.json --noEmit && eslint src tests",
"test": "npm run build && tsc -p tests/tsconfig.json --noEmit && cross-env NODE_OPTIONS=--experimental-vm-modules npx jest",

@@ -44,0 +44,0 @@ "build": "node scripts/build.js --globalName=ZenFS --entry src/index.ts",

@@ -7,3 +7,3 @@ # ZenFS

ZenFS is a fork of [BrowserFS](https://github.com/jvilk/BrowserFS). If you are using ZenFS in a research paper, you may want to [cite BrowserFS](https://github.com/jvilk/BrowserFS?tab=readme-ov-file#citing).
ZenFS is a fork of [BrowserFS](https://github.com/jvilk/BrowserFS). If you are using ZenFS in a research paper, you may want to [cite BrowserFS](https://github.com/jvilk/BrowserFS#citing).

@@ -10,0 +10,0 @@ ## Backends

import type { RequiredKeys } from 'utilium';
import { ErrnoError, Errno } from '../error.js';
import { FileSystem } from '../filesystem.js';
import type { FileSystem } from '../filesystem.js';
import { levenshtein } from '../utils.js';

@@ -5,0 +5,0 @@

import { Errno, ErrnoError } from '../error.js';
import type { FileSystemMetadata } from '../filesystem.js';
import { Stats } from '../stats.js';
import type { Stats } from '../stats.js';
import type { Backend } from './backend.js';

@@ -5,0 +5,0 @@ import { IndexFS } from './index/fs.js';

@@ -7,3 +7,4 @@ import type { Cred } from '../../cred.js';

import { decode } from '../../utils.js';
import { Index, IndexData } from './index.js';
import type { IndexData } from './index.js';
import { Index } from './index.js';

@@ -10,0 +11,0 @@ export abstract class IndexFS extends Readonly(FileSystem) {

import { isJSON } from 'utilium';
import { Errno, ErrnoError } from '../../error.js';
import { Stats, StatsLike } from '../../stats.js';
import type { StatsLike } from '../../stats.js';
import { Stats } from '../../stats.js';
import { encode } from '../../utils.js';

@@ -5,0 +6,0 @@ import { basename, dirname } from '../../emulation/path.js';

@@ -1,8 +0,11 @@

import { FileSystem, FileSystemMetadata } from '../filesystem.js';
import type { FileSystemMetadata } from '../filesystem.js';
import { FileSystem } from '../filesystem.js';
import { ErrnoError, Errno } from '../error.js';
import { File, PreloadFile, parseFlag } from '../file.js';
import type { File } from '../file.js';
import { PreloadFile, parseFlag } from '../file.js';
import { Stats } from '../stats.js';
import { LockedFS } from './locked.js';
import { dirname } from '../emulation/path.js';
import { Cred, rootCred } from '../cred.js';
import type { Cred } from '../cred.js';
import { rootCred } from '../cred.js';
import { decode, encode } from '../utils.js';

@@ -9,0 +12,0 @@ import type { Backend } from './backend.js';

@@ -41,2 +41,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */

protected _throwNoSync(syscall: string): never {
throw new ErrnoError(Errno.ENOTSUP, 'Syncrohnous operations not support on PortFile', this.path, syscall);
}
public stat(): Promise<Stats> {

@@ -47,3 +51,3 @@ return this.rpc('stat');

public statSync(): Stats {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.stat');
this._throwNoSync('stat');
}

@@ -56,3 +60,3 @@

public truncateSync(): void {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.truncate');
this._throwNoSync('truncate');
}

@@ -65,3 +69,3 @@

public writeSync(): number {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.write');
this._throwNoSync('write');
}

@@ -75,3 +79,3 @@

public readSync(): number {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.read');
this._throwNoSync('read');
}

@@ -84,3 +88,3 @@

public chownSync(): void {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.chown');
this._throwNoSync('chown');
}

@@ -93,3 +97,3 @@

public chmodSync(): void {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.chmod');
this._throwNoSync('chmod');
}

@@ -102,3 +106,3 @@

public utimesSync(): void {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.utimes');
this._throwNoSync('utimes');
}

@@ -111,3 +115,3 @@

public _setTypeSync(): void {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile._setType');
this._throwNoSync('_setType');
}

@@ -120,3 +124,3 @@

public closeSync(): void {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.close');
this._throwNoSync('close');
}

@@ -129,3 +133,3 @@

public syncSync(): void {
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.sync');
this._throwNoSync('sync');
}

@@ -132,0 +136,0 @@ }

@@ -21,3 +21,3 @@ import { type Entries } from 'utilium';

* Retrieve a file system with the given configuration.
* @param config A BackendConfig object.
* @see MountConfiguration
*/

@@ -24,0 +24,0 @@ export async function resolveMountConfig<T extends Backend>(config: MountConfiguration<T>, _depth = 0): Promise<FilesystemOf<T>> {

/**
* Credentials used for various operations.
* Similar to Linux's cred struct. See https://github.com/torvalds/linux/blob/master/include/linux/cred.h
* Similar to Linux's cred struct.
* @see https://github.com/torvalds/linux/blob/master/include/linux/cred.h
*/

@@ -5,0 +6,0 @@ export interface Cred {

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

import { R_OK } from './constants.js';
import { Dirent, type Dir } from './dir.js';
import type { Dirent } from './dir.js';
import { type Dir } from './dir.js';
import * as promises from './promises.js';

@@ -11,0 +12,0 @@ import { fd2file } from './shared.js';

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

import { Errno, ErrnoError } from '../error.js';
import { ActionType, File, isAppendable, isReadable, isWriteable, parseFlag, pathExistsAction, pathNotExistsAction } from '../file.js';
import type { File } from '../file.js';
import { isAppendable, isExclusive, isReadable, isTruncating, isWriteable, parseFlag } from '../file.js';
import type { FileContents } from '../filesystem.js';

@@ -114,3 +115,3 @@ import { BigIntStats, FileType, type Stats } from '../stats.js';

const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding!) : data;
await this.file.write(encodedData, 0, encodedData.length, null);
await this.file.write(encodedData, 0, encodedData.length);
}

@@ -497,37 +498,31 @@

if (!(await fs.exists(path, cred))) {
switch (pathNotExistsAction(flag)) {
case ActionType.CREATE:
// Ensure parent exists.
const parentStats: Stats = await fs.stat(dirname(resolved), cred);
if (parentStats && !parentStats.isDirectory()) {
throw ErrnoError.With('ENOTDIR', dirname(path), '_open');
}
return new FileHandle(await fs.createFile(resolved, flag, mode, cred));
case ActionType.THROW:
throw ErrnoError.With('ENOENT', path, '_open');
default:
throw new ErrnoError(Errno.EINVAL, 'Invalid file flag');
if ((!isWriteable(flag) && !isAppendable(flag)) || flag == 'r+') {
throw ErrnoError.With('ENOENT', path, '_open');
}
// Create the file
const parentStats: Stats = await fs.stat(dirname(resolved), cred);
if (parentStats && !parentStats.isDirectory()) {
throw ErrnoError.With('ENOTDIR', dirname(path), '_open');
}
return new FileHandle(await fs.createFile(resolved, flag, mode, cred));
}
switch (pathExistsAction(flag)) {
case ActionType.THROW:
throw ErrnoError.With('EEXIST', path, '_open');
case ActionType.TRUNCATE:
/*
In a previous implementation, we deleted the file and
re-created it. However, this created a race condition if another
asynchronous request was trying to read the file, as the file
would not exist for a small period of time.
*/
const file: File = await fs.openFile(resolved, flag, cred);
await file.truncate(0);
await file.sync();
return new FileHandle(file);
case ActionType.NOP:
// Must await so thrown errors are caught by the catch below
return new FileHandle(await fs.openFile(resolved, flag, cred));
default:
throw new ErrnoError(Errno.EINVAL, 'Invalid file flag');
if (isExclusive(flag)) {
throw ErrnoError.With('EEXIST', path, '_open');
}
if (!isTruncating(flag)) {
return new FileHandle(await fs.openFile(resolved, flag, cred));
}
/*
In a previous implementation, we deleted the file and
re-created it. However, this created a race condition if another
asynchronous request was trying to read the file, as the file
would not exist for a small period of time.
*/
const file: File = await fs.openFile(resolved, flag, cred);
await file.truncate(0);
await file.sync();
return new FileHandle(file);
}

@@ -534,0 +529,0 @@

@@ -5,8 +5,8 @@ // Utilities and shared data

import { InMemory } from '../backends/memory.js';
import { Cred, rootCred } from '../cred.js';
import type { Cred } from '../cred.js';
import { rootCred } from '../cred.js';
import { Errno, ErrnoError } from '../error.js';
import type { File } from '../file.js';
import { FileSystem } from '../filesystem.js';
import type { FileSystem } from '../filesystem.js';
import { size_max } from '../inode.js';
import { ZenFsType } from '../stats.js';
import { normalizePath } from '../utils.js';

@@ -133,3 +133,3 @@ import { resolve, type AbsolutePath } from './path.js';

return {
type: (bigint ? BigInt : Number)(md.type || ZenFsType),
type: (bigint ? BigInt : Number)(md.type),
bsize: (bigint ? BigInt : Number)(bs),

@@ -136,0 +136,0 @@ ffree: (bigint ? BigInt : Number)(md.freeNodes || size_max),

import type * as Node from 'fs';
import { Readable, Writable } from 'readable-stream';
import { Callback } from '../utils.js';
import type { Callback } from '../utils.js';
import { ErrnoError, Errno } from '../error.js';

@@ -5,0 +5,0 @@

import { Buffer } from 'buffer';
import type * as fs from 'node:fs';
import { Errno, ErrnoError } from '../error.js';
import { ActionType, File, isAppendable, isReadable, isWriteable, parseFlag, pathExistsAction, pathNotExistsAction } from '../file.js';
import { FileContents } from '../filesystem.js';
import type { File } from '../file.js';
import { isAppendable, isExclusive, isReadable, isTruncating, isWriteable, parseFlag } from '../file.js';
import type { FileContents } from '../filesystem.js';
import { BigIntStats, FileType, type Stats } from '../stats.js';

@@ -134,15 +135,11 @@ import { normalizeMode, normalizeOptions, normalizePath, normalizeTime } from '../utils.js';

if (!fs.existsSync(resolved, cred)) {
switch (pathNotExistsAction(flag)) {
case ActionType.CREATE:
// Ensure parent exists.
const parentStats: Stats = fs.statSync(dirname(resolved), cred);
if (!parentStats.isDirectory()) {
throw ErrnoError.With('ENOTDIR', dirname(path), '_open');
}
return fs.createFileSync(resolved, flag, mode, cred);
case ActionType.THROW:
throw ErrnoError.With('ENOENT', path, '_open');
default:
throw new ErrnoError(Errno.EINVAL, 'Invalid FileFlag object.');
if ((!isWriteable(flag) && !isAppendable(flag)) || flag == 'r+') {
throw ErrnoError.With('ENOENT', path, '_open');
}
// Create the file
const parentStats: Stats = fs.statSync(dirname(resolved), cred);
if (!parentStats.isDirectory()) {
throw ErrnoError.With('ENOTDIR', dirname(path), '_open');
}
return fs.createFileSync(resolved, flag, mode, cred);
}

@@ -156,21 +153,19 @@

// File exists.
switch (pathExistsAction(flag)) {
case ActionType.THROW:
throw ErrnoError.With('EEXIST', path, '_open');
case ActionType.TRUNCATE:
// Delete file.
fs.unlinkSync(resolved, cred);
/*
Create file. Use the same mode as the old file.
Node itself modifies the ctime when this occurs, so this action
will preserve that behavior if the underlying file system
supports those properties.
*/
return fs.createFileSync(resolved, flag, stats.mode, cred);
case ActionType.NOP:
return fs.openFileSync(resolved, flag, cred);
default:
throw new ErrnoError(Errno.EINVAL, 'Invalid FileFlag object.');
if (isExclusive(flag)) {
throw ErrnoError.With('EEXIST', path, '_open');
}
if (!isTruncating(flag)) {
return fs.openFileSync(resolved, flag, cred);
}
// Delete file.
fs.unlinkSync(resolved, cred);
/*
Create file. Use the same mode as the old file.
Node itself modifies the ctime when this occurs, so this action
will preserve that behavior if the underlying file system
supports those properties.
*/
return fs.createFileSync(resolved, flag, stats.mode, cred);
}

@@ -297,3 +292,3 @@

try {
file.writeSync(encodedData, 0, encodedData.byteLength, null);
file.writeSync(encodedData, 0, encodedData.byteLength);
} finally {

@@ -300,0 +295,0 @@ file.closeSync();

/**
* Standard libc error codes. More will be added to this enum and error strings as they are
* needed.
* @url https://en.wikipedia.org/wiki/Errno.h
* @see https://en.wikipedia.org/wiki/Errno.h
*/

@@ -6,0 +6,0 @@ export enum Errno {

import type { FileReadResult } from 'node:fs/promises';
import { ErrnoError, Errno } from './error.js';
import { O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY, S_IFMT } from './emulation/constants.js';
import { Errno, ErrnoError } from './error.js';
import type { FileSystem } from './filesystem.js';

@@ -35,16 +35,2 @@ import { size_max } from './inode.js';

/**
* @hidden
*/
export enum ActionType {
// Indicates that the code should not do anything.
NOP = 0,
// Indicates that the code should throw an exception.
THROW = 1,
// Indicates that the code should truncate the file, but only if it is a file.
TRUNCATE = 2,
// Indicates that the code should create the file.
CREATE = 3,
}
const validFlags = ['r', 'r+', 'rs', 'rs+', 'w', 'wx', 'w+', 'wx+', 'a', 'ax', 'a+', 'ax+'];

@@ -162,21 +148,2 @@

export function pathExistsAction(flag: string): ActionType {
if (isExclusive(flag)) {
return ActionType.THROW;
}
if (isTruncating(flag)) {
return ActionType.TRUNCATE;
}
return ActionType.NOP;
}
export function pathNotExistsAction(flag: string): ActionType {
if ((isWriteable(flag) || isAppendable(flag)) && flag !== 'r+') {
return ActionType.CREATE;
}
return ActionType.THROW;
}
export abstract class File {

@@ -254,3 +221,3 @@ /**

*/
public abstract write(buffer: Uint8Array, offset?: number, length?: number, position?: number | null): Promise<number>;
public abstract write(buffer: Uint8Array, offset?: number, length?: number, position?: number): Promise<number>;

@@ -269,3 +236,3 @@ /**

*/
public abstract writeSync(buffer: Uint8Array, offset?: number, length?: number, position?: number | null): number;
public abstract writeSync(buffer: Uint8Array, offset?: number, length?: number, position?: number): number;

@@ -522,3 +489,3 @@ /**

*/
public async write(buffer: Uint8Array, offset: number = 0, length: number = this.stats.size, position: number = 0): Promise<number> {
public async write(buffer: Uint8Array, offset: number = 0, length: number = this.stats.size, position: number = this.position): Promise<number> {
const bytesWritten = this.writeSync(buffer, offset, length, position);

@@ -542,5 +509,4 @@ await this.sync();

*/
public writeSync(buffer: Uint8Array, offset: number = 0, length: number = this.stats.size, position: number = 0): number {
public writeSync(buffer: Uint8Array, offset: number = 0, length: number = this.stats.size, position: number = this.position): number {
this.dirty = true;
position ??= this.position;
if (!isWriteable(this.flag)) {

@@ -547,0 +513,0 @@ throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode.');

@@ -6,3 +6,3 @@ import type { ExtractProperties } from 'utilium';

import { PreloadFile, parseFlag, type File } from './file.js';
import type { Stats } from './stats.js';
import { ZenFsType, type Stats } from './stats.js';

@@ -68,3 +68,3 @@ export type FileContents = ArrayBufferView | string;

*/
type?: number;
type: number;
}

@@ -75,17 +75,8 @@

*
* This class includes some default implementations
* This class includes default implementations for `exists` and `existsSync`
*
* Assume the following about arguments passed to each API method:
*
* - Every path is an absolute path. `.`, `..`, and other items are resolved into an absolute form.
* - All arguments are present. Any optional arguments at the Node API level have been passed in with their default values.
* If you are extending this class, note that every path is an absolute path and all arguments are present.
*/
export abstract class FileSystem {
/**
* Numeric type, used for statfs
* @internal @protected
*/
_type?: number;
/**
* Get metadata about the current file system

@@ -101,3 +92,3 @@ */

noAsyncCache: false,
type: this._type,
type: ZenFsType,
};

@@ -111,4 +102,3 @@ }

/**
* Asynchronous rename. No arguments other than a possible exception
* are given to the completion callback.
* Asynchronous rename.
*/

@@ -132,4 +122,4 @@ public abstract rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;

/**
* Opens the file at path p with the given flag. The file must exist.
* @param p The path to open.
* Opens the file at `path` with the given flag. The file must exist.
* @param path The path to open.
* @param flag The flag to use when opening the file.

@@ -140,4 +130,4 @@ */

/**
* Opens the file at path p with the given flag. The file must exist.
* @param p The path to open.
* Opens the file at `path` with the given flag. The file must exist.
* @param path The path to open.
* @param flag The flag to use when opening the file.

@@ -149,4 +139,3 @@ * @return A File object corresponding to the opened file.

/**
* Create the file at path p with the given mode. Then, open it with the given
* flag.
* Create the file at `path` with the given mode. Then, open it with the given flag.
*/

@@ -156,4 +145,3 @@ public abstract createFile(path: string, flag: string, mode: number, cred: Cred): Promise<File>;

/**
* Create the file at path p with the given mode. Then, open it with the given
* flag.
* Create the file at `path` with the given mode. Then, open it with the given flag.
*/

@@ -181,4 +169,3 @@ public abstract createFileSync(path: string, flag: string, mode: number, cred: Cred): File;

* Asynchronous `mkdir`.
* @param mode Mode to make the directory using. Can be ignored if
* the filesystem doesn't support permissions.
* @param mode Mode to make the directory using.
*/

@@ -188,4 +175,3 @@ public abstract mkdir(path: string, mode: number, cred: Cred): Promise<void>;

* Synchronous `mkdir`.
* @param mode Mode to make the directory using. Can be ignored if
* the filesystem doesn't support permissions.
* @param mode Mode to make the directory using.
*/

@@ -195,5 +181,2 @@ public abstract mkdirSync(path: string, mode: number, cred: Cred): void;

* Asynchronous `readdir`. Reads the contents of a directory.
*
* The callback gets two arguments `(err, files)` where `files` is an array of
* the names of the files in the directory excluding `'.'` and `'..'`.
*/

@@ -367,10 +350,8 @@ public abstract readdir(path: string, cred: Cred): Promise<string[]>;

*
* Implementing classes must define a protected _sync property for the synchronous file system used as a cache.
* by:
* Implementing classes must define `_sync` for the synchronous file system used as a cache.
* Synchronous methods on an asynchronous FS are implemented by:
* - Performing operations over the in-memory copy,
* while asynchronously pipelining them to the backing store.
* - During loading, the contents of the async file system are eloaded into the synchronous store.
*
* - Performing operations over the in-memory copy, while asynchronously pipelining them
* to the backing store.
* - During application loading, the contents of the async file system can be reloaded into
* the synchronous store, if desired.
*
*/

@@ -377,0 +358,0 @@ // eslint-disable-next-line @typescript-eslint/no-explicit-any

import type * as Node from 'fs';
import { Cred } from './cred.js';
import type { Cred } from './cred.js';
import { S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFREG, S_IFSOCK, S_IRWXG, S_IRWXO, S_IRWXU } from './emulation/constants.js';

@@ -4,0 +4,0 @@ import { size_max } from './inode.js';

import type { OptionalTuple } from 'utilium';
import { ErrnoError, Errno } from './error.js';
import { Cred } from './cred.js';
import type { Cred } from './cred.js';
import { dirname, resolve, type AbsolutePath } from './emulation/path.js';
import { FileSystem } from './filesystem.js';
import type { FileSystem } from './filesystem.js';
import type * as fs from 'node:fs';

@@ -7,0 +7,0 @@

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

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