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
170
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.11.1 to 0.11.2

2

dist/backends/fetch.d.ts

@@ -74,3 +74,3 @@ import { NoSyncFile } from '../file.js';

readonly required: false;
readonly description: "URL to a file index as a JSON file or the file index object itself, generated with the make_http_index script. Defaults to `index.json`.";
readonly description: "URL to a file index as a JSON file or the file index object itself, generated with the make-index script. Defaults to `index.json`.";
};

@@ -77,0 +77,0 @@ readonly baseUrl: {

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

import { FileIndex, AsyncIndexFS } from './Index.js';
/**
* @hidden
*/
function convertError(e) {
throw new ErrnoError(Errno.EIO, e.message);
}
async function fetchFile(path, type) {
const response = await fetch(path).catch(convertError);
const response = await fetch(path).catch(e => {
throw new ErrnoError(Errno.EIO, e.message);
});
if (!response.ok) {

@@ -19,6 +15,10 @@ throw new ErrnoError(Errno.EIO, 'fetch failed: response returned code ' + response.status);

case 'buffer':
const arrayBuffer = await response.arrayBuffer().catch(convertError);
const arrayBuffer = await response.arrayBuffer().catch(e => {
throw new ErrnoError(Errno.EIO, e.message);
});
return new Uint8Array(arrayBuffer);
case 'json':
return response.json().catch(convertError);
return response.json().catch(e => {
throw new ErrnoError(Errno.EIO, e.message);
});
default:

@@ -33,3 +33,5 @@ throw new ErrnoError(Errno.EINVAL, 'Invalid download type: ' + type);

async function fetchSize(path) {
const response = await fetch(path, { method: 'HEAD' }).catch(convertError);
const response = await fetch(path, { method: 'HEAD' }).catch(e => {
throw new ErrnoError(Errno.EIO, e.message);
});
if (!response.ok) {

@@ -159,3 +161,3 @@ throw new ErrnoError(Errno.EIO, 'fetch failed: HEAD response returned code ' + response.status);

required: false,
description: 'URL to a file index as a JSON file or the file index object itself, generated with the make_http_index script. Defaults to `index.json`.',
description: 'URL to a file index as a JSON file or the file index object itself, generated with the make-index script. Defaults to `index.json`.',
},

@@ -162,0 +164,0 @@ baseUrl: {

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

readonly fs: FS;
private _mu;
private mutex;
constructor(fs: FS);

@@ -20,0 +20,0 @@ ready(): Promise<void>;

@@ -16,3 +16,3 @@ import { ErrnoError } from '../error.js';

this.fs = fs;
this._mu = new Mutex();
this.mutex = new Mutex();
}

@@ -29,8 +29,8 @@ async ready() {

async rename(oldPath, newPath, cred) {
await this._mu.lock(oldPath);
await this.mutex.lock(oldPath);
await this.fs.rename(oldPath, newPath, cred);
this._mu.unlock(oldPath);
this.mutex.unlock(oldPath);
}
renameSync(oldPath, newPath, cred) {
if (this._mu.isLocked(oldPath)) {
if (this.mutex.isLocked(oldPath)) {
throw ErrnoError.With('EBUSY', oldPath, 'rename');

@@ -41,9 +41,9 @@ }

async stat(path, cred) {
await this._mu.lock(path);
await this.mutex.lock(path);
const stats = await this.fs.stat(path, cred);
this._mu.unlock(path);
this.mutex.unlock(path);
return stats;
}
statSync(path, cred) {
if (this._mu.isLocked(path)) {
if (this.mutex.isLocked(path)) {
throw ErrnoError.With('EBUSY', path, 'stat');

@@ -54,9 +54,9 @@ }

async openFile(path, flag, cred) {
await this._mu.lock(path);
await this.mutex.lock(path);
const fd = await this.fs.openFile(path, flag, cred);
this._mu.unlock(path);
this.mutex.unlock(path);
return fd;
}
openFileSync(path, flag, cred) {
if (this._mu.isLocked(path)) {
if (this.mutex.isLocked(path)) {
throw ErrnoError.With('EBUSY', path, 'openFile');

@@ -67,9 +67,9 @@ }

async createFile(path, flag, mode, cred) {
await this._mu.lock(path);
await this.mutex.lock(path);
const fd = await this.fs.createFile(path, flag, mode, cred);
this._mu.unlock(path);
this.mutex.unlock(path);
return fd;
}
createFileSync(path, flag, mode, cred) {
if (this._mu.isLocked(path)) {
if (this.mutex.isLocked(path)) {
throw ErrnoError.With('EBUSY', path, 'createFile');

@@ -80,8 +80,8 @@ }

async unlink(path, cred) {
await this._mu.lock(path);
await this.mutex.lock(path);
await this.fs.unlink(path, cred);
this._mu.unlock(path);
this.mutex.unlock(path);
}
unlinkSync(path, cred) {
if (this._mu.isLocked(path)) {
if (this.mutex.isLocked(path)) {
throw ErrnoError.With('EBUSY', path, 'unlink');

@@ -92,8 +92,8 @@ }

async rmdir(path, cred) {
await this._mu.lock(path);
await this.mutex.lock(path);
await this.fs.rmdir(path, cred);
this._mu.unlock(path);
this.mutex.unlock(path);
}
rmdirSync(path, cred) {
if (this._mu.isLocked(path)) {
if (this.mutex.isLocked(path)) {
throw ErrnoError.With('EBUSY', path, 'rmdir');

@@ -104,8 +104,8 @@ }

async mkdir(path, mode, cred) {
await this._mu.lock(path);
await this.mutex.lock(path);
await this.fs.mkdir(path, mode, cred);
this._mu.unlock(path);
this.mutex.unlock(path);
}
mkdirSync(path, mode, cred) {
if (this._mu.isLocked(path)) {
if (this.mutex.isLocked(path)) {
throw ErrnoError.With('EBUSY', path, 'mkdir');

@@ -116,9 +116,9 @@ }

async readdir(path, cred) {
await this._mu.lock(path);
await this.mutex.lock(path);
const files = await this.fs.readdir(path, cred);
this._mu.unlock(path);
this.mutex.unlock(path);
return files;
}
readdirSync(path, cred) {
if (this._mu.isLocked(path)) {
if (this.mutex.isLocked(path)) {
throw ErrnoError.With('EBUSY', path, 'readdir');

@@ -129,9 +129,9 @@ }

async exists(path, cred) {
await this._mu.lock(path);
await this.mutex.lock(path);
const exists = await this.fs.exists(path, cred);
this._mu.unlock(path);
this.mutex.unlock(path);
return exists;
}
existsSync(path, cred) {
if (this._mu.isLocked(path)) {
if (this.mutex.isLocked(path)) {
throw ErrnoError.With('EBUSY', path, 'exists');

@@ -142,8 +142,8 @@ }

async link(srcpath, dstpath, cred) {
await this._mu.lock(srcpath);
await this.mutex.lock(srcpath);
await this.fs.link(srcpath, dstpath, cred);
this._mu.unlock(srcpath);
this.mutex.unlock(srcpath);
}
linkSync(srcpath, dstpath, cred) {
if (this._mu.isLocked(srcpath)) {
if (this.mutex.isLocked(srcpath)) {
throw ErrnoError.With('EBUSY', srcpath, 'link');

@@ -154,8 +154,8 @@ }

async sync(path, data, stats) {
await this._mu.lock(path);
await this.mutex.lock(path);
await this.fs.sync(path, data, stats);
this._mu.unlock(path);
this.mutex.unlock(path);
}
syncSync(path, data, stats) {
if (this._mu.isLocked(path)) {
if (this.mutex.isLocked(path)) {
throw ErrnoError.With('EBUSY', path, 'sync');

@@ -162,0 +162,0 @@ }

@@ -30,3 +30,3 @@ import type { Ino } from '../inode.js';

name?: string;
}) => StoreFS;
}) => StoreFS<InMemoryStore>;
};

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

*/
_sync: import("../store/fs.js").StoreFS;
_sync: import("../store/fs.js").StoreFS<import("../memory.js").InMemoryStore>;
/**

@@ -85,0 +85,0 @@ * Constructs a new PortFS instance that connects with ZenFS running on

@@ -42,3 +42,4 @@ import { Errno, ErrnoError } from '../../error.js';

async read(buffer, offset, length, position) {
return (await this.rpc('read', buffer, offset, length, position));
const result = await this.rpc('read', buffer, offset, length, position);
return result;
}

@@ -45,0 +46,0 @@ readSync() {

@@ -20,6 +20,8 @@ import { ErrnoError, Errno } from '../../error.js';

port.postMessage({ ...request, _zenfs: true, id, stack });
setTimeout(() => {
const _ = setTimeout(() => {
const error = new ErrnoError(Errno.EIO, 'RPC Failed');
error.stack += stack;
reject(error);
if (typeof _ == 'object')
_.unref();
}, timeout);

@@ -26,0 +28,0 @@ });

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

/**
* A synchronous key-value file system. Uses a SyncStore to store the data.
* A file system which uses a key-value store.
*

@@ -16,9 +16,9 @@ * We use a unique ID for each node in the file system. The root node has a fixed ID.

*/
export declare class StoreFS extends FileSystem {
export declare class StoreFS<T extends Store = Store> extends FileSystem {
private $store;
protected get store(): Store;
protected _store?: Store;
protected get store(): T;
protected _store?: T;
private _initialized;
ready(): Promise<void>;
constructor($store: Store | Promise<Store>);
constructor($store: T | Promise<T>);
metadata(): FileSystemMetadata;

@@ -25,0 +25,0 @@ /**

@@ -11,3 +11,3 @@ import { W_OK, R_OK } from '../../emulation/constants.js';

/**
* A synchronous key-value file system. Uses a SyncStore to store the data.
* A file system which uses a key-value store.
*

@@ -14,0 +14,0 @@ * We use a unique ID for each node in the file system. The root node has a fixed ID.

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

const { size } = await this.stat();
const data = new Uint8Array(size);
await this.file.read(data, 0, size, 0);
const { buffer: data } = await this.file.read(new Uint8Array(size), 0, size, 0);
const buffer = Buffer.from(data);

@@ -113,0 +112,0 @@ return options.encoding ? buffer.toString(options.encoding) : buffer;

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

import { cred, fd2file, fdMap, fixError, file2fd, mounts, resolveMount } from './shared.js';
function doOp(...[name, resolveSymlinks, path, ...args]) {
function wrap(...[name, resolveSymlinks, path, ...args]) {
path = normalizePath(path);

@@ -64,3 +64,3 @@ const { fs, path: resolvedPath } = resolveMount(resolveSymlinks && existsSync(path) ? realpathSync(path) : path);

export function statSync(path, options) {
const stats = doOp('statSync', true, path.toString(), cred);
const stats = wrap('statSync', true, path.toString(), cred);
return options?.bigint ? new BigIntStats(stats) : stats;

@@ -70,3 +70,3 @@ }

export function lstatSync(path, options) {
const stats = doOp('statSync', false, path.toString(), cred);
const stats = wrap('statSync', false, path.toString(), cred);
return options?.bigint ? new BigIntStats(stats) : stats;

@@ -95,3 +95,3 @@ }

export function unlinkSync(path) {
return doOp('unlinkSync', false, path.toString(), cred);
return wrap('unlinkSync', false, path.toString(), cred);
}

@@ -104,3 +104,3 @@ unlinkSync;

try {
stats = doOp('statSync', resolveSymlinks, path, cred);
stats = wrap('statSync', resolveSymlinks, path, cred);
}

@@ -112,7 +112,7 @@ catch (e) {

// Ensure parent exists.
const parentStats = doOp('statSync', resolveSymlinks, dirname(path), cred);
const parentStats = wrap('statSync', resolveSymlinks, dirname(path), cred);
if (!parentStats.isDirectory()) {
throw ErrnoError.With('ENOTDIR', dirname(path), '_open');
}
return doOp('createFileSync', resolveSymlinks, path, flag, mode, cred);
return wrap('createFileSync', resolveSymlinks, path, flag, mode, cred);
case ActionType.THROW:

@@ -133,3 +133,3 @@ throw ErrnoError.With('ENOENT', path, '_open');

// Delete file.
doOp('unlinkSync', resolveSymlinks, path, cred);
wrap('unlinkSync', resolveSymlinks, path, cred);
/*

@@ -141,5 +141,5 @@ Create file. Use the same mode as the old file.

*/
return doOp('createFileSync', resolveSymlinks, path, flag, stats.mode, cred);
return wrap('createFileSync', resolveSymlinks, path, flag, stats.mode, cred);
case ActionType.NOP:
return doOp('openFileSync', resolveSymlinks, path, flag, cred);
return wrap('openFileSync', resolveSymlinks, path, flag, cred);
default:

@@ -196,17 +196,2 @@ throw new ErrnoError(Errno.EINVAL, 'Invalid FileFlag object.');

readFileSync;
/**
* Synchronously writes data to a file, replacing the file
* if it already exists.
*
* The encoding option is ignored if data is a buffer.
*/
function _writeFileSync(fname, data, flag, mode, resolveSymlinks) {
const file = _openSync(fname, flag, mode, resolveSymlinks);
try {
file.writeSync(data, 0, data.byteLength, 0);
}
finally {
file.closeSync();
}
}
export function writeFileSync(path, data, _options = {}) {

@@ -225,13 +210,5 @@ const options = normalizeOptions(_options, 'utf8', 'w+', 0o644);

}
_writeFileSync(typeof path == 'number' ? fd2file(path).path : path.toString(), encodedData, options.flag, options.mode, true);
}
writeFileSync;
/**
* Synchronously append data to a file, creating the file if
* it not yet exists.
*/
function _appendFileSync(fname, data, flag, mode, resolveSymlinks) {
const file = _openSync(fname, flag, mode, resolveSymlinks);
const file = _openSync(typeof path == 'number' ? fd2file(path).path : path.toString(), flag, options.mode, true);
try {
file.writeSync(data, 0, data.byteLength, null);
file.writeSync(encodedData, 0, encodedData.byteLength, 0);
}

@@ -242,2 +219,3 @@ finally {

}
writeFileSync;
/**

@@ -264,3 +242,9 @@ * Asynchronously append data to a file, creating the file if it not yet

const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
_appendFileSync(typeof filename == 'number' ? fd2file(filename).path : filename.toString(), encodedData, options.flag, options.mode, true);
const file = _openSync(typeof filename == 'number' ? fd2file(filename).path : filename.toString(), flag, options.mode, true);
try {
file.writeSync(encodedData, 0, encodedData.byteLength, null);
}
finally {
file.closeSync();
}
}

@@ -386,3 +370,3 @@ appendFileSync;

export function rmdirSync(path) {
return doOp('rmdirSync', true, path.toString(), cred);
return wrap('rmdirSync', true, path.toString(), cred);
}

@@ -393,3 +377,3 @@ rmdirSync;

const recursive = typeof options == 'object' && options?.recursive;
doOp('mkdirSync', true, path.toString(), normalizeMode(mode, 0o777), cred);
wrap('mkdirSync', true, path.toString(), normalizeMode(mode, 0o777), cred);
}

@@ -399,3 +383,3 @@ mkdirSync;

path = normalizePath(path);
const entries = doOp('readdirSync', true, path, cred);
const entries = wrap('readdirSync', true, path, cred);
for (const mount of mounts.keys()) {

@@ -431,3 +415,3 @@ if (!mount.startsWith(path)) {

newpath = normalizePath(newpath);
return doOp('linkSync', false, existing.toString(), newpath.toString(), cred);
return wrap('linkSync', false, existing.toString(), newpath.toString(), cred);
}

@@ -434,0 +418,0 @@ linkSync;

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

*/
declare abstract class SyncFileSystem extends FileSystem {
declare abstract class SyncFS extends FileSystem {
metadata(): FileSystemMetadata;

@@ -169,7 +169,7 @@ ready(): Promise<void>;

*/
export declare function Sync<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => SyncFileSystem) & T;
export declare function Sync<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => SyncFS) & T;
/**
* @internal
*/
declare abstract class AsyncFileSystem extends FileSystem {
declare abstract class AsyncFS extends FileSystem {
/**

@@ -205,7 +205,7 @@ * @hidden

*/
export declare function Async<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => AsyncFileSystem) & T;
export declare function Async<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => AsyncFS) & T;
/**
* @internal
*/
declare abstract class ReadonlyFileSystem extends FileSystem {
declare abstract class ReadonlyFS extends FileSystem {
metadata(): FileSystemMetadata;

@@ -230,3 +230,3 @@ rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;

*/
export declare function Readonly<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => ReadonlyFileSystem) & T;
export declare function Readonly<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => ReadonlyFS) & T;
export {};

@@ -61,3 +61,3 @@ import { ErrnoError, Errno } from './error.js';

export function Sync(FS) {
class _SyncFileSystem extends FS {
class _SyncFS extends FS {
async exists(path, cred) {

@@ -97,3 +97,3 @@ return this.existsSync(path, cred);

}
return _SyncFileSystem;
return _SyncFS;
}

@@ -114,3 +114,3 @@ /**

export function Async(FS) {
class _AsyncFileSystem extends FS {
class _AsyncFS extends FS {
constructor() {

@@ -156,4 +156,8 @@ super(...arguments);

createFileSync(path, flag, mode, cred) {
const file = this._sync.createFileSync(path, flag, mode, cred);
this._sync.createFileSync(path, flag, mode, cred);
this.queue('createFile', path, flag, mode, cred);
return this.openFileSync(path, flag, cred);
}
openFileSync(path, flag, cred) {
const file = this._sync.openFileSync(path, flag, cred);
const stats = file.statSync();

@@ -164,5 +168,2 @@ const buffer = new Uint8Array(stats.size);

}
openFileSync(path, flag, cred) {
return this._sync.openFileSync(path, flag, cred);
}
unlinkSync(path, cred) {

@@ -243,3 +244,3 @@ this._sync.unlinkSync(path, cred);

}
return _AsyncFileSystem;
return _AsyncFS;
}

@@ -251,3 +252,3 @@ /**

export function Readonly(FS) {
class _ReadonlyFileSystem extends FS {
class _ReadonlyFS extends FS {
metadata() {

@@ -300,3 +301,3 @@ return { ...super.metadata(), readonly: true };

}
return _ReadonlyFileSystem;
return _ReadonlyFS;
}

@@ -6,3 +6,3 @@ /**

export declare class Mutex {
private _locks;
protected locks: Map<string, (() => void)[]>;
lock(path: string): Promise<void>;

@@ -9,0 +9,0 @@ unlock(path: string): void;

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

constructor() {
this._locks = new Map();
this.locks = new Map();
}
lock(path) {
return new Promise(resolve => {
if (this._locks.has(path)) {
this._locks.get(path).push(resolve);
if (this.locks.has(path)) {
this.locks.get(path).push(resolve);
}
else {
this._locks.set(path, [resolve]);
this.locks.set(path, [resolve]);
}

@@ -22,6 +22,6 @@ });

unlock(path) {
if (!this._locks.has(path)) {
if (!this.locks.has(path)) {
throw new ErrnoError(Errno.EPERM, 'Can not unlock an already unlocked path', path);
}
const next = this._locks.get(path)?.shift();
const next = this.locks.get(path)?.shift();
/*

@@ -36,17 +36,17 @@ don't unlock - we want to queue up next for the

if (next) {
setTimeout(next, 0);
setTimeout(next);
return;
}
this._locks.delete(path);
this.locks.delete(path);
}
tryLock(path) {
if (this._locks.has(path)) {
if (this.locks.has(path)) {
return false;
}
this._locks.set(path, []);
this.locks.set(path, []);
return true;
}
isLocked(path) {
return this._locks.has(path);
return this.locks.has(path);
}
}
{
"name": "@zenfs/core",
"version": "0.11.1",
"version": "0.11.2",
"description": "A filesystem in your browser",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -19,15 +19,15 @@ #!/usr/bin/env node

const root = positionals.at(-1) == 'make-index' ? '.' : positionals.at(-1);
const root = positionals.at(-1) || '.';
if (options.help) {
console.log(`make-index <path> [...options]
path: The path to create a listing for
options:
--help, -h Outputs this help message
--quiet, -q Do not output messages about individual files
--verbose Output verbose messages
path: The path to create a listing for
--output, -o <path> Path to the output file. Defaults to listing.
--ignore, -i <pattern> Ignores files which match the glob <pattern>. Can be passed multiple times.
options:
--help, -h Outputs this help message
--quiet, -q The command will not generate any output, including error messages.
--verbose Output verbose messages
--output, -o <path> Path to the output file. Defaults to listing.
--ignore, -i <pattern> Ignores files which match the glob <pattern>. Can be passed multiple times.
`);

@@ -70,7 +70,9 @@ process.exit();

function makeListing(path, seen = new Set()) {
function listing(path, seen = new Set()) {
try {
if (options.verbose) console.log(`${color('blue', 'list')} ${path}`);
const stats = statSync(path);
if (stats.isFile()) {
if (options.verbose) console.log(`${color('green', 'file')} ${path}`);
return null;

@@ -87,4 +89,5 @@ }

entries[file] = makeListing(full, seen);
entries[file] = listing(full, seen);
}
if (options.verbose) console.log(`${color('bright_green', ' dir')} ${path}`);
return entries;

@@ -98,5 +101,5 @@ } catch (e) {

const listing = makeListing(pathToPosix(root));
const rootListing = listing(pathToPosix(root));
if (!options.quiet) console.log('Generated listing for ' + pathToPosix(resolve(root)));
writeFileSync(options.output, JSON.stringify(listing));
writeFileSync(options.output, JSON.stringify(rootListing));

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

/**
* @hidden
*/
function convertError(e: Error): never {
throw new ErrnoError(Errno.EIO, e.message);
}
/**
* Asynchronously download a file as a buffer or a JSON object.

@@ -27,3 +20,5 @@ * Note that the third function signature with a non-specialized type is

async function fetchFile<T extends object>(path: string, type: 'buffer' | 'json'): Promise<T | Uint8Array> {
const response = await fetch(path).catch(convertError);
const response = await fetch(path).catch(e => {
throw new ErrnoError(Errno.EIO, e.message);
});
if (!response.ok) {

@@ -34,6 +29,10 @@ throw new ErrnoError(Errno.EIO, 'fetch failed: response returned code ' + response.status);

case 'buffer':
const arrayBuffer = await response.arrayBuffer().catch(convertError);
const arrayBuffer = await response.arrayBuffer().catch(e => {
throw new ErrnoError(Errno.EIO, e.message);
});
return new Uint8Array(arrayBuffer);
case 'json':
return response.json().catch(convertError) as Promise<T>;
return response.json().catch(e => {
throw new ErrnoError(Errno.EIO, e.message);
}) as Promise<T>;
default:

@@ -49,3 +48,5 @@ throw new ErrnoError(Errno.EINVAL, 'Invalid download type: ' + type);

async function fetchSize(path: string): Promise<number> {
const response = await fetch(path, { method: 'HEAD' }).catch(convertError);
const response = await fetch(path, { method: 'HEAD' }).catch(e => {
throw new ErrnoError(Errno.EIO, e.message);
});
if (!response.ok) {

@@ -217,3 +218,3 @@ throw new ErrnoError(Errno.EIO, 'fetch failed: HEAD response returned code ' + response.status);

required: false,
description: 'URL to a file index as a JSON file or the file index object itself, generated with the make_http_index script. Defaults to `index.json`.',
description: 'URL to a file index as a JSON file or the file index object itself, generated with the make-index script. Defaults to `index.json`.',
},

@@ -220,0 +221,0 @@ baseUrl: {

@@ -19,3 +19,3 @@ import { ErrnoError } from '../error.js';

export class LockedFS<FS extends FileSystem> implements FileSystem {
private _mu: Mutex = new Mutex();
private mutex: Mutex = new Mutex();

@@ -36,9 +36,9 @@ constructor(public readonly fs: FS) {}

public async rename(oldPath: string, newPath: string, cred: Cred): Promise<void> {
await this._mu.lock(oldPath);
await this.mutex.lock(oldPath);
await this.fs.rename(oldPath, newPath, cred);
this._mu.unlock(oldPath);
this.mutex.unlock(oldPath);
}
public renameSync(oldPath: string, newPath: string, cred: Cred): void {
if (this._mu.isLocked(oldPath)) {
if (this.mutex.isLocked(oldPath)) {
throw ErrnoError.With('EBUSY', oldPath, 'rename');

@@ -50,5 +50,5 @@ }

public async stat(path: string, cred: Cred): Promise<Stats> {
await this._mu.lock(path);
await this.mutex.lock(path);
const stats = await this.fs.stat(path, cred);
this._mu.unlock(path);
this.mutex.unlock(path);
return stats;

@@ -58,3 +58,3 @@ }

public statSync(path: string, cred: Cred): Stats {
if (this._mu.isLocked(path)) {
if (this.mutex.isLocked(path)) {
throw ErrnoError.With('EBUSY', path, 'stat');

@@ -66,5 +66,5 @@ }

public async openFile(path: string, flag: string, cred: Cred): Promise<File> {
await this._mu.lock(path);
await this.mutex.lock(path);
const fd = await this.fs.openFile(path, flag, cred);
this._mu.unlock(path);
this.mutex.unlock(path);
return fd;

@@ -74,3 +74,3 @@ }

public openFileSync(path: string, flag: string, cred: Cred): File {
if (this._mu.isLocked(path)) {
if (this.mutex.isLocked(path)) {
throw ErrnoError.With('EBUSY', path, 'openFile');

@@ -82,5 +82,5 @@ }

public async createFile(path: string, flag: string, mode: number, cred: Cred): Promise<File> {
await this._mu.lock(path);
await this.mutex.lock(path);
const fd = await this.fs.createFile(path, flag, mode, cred);
this._mu.unlock(path);
this.mutex.unlock(path);
return fd;

@@ -90,3 +90,3 @@ }

public createFileSync(path: string, flag: string, mode: number, cred: Cred): File {
if (this._mu.isLocked(path)) {
if (this.mutex.isLocked(path)) {
throw ErrnoError.With('EBUSY', path, 'createFile');

@@ -98,9 +98,9 @@ }

public async unlink(path: string, cred: Cred): Promise<void> {
await this._mu.lock(path);
await this.mutex.lock(path);
await this.fs.unlink(path, cred);
this._mu.unlock(path);
this.mutex.unlock(path);
}
public unlinkSync(path: string, cred: Cred): void {
if (this._mu.isLocked(path)) {
if (this.mutex.isLocked(path)) {
throw ErrnoError.With('EBUSY', path, 'unlink');

@@ -112,9 +112,9 @@ }

public async rmdir(path: string, cred: Cred): Promise<void> {
await this._mu.lock(path);
await this.mutex.lock(path);
await this.fs.rmdir(path, cred);
this._mu.unlock(path);
this.mutex.unlock(path);
}
public rmdirSync(path: string, cred: Cred): void {
if (this._mu.isLocked(path)) {
if (this.mutex.isLocked(path)) {
throw ErrnoError.With('EBUSY', path, 'rmdir');

@@ -126,9 +126,9 @@ }

public async mkdir(path: string, mode: number, cred: Cred): Promise<void> {
await this._mu.lock(path);
await this.mutex.lock(path);
await this.fs.mkdir(path, mode, cred);
this._mu.unlock(path);
this.mutex.unlock(path);
}
public mkdirSync(path: string, mode: number, cred: Cred): void {
if (this._mu.isLocked(path)) {
if (this.mutex.isLocked(path)) {
throw ErrnoError.With('EBUSY', path, 'mkdir');

@@ -140,5 +140,5 @@ }

public async readdir(path: string, cred: Cred): Promise<string[]> {
await this._mu.lock(path);
await this.mutex.lock(path);
const files = await this.fs.readdir(path, cred);
this._mu.unlock(path);
this.mutex.unlock(path);
return files;

@@ -148,3 +148,3 @@ }

public readdirSync(path: string, cred: Cred): string[] {
if (this._mu.isLocked(path)) {
if (this.mutex.isLocked(path)) {
throw ErrnoError.With('EBUSY', path, 'readdir');

@@ -156,5 +156,5 @@ }

public async exists(path: string, cred: Cred): Promise<boolean> {
await this._mu.lock(path);
await this.mutex.lock(path);
const exists = await this.fs.exists(path, cred);
this._mu.unlock(path);
this.mutex.unlock(path);
return exists;

@@ -164,3 +164,3 @@ }

public existsSync(path: string, cred: Cred): boolean {
if (this._mu.isLocked(path)) {
if (this.mutex.isLocked(path)) {
throw ErrnoError.With('EBUSY', path, 'exists');

@@ -172,9 +172,9 @@ }

public async link(srcpath: string, dstpath: string, cred: Cred): Promise<void> {
await this._mu.lock(srcpath);
await this.mutex.lock(srcpath);
await this.fs.link(srcpath, dstpath, cred);
this._mu.unlock(srcpath);
this.mutex.unlock(srcpath);
}
public linkSync(srcpath: string, dstpath: string, cred: Cred): void {
if (this._mu.isLocked(srcpath)) {
if (this.mutex.isLocked(srcpath)) {
throw ErrnoError.With('EBUSY', srcpath, 'link');

@@ -186,9 +186,9 @@ }

public async sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void> {
await this._mu.lock(path);
await this.mutex.lock(path);
await this.fs.sync(path, data, stats);
this._mu.unlock(path);
this.mutex.unlock(path);
}
public syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void {
if (this._mu.isLocked(path)) {
if (this.mutex.isLocked(path)) {
throw ErrnoError.With('EBUSY', path, 'sync');

@@ -195,0 +195,0 @@ }

@@ -44,2 +44,2 @@ import type { Ino } from '../inode.js';

},
} as const satisfies Backend<StoreFS, { name?: string }>;
} as const satisfies Backend<StoreFS<InMemoryStore>, { name?: string }>;

@@ -66,3 +66,4 @@ /* eslint-disable @typescript-eslint/no-explicit-any */

public async read<TBuffer extends NodeJS.ArrayBufferView>(buffer: TBuffer, offset?: number, length?: number, position?: number): Promise<FileReadResult<TBuffer>> {
return (await this.rpc('read', buffer, offset, length, position)) as FileReadResult<TBuffer>;
const result = await this.rpc('read', buffer, offset, length, position);
return result as FileReadResult<TBuffer>;
}

@@ -69,0 +70,0 @@

@@ -88,6 +88,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */

port.postMessage({ ...request, _zenfs: true, id, stack });
setTimeout(() => {
const _ = setTimeout(() => {
const error = new ErrnoError(Errno.EIO, 'RPC Failed');
error.stack += stack;
reject(error);
if (typeof _ == 'object') _.unref();
}, timeout);

@@ -94,0 +95,0 @@ });

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

/**
* A synchronous key-value file system. Uses a SyncStore to store the data.
* A file system which uses a key-value store.
*

@@ -23,4 +23,4 @@ * We use a unique ID for each node in the file system. The root node has a fixed ID.

*/
export class StoreFS extends FileSystem {
protected get store(): Store {
export class StoreFS<T extends Store = Store> extends FileSystem {
protected get store(): T {
if (!this._store) {

@@ -32,3 +32,3 @@ throw new ErrnoError(Errno.ENODATA, 'No store attached');

protected _store?: Store;
protected _store?: T;

@@ -46,3 +46,3 @@ private _initialized: boolean = false;

constructor(private $store: Store | Promise<Store>) {
constructor(private $store: T | Promise<T>) {
super();

@@ -49,0 +49,0 @@

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

const { size } = await this.stat();
const data = new Uint8Array(size);
await this.file.read(data, 0, size, 0);
const { buffer: data } = await this.file.read(new Uint8Array(size), 0, size, 0);
const buffer = Buffer.from(data);

@@ -151,0 +150,0 @@ return options.encoding ? buffer.toString(options.encoding) : buffer;

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

function doOp<M extends FileSystemMethod, RT extends ReturnType<M>>(...[name, resolveSymlinks, path, ...args]: Parameters<M>): RT {
function wrap<M extends FileSystemMethod, RT extends ReturnType<M>>(...[name, resolveSymlinks, path, ...args]: Parameters<M>): RT {
path = normalizePath(path!);

@@ -82,3 +82,3 @@ const { fs, path: resolvedPath } = resolveMount(resolveSymlinks && existsSync(path) ? realpathSync(path) : path);

export function statSync(path: fs.PathLike, options?: fs.StatOptions): Stats | BigIntStats {
const stats: Stats = doOp('statSync', true, path.toString(), cred);
const stats: Stats = wrap('statSync', true, path.toString(), cred);
return options?.bigint ? new BigIntStats(stats) : stats;

@@ -97,3 +97,3 @@ }

export function lstatSync(path: fs.PathLike, options?: fs.StatOptions): Stats | BigIntStats {
const stats: Stats = doOp('statSync', false, path.toString(), cred);
const stats: Stats = wrap('statSync', false, path.toString(), cred);
return options?.bigint ? new BigIntStats(stats) : stats;

@@ -123,3 +123,3 @@ }

export function unlinkSync(path: fs.PathLike): void {
return doOp('unlinkSync', false, path.toString(), cred);
return wrap('unlinkSync', false, path.toString(), cred);
}

@@ -135,3 +135,3 @@ unlinkSync satisfies typeof fs.unlinkSync;

try {
stats = doOp('statSync', resolveSymlinks, path, cred);
stats = wrap('statSync', resolveSymlinks, path, cred);
} catch (e) {

@@ -142,7 +142,7 @@ // File does not exist.

// Ensure parent exists.
const parentStats: Stats = doOp('statSync', resolveSymlinks, dirname(path), cred);
const parentStats: Stats = wrap('statSync', resolveSymlinks, dirname(path), cred);
if (!parentStats.isDirectory()) {
throw ErrnoError.With('ENOTDIR', dirname(path), '_open');
}
return doOp('createFileSync', resolveSymlinks, path, flag, mode, cred);
return wrap('createFileSync', resolveSymlinks, path, flag, mode, cred);
case ActionType.THROW:

@@ -164,3 +164,3 @@ throw ErrnoError.With('ENOENT', path, '_open');

// Delete file.
doOp('unlinkSync', resolveSymlinks, path, cred);
wrap('unlinkSync', resolveSymlinks, path, cred);
/*

@@ -172,5 +172,5 @@ Create file. Use the same mode as the old file.

*/
return doOp('createFileSync', resolveSymlinks, path, flag, stats.mode, cred);
return wrap('createFileSync', resolveSymlinks, path, flag, stats.mode, cred);
case ActionType.NOP:
return doOp('openFileSync', resolveSymlinks, path, flag, cred);
return wrap('openFileSync', resolveSymlinks, path, flag, cred);
default:

@@ -242,17 +242,2 @@ throw new ErrnoError(Errno.EINVAL, 'Invalid FileFlag object.');

/**
* Synchronously writes data to a file, replacing the file
* if it already exists.
*
* The encoding option is ignored if data is a buffer.
*/
function _writeFileSync(fname: string, data: Uint8Array, flag: string, mode: number, resolveSymlinks: boolean): void {
const file = _openSync(fname, flag, mode, resolveSymlinks);
try {
file.writeSync(data, 0, data.byteLength, 0);
} finally {
file.closeSync();
}
}
/**
* Synchronously writes data to a file, replacing the file if it already

@@ -284,14 +269,5 @@ * exists.

}
_writeFileSync(typeof path == 'number' ? fd2file(path).path! : path.toString(), encodedData, options.flag, options.mode, true);
}
writeFileSync satisfies typeof fs.writeFileSync;
/**
* Synchronously append data to a file, creating the file if
* it not yet exists.
*/
function _appendFileSync(fname: string, data: Uint8Array, flag: string, mode: number, resolveSymlinks: boolean): void {
const file = _openSync(fname, flag, mode, resolveSymlinks);
const file = _openSync(typeof path == 'number' ? fd2file(path).path! : path.toString(), flag, options.mode, true);
try {
file.writeSync(data, 0, data.byteLength, null);
file.writeSync(encodedData, 0, encodedData.byteLength, 0);
} finally {

@@ -301,2 +277,3 @@ file.closeSync();

}
writeFileSync satisfies typeof fs.writeFileSync;

@@ -324,3 +301,8 @@ /**

const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding!) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
_appendFileSync(typeof filename == 'number' ? fd2file(filename).path! : filename.toString(), encodedData, options.flag, options.mode, true);
const file = _openSync(typeof filename == 'number' ? fd2file(filename).path! : filename.toString(), flag, options.mode, true);
try {
file.writeSync(encodedData, 0, encodedData.byteLength, null);
} finally {
file.closeSync();
}
}

@@ -496,3 +478,3 @@ appendFileSync satisfies typeof fs.appendFileSync;

export function rmdirSync(path: fs.PathLike): void {
return doOp('rmdirSync', true, path.toString(), cred);
return wrap('rmdirSync', true, path.toString(), cred);
}

@@ -513,3 +495,3 @@ rmdirSync satisfies typeof fs.rmdirSync;

const recursive = typeof options == 'object' && options?.recursive;
doOp('mkdirSync', true, path.toString(), normalizeMode(mode, 0o777), cred);
wrap('mkdirSync', true, path.toString(), normalizeMode(mode, 0o777), cred);
}

@@ -531,3 +513,3 @@ mkdirSync satisfies typeof fs.mkdirSync;

path = normalizePath(path);
const entries: string[] = doOp('readdirSync', true, path, cred);
const entries: string[] = wrap('readdirSync', true, path, cred);
for (const mount of mounts.keys()) {

@@ -567,3 +549,3 @@ if (!mount.startsWith(path)) {

newpath = normalizePath(newpath);
return doOp('linkSync', false, existing.toString(), newpath.toString(), cred);
return wrap('linkSync', false, existing.toString(), newpath.toString(), cred);
}

@@ -570,0 +552,0 @@ linkSync satisfies typeof fs.linkSync;

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

*/
declare abstract class SyncFileSystem extends FileSystem {
declare abstract class SyncFS extends FileSystem {
metadata(): FileSystemMetadata;

@@ -221,4 +221,4 @@ ready(): Promise<void>;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function Sync<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => SyncFileSystem) & T {
abstract class _SyncFileSystem extends FS implements SyncFileSystem {
export function Sync<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => SyncFS) & T {
abstract class _SyncFS extends FS implements SyncFS {
public async exists(path: string, cred: Cred): Promise<boolean> {

@@ -268,3 +268,3 @@ return this.existsSync(path, cred);

}
return _SyncFileSystem;
return _SyncFS;
}

@@ -275,3 +275,3 @@

*/
declare abstract class AsyncFileSystem extends FileSystem {
declare abstract class AsyncFS extends FileSystem {
/**

@@ -319,4 +319,4 @@ * @hidden

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function Async<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => AsyncFileSystem) & T {
abstract class _AsyncFileSystem extends FS implements AsyncFileSystem {
export function Async<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => AsyncFS) & T {
abstract class _AsyncFS extends FS implements AsyncFS {
/**

@@ -367,4 +367,9 @@ * Queue of pending asynchronous operations.

public createFileSync(path: string, flag: string, mode: number, cred: Cred): PreloadFile<this> {
const file = this._sync.createFileSync(path, flag, mode, cred);
this._sync.createFileSync(path, flag, mode, cred);
this.queue('createFile', path, flag, mode, cred);
return this.openFileSync(path, flag, cred);
}
public openFileSync(path: string, flag: string, cred: Cred): PreloadFile<this> {
const file = this._sync.openFileSync(path, flag, cred);
const stats = file.statSync();

@@ -376,6 +381,2 @@ const buffer = new Uint8Array(stats.size);

public openFileSync(path: string, flag: string, cred: Cred): File {
return this._sync.openFileSync(path, flag, cred);
}
public unlinkSync(path: string, cred: Cred): void {

@@ -465,3 +466,3 @@ this._sync.unlinkSync(path, cred);

return _AsyncFileSystem;
return _AsyncFS;
}

@@ -472,3 +473,3 @@

*/
declare abstract class ReadonlyFileSystem extends FileSystem {
declare abstract class ReadonlyFS extends FileSystem {
metadata(): FileSystemMetadata;

@@ -495,4 +496,4 @@ rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function Readonly<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => ReadonlyFileSystem) & T {
abstract class _ReadonlyFileSystem extends FS implements ReadonlyFileSystem {
export function Readonly<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => ReadonlyFS) & T {
abstract class _ReadonlyFS extends FS implements ReadonlyFS {
public metadata(): FileSystemMetadata {

@@ -559,3 +560,3 @@ return { ...super.metadata(), readonly: true };

}
return _ReadonlyFileSystem;
return _ReadonlyFS;
}

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

export class Mutex {
private _locks: Map<string, (() => void)[]> = new Map();
protected locks: Map<string, (() => void)[]> = new Map();
public lock(path: string): Promise<void> {
return new Promise(resolve => {
if (this._locks.has(path)) {
this._locks.get(path)!.push(resolve);
if (this.locks.has(path)) {
this.locks.get(path)!.push(resolve);
} else {
this._locks.set(path, [resolve]);
this.locks.set(path, [resolve]);
}

@@ -22,7 +22,7 @@ });

public unlock(path: string): void {
if (!this._locks.has(path)) {
if (!this.locks.has(path)) {
throw new ErrnoError(Errno.EPERM, 'Can not unlock an already unlocked path', path);
}
const next = this._locks.get(path)?.shift();
const next = this.locks.get(path)?.shift();
/*

@@ -37,15 +37,15 @@ don't unlock - we want to queue up next for the

if (next) {
setTimeout(next, 0);
setTimeout(next);
return;
}
this._locks.delete(path);
this.locks.delete(path);
}
public tryLock(path: string): boolean {
if (this._locks.has(path)) {
if (this.locks.has(path)) {
return false;
}
this._locks.set(path, []);
this.locks.set(path, []);
return true;

@@ -55,4 +55,4 @@ }

public isLocked(path: string): boolean {
return this._locks.has(path);
return this.locks.has(path);
}
}

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