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.2.3 to 0.3.0

33

dist/backends/AsyncMirror.d.ts

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

import { type FileSystem, SyncFileSystem, FileSystemMetadata } from '../filesystem.js';
import { FileSystem, FileSystemMetadata } from '../filesystem.js';
import { File, FileFlag, PreloadFile } from '../file.js';

@@ -31,2 +31,31 @@ import { Stats } from '../stats.js';

}
declare const AsyncMirrorFS_base: (abstract new (...args: any[]) => {
readonly metadata: FileSystemMetadata;
ready(): Promise<any>;
exists(path: string, cred: Cred): Promise<boolean>;
rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;
stat(path: string, cred: Cred): Promise<Stats>;
createFile(path: string, flag: FileFlag, mode: number, cred: Cred): Promise<File>;
/**
* @internal
*/
openFile(path: string, flag: FileFlag, cred: Cred): Promise<File>;
unlink(path: string, cred: Cred): Promise<void>;
rmdir(path: string, cred: Cred): Promise<void>;
mkdir(path: string, mode: number, cred: Cred): Promise<void>;
readdir(path: string, cred: Cred): Promise<string[]>;
link(srcpath: string, dstpath: string, cred: Cred): Promise<void>;
sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void>;
renameSync(oldPath: string, newPath: string, cred: Cred): void;
statSync(path: string, cred: Cred): Stats;
openFileSync(path: string, flag: FileFlag, cred: Cred): File;
createFileSync(path: string, flag: FileFlag, mode: number, cred: Cred): File;
unlinkSync(path: string, cred: Cred): void;
rmdirSync(path: string, cred: Cred): void;
mkdirSync(path: string, mode: number, cred: Cred): void;
readdirSync(path: string, cred: Cred): string[];
existsSync(path: string, cred: Cred): boolean;
linkSync(srcpath: string, dstpath: string, cred: Cred): void;
syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
}) & typeof FileSystem;
/**

@@ -45,3 +74,3 @@ * AsyncMirrorFS mirrors a synchronous filesystem into an asynchronous filesystem

*/
export declare class AsyncMirrorFS extends SyncFileSystem {
export declare class AsyncMirrorFS extends AsyncMirrorFS_base {
/**

@@ -48,0 +77,0 @@ * Queue of pending asynchronous operations.

14

dist/backends/AsyncMirror.js

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

import { SyncFileSystem } from '../filesystem.js';
import { FileSystem, Sync } from '../filesystem.js';
import { ApiError, ErrorCode } from '../ApiError.js';

@@ -42,3 +42,3 @@ import { FileFlag, PreloadFile } from '../file.js';

*/
export class AsyncMirrorFS extends SyncFileSystem {
export class AsyncMirrorFS extends Sync(FileSystem) {
async ready() {

@@ -67,2 +67,3 @@ await this._ready;

}
// @ts-expect-error 2611
get metadata() {

@@ -76,11 +77,2 @@ return {

}
/*public _syncSync(file: PreloadFile<AsyncMirror>, cred: Cred) {
const sync = this._sync.openFileSync(file.path, FileFlag.FromString('w'), cred);
sync.writeSync(file.buffer);
this.enqueue({
apiMethod: 'writeFile',
arguments: [file.path, file.buffer, file.flag, file.stats.mode, cred],
});
}*/
syncSync(path, data, stats) {

@@ -87,0 +79,0 @@ this._sync.syncSync(path, data, stats);

import { Cred } from '../cred.js';
import { PreloadFile, File, FileFlag } from '../file.js';
import { AsyncFileSystem, type FileSystemMetadata } from '../filesystem.js';
import { FileSystem, type FileSystemMetadata } from '../filesystem.js';
import { type Ino } from '../inode.js';

@@ -82,2 +82,28 @@ import { Stats } from '../stats.js';

}
declare const AsyncStoreFileSystem_base: (abstract new (...args: any[]) => {
renameSync(oldPath: string, newPath: string, cred: Cred): void;
statSync(path: string, cred: Cred): Stats;
createFileSync(path: string, flag: FileFlag, mode: number, cred: Cred): File;
openFileSync(path: string, flag: FileFlag, cred: Cred): File;
unlinkSync(path: string, cred: Cred): void;
rmdirSync(path: string, cred: Cred): void;
mkdirSync(path: string, mode: number, cred: Cred): void;
readdirSync(path: string, cred: Cred): string[];
linkSync(srcpath: string, dstpath: string, cred: Cred): void;
syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
readonly metadata: FileSystemMetadata;
ready(): Promise<any>;
rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;
stat(path: string, cred: Cred): Promise<Stats>;
openFile(path: string, flag: FileFlag, cred: Cred): Promise<File>;
createFile(path: string, flag: FileFlag, mode: number, cred: Cred): Promise<File>;
unlink(path: string, cred: Cred): Promise<void>;
rmdir(path: string, cred: Cred): Promise<void>;
mkdir(path: string, mode: number, cred: Cred): Promise<void>;
readdir(path: string, cred: Cred): Promise<string[]>;
exists(path: string, cred: Cred): Promise<boolean>;
existsSync(path: string, cred: Cred): boolean;
link(srcpath: string, dstpath: string, cred: Cred): Promise<void>;
sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void>;
}) & typeof FileSystem;
/**

@@ -87,3 +113,3 @@ * An "Asynchronous key-value file system". Stores data to/retrieves data from

*/
export declare class AsyncStoreFileSystem extends AsyncFileSystem {
export declare class AsyncStoreFileSystem extends AsyncStoreFileSystem_base {
protected store: AsyncStore;

@@ -180,1 +206,2 @@ private _cache?;

}
export {};

@@ -5,3 +5,3 @@ import { dirname, basename, join, resolve } from '../emulation/path.js';

import { PreloadFile } from '../file.js';
import { AsyncFileSystem } from '../filesystem.js';
import { Async, FileSystem } from '../filesystem.js';
import { randomIno, Inode } from '../inode.js';

@@ -73,3 +73,3 @@ import { FileType } from '../stats.js';

*/
export class AsyncStoreFileSystem extends AsyncFileSystem {
export class AsyncStoreFileSystem extends Async(FileSystem) {
ready() {

@@ -76,0 +76,0 @@ return this._ready;

@@ -15,3 +15,3 @@ import { FileSystem, FileSystemMetadata } from '../filesystem.js';

*/
export default class LockedFS<T extends FileSystem> implements FileSystem {
export declare class LockedFS<T extends FileSystem> implements FileSystem {
readonly fs: T;

@@ -18,0 +18,0 @@ private _mu;

@@ -11,3 +11,3 @@ import Mutex from '../mutex.js';

*/
export default class LockedFS {
export class LockedFS {
constructor(fs) {

@@ -14,0 +14,0 @@ this.fs = fs;

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

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

@@ -5,3 +5,3 @@ import { FileSystem } from '../filesystem.js';

import { Stats } from '../stats.js';
import LockedFS from './Locked.js';
import { LockedFS } from './Locked.js';
import { dirname } from '../emulation/path.js';

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

import { Cred } from '../cred.js';
import { FileFlag, PreloadFile } from '../file.js';
import { SyncFileSystem, type FileSystemMetadata } from '../filesystem.js';
import { type FileSystemMetadata, FileSystem } from '../filesystem.js';
import { type Ino, Inode } from '../inode.js';

@@ -122,2 +122,28 @@ import { Stats, FileType } from '../stats.js';

}
declare const SyncStoreFileSystem_base: (abstract new (...args: any[]) => {
readonly metadata: FileSystemMetadata;
ready(): Promise<any>;
exists(path: string, cred: Cred): Promise<boolean>;
rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;
stat(path: string, cred: Cred): Promise<Stats>;
createFile(path: string, flag: FileFlag, mode: number, cred: Cred): Promise<import("../file.js").File>;
openFile(path: string, flag: FileFlag, cred: Cred): Promise<import("../file.js").File>;
unlink(path: string, cred: Cred): Promise<void>;
rmdir(path: string, cred: Cred): Promise<void>;
mkdir(path: string, mode: number, cred: Cred): Promise<void>;
readdir(path: string, cred: Cred): Promise<string[]>;
link(srcpath: string, dstpath: string, cred: Cred): Promise<void>;
sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void>;
renameSync(oldPath: string, newPath: string, cred: Cred): void;
statSync(path: string, cred: Cred): Stats;
openFileSync(path: string, flag: FileFlag, cred: Cred): import("../file.js").File;
createFileSync(path: string, flag: FileFlag, mode: number, cred: Cred): import("../file.js").File;
unlinkSync(path: string, cred: Cred): void;
rmdirSync(path: string, cred: Cred): void;
mkdirSync(path: string, mode: number, cred: Cred): void;
readdirSync(path: string, cred: Cred): string[];
existsSync(path: string, cred: Cred): boolean;
linkSync(srcpath: string, dstpath: string, cred: Cred): void;
syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
}) & typeof FileSystem;
/**

@@ -132,3 +158,3 @@ * A "Synchronous key-value file system". Stores data to/retrieves data from an

*/
export declare class SyncStoreFileSystem extends SyncFileSystem {
export declare class SyncStoreFileSystem extends SyncStoreFileSystem_base {
protected store: SyncStore;

@@ -207,1 +233,2 @@ constructor(options: SyncStoreFileSystemOptions);

}
export {};

@@ -5,3 +5,3 @@ import { dirname, basename, join, resolve, sep } from '../emulation/path.js';

import { PreloadFile } from '../file.js';
import { SyncFileSystem } from '../filesystem.js';
import { FileSystem, Sync } from '../filesystem.js';
import { randomIno, Inode } from '../inode.js';

@@ -109,3 +109,3 @@ import { FileType } from '../stats.js';

*/
export class SyncStoreFileSystem extends SyncFileSystem {
export class SyncStoreFileSystem extends Sync(FileSystem) {
constructor(options) {

@@ -117,2 +117,3 @@ super();

}
// @ts-expect-error 2611
get metadata() {

@@ -119,0 +120,0 @@ return {

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

import type { FileSystem } from './filesystem.js';
import { Stats, type FileType } from './stats.js';
import { FileSystem, type SyncFileSystem } from './filesystem.js';
declare global {

@@ -422,3 +422,3 @@ interface ArrayBuffer {

*/
export declare class SyncFile<FS extends SyncFileSystem> extends PreloadFile<FS> {
export declare class SyncFile<FS extends FileSystem> extends PreloadFile<FS> {
constructor(_fs: FS, _path: string, _flag: FileFlag, _stat: Stats, contents?: Uint8Array);

@@ -425,0 +425,0 @@ sync(): Promise<void>;

import { ApiError, ErrorCode } from './ApiError.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 { size_max } from './inode.js';
import { Stats } from './stats.js';
import { O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_EXCL, O_TRUNC, O_APPEND, O_SYNC, S_IFMT } from './emulation/constants.js';
import { size_max } from './inode.js';
export var ActionType;

@@ -6,0 +6,0 @@ (function (ActionType) {

@@ -0,6 +1,20 @@

import type { Cred } from './cred.js';
import { NoSyncFile, type FileFlag } from './file.js';
import { FileSystem } from './filesystem.js';
import { Stats } from './stats.js';
type ListingTree = {
/**
* @internal
*/
export type ListingTree = {
[key: string]: ListingTree | null;
};
/**
* @internal
*/
export interface ListingQueueNode<T> {
pwd: string;
tree: ListingTree;
parent: IndexDirInode<T>;
}
/**
* A simple class for storing a filesystem index. Assumes that all paths passed

@@ -11,2 +25,4 @@ * to it are *absolute* paths.

* for the former purpose, especially when directories are concerned.
*
* @internal
*/

@@ -19,3 +35,3 @@ export declare class FileIndex<T> {

*/
static fromListing<T>(listing: ListingTree): FileIndex<T>;
static FromListing<T>(listing: ListingTree): FileIndex<T>;
protected _index: Map<string, IndexDirInode<T>>;

@@ -26,7 +42,4 @@ /**

constructor();
files(): IndexFileInode<T>[];
/**
* Runs the given function over all files in the index.
*/
forEachFile(cb: (file?: T) => void): void;
/**
* Adds the given absolute path to the index if it is not already in the index.

@@ -43,3 +56,3 @@ * Creates any needed parent directories.

*/
addPath(path: string, inode: IndexInode<T>): boolean;
add(path: string, inode: IndexInode<T>): boolean;
/**

@@ -50,11 +63,9 @@ * Adds the given absolute path to the index if it is not already in the index.

* @param path The path to add to the index.
* @param inode The inode for the
* path to add.
* @param inode The inode for the path to add.
* @return 'True' if it was added or already exists, 'false' if there
* was an issue adding it (e.g. item in path is a file, item exists but is
* different).
* @todo If adding fails and implicitly creates directories, we do not clean up
* the new empty directories.
* @todo If adding fails and implicitly creates directories, we do not clean up the new empty directories.
*/
addPathFast(path: string, inode: IndexInode<T>): boolean;
addFast(path: string, inode: IndexInode<T>): boolean;
/**

@@ -65,3 +76,3 @@ * Removes the given path. Can be a file or a directory.

*/
removePath(path: string): IndexInode<T> | null;
remove(path: string): IndexInode<T> | null;
/**

@@ -76,7 +87,3 @@ * Retrieves the directory listing of the given path.

*/
getInode(path: string): IndexInode<T> | null;
/**
* Split into a (directory path, item name) pair
*/
protected splitPath(p: string): string[];
get(path: string): IndexInode<T> | null;
}

@@ -90,4 +97,10 @@ /**

constructor(data?: T);
abstract isFile(): boolean;
abstract isDir(): boolean;
/**
* Whether this inode is for a file
*/
abstract isFile(): this is IndexFileInode<T>;
/**
* Whether this inode is for a directory
*/
abstract isDirectory(): this is IndexDirInode<T>;
abstract toStats(): Stats;

@@ -100,3 +113,3 @@ }

isFile(): boolean;
isDir(): boolean;
isDirectory(): boolean;
toStats(): Stats;

@@ -113,3 +126,3 @@ }

isFile(): boolean;
isDir(): boolean;
isDirectory(): boolean;
/**

@@ -133,9 +146,9 @@ * Return a Stats object for this inode.

* Returns the inode for the indicated item, or null if it does not exist.
* @param p Name of item in this directory.
* @param path Name of item in this directory.
*/
get(p: string): IndexInode<T> | null;
get(path: string): IndexInode<T> | null;
/**
* Add the given item to the directory listing. Note that the given inode is
* not copied, and will be mutated by the DirInode if it is a DirInode.
* @param p Item name to add to the directory listing.
* @param path Item name to add to the directory listing.
* @param inode The inode for the

@@ -145,3 +158,3 @@ * item to add to the directory inode.

*/
add(p: string, inode: IndexInode<T>): boolean;
add(path: string, inode: IndexInode<T>): boolean;
/**

@@ -155,10 +168,102 @@ * Removes the given item from the directory listing.

}
/**
* @hidden
*/
export declare function isIndexFileInode<T>(inode?: IndexInode<T>): inode is IndexFileInode<T>;
/**
* @hidden
*/
export declare function isIndexDirInode<T>(inode?: IndexInode<T>): inode is IndexDirInode<T>;
declare const FileIndexFS_base: (abstract new (...args: any[]) => {
rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;
renameSync(oldPath: string, newPath: string, cred: Cred): void;
createFile(path: string, flag: FileFlag, mode: number, cred: Cred): Promise<import("./file.js").File>;
createFileSync(path: string, flag: FileFlag, mode: number, cred: Cred): import("./file.js").File;
unlink(path: string, cred: Cred): Promise<void>;
unlinkSync(path: string, cred: Cred): void;
rmdir(path: string, cred: Cred): Promise<void>;
rmdirSync(path: string, cred: Cred): void;
mkdir(path: string, mode: number, cred: Cred): Promise<void>;
mkdirSync(path: string, mode: number, cred: Cred): void;
link(srcpath: string, dstpath: string, cred: Cred): Promise<void>;
linkSync(srcpath: string, dstpath: string, cred: Cred): void;
sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void>;
syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
readonly metadata: import("./filesystem.js").FileSystemMetadata;
ready(): Promise<any>;
stat(path: string, cred: Cred): Promise<Stats>;
statSync(path: string, cred: Cred): Stats;
openFile(path: string, flag: FileFlag, cred: Cred): Promise<import("./file.js").File>;
openFileSync(path: string, flag: FileFlag, cred: Cred): import("./file.js").File;
readdir(path: string, cred: Cred): Promise<string[]>;
readdirSync(path: string, cred: Cred): string[];
exists(path: string, cred: Cred): Promise<boolean>;
existsSync(path: string, cred: Cred): boolean;
}) & typeof FileSystem;
export declare abstract class FileIndexFS<TIndex> extends FileIndexFS_base {
protected _index: FileIndex<TIndex>;
constructor(index: ListingTree);
stat(path: string): Promise<Stats>;
statSync(path: string): Stats;
openFile(path: string, flag: FileFlag, cred: Cred): Promise<NoSyncFile<this>>;
openFileSync(path: string, flag: FileFlag, cred: Cred): NoSyncFile<this>;
readdir(path: string): Promise<string[]>;
readdirSync(path: string): string[];
protected abstract statFileInode(inode: IndexFileInode<TIndex>): Promise<Stats>;
protected abstract fileForFileInode(inode: IndexFileInode<TIndex>): Promise<NoSyncFile<this>>;
protected abstract statFileInodeSync(inode: IndexFileInode<TIndex>): Stats;
protected abstract fileForFileInodeSync(inode: IndexFileInode<TIndex>): NoSyncFile<this>;
}
declare const SyncFileIndexFS_base: (abstract new (...args: any[]) => {
readonly metadata: import("./filesystem.js").FileSystemMetadata;
ready(): Promise<any>;
exists(path: string, cred: Cred): Promise<boolean>;
rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;
stat(path: string, cred: Cred): Promise<Stats>;
createFile(path: string, flag: FileFlag, mode: number, cred: Cred): Promise<import("./file.js").File>;
openFile(path: string, flag: FileFlag, cred: Cred): Promise<import("./file.js").File>;
unlink(path: string, cred: Cred): Promise<void>;
rmdir(path: string, cred: Cred): Promise<void>;
mkdir(path: string, mode: number, cred: Cred): Promise<void>;
readdir(path: string, cred: Cred): Promise<string[]>;
link(srcpath: string, dstpath: string, cred: Cred): Promise<void>;
sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void>;
renameSync(oldPath: string, newPath: string, cred: Cred): void;
statSync(path: string, cred: Cred): Stats;
openFileSync(path: string, flag: FileFlag, cred: Cred): import("./file.js").File;
createFileSync(path: string, flag: FileFlag, mode: number, cred: Cred): import("./file.js").File;
unlinkSync(path: string, cred: Cred): void;
rmdirSync(path: string, cred: Cred): void;
mkdirSync(path: string, mode: number, cred: Cred): void;
readdirSync(path: string, cred: Cred): string[];
existsSync(path: string, cred: Cred): boolean;
linkSync(srcpath: string, dstpath: string, cred: Cred): void;
syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
}) & (abstract new (index: ListingTree) => FileIndexFS<unknown>);
export declare abstract class SyncFileIndexFS<TIndex> extends SyncFileIndexFS_base {
protected statFileInode(inode: IndexFileInode<TIndex>): Promise<Stats>;
protected fileForFileInode(inode: IndexFileInode<TIndex>): Promise<NoSyncFile<this>>;
}
declare const AsyncFileIndexFS_base: (abstract new (...args: any[]) => {
renameSync(oldPath: string, newPath: string, cred: Cred): void;
statSync(path: string, cred: Cred): Stats;
createFileSync(path: string, flag: FileFlag, mode: number, cred: Cred): import("./file.js").File;
openFileSync(path: string, flag: FileFlag, cred: Cred): import("./file.js").File;
unlinkSync(path: string, cred: Cred): void;
rmdirSync(path: string, cred: Cred): void;
mkdirSync(path: string, mode: number, cred: Cred): void;
readdirSync(path: string, cred: Cred): string[];
linkSync(srcpath: string, dstpath: string, cred: Cred): void;
syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
readonly metadata: import("./filesystem.js").FileSystemMetadata;
ready(): Promise<any>;
rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;
stat(path: string, cred: Cred): Promise<Stats>;
openFile(path: string, flag: FileFlag, cred: Cred): Promise<import("./file.js").File>;
createFile(path: string, flag: FileFlag, mode: number, cred: Cred): Promise<import("./file.js").File>;
unlink(path: string, cred: Cred): Promise<void>;
rmdir(path: string, cred: Cred): Promise<void>;
mkdir(path: string, mode: number, cred: Cred): Promise<void>;
readdir(path: string, cred: Cred): Promise<string[]>;
exists(path: string, cred: Cred): Promise<boolean>;
existsSync(path: string, cred: Cred): boolean;
link(srcpath: string, dstpath: string, cred: Cred): Promise<void>;
sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void>;
}) & (abstract new (index: ListingTree) => FileIndexFS<unknown>);
export declare abstract class AsyncFileIndexFS<TIndex> extends AsyncFileIndexFS_base {
protected statFileInodeSync(): Stats;
protected fileForFileInodeSync(): NoSyncFile<this>;
}
export {};

@@ -1,3 +0,6 @@

import { Stats, FileType } from './stats.js';
import * as path from './emulation/path.js';
import { ApiError, ErrorCode } from './ApiError.js';
import { basename, dirname, join } from './emulation/path.js';
import { NoSyncFile } from './file.js';
import { FileSystem, Sync, Async, Readonly } from './filesystem.js';
import { FileType, Stats } from './stats.js';
/**

@@ -9,2 +12,4 @@ * A simple class for storing a filesystem index. Assumes that all paths passed

* for the former purpose, especially when directories are concerned.
*
* @internal
*/

@@ -17,3 +22,3 @@ export class FileIndex {

*/
static fromListing(listing) {
static FromListing(listing) {
const index = new FileIndex();

@@ -33,3 +38,3 @@ // Add a root DirNode.

if (children) {
const path = `${pwd}/${node}`;
const path = pwd + '/' + node;
inode = new IndexDirInode();

@@ -60,8 +65,6 @@ index._index.set(path, inode);

// Create the root directory.
this.addPath('/', new IndexDirInode());
this.add('/', new IndexDirInode());
}
/**
* Runs the given function over all files in the index.
*/
forEachFile(cb) {
files() {
const files = [];
for (const dir of this._index.values()) {

@@ -73,5 +76,6 @@ for (const file of dir.listing) {

}
cb(item.data);
files.push(item);
}
}
return files;
}

@@ -90,7 +94,7 @@ /**

*/
addPath(path, inode) {
add(path, inode) {
if (!inode) {
throw new Error('Inode must be specified');
}
if (path[0] !== '/') {
if (!path.startsWith('/')) {
throw new Error('Path must be absolute, got: ' + path);

@@ -102,23 +106,19 @@ }

}
const splitPath = this.splitPath(path);
const dirpath = splitPath[0];
const itemname = splitPath[1];
const dirpath = dirname(path);
// Try to add to its parent directory first.
let parent = this._index.get(dirpath);
if (!parent && path !== '/') {
if (!parent && path != '/') {
// Create parent.
parent = new IndexDirInode();
if (!this.addPath(dirpath, parent)) {
if (!this.add(dirpath, parent)) {
return false;
}
}
// Add myself to my parent.
if (path !== '/') {
if (!parent.add(itemname, inode)) {
return false;
}
// Add to parent.
if (path != '/' && !parent.add(basename(path), inode)) {
return false;
}
// If I'm a directory, add myself to the index.
if (isIndexDirInode(inode)) {
this._index[path] = inode;
// If a directory, add to the index.
if (inode.isDirectory()) {
this._index.set(path, inode);
}

@@ -132,14 +132,11 @@ return true;

* @param path The path to add to the index.
* @param inode The inode for the
* path to add.
* @param inode The inode for the path to add.
* @return 'True' if it was added or already exists, 'false' if there
* was an issue adding it (e.g. item in path is a file, item exists but is
* different).
* @todo If adding fails and implicitly creates directories, we do not clean up
* the new empty directories.
* @todo If adding fails and implicitly creates directories, we do not clean up the new empty directories.
*/
addPathFast(path, inode) {
const itemNameMark = path.lastIndexOf('/');
const parentPath = itemNameMark === 0 ? '/' : path.substring(0, itemNameMark);
const itemName = path.substring(itemNameMark + 1);
addFast(path, inode) {
const parentPath = dirname(path);
const itemName = basename(path);
// Try to add to its parent directory first.

@@ -150,3 +147,3 @@ let parent = this._index.get(parentPath);

parent = new IndexDirInode();
this.addPathFast(parentPath, parent);
this.addFast(parentPath, parent);
}

@@ -157,4 +154,4 @@ if (!parent.add(itemName, inode)) {

// If adding a directory, add to the index as well.
if (inode.isDir()) {
this._index[path] = inode;
if (inode.isDirectory()) {
this._index.set(path, inode);
}

@@ -168,26 +165,24 @@ return true;

*/
removePath(path) {
const splitPath = this.splitPath(path);
const dirpath = splitPath[0];
const itemname = splitPath[1];
remove(path) {
const dirpath = dirname(path);
// Try to remove it from its parent directory first.
const parent = this._index[dirpath];
const parent = this._index.get(dirpath);
if (!parent) {
return;
}
// Remove myself from my parent.
const inode = parent.remove(itemname);
// Remove from parent.
const inode = parent.remove(basename(path));
if (!inode) {
return;
}
// If I'm a directory, remove myself from the index, and remove my children.
if (!isIndexDirInode(inode)) {
if (!inode.isDirectory()) {
return inode;
}
// If a directory, remove from the index, and remove children.
const children = inode.listing;
for (const child of children) {
this.removePath(path + '/' + child);
this.remove(join(path, child));
}
// Remove the directory from the index, unless it's the root.
if (path !== '/') {
if (path != '/') {
this._index.delete(path);

@@ -207,20 +202,12 @@ }

*/
getInode(path) {
const [dirpath, itemname] = this.splitPath(path);
get(path) {
const dirpath = dirname(path);
// Retrieve from its parent directory.
const parent = this._index.get(dirpath);
// Root case
if (dirpath === path) {
if (dirpath == path) {
return parent;
}
return parent?.get(itemname);
return parent?.get(basename(path));
}
/**
* Split into a (directory path, item name) pair
*/
splitPath(p) {
const dirpath = path.dirname(p);
const itemname = p.slice(dirpath.length + (dirpath === '/' ? 0 : 1));
return [dirpath, itemname];
}
}

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

}
isDir() {
isDirectory() {
return false;

@@ -265,3 +252,3 @@ }

}
isDir() {
isDirectory() {
return true;

@@ -289,11 +276,10 @@ }

get listing() {
return Object.keys(this._listing);
return [...this._listing.keys()];
}
/**
* Returns the inode for the indicated item, or null if it does not exist.
* @param p Name of item in this directory.
* @param path Name of item in this directory.
*/
get(p) {
const item = this._listing[p];
return item ? item : null;
get(path) {
return this._listing.get(path);
}

@@ -303,3 +289,3 @@ /**

* not copied, and will be mutated by the DirInode if it is a DirInode.
* @param p Item name to add to the directory listing.
* @param path Item name to add to the directory listing.
* @param inode The inode for the

@@ -309,7 +295,7 @@ * item to add to the directory inode.

*/
add(p, inode) {
if (p in this._listing) {
add(path, inode) {
if (this._listing.has(path)) {
return false;
}
this._listing[p] = inode;
this._listing.set(path, inode);
return true;

@@ -324,21 +310,117 @@ }

remove(p) {
const item = this._listing[p];
if (item === undefined) {
return null;
const item = this._listing.get(p);
if (!item) {
return;
}
delete this._listing[p];
this._listing.delete(p);
return item;
}
}
/**
* @hidden
*/
export function isIndexFileInode(inode) {
return inode?.isFile();
export class FileIndexFS extends Readonly(FileSystem) {
constructor(index) {
super();
this._index = FileIndex.FromListing(index);
}
async stat(path) {
const inode = this._index.get(path);
if (!inode) {
throw ApiError.ENOENT(path);
}
if (inode.isDirectory()) {
return inode.stats;
}
if (inode.isFile()) {
return this.statFileInode(inode);
}
throw new ApiError(ErrorCode.EINVAL, 'Invalid inode.');
}
statSync(path) {
const inode = this._index.get(path);
if (!inode) {
throw ApiError.ENOENT(path);
}
if (inode.isDirectory()) {
return inode.stats;
}
if (inode.isFile()) {
return this.statFileInodeSync(inode);
}
throw new ApiError(ErrorCode.EINVAL, 'Invalid inode.');
}
async openFile(path, flag, cred) {
if (flag.isWriteable()) {
// You can't write to files on this file system.
throw new ApiError(ErrorCode.EPERM, path);
}
// Check if the path exists, and is a file.
const inode = this._index.get(path);
if (!inode) {
throw ApiError.ENOENT(path);
}
if (!inode.toStats().hasAccess(flag.mode, cred)) {
throw ApiError.EACCES(path);
}
if (inode.isDirectory()) {
const stats = inode.stats;
return new NoSyncFile(this, path, flag, stats, stats.fileData);
}
return this.fileForFileInode(inode);
}
openFileSync(path, flag, cred) {
if (flag.isWriteable()) {
// You can't write to files on this file system.
throw new ApiError(ErrorCode.EPERM, path);
}
// Check if the path exists, and is a file.
const inode = this._index.get(path);
if (!inode) {
throw ApiError.ENOENT(path);
}
if (!inode.toStats().hasAccess(flag.mode, cred)) {
throw ApiError.EACCES(path);
}
if (inode.isDirectory()) {
const stats = inode.stats;
return new NoSyncFile(this, path, flag, stats, stats.fileData);
}
return this.fileForFileInodeSync(inode);
}
async readdir(path) {
// Check if it exists.
const inode = this._index.get(path);
if (!inode) {
throw ApiError.ENOENT(path);
}
if (inode.isDirectory()) {
return inode.listing;
}
throw ApiError.ENOTDIR(path);
}
readdirSync(path) {
// Check if it exists.
const inode = this._index.get(path);
if (!inode) {
throw ApiError.ENOENT(path);
}
if (inode.isDirectory()) {
return inode.listing;
}
throw ApiError.ENOTDIR(path);
}
}
/**
* @hidden
*/
export function isIndexDirInode(inode) {
return inode?.isDir();
export class SyncFileIndexFS extends Sync((FileIndexFS)) {
async statFileInode(inode) {
return this.statFileInodeSync(inode);
}
async fileForFileInode(inode) {
return this.fileForFileInodeSync(inode);
}
}
export class AsyncFileIndexFS extends Async((FileIndexFS)) {
statFileInodeSync() {
throw new ApiError(ErrorCode.ENOTSUP);
}
fileForFileInodeSync() {
throw new ApiError(ErrorCode.ENOTSUP);
}
}

@@ -49,3 +49,2 @@ import { ApiError } from './ApiError.js';

export declare abstract class FileSystem {
static get Name(): string;
get metadata(): FileSystemMetadata;

@@ -160,6 +159,11 @@ constructor(options?: object);

* Implements the asynchronous API in terms of the synchronous API.
*
* @example ```ts
* class SyncFS extends Sync(FileSystem) {}
* ```
*/
export declare abstract class SyncFileSystem extends FileSystem {
get metadata(): FileSystemMetadata;
ready(): Promise<this>;
export declare function Sync<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => {
readonly metadata: FileSystemMetadata;
ready(): Promise<any>;
exists(path: string, cred: Cred): Promise<boolean>;
rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;

@@ -175,17 +179,57 @@ stat(path: string, cred: Cred): Promise<Stats>;

sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void>;
}
export declare abstract class ReadonlySyncFileSystem extends SyncFileSystem {
/**
* Synchronous rename.
*/
renameSync(oldPath: string, newPath: string, cred: Cred): void;
/**
* Synchronous `stat`.
*/
statSync(path: string, cred: Cred): Stats;
/**
* Opens the file at path p with the given flag. The file must exist.
* @param p The path to open.
* @param flag The flag to use when opening the file.
* @return A File object corresponding to the opened file.
*/
openFileSync(path: string, flag: FileFlag, cred: Cred): File;
/**
* Create the file at path p with the given mode. Then, open it with the given
* flag.
*/
createFileSync(path: string, flag: FileFlag, mode: number, cred: Cred): File;
/**
* Synchronous `unlink`.
*/
unlinkSync(path: string, cred: Cred): void;
/**
* Synchronous `rmdir`.
*/
rmdirSync(path: string, cred: Cred): void;
/**
* Synchronous `mkdir`.
* @param mode Mode to make the directory using. Can be ignored if
* the filesystem doesn't support permissions.
*/
mkdirSync(path: string, mode: number, cred: Cred): void;
/**
* Synchronous `readdir`. Reads the contents of a directory.
*/
readdirSync(path: string, cred: Cred): string[];
/**
* Test whether or not the given path exists by checking with the file system.
*/
existsSync(path: string, cred: Cred): boolean;
/**
* Synchronous `link`.
*/
linkSync(srcpath: string, dstpath: string, cred: Cred): void;
/**
* Synchronize the data and stats for path synchronously
*/
syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
}
export declare abstract class AsyncFileSystem extends FileSystem {
}) & T;
export declare function Async<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => {
renameSync(oldPath: string, newPath: string, cred: Cred): void;
statSync(path: string, cred: Cred): Stats;
createFileSync(path: string, flag: FileFlag, mode: number, cred: Cred): File;
openSync(path: string, flags: FileFlag, mode: number, cred: Cred): File;
openFileSync(path: string, flag: FileFlag, cred: Cred): File;

@@ -198,11 +242,119 @@ unlinkSync(path: string, cred: Cred): void;

syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
}
export declare abstract class ReadonlyAsyncFileSystem extends AsyncFileSystem {
readonly metadata: FileSystemMetadata;
ready(): Promise<any>;
/**
* Asynchronous rename. No arguments other than a possible exception
* are given to the completion callback.
*/
rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;
/**
* Asynchronous `stat`.
*/
stat(path: string, cred: Cred): Promise<Stats>;
/**
* Opens the file at path p with the given flag. The file must exist.
* @param p The path to open.
* @param flag The flag to use when opening the file.
*/
openFile(path: string, flag: FileFlag, cred: Cred): Promise<File>;
/**
* Create the file at path p with the given mode. Then, open it with the given
* flag.
*/
createFile(path: string, flag: FileFlag, mode: number, cred: Cred): Promise<File>;
/**
* Asynchronous `unlink`.
*/
unlink(path: string, cred: Cred): Promise<void>;
/**
* Asynchronous `rmdir`.
*/
rmdir(path: string, cred: Cred): Promise<void>;
/**
* Asynchronous `mkdir`.
* @param mode Mode to make the directory using. Can be ignored if
* the filesystem doesn't support permissions.
*/
mkdir(path: string, mode: number, cred: Cred): Promise<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 `'..'`.
*/
readdir(path: string, cred: Cred): Promise<string[]>;
/**
* Test whether or not the given path exists by checking with the file system.
*/
exists(path: string, cred: Cred): Promise<boolean>;
/**
* Test whether or not the given path exists by checking with the file system.
*/
existsSync(path: string, cred: Cred): boolean;
/**
* Asynchronous `link`.
*/
link(srcpath: string, dstpath: string, cred: Cred): Promise<void>;
/**
* Synchronize the data and stats for path asynchronously
*/
sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void>;
}
}) & T;
export declare function Readonly<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => {
rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;
renameSync(oldPath: string, newPath: string, cred: Cred): void;
createFile(path: string, flag: FileFlag, mode: number, cred: Cred): Promise<File>;
createFileSync(path: string, flag: FileFlag, mode: number, cred: Cred): File;
unlink(path: string, cred: Cred): Promise<void>;
unlinkSync(path: string, cred: Cred): void;
rmdir(path: string, cred: Cred): Promise<void>;
rmdirSync(path: string, cred: Cred): void;
mkdir(path: string, mode: number, cred: Cred): Promise<void>;
mkdirSync(path: string, mode: number, cred: Cred): void;
link(srcpath: string, dstpath: string, cred: Cred): Promise<void>;
linkSync(srcpath: string, dstpath: string, cred: Cred): void;
sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void>;
syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
readonly metadata: FileSystemMetadata;
ready(): Promise<any>;
/**
* Asynchronous `stat`.
*/
stat(path: string, cred: Cred): Promise<Stats>;
/**
* Synchronous `stat`.
*/
statSync(path: string, cred: Cred): Stats;
/**
* Opens the file at path p with the given flag. The file must exist.
* @param p The path to open.
* @param flag The flag to use when opening the file.
*/
openFile(path: string, flag: FileFlag, cred: Cred): Promise<File>;
/**
* Opens the file at path p with the given flag. The file must exist.
* @param p The path to open.
* @param flag The flag to use when opening the file.
* @return A File object corresponding to the opened file.
*/
openFileSync(path: string, flag: FileFlag, cred: Cred): File;
/**
* 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 `'..'`.
*/
readdir(path: string, cred: Cred): Promise<string[]>;
/**
* Synchronous `readdir`. Reads the contents of a directory.
*/
readdirSync(path: string, cred: Cred): string[];
/**
* Test whether or not the given path exists by checking with the file system.
*/
exists(path: string, cred: Cred): Promise<boolean>;
/**
* Test whether or not the given path exists by checking with the file system.
*/
existsSync(path: string, cred: Cred): boolean;
}) & T;

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

/* eslint-disable @typescript-eslint/no-unused-vars */
// disable no-unused-vars since BaseFileSystem uses them a lot
import { ApiError, ErrorCode } from './ApiError.js';

@@ -15,5 +13,2 @@ /**

export class FileSystem {
static get Name() {
return this.name;
}
get metadata() {

@@ -29,2 +24,3 @@ return {

}
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
constructor(options) {

@@ -60,121 +56,138 @@ // unused

* Implements the asynchronous API in terms of the synchronous API.
*
* @example ```ts
* class SyncFS extends Sync(FileSystem) {}
* ```
*/
export class SyncFileSystem extends FileSystem {
get metadata() {
return { ...super.metadata, synchronous: true };
export function Sync(FS) {
/**
* Implements the asynchronous API in terms of the synchronous API.
*/
class SyncFileSystem extends FS {
get metadata() {
return { ...super.metadata, synchronous: true };
}
async ready() {
return this;
}
async exists(path, cred) {
return this.existsSync(path, cred);
}
async rename(oldPath, newPath, cred) {
return this.renameSync(oldPath, newPath, cred);
}
async stat(path, cred) {
return this.statSync(path, cred);
}
async createFile(path, flag, mode, cred) {
return this.createFileSync(path, flag, mode, cred);
}
async openFile(path, flag, cred) {
return this.openFileSync(path, flag, cred);
}
async unlink(path, cred) {
return this.unlinkSync(path, cred);
}
async rmdir(path, cred) {
return this.rmdirSync(path, cred);
}
async mkdir(path, mode, cred) {
return this.mkdirSync(path, mode, cred);
}
async readdir(path, cred) {
return this.readdirSync(path, cred);
}
async link(srcpath, dstpath, cred) {
return this.linkSync(srcpath, dstpath, cred);
}
async sync(path, data, stats) {
return this.syncSync(path, data, stats);
}
}
async ready() {
return this;
}
async rename(oldPath, newPath, cred) {
return this.renameSync(oldPath, newPath, cred);
}
async stat(path, cred) {
return this.statSync(path, cred);
}
async createFile(path, flag, mode, cred) {
return this.createFileSync(path, flag, mode, cred);
}
async openFile(path, flag, cred) {
return this.openFileSync(path, flag, cred);
}
async unlink(path, cred) {
return this.unlinkSync(path, cred);
}
async rmdir(path, cred) {
return this.rmdirSync(path, cred);
}
async mkdir(path, mode, cred) {
return this.mkdirSync(path, mode, cred);
}
async readdir(path, cred) {
return this.readdirSync(path, cred);
}
async link(srcpath, dstpath, cred) {
return this.linkSync(srcpath, dstpath, cred);
}
async sync(path, data, stats) {
return this.syncSync(path, data, stats);
}
return SyncFileSystem;
}
export class ReadonlySyncFileSystem extends SyncFileSystem {
renameSync(oldPath, newPath, cred) {
throw new ApiError(ErrorCode.EROFS);
export function Async(FS) {
class AsyncFileSystem extends FS {
/* eslint-disable @typescript-eslint/no-unused-vars */
renameSync(oldPath, newPath, cred) {
throw new ApiError(ErrorCode.ENOTSUP);
}
statSync(path, cred) {
throw new ApiError(ErrorCode.ENOTSUP);
}
createFileSync(path, flag, mode, cred) {
throw new ApiError(ErrorCode.ENOTSUP);
}
openFileSync(path, flag, cred) {
throw new ApiError(ErrorCode.ENOTSUP);
}
unlinkSync(path, cred) {
throw new ApiError(ErrorCode.ENOTSUP);
}
rmdirSync(path, cred) {
throw new ApiError(ErrorCode.ENOTSUP);
}
mkdirSync(path, mode, cred) {
throw new ApiError(ErrorCode.ENOTSUP);
}
readdirSync(path, cred) {
throw new ApiError(ErrorCode.ENOTSUP);
}
linkSync(srcpath, dstpath, cred) {
throw new ApiError(ErrorCode.ENOTSUP);
}
syncSync(path, data, stats) {
throw new ApiError(ErrorCode.ENOTSUP);
}
}
createFileSync(path, flag, mode, cred) {
throw new ApiError(ErrorCode.EROFS);
}
unlinkSync(path, cred) {
throw new ApiError(ErrorCode.EROFS);
}
rmdirSync(path, cred) {
throw new ApiError(ErrorCode.EROFS);
}
mkdirSync(path, mode, cred) {
throw new ApiError(ErrorCode.EROFS);
}
linkSync(srcpath, dstpath, cred) {
throw new ApiError(ErrorCode.EROFS);
}
syncSync(path, data, stats) {
throw new ApiError(ErrorCode.EROFS);
}
/* eslint-enable @typescript-eslint/no-unused-vars */
return AsyncFileSystem;
}
export class AsyncFileSystem extends FileSystem {
renameSync(oldPath, newPath, cred) {
throw new ApiError(ErrorCode.ENOTSUP);
export function Readonly(FS) {
class ReadonlyFileSystem extends FS {
/* eslint-disable @typescript-eslint/no-unused-vars */
async rename(oldPath, newPath, cred) {
throw new ApiError(ErrorCode.EROFS);
}
renameSync(oldPath, newPath, cred) {
throw new ApiError(ErrorCode.EROFS);
}
async createFile(path, flag, mode, cred) {
throw new ApiError(ErrorCode.EROFS);
}
createFileSync(path, flag, mode, cred) {
throw new ApiError(ErrorCode.EROFS);
}
async unlink(path, cred) {
throw new ApiError(ErrorCode.EROFS);
}
unlinkSync(path, cred) {
throw new ApiError(ErrorCode.EROFS);
}
async rmdir(path, cred) {
throw new ApiError(ErrorCode.EROFS);
}
rmdirSync(path, cred) {
throw new ApiError(ErrorCode.EROFS);
}
async mkdir(path, mode, cred) {
throw new ApiError(ErrorCode.EROFS);
}
mkdirSync(path, mode, cred) {
throw new ApiError(ErrorCode.EROFS);
}
async link(srcpath, dstpath, cred) {
throw new ApiError(ErrorCode.EROFS);
}
linkSync(srcpath, dstpath, cred) {
throw new ApiError(ErrorCode.EROFS);
}
async sync(path, data, stats) {
throw new ApiError(ErrorCode.EROFS);
}
syncSync(path, data, stats) {
throw new ApiError(ErrorCode.EROFS);
}
}
statSync(path, cred) {
throw new ApiError(ErrorCode.ENOTSUP);
}
createFileSync(path, flag, mode, cred) {
throw new ApiError(ErrorCode.ENOTSUP);
}
openSync(path, flags, mode, cred) {
throw new ApiError(ErrorCode.ENOTSUP);
}
openFileSync(path, flag, cred) {
throw new ApiError(ErrorCode.ENOTSUP);
}
unlinkSync(path, cred) {
throw new ApiError(ErrorCode.ENOTSUP);
}
rmdirSync(path, cred) {
throw new ApiError(ErrorCode.ENOTSUP);
}
mkdirSync(path, mode, cred) {
throw new ApiError(ErrorCode.ENOTSUP);
}
readdirSync(path, cred) {
throw new ApiError(ErrorCode.ENOTSUP);
}
linkSync(srcpath, dstpath, cred) {
throw new ApiError(ErrorCode.ENOTSUP);
}
syncSync(path, data, stats) {
throw new ApiError(ErrorCode.ENOTSUP);
}
return ReadonlyFileSystem;
}
export class ReadonlyAsyncFileSystem extends AsyncFileSystem {
async rename(oldPath, newPath, cred) {
throw new ApiError(ErrorCode.EROFS);
}
async createFile(path, flag, mode, cred) {
throw new ApiError(ErrorCode.EROFS);
}
async unlink(path, cred) {
throw new ApiError(ErrorCode.EROFS);
}
async rmdir(path, cred) {
throw new ApiError(ErrorCode.EROFS);
}
async mkdir(path, mode, cred) {
throw new ApiError(ErrorCode.EROFS);
}
async link(srcpath, dstpath, cred) {
throw new ApiError(ErrorCode.EROFS);
}
async sync(path, data, stats) {
throw new ApiError(ErrorCode.EROFS);
}
}
{
"name": "@zenfs/core",
"version": "0.2.3",
"version": "0.3.0",
"description": "A filesystem in your browser",

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

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