@zenfs/core
Advanced tools
Comparing version 0.3.5 to 0.4.0
import { FileSystem, FileSystemMetadata } from '../filesystem.js'; | ||
import { File, FileFlag, PreloadFile } from '../file.js'; | ||
import { Stats } from '../stats.js'; | ||
import type { Stats } from '../stats.js'; | ||
import { Cred } from '../cred.js'; | ||
@@ -8,4 +8,5 @@ import type { Backend } from './backend.js'; | ||
* We define our own file to interpose on syncSync() for mirroring purposes. | ||
* @internal | ||
*/ | ||
declare class MirrorFile extends PreloadFile<AsyncMirrorFS> { | ||
export declare class MirrorFile extends PreloadFile<AsyncMirrorFS> { | ||
constructor(fs: AsyncMirrorFS, path: string, flag: FileFlag, stat: Stats, data: Uint8Array); | ||
@@ -45,5 +46,2 @@ sync(): Promise<void>; | ||
renameSync(oldPath: string, newPath: string, cred: Cred): void; | ||
/** | ||
* Queue of pending asynchronous operations. | ||
*/ | ||
statSync(path: string, cred: Cred): Stats; | ||
@@ -50,0 +48,0 @@ openFileSync(path: string, flag: FileFlag, cred: Cred): File; |
@@ -8,4 +8,5 @@ import { FileSystem, Sync } from '../filesystem.js'; | ||
* We define our own file to interpose on syncSync() for mirroring purposes. | ||
* @internal | ||
*/ | ||
class MirrorFile extends PreloadFile { | ||
export class MirrorFile extends PreloadFile { | ||
constructor(fs, path, flag, stat, data) { | ||
@@ -157,4 +158,4 @@ super(fs, path, flag, stat, data); | ||
async crossCopyFile(p, mode) { | ||
const asyncFile = await this._async.openFile(p, FileFlag.FromString('r'), Cred.Root); | ||
const syncFile = this._sync.createFileSync(p, FileFlag.FromString('w'), mode, Cred.Root); | ||
const asyncFile = await this._async.openFile(p, FileFlag.Get('r'), Cred.Root); | ||
const syncFile = this._sync.createFileSync(p, FileFlag.Get('w'), mode, Cred.Root); | ||
try { | ||
@@ -235,5 +236,5 @@ const { size } = await asyncFile.stat(); | ||
description: 'The synchronous file system to mirror the asynchronous file system to.', | ||
validator: async (v) => { | ||
if (!v?.metadata().synchronous) { | ||
throw new ApiError(ErrorCode.EINVAL, `'sync' option must be a file system that supports synchronous operations`); | ||
validator: async (backend) => { | ||
if ('metadata' in backend && !backend.metadata().synchronous) { | ||
throw new ApiError(ErrorCode.EINVAL, '"sync" option must be a file system that supports synchronous operations'); | ||
} | ||
@@ -240,0 +241,0 @@ }, |
@@ -1,6 +0,6 @@ | ||
import { Cred } from '../cred.js'; | ||
import type { Cred } from '../cred.js'; | ||
import { PreloadFile, File, FileFlag } from '../file.js'; | ||
import { FileSystem, type FileSystemMetadata } from '../filesystem.js'; | ||
import { type Ino } from '../inode.js'; | ||
import { Stats } from '../stats.js'; | ||
import { type Stats } from '../stats.js'; | ||
/** | ||
@@ -65,2 +65,6 @@ * Represents an *asynchronous* key-value store. | ||
} | ||
/** | ||
* Async preload file for usage with AsyncStore | ||
* @internal | ||
*/ | ||
export declare class AsyncFile extends PreloadFile<AsyncStoreFS> { | ||
@@ -97,4 +101,5 @@ constructor(_fs: AsyncStoreFS, _path: string, _flag: FileFlag, _stat: Stats, contents?: Uint8Array); | ||
/** | ||
* An "Asynchronous key-value file system". Stores data to/retrieves data from | ||
* an underlying asynchronous key-value store. | ||
* An asynchronous file system which uses an async store to store its data. | ||
* @see AsyncStore | ||
* @internal | ||
*/ | ||
@@ -101,0 +106,0 @@ export declare class AsyncStoreFS extends AsyncStoreFS_base { |
@@ -47,2 +47,6 @@ import { dirname, basename, join, resolve } from '../emulation/path.js'; | ||
} | ||
/** | ||
* Async preload file for usage with AsyncStore | ||
* @internal | ||
*/ | ||
export class AsyncFile extends PreloadFile { | ||
@@ -70,4 +74,5 @@ constructor(_fs, _path, _flag, _stat, contents) { | ||
/** | ||
* An "Asynchronous key-value file system". Stores data to/retrieves data from | ||
* an underlying asynchronous key-value store. | ||
* An asynchronous file system which uses an async store to store its data. | ||
* @see AsyncStore | ||
* @internal | ||
*/ | ||
@@ -74,0 +79,0 @@ export class AsyncStoreFS extends Async(FileSystem) { |
@@ -19,3 +19,3 @@ import { ApiError, ErrorCode } from '../ApiError.js'; | ||
for (const [optName, opt] of Object.entries(backend.options)) { | ||
const providedValue = opts && opt; | ||
const providedValue = opts?.[optName]; | ||
if (providedValue === undefined || providedValue === null) { | ||
@@ -40,3 +40,3 @@ if (!opt.required) { | ||
if (!typeMatches) { | ||
throw new ApiError(ErrorCode.EINVAL, `${backend.name}: Value provided for option ${optName} is not the proper type. Expected ${Array.isArray(opt.type) ? `one of {${opt.type.join(', ')}}` : opt.type}, but received ${typeof providedValue}\nOption description: ${opt.description}`); | ||
throw new ApiError(ErrorCode.EINVAL, `${backend.name}: Value provided for option ${optName} is not the proper type. Expected ${Array.isArray(opt.type) ? `one of {${opt.type.join(', ')}}` : opt.type}, but received ${typeof providedValue}`); | ||
} | ||
@@ -65,9 +65,9 @@ if (opt.validator) { | ||
export async function resolveBackendConfig(options) { | ||
const { backend } = options; | ||
if (!backend) { | ||
throw new ApiError(ErrorCode.EPERM, 'Missing backend'); | ||
} | ||
if (typeof options !== 'object' || options == null) { | ||
throw new ApiError(ErrorCode.EINVAL, 'Invalid options on configuration object.'); | ||
} | ||
const { backend } = options; | ||
if (!isBackend(backend)) { | ||
throw new ApiError(ErrorCode.EINVAL, 'Missing or invalid backend'); | ||
} | ||
const props = Object.keys(options).filter(k => k != 'backend'); | ||
@@ -83,4 +83,4 @@ for (const prop of props) { | ||
} | ||
if (!backend) { | ||
throw new ApiError(ErrorCode.EPERM, `Backend "${backend}" is not available`); | ||
if (!backend.isAvailable()) { | ||
throw new ApiError(ErrorCode.EPERM, 'Backend not available: ' + backend); | ||
} | ||
@@ -87,0 +87,0 @@ checkOptions(backend, options); |
@@ -1,6 +0,5 @@ | ||
import { FileSystem, FileSystemMetadata } from '../filesystem.js'; | ||
import { FileFlag } from '../file.js'; | ||
import { Stats } from '../stats.js'; | ||
import { File } from '../file.js'; | ||
import { Cred } from '../cred.js'; | ||
import type { Cred } from '../cred.js'; | ||
import type { File, FileFlag } from '../file.js'; | ||
import type { FileSystem, FileSystemMetadata } from '../filesystem.js'; | ||
import type { Stats } from '../stats.js'; | ||
/** | ||
@@ -14,7 +13,8 @@ * This class serializes access to an underlying async filesystem. | ||
* multiple requests interleaving. | ||
* @internal | ||
*/ | ||
export declare class LockedFS<T extends FileSystem> implements FileSystem { | ||
readonly fs: T; | ||
export declare class LockedFS<FS extends FileSystem> implements FileSystem { | ||
readonly fs: FS; | ||
private _mu; | ||
constructor(fs: T); | ||
constructor(fs: FS); | ||
ready(): Promise<this>; | ||
@@ -21,0 +21,0 @@ metadata(): FileSystemMetadata; |
@@ -1,2 +0,2 @@ | ||
import Mutex from '../mutex.js'; | ||
import { Mutex } from '../mutex.js'; | ||
/** | ||
@@ -10,2 +10,3 @@ * This class serializes access to an underlying async filesystem. | ||
* multiple requests interleaving. | ||
* @internal | ||
*/ | ||
@@ -12,0 +13,0 @@ export class LockedFS { |
import { FileSystem, FileSystemMetadata } from '../filesystem.js'; | ||
import { File, FileFlag } from '../file.js'; | ||
import { File, FileFlag, PreloadFile } from '../file.js'; | ||
import { Stats } from '../stats.js'; | ||
@@ -8,2 +8,13 @@ import { LockedFS } from './Locked.js'; | ||
/** | ||
* Overlays a RO file to make it writable. | ||
* @internal | ||
*/ | ||
export declare class OverlayFile extends PreloadFile<UnlockedOverlayFS> implements File { | ||
constructor(fs: UnlockedOverlayFS, path: string, flag: FileFlag, stats: Stats, data: Uint8Array); | ||
sync(): Promise<void>; | ||
syncSync(): void; | ||
close(): Promise<void>; | ||
closeSync(): void; | ||
} | ||
/** | ||
* Configuration options for OverlayFS instances. | ||
@@ -99,2 +110,3 @@ */ | ||
* file system. | ||
* @internal | ||
*/ | ||
@@ -101,0 +113,0 @@ export declare class OverlayFS extends LockedFS<UnlockedOverlayFS> { |
@@ -15,4 +15,5 @@ import { FileSystem } from '../filesystem.js'; | ||
* Overlays a RO file to make it writable. | ||
* @internal | ||
*/ | ||
class OverlayFile extends PreloadFile { | ||
export class OverlayFile extends PreloadFile { | ||
constructor(fs, path, flag, stats, data) { | ||
@@ -107,3 +108,3 @@ super(fs, path, flag, stats, data); | ||
try { | ||
const file = await this._writable.openFile(deletionLogPath, FileFlag.FromString('r'), Cred.Root); | ||
const file = await this._writable.openFile(deletionLogPath, FileFlag.Get('r'), Cred.Root); | ||
const { size } = await file.stat(); | ||
@@ -164,5 +165,4 @@ const { buffer } = await file.read(new Uint8Array(size)); | ||
} | ||
const oldStat = Stats.clone(await this._readable.stat(p, cred)); | ||
// Make the oldStat's mode writable. Preserve the topmost part of the | ||
// mode, which specifies if it is a file or a directory. | ||
const oldStat = new Stats(await this._readable.stat(p, cred)); | ||
// Make the oldStat's mode writable. Preserve the topmost part of the mode, which specifies the type | ||
oldStat.mode |= 0o222; | ||
@@ -181,5 +181,4 @@ return oldStat; | ||
} | ||
const oldStat = Stats.clone(this._readable.statSync(p, cred)); | ||
// Make the oldStat's mode writable. Preserve the topmost part of the | ||
// mode, which specifies if it is a file or a directory. | ||
const oldStat = new Stats(this._readable.statSync(p, cred)); | ||
// Make the oldStat's mode writable. Preserve the topmost part of the mode, which specifies the type. | ||
oldStat.mode |= 0o222; | ||
@@ -194,4 +193,4 @@ return oldStat; | ||
// Create an OverlayFile. | ||
const file = await this._readable.openFile(path, FileFlag.FromString('r'), cred); | ||
const stats = Stats.clone(await file.stat()); | ||
const file = await this._readable.openFile(path, FileFlag.Get('r'), cred); | ||
const stats = new Stats(await file.stat()); | ||
const { buffer } = await file.read(new Uint8Array(stats.size)); | ||
@@ -205,3 +204,3 @@ return new OverlayFile(this, path, flag, stats, buffer); | ||
// Create an OverlayFile. | ||
const file = this._readable.openFileSync(path, FileFlag.FromString('r'), cred); | ||
const file = this._readable.openFileSync(path, FileFlag.Get('r'), cred); | ||
const stats = Stats.clone(file.statSync()); | ||
@@ -377,3 +376,3 @@ const data = new Uint8Array(stats.size); | ||
this._deleteLogUpdatePending = true; | ||
const log = await this._writable.openFile(deletionLogPath, FileFlag.FromString('w'), cred); | ||
const log = await this._writable.openFile(deletionLogPath, FileFlag.Get('w'), cred); | ||
try { | ||
@@ -480,6 +479,6 @@ await log.write(encode(this._deleteLog)); | ||
const data = new Uint8Array(stats.size); | ||
const readable = this._readable.openFileSync(p, FileFlag.FromString('r'), cred); | ||
const readable = this._readable.openFileSync(p, FileFlag.Get('r'), cred); | ||
readable.readSync(data); | ||
readable.closeSync(); | ||
const writable = this._writable.openFileSync(p, FileFlag.FromString('w'), cred); | ||
const writable = this._writable.openFileSync(p, FileFlag.Get('w'), cred); | ||
writable.writeSync(data); | ||
@@ -495,6 +494,6 @@ writable.closeSync(); | ||
const data = new Uint8Array(stats.size); | ||
const readable = await this._readable.openFile(p, FileFlag.FromString('r'), cred); | ||
const readable = await this._readable.openFile(p, FileFlag.Get('r'), cred); | ||
await readable.read(data); | ||
await readable.close(); | ||
const writable = await this._writable.openFile(p, FileFlag.FromString('w'), cred); | ||
const writable = await this._writable.openFile(p, FileFlag.Get('w'), cred); | ||
await writable.write(data); | ||
@@ -508,2 +507,3 @@ await writable.close(); | ||
* file system. | ||
* @internal | ||
*/ | ||
@@ -510,0 +510,0 @@ export class OverlayFS extends LockedFS { |
@@ -5,3 +5,3 @@ import { Cred } from '../cred.js'; | ||
import { type Ino, Inode } from '../inode.js'; | ||
import { Stats, FileType } from '../stats.js'; | ||
import { type Stats, FileType } from '../stats.js'; | ||
/** | ||
@@ -116,2 +116,6 @@ * Represents a *synchronous* key-value store. | ||
} | ||
/** | ||
* File backend by a SyncStoreFS | ||
* @internal | ||
*/ | ||
export declare class SyncStoreFile extends PreloadFile<SyncStoreFS> { | ||
@@ -151,9 +155,8 @@ constructor(_fs: SyncStoreFS, _path: string, _flag: FileFlag, _stat: Stats, contents?: Uint8Array); | ||
/** | ||
* A "Synchronous key-value file system". Stores data to/retrieves data from an | ||
* underlying key-value store. | ||
* A synchronous key-value file system. Uses a SyncStore to store the data. | ||
* | ||
* We use a unique ID for each node in the file system. The root node has a | ||
* fixed ID. | ||
* We use a unique ID for each node in the file system. The root node has a fixed ID. | ||
* @todo Introduce Node ID caching. | ||
* @todo Check modes. | ||
* @internal | ||
*/ | ||
@@ -160,0 +163,0 @@ export declare class SyncStoreFS extends SyncStoreFS_base { |
@@ -79,2 +79,6 @@ import { dirname, basename, join, resolve, sep } from '../emulation/path.js'; | ||
} | ||
/** | ||
* File backend by a SyncStoreFS | ||
* @internal | ||
*/ | ||
export class SyncStoreFile extends PreloadFile { | ||
@@ -101,9 +105,8 @@ constructor(_fs, _path, _flag, _stat, contents) { | ||
/** | ||
* A "Synchronous key-value file system". Stores data to/retrieves data from an | ||
* underlying key-value store. | ||
* A synchronous key-value file system. Uses a SyncStore to store the data. | ||
* | ||
* We use a unique ID for each node in the file system. The root node has a | ||
* fixed ID. | ||
* We use a unique ID for each node in the file system. The root node has a fixed ID. | ||
* @todo Introduce Node ID caching. | ||
* @todo Check modes. | ||
* @internal | ||
*/ | ||
@@ -352,3 +355,4 @@ export class SyncStoreFS extends Sync(FileSystem) { | ||
} | ||
return new Inode(data.buffer); | ||
const inode = new Inode(data.buffer); | ||
return inode; | ||
} | ||
@@ -355,0 +359,0 @@ /** |
/** | ||
* Credentials used for FS ops. | ||
* Credentials used for various operations. | ||
* Similar to Linux's cred struct. See https://github.com/torvalds/linux/blob/master/include/linux/cred.h | ||
@@ -4,0 +4,0 @@ */ |
/** | ||
* Credentials used for FS ops. | ||
* Credentials used for various operations. | ||
* Similar to Linux's cred struct. See https://github.com/torvalds/linux/blob/master/include/linux/cred.h | ||
@@ -4,0 +4,0 @@ */ |
@@ -5,3 +5,3 @@ /// <reference types="node" resolution-mode="require"/> | ||
import { TwoArgCallback, NoArgCallback, ThreeArgCallback, FileContents } from '../filesystem.js'; | ||
import { BigIntStats, Stats } from '../stats.js'; | ||
import { BigIntStats, type Stats } from '../stats.js'; | ||
import { PathLike } from './shared.js'; | ||
@@ -8,0 +8,0 @@ import { ReadStream, WriteStream } from './streams.js'; |
@@ -105,3 +105,3 @@ import { ApiError, ErrorCode } from '../ApiError.js'; | ||
.stat() | ||
.then(stats => cb(null, (typeof options == 'object' && options?.bigint ? BigIntStats.clone(stats) : stats))) | ||
.then(stats => cb(null, (typeof options == 'object' && options?.bigint ? new BigIntStats(stats) : stats))) | ||
.catch(cb); | ||
@@ -108,0 +108,0 @@ } |
@@ -1,8 +0,8 @@ | ||
/** Constant for fs.access(). File is visible to the calling process. */ | ||
/** File is visible to the calling process. */ | ||
export declare const F_OK = 0; | ||
/** Constant for fs.access(). File can be read by the calling process. */ | ||
/** File can be read by the calling process. */ | ||
export declare const R_OK = 4; | ||
/** Constant for fs.access(). File can be written by the calling process. */ | ||
/** File can be written by the calling process. */ | ||
export declare const W_OK = 2; | ||
/** Constant for fs.access(). File can be executed by the calling process. */ | ||
/** File can be executed by the calling process. */ | ||
export declare const X_OK = 1; | ||
@@ -21,14 +21,14 @@ /** Constant for fs.copyFile. Flag indicating the destination file should not be overwritten if it already exists. */ | ||
export declare const COPYFILE_FICLONE_FORCE = 4; | ||
/** Constant for fs.open(). Flag indicating to open a file for read-only access. */ | ||
/** Flag indicating to open a file for read-only access. */ | ||
export declare const O_RDONLY = 0; | ||
/** Constant for fs.open(). Flag indicating to open a file for write-only access. */ | ||
/** Flag indicating to open a file for write-only access. */ | ||
export declare const O_WRONLY = 1; | ||
/** Constant for fs.open(). Flag indicating to open a file for read-write access. */ | ||
/** Flag indicating to open a file for read-write access. */ | ||
export declare const O_RDWR = 2; | ||
/** Constant for fs.open(). Flag indicating to create the file if it does not already exist. */ | ||
/** Flag indicating to create the file if it does not already exist. */ | ||
export declare const O_CREAT = 64; | ||
/** Constant for fs.open(). Flag indicating that opening a file should fail if the O_CREAT flag is set and the file already exists. */ | ||
/** Flag indicating that opening a file should fail if the O_CREAT flag is set and the file already exists. */ | ||
export declare const O_EXCL = 128; | ||
/** | ||
* Constant for fs.open(). Flag indicating that if path identifies a terminal device, | ||
* Flag indicating that if path identifies a terminal device, | ||
* opening the path shall not cause that terminal to become the controlling terminal for the process | ||
@@ -38,7 +38,7 @@ * (if the process does not already have one). | ||
export declare const O_NOCTTY = 256; | ||
/** Constant for fs.open(). Flag indicating that if the file exists and is a regular file, and the file is opened successfully for write access, its length shall be truncated to zero. */ | ||
/** Flag indicating that if the file exists and is a regular file, and the file is opened successfully for write access, its length shall be truncated to zero. */ | ||
export declare const O_TRUNC = 512; | ||
/** Constant for fs.open(). Flag indicating that data will be appended to the end of the file. */ | ||
/** Flag indicating that data will be appended to the end of the file. */ | ||
export declare const O_APPEND = 1024; | ||
/** Constant for fs.open(). Flag indicating that the open should fail if the path is not a directory. */ | ||
/** Flag indicating that the open should fail if the path is not a directory. */ | ||
export declare const O_DIRECTORY = 65536; | ||
@@ -52,53 +52,59 @@ /** | ||
export declare const O_NOATIME = 262144; | ||
/** Constant for fs.open(). Flag indicating that the open should fail if the path is a symbolic link. */ | ||
/** Flag indicating that the open should fail if the path is a symbolic link. */ | ||
export declare const O_NOFOLLOW = 131072; | ||
/** Constant for fs.open(). Flag indicating that the file is opened for synchronous I/O. */ | ||
/** Flag indicating that the file is opened for synchronous I/O. */ | ||
export declare const O_SYNC = 1052672; | ||
/** Constant for fs.open(). Flag indicating that the file is opened for synchronous I/O with write operations waiting for data integrity. */ | ||
/** Flag indicating that the file is opened for synchronous I/O with write operations waiting for data integrity. */ | ||
export declare const O_DSYNC = 4096; | ||
/** Constant for fs.open(). Flag indicating to open the symbolic link itself rather than the resource it is pointing to. */ | ||
/** Flag indicating to open the symbolic link itself rather than the resource it is pointing to. */ | ||
export declare const O_SYMLINK = 32768; | ||
/** Constant for fs.open(). When set, an attempt will be made to minimize caching effects of file I/O. */ | ||
/** When set, an attempt will be made to minimize caching effects of file I/O. */ | ||
export declare const O_DIRECT = 16384; | ||
/** Constant for fs.open(). Flag indicating to open the file in nonblocking mode when possible. */ | ||
/** Flag indicating to open the file in nonblocking mode when possible. */ | ||
export declare const O_NONBLOCK = 2048; | ||
/** Constant for fs.Stats mode property for determining a file's type. Bit mask used to extract the file type code. */ | ||
/** Bit mask used to extract the file type from mode. */ | ||
export declare const S_IFMT = 61440; | ||
/** Constant for fs.Stats mode property for determining a file's type. File type constant for a regular file. */ | ||
/** File type constant for a socket. */ | ||
export declare const S_IFSOCK = 49152; | ||
/** File type constant for a symbolic link. */ | ||
export declare const S_IFLNK = 40960; | ||
/** File type constant for a regular file. */ | ||
export declare const S_IFREG = 32768; | ||
/** Constant for fs.Stats mode property for determining a file's type. File type constant for a directory. */ | ||
/** File type constant for a block-oriented device file. */ | ||
export declare const S_IFBLK = 24576; | ||
/** File type constant for a directory. */ | ||
export declare const S_IFDIR = 16384; | ||
/** Constant for fs.Stats mode property for determining a file's type. File type constant for a character-oriented device file. */ | ||
/** File type constant for a character-oriented device file. */ | ||
export declare const S_IFCHR = 8192; | ||
/** Constant for fs.Stats mode property for determining a file's type. File type constant for a block-oriented device file. */ | ||
export declare const S_IFBLK = 24576; | ||
/** Constant for fs.Stats mode property for determining a file's type. File type constant for a FIFO/pipe. */ | ||
/** File type constant for a FIFO/pipe. */ | ||
export declare const S_IFIFO = 4096; | ||
/** Constant for fs.Stats mode property for determining a file's type. File type constant for a symbolic link. */ | ||
export declare const S_IFLNK = 40960; | ||
/** Constant for fs.Stats mode property for determining a file's type. File type constant for a socket. */ | ||
export declare const S_IFSOCK = 49152; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable, writable and executable by owner. */ | ||
/** Set user id */ | ||
export declare const S_ISUID = 2048; | ||
/** Set group id */ | ||
export declare const S_ISGID = 1024; | ||
/** Sticky bit */ | ||
export declare const S_ISVTX = 512; | ||
/** File mode indicating readable, writable and executable by owner. */ | ||
export declare const S_IRWXU = 448; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable by owner. */ | ||
/** File mode indicating readable by owner. */ | ||
export declare const S_IRUSR = 256; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating writable by owner. */ | ||
/** File mode indicating writable by owner. */ | ||
export declare const S_IWUSR = 128; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating executable by owner. */ | ||
/** File mode indicating executable by owner. */ | ||
export declare const S_IXUSR = 64; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable, writable and executable by group. */ | ||
/** File mode indicating readable, writable and executable by group. */ | ||
export declare const S_IRWXG = 56; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable by group. */ | ||
/** File mode indicating readable by group. */ | ||
export declare const S_IRGRP = 32; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating writable by group. */ | ||
/** File mode indicating writable by group. */ | ||
export declare const S_IWGRP = 16; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating executable by group. */ | ||
/** File mode indicating executable by group. */ | ||
export declare const S_IXGRP = 8; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable, writable and executable by others. */ | ||
/** File mode indicating readable, writable and executable by others. */ | ||
export declare const S_IRWXO = 7; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable by others. */ | ||
/** File mode indicating readable by others. */ | ||
export declare const S_IROTH = 4; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating writable by others. */ | ||
/** File mode indicating writable by others. */ | ||
export declare const S_IWOTH = 2; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating executable by others. */ | ||
/** File mode indicating executable by others. */ | ||
export declare const S_IXOTH = 1; |
/* | ||
FS Constants | ||
See https://nodejs.org/api/fs.html#file-access-constants | ||
Note: Many of these are pulled from | ||
https://github.com/torvalds/linux/blob/master/include/uapi/linux/stat.h | ||
*/ | ||
// File Access Constants | ||
/** Constant for fs.access(). File is visible to the calling process. */ | ||
/** File is visible to the calling process. */ | ||
export const F_OK = 0; | ||
/** Constant for fs.access(). File can be read by the calling process. */ | ||
/** File can be read by the calling process. */ | ||
export const R_OK = 4; | ||
/** Constant for fs.access(). File can be written by the calling process. */ | ||
/** File can be written by the calling process. */ | ||
export const W_OK = 2; | ||
/** Constant for fs.access(). File can be executed by the calling process. */ | ||
/** File can be executed by the calling process. */ | ||
export const X_OK = 1; | ||
@@ -28,24 +31,24 @@ // File Copy Constants | ||
// File Open Constants | ||
/** Constant for fs.open(). Flag indicating to open a file for read-only access. */ | ||
/** Flag indicating to open a file for read-only access. */ | ||
export const O_RDONLY = 0; | ||
/** Constant for fs.open(). Flag indicating to open a file for write-only access. */ | ||
/** Flag indicating to open a file for write-only access. */ | ||
export const O_WRONLY = 1; | ||
/** Constant for fs.open(). Flag indicating to open a file for read-write access. */ | ||
/** Flag indicating to open a file for read-write access. */ | ||
export const O_RDWR = 2; | ||
/** Constant for fs.open(). Flag indicating to create the file if it does not already exist. */ | ||
export const O_CREAT = 0o100; // Node internal is | ||
/** Constant for fs.open(). Flag indicating that opening a file should fail if the O_CREAT flag is set and the file already exists. */ | ||
export const O_EXCL = 0o200; | ||
/** Flag indicating to create the file if it does not already exist. */ | ||
export const O_CREAT = 0x40; // bit 6 | ||
/** Flag indicating that opening a file should fail if the O_CREAT flag is set and the file already exists. */ | ||
export const O_EXCL = 0x80; // bit 7 | ||
/** | ||
* Constant for fs.open(). Flag indicating that if path identifies a terminal device, | ||
* Flag indicating that if path identifies a terminal device, | ||
* opening the path shall not cause that terminal to become the controlling terminal for the process | ||
* (if the process does not already have one). | ||
*/ | ||
export const O_NOCTTY = 0o400; | ||
/** Constant for fs.open(). Flag indicating that if the file exists and is a regular file, and the file is opened successfully for write access, its length shall be truncated to zero. */ | ||
export const O_TRUNC = 0o1000; | ||
/** Constant for fs.open(). Flag indicating that data will be appended to the end of the file. */ | ||
export const O_APPEND = 0o2000; | ||
/** Constant for fs.open(). Flag indicating that the open should fail if the path is not a directory. */ | ||
export const O_DIRECTORY = 0o200000; | ||
export const O_NOCTTY = 0x100; // bit 8 | ||
/** Flag indicating that if the file exists and is a regular file, and the file is opened successfully for write access, its length shall be truncated to zero. */ | ||
export const O_TRUNC = 0x200; // bit 9 | ||
/** Flag indicating that data will be appended to the end of the file. */ | ||
export const O_APPEND = 0x400; // bit 10 | ||
/** Flag indicating that the open should fail if the path is not a directory. */ | ||
export const O_DIRECTORY = 0x10000; // bit 16 | ||
/** | ||
@@ -57,56 +60,62 @@ * constant for fs.open(). | ||
*/ | ||
export const O_NOATIME = 0o1000000; | ||
/** Constant for fs.open(). Flag indicating that the open should fail if the path is a symbolic link. */ | ||
export const O_NOFOLLOW = 0o400000; | ||
/** Constant for fs.open(). Flag indicating that the file is opened for synchronous I/O. */ | ||
export const O_SYNC = 0o4010000; | ||
/** Constant for fs.open(). Flag indicating that the file is opened for synchronous I/O with write operations waiting for data integrity. */ | ||
export const O_DSYNC = 0o10000; | ||
/** Constant for fs.open(). Flag indicating to open the symbolic link itself rather than the resource it is pointing to. */ | ||
export const O_SYMLINK = 0o100000; | ||
/** Constant for fs.open(). When set, an attempt will be made to minimize caching effects of file I/O. */ | ||
export const O_DIRECT = 0o40000; | ||
/** Constant for fs.open(). Flag indicating to open the file in nonblocking mode when possible. */ | ||
export const O_NONBLOCK = 0o4000; | ||
export const O_NOATIME = 0x40000; // bit 18 | ||
/** Flag indicating that the open should fail if the path is a symbolic link. */ | ||
export const O_NOFOLLOW = 0x20000; // bit 17 | ||
/** Flag indicating that the file is opened for synchronous I/O. */ | ||
export const O_SYNC = 0x101000; // bit 20 and bit 12 | ||
/** Flag indicating that the file is opened for synchronous I/O with write operations waiting for data integrity. */ | ||
export const O_DSYNC = 0x1000; // bit 12 | ||
/** Flag indicating to open the symbolic link itself rather than the resource it is pointing to. */ | ||
export const O_SYMLINK = 0x8000; // bit 15 | ||
/** When set, an attempt will be made to minimize caching effects of file I/O. */ | ||
export const O_DIRECT = 0x4000; // bit 14 | ||
/** Flag indicating to open the file in nonblocking mode when possible. */ | ||
export const O_NONBLOCK = 0x800; // bit 11 | ||
// File Type Constants | ||
/** Constant for fs.Stats mode property for determining a file's type. Bit mask used to extract the file type code. */ | ||
/** Bit mask used to extract the file type from mode. */ | ||
export const S_IFMT = 0xf000; | ||
/** Constant for fs.Stats mode property for determining a file's type. File type constant for a regular file. */ | ||
export const S_IFREG = 0o100000; | ||
/** Constant for fs.Stats mode property for determining a file's type. File type constant for a directory. */ | ||
export const S_IFDIR = 0o40000; | ||
/** Constant for fs.Stats mode property for determining a file's type. File type constant for a character-oriented device file. */ | ||
export const S_IFCHR = 0o20000; | ||
/** Constant for fs.Stats mode property for determining a file's type. File type constant for a block-oriented device file. */ | ||
export const S_IFBLK = 0o60000; | ||
/** Constant for fs.Stats mode property for determining a file's type. File type constant for a FIFO/pipe. */ | ||
export const S_IFIFO = 0o10000; | ||
/** Constant for fs.Stats mode property for determining a file's type. File type constant for a symbolic link. */ | ||
export const S_IFLNK = 0o120000; | ||
/** Constant for fs.Stats mode property for determining a file's type. File type constant for a socket. */ | ||
export const S_IFSOCK = 0o140000; | ||
/** File type constant for a socket. */ | ||
export const S_IFSOCK = 0xc000; | ||
/** File type constant for a symbolic link. */ | ||
export const S_IFLNK = 0xa000; | ||
/** File type constant for a regular file. */ | ||
export const S_IFREG = 0x8000; | ||
/** File type constant for a block-oriented device file. */ | ||
export const S_IFBLK = 0x6000; | ||
/** File type constant for a directory. */ | ||
export const S_IFDIR = 0x4000; | ||
/** File type constant for a character-oriented device file. */ | ||
export const S_IFCHR = 0x2000; | ||
/** File type constant for a FIFO/pipe. */ | ||
export const S_IFIFO = 0x1000; | ||
/** Set user id */ | ||
export const S_ISUID = 0o4000; | ||
/** Set group id */ | ||
export const S_ISGID = 0o2000; | ||
/** Sticky bit */ | ||
export const S_ISVTX = 0o1000; | ||
// File Mode Constants | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable, writable and executable by owner. */ | ||
/** File mode indicating readable, writable and executable by owner. */ | ||
export const S_IRWXU = 0o700; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable by owner. */ | ||
/** File mode indicating readable by owner. */ | ||
export const S_IRUSR = 0o400; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating writable by owner. */ | ||
/** File mode indicating writable by owner. */ | ||
export const S_IWUSR = 0o200; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating executable by owner. */ | ||
/** File mode indicating executable by owner. */ | ||
export const S_IXUSR = 0o100; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable, writable and executable by group. */ | ||
/** File mode indicating readable, writable and executable by group. */ | ||
export const S_IRWXG = 0o70; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable by group. */ | ||
/** File mode indicating readable by group. */ | ||
export const S_IRGRP = 0o40; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating writable by group. */ | ||
/** File mode indicating writable by group. */ | ||
export const S_IWGRP = 0o20; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating executable by group. */ | ||
/** File mode indicating executable by group. */ | ||
export const S_IXGRP = 0o10; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable, writable and executable by others. */ | ||
/** File mode indicating readable, writable and executable by others. */ | ||
export const S_IRWXO = 7; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable by others. */ | ||
/** File mode indicating readable by others. */ | ||
export const S_IROTH = 4; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating writable by others. */ | ||
/** File mode indicating writable by others. */ | ||
export const S_IWOTH = 2; | ||
/** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating executable by others. */ | ||
/** File mode indicating executable by others. */ | ||
export const S_IXOTH = 1; |
/// <reference types="node" resolution-mode="require"/> | ||
import type { Dirent as _Dirent, Dir as _Dir } from 'fs'; | ||
import { NoArgCallback, TwoArgCallback } from '../filesystem.js'; | ||
import { Stats } from '../stats.js'; | ||
import type { NoArgCallback, TwoArgCallback } from '../filesystem.js'; | ||
import type { Stats } from '../stats.js'; | ||
export declare class Dirent implements _Dirent { | ||
@@ -6,0 +6,0 @@ name: string; |
@@ -8,3 +8,3 @@ /// <reference types="node" resolution-mode="require"/> | ||
import { FileContents } from '../filesystem.js'; | ||
import { BigIntStats, Stats } from '../stats.js'; | ||
import { BigIntStats, type Stats } from '../stats.js'; | ||
import { Dirent } from './dir.js'; | ||
@@ -11,0 +11,0 @@ export declare class FileHandle implements BufferToUint8Array<Node.promises.FileHandle> { |
@@ -214,3 +214,3 @@ import { ApiError, ErrorCode } from '../ApiError.js'; | ||
const stats = await doOp('stat', true, path, cred); | ||
return options?.bigint ? BigIntStats.clone(stats) : stats; | ||
return options?.bigint ? new BigIntStats(stats) : stats; | ||
} | ||
@@ -220,3 +220,3 @@ stat; | ||
const stats = await doOp('stat', false, path, cred); | ||
return options?.bigint ? BigIntStats.clone(stats) : stats; | ||
return options?.bigint ? new BigIntStats(stats) : stats; | ||
} | ||
@@ -253,3 +253,3 @@ lstat; | ||
async function _open(_path, _flag, _mode = 0o644, resolveSymlinks) { | ||
const path = normalizePath(_path), mode = normalizeMode(_mode, 0o644), flag = FileFlag.FromString(_flag); | ||
const path = normalizePath(_path), mode = normalizeMode(_mode, 0o644), flag = FileFlag.Get(_flag); | ||
try { | ||
@@ -333,3 +333,3 @@ switch (flag.pathExistsAction()) { | ||
const options = normalizeOptions(_options, null, 'r', null); | ||
const flag = FileFlag.FromString(options.flag); | ||
const flag = FileFlag.Get(options.flag); | ||
if (!flag.isReadable()) { | ||
@@ -370,3 +370,3 @@ throw new ApiError(ErrorCode.EINVAL, 'Flag passed must allow for reading.'); | ||
const options = normalizeOptions(_options, 'utf8', 'w', 0o644); | ||
const flag = FileFlag.FromString(options.flag); | ||
const flag = FileFlag.Get(options.flag); | ||
if (!flag.isWriteable()) { | ||
@@ -407,3 +407,3 @@ throw new ApiError(ErrorCode.EINVAL, 'Flag passed must allow for writing.'); | ||
const options = normalizeOptions(_options, 'utf8', 'a', 0o644); | ||
const flag = FileFlag.FromString(options.flag); | ||
const flag = FileFlag.Get(options.flag); | ||
if (!flag.isAppendable()) { | ||
@@ -410,0 +410,0 @@ throw new ApiError(ErrorCode.EINVAL, 'Flag passed to appendFile must allow for appending.'); |
/// <reference types="node" resolution-mode="require"/> | ||
/// <reference types="node" resolution-mode="require"/> | ||
import { FileContents } from '../filesystem.js'; | ||
import { BigIntStats, Stats } from '../stats.js'; | ||
import { BigIntStats, type Stats } from '../stats.js'; | ||
import type { symlink, ReadSyncOptions, BaseEncodingOptions, BufferEncodingOption } from 'fs'; | ||
@@ -6,0 +6,0 @@ import type * as Node from 'fs'; |
@@ -63,3 +63,3 @@ import { ApiError, ErrorCode } from '../ApiError.js'; | ||
const stats = doOp('statSync', true, path, cred); | ||
return options?.bigint ? BigIntStats.clone(stats) : stats; | ||
return options?.bigint ? new BigIntStats(stats) : stats; | ||
} | ||
@@ -69,3 +69,3 @@ statSync; | ||
const stats = doOp('statSync', false, path, cred); | ||
return options?.bigint ? BigIntStats.clone(stats) : stats; | ||
return options?.bigint ? new BigIntStats(stats) : stats; | ||
} | ||
@@ -97,3 +97,3 @@ lstatSync; | ||
function _openSync(_path, _flag, _mode, resolveSymlinks) { | ||
const path = normalizePath(_path), mode = normalizeMode(_mode, 0o644), flag = FileFlag.FromString(_flag); | ||
const path = normalizePath(_path), mode = normalizeMode(_mode, 0o644), flag = FileFlag.Get(_flag); | ||
// Check if the path exists, and is a file. | ||
@@ -182,3 +182,3 @@ let stats; | ||
const options = normalizeOptions(arg2, null, 'r', 0o644); | ||
const flag = FileFlag.FromString(options.flag); | ||
const flag = FileFlag.Get(options.flag); | ||
if (!flag.isReadable()) { | ||
@@ -208,3 +208,3 @@ throw new ApiError(ErrorCode.EINVAL, 'Flag passed to readFile must allow for reading.'); | ||
const options = normalizeOptions(_options, 'utf8', 'w', 0o644); | ||
const flag = FileFlag.FromString(options.flag); | ||
const flag = FileFlag.Get(options.flag); | ||
if (!flag.isWriteable()) { | ||
@@ -238,3 +238,3 @@ throw new ApiError(ErrorCode.EINVAL, 'Flag passed to writeFile must allow for writing.'); | ||
const options = normalizeOptions(arg3, 'utf8', 'a', 0o644); | ||
const flag = FileFlag.FromString(options.flag); | ||
const flag = FileFlag.Get(options.flag); | ||
if (!flag.isAppendable()) { | ||
@@ -252,3 +252,3 @@ throw new ApiError(ErrorCode.EINVAL, 'Flag passed to appendFile must allow for appending.'); | ||
const stats = fd2file(fd).statSync(); | ||
return options?.bigint ? BigIntStats.clone(stats) : stats; | ||
return options?.bigint ? new BigIntStats(stats) : stats; | ||
} | ||
@@ -255,0 +255,0 @@ fstatSync; |
@@ -20,2 +20,5 @@ import type { FileSystem } from './filesystem.js'; | ||
} | ||
/** | ||
* @hidden | ||
*/ | ||
export declare enum ActionType { | ||
@@ -46,5 +49,11 @@ NOP = 0, | ||
export declare class FileFlag { | ||
private static flagCache; | ||
private static validFlagStrs; | ||
/** | ||
* Contains cached FileMode instances. | ||
*/ | ||
protected static cache: Map<string | number, FileFlag>; | ||
/** | ||
* Array of valid mode strings. | ||
*/ | ||
protected static validStrings: string[]; | ||
/** | ||
* Get an object representing the given file flag. | ||
@@ -55,17 +64,22 @@ * @param flag The string or number representing the flag | ||
*/ | ||
static FromString(flag: string | number): FileFlag; | ||
private flagStr; | ||
static Get(flag: string | number): FileFlag; | ||
protected _flag: string; | ||
/** | ||
* This should never be called directly. | ||
* @param flag The string or number representing the flag | ||
* @throw when the flag is invalid | ||
*/ | ||
constructor(flag: string | number); | ||
protected constructor(flag: string | number); | ||
/** | ||
* @param flag The number representing the flag | ||
* @return The string representing the flag | ||
* @throw when the flag number is invalid | ||
* @returns The string representing the flag | ||
* @throws when the flag number is invalid | ||
*/ | ||
static NumberToString(flag: number): string; | ||
static StringOf(flag: number): string; | ||
/** | ||
* @param flag The string representing the flag | ||
* @returns The number representing the flag | ||
* @throws when the flag string is invalid | ||
*/ | ||
static NumberOf(flag: string): number; | ||
/** | ||
* Get the underlying flag string for this flag. | ||
@@ -264,7 +278,7 @@ */ | ||
*/ | ||
export declare abstract class PreloadFile<T extends FileSystem> extends File { | ||
export declare abstract class PreloadFile<FS extends FileSystem> extends File { | ||
/** | ||
* The file system that created the file. | ||
*/ | ||
protected fs: T; | ||
protected fs: FS; | ||
/** | ||
@@ -295,3 +309,3 @@ * Path to the file | ||
*/ | ||
fs: T, | ||
fs: FS, | ||
/** | ||
@@ -298,0 +312,0 @@ * Path to the file |
@@ -5,2 +5,5 @@ import { ApiError, ErrorCode } from './ApiError.js'; | ||
import { Stats } from './stats.js'; | ||
/** | ||
* @hidden | ||
*/ | ||
export var ActionType; | ||
@@ -42,11 +45,10 @@ (function (ActionType) { | ||
*/ | ||
static FromString(flag) { | ||
static Get(flag) { | ||
// Check cache first. | ||
if (!FileFlag.flagCache.has(flag)) { | ||
FileFlag.flagCache.set(flag, new FileFlag(flag)); | ||
if (!FileFlag.cache.has(flag)) { | ||
FileFlag.cache.set(flag, new FileFlag(flag)); | ||
} | ||
return FileFlag.flagCache.get(flag); | ||
return FileFlag.cache.get(flag); | ||
} | ||
/** | ||
* This should never be called directly. | ||
* @param flag The string or number representing the flag | ||
@@ -56,16 +58,16 @@ * @throw when the flag is invalid | ||
constructor(flag) { | ||
if (typeof flag === 'number') { | ||
flag = FileFlag.NumberToString(flag); | ||
if (typeof flag == 'number') { | ||
flag = FileFlag.StringOf(flag); | ||
} | ||
if (FileFlag.validFlagStrs.indexOf(flag) < 0) { | ||
if (!FileFlag.validStrings.includes(flag)) { | ||
throw new ApiError(ErrorCode.EINVAL, 'Invalid flag string: ' + flag); | ||
} | ||
this.flagStr = flag; | ||
this._flag = flag; | ||
} | ||
/** | ||
* @param flag The number representing the flag | ||
* @return The string representing the flag | ||
* @throw when the flag number is invalid | ||
* @returns The string representing the flag | ||
* @throws when the flag number is invalid | ||
*/ | ||
static NumberToString(flag) { | ||
static StringOf(flag) { | ||
// based on https://github.com/nodejs/node/blob/abbdc3efaa455e6c907ebef5409ac8b0f222f969/lib/internal/fs/utils.js#L619 | ||
@@ -102,6 +104,41 @@ switch (flag) { | ||
/** | ||
* @param flag The string representing the flag | ||
* @returns The number representing the flag | ||
* @throws when the flag string is invalid | ||
*/ | ||
static NumberOf(flag) { | ||
switch (flag) { | ||
case 'r': | ||
return O_RDONLY; | ||
case 'rs': | ||
return O_RDONLY | O_SYNC; | ||
case 'r+': | ||
return O_RDWR; | ||
case 'rs+': | ||
return O_RDWR | O_SYNC; | ||
case 'w': | ||
return O_TRUNC | O_CREAT | O_WRONLY; | ||
case 'wx': | ||
return O_TRUNC | O_CREAT | O_WRONLY | O_EXCL; | ||
case 'w+': | ||
return O_TRUNC | O_CREAT | O_RDWR; | ||
case 'wx+': | ||
return O_TRUNC | O_CREAT | O_RDWR | O_EXCL; | ||
case 'a': | ||
return O_APPEND | O_CREAT | O_WRONLY; | ||
case 'ax': | ||
return O_APPEND | O_CREAT | O_WRONLY | O_EXCL; | ||
case 'a+': | ||
return O_APPEND | O_CREAT | O_RDWR; | ||
case 'ax+': | ||
return O_APPEND | O_CREAT | O_RDWR | O_EXCL; | ||
default: | ||
throw new ApiError(ErrorCode.EINVAL, 'Invalid flag string: ' + flag); | ||
} | ||
} | ||
/** | ||
* Get the underlying flag string for this flag. | ||
*/ | ||
toString() { | ||
return this.flagStr; | ||
return this._flag; | ||
} | ||
@@ -125,3 +162,3 @@ /** | ||
isReadable() { | ||
return this.flagStr.indexOf('r') !== -1 || this.flagStr.indexOf('+') !== -1; | ||
return this._flag.indexOf('r') != -1 || this._flag.indexOf('+') != -1; | ||
} | ||
@@ -132,3 +169,3 @@ /** | ||
isWriteable() { | ||
return this.flagStr.indexOf('w') !== -1 || this.flagStr.indexOf('a') !== -1 || this.flagStr.indexOf('+') !== -1; | ||
return this._flag.indexOf('w') != -1 || this._flag.indexOf('a') != -1 || this._flag.indexOf('+') != -1; | ||
} | ||
@@ -139,3 +176,3 @@ /** | ||
isTruncating() { | ||
return this.flagStr.indexOf('w') !== -1; | ||
return this._flag.indexOf('w') !== -1; | ||
} | ||
@@ -146,3 +183,3 @@ /** | ||
isAppendable() { | ||
return this.flagStr.indexOf('a') !== -1; | ||
return this._flag.indexOf('a') !== -1; | ||
} | ||
@@ -153,3 +190,3 @@ /** | ||
isSynchronous() { | ||
return this.flagStr.indexOf('s') !== -1; | ||
return this._flag.indexOf('s') !== -1; | ||
} | ||
@@ -160,3 +197,3 @@ /** | ||
isExclusive() { | ||
return this.flagStr.indexOf('x') !== -1; | ||
return this._flag.indexOf('x') !== -1; | ||
} | ||
@@ -181,14 +218,16 @@ /** | ||
pathNotExistsAction() { | ||
if ((this.isWriteable() || this.isAppendable()) && this.flagStr !== 'r+') { | ||
if ((this.isWriteable() || this.isAppendable()) && this._flag != 'r+') { | ||
return ActionType.CREATE; | ||
} | ||
else { | ||
return ActionType.THROW; | ||
} | ||
return ActionType.THROW; | ||
} | ||
} | ||
// Contains cached FileMode instances. | ||
FileFlag.flagCache = new Map(); | ||
// Array of valid mode strings. | ||
FileFlag.validFlagStrs = ['r', 'r+', 'rs', 'rs+', 'w', 'wx', 'w+', 'wx+', 'a', 'ax', 'a+', 'ax+']; | ||
/** | ||
* Contains cached FileMode instances. | ||
*/ | ||
FileFlag.cache = new Map(); | ||
/** | ||
* Array of valid mode strings. | ||
*/ | ||
FileFlag.validStrings = ['r', 'r+', 'rs', 'rs+', 'w', 'wx', 'w+', 'wx+', 'a', 'ax', 'a+', 'ax+']; | ||
export class File { | ||
@@ -296,3 +335,3 @@ /** | ||
async stat() { | ||
return Stats.clone(this.stats); | ||
return new Stats(this.stats); | ||
} | ||
@@ -303,3 +342,3 @@ /** | ||
statSync() { | ||
return Stats.clone(this.stats); | ||
return new Stats(this.stats); | ||
} | ||
@@ -306,0 +345,0 @@ /** |
@@ -219,2 +219,6 @@ import type { Cred } from './cred.js'; | ||
declare const AsyncFileIndexFS_base: (abstract new (...args: any[]) => { | ||
/** | ||
* Returns the inode for the indicated item, or null if it does not exist. | ||
* @param path Name of item in this directory. | ||
*/ | ||
metadata(): import("./filesystem.js").FileSystemMetadata; | ||
@@ -221,0 +225,0 @@ renameSync(oldPath: string, newPath: string, cred: Cred): void; |
@@ -43,3 +43,3 @@ import { ApiError, ErrorCode } from './ApiError.js'; | ||
// This inode doesn't have correct size information, noted with -1. | ||
inode = new IndexFileInode(new Stats(FileType.FILE, -1, 0o555)); | ||
inode = new IndexFileInode(new Stats({ mode: FileType.FILE | 0o555 })); | ||
} | ||
@@ -223,3 +223,3 @@ if (!parent) { | ||
toStats() { | ||
return new Stats(FileType.FILE, 4096, 0o666); | ||
return new Stats({ mode: FileType.FILE | 0o666, size: 4096 }); | ||
} | ||
@@ -249,3 +249,3 @@ } | ||
get stats() { | ||
return new Stats(FileType.DIRECTORY, 4096, 0o555); | ||
return new Stats({ mode: FileType.DIRECTORY | 0o555, size: 4096 }); | ||
} | ||
@@ -252,0 +252,0 @@ /** |
import { ApiError } from './ApiError.js'; | ||
import { Stats } from './stats.js'; | ||
import { File, FileFlag } from './file.js'; | ||
import { Cred } from './cred.js'; | ||
import type { Stats } from './stats.js'; | ||
import type { File, FileFlag } from './file.js'; | ||
import type { Cred } from './cred.js'; | ||
export type NoArgCallback = (e?: ApiError) => unknown; | ||
@@ -6,0 +6,0 @@ export type TwoArgCallback<T> = (e?: ApiError, rv?: T) => unknown; |
@@ -6,3 +6,2 @@ /** | ||
import { FileSystem } from './filesystem.js'; | ||
import { backends } from './backends/index.js'; | ||
import { type Backend, type BackendConfig } from './backends/backend.js'; | ||
@@ -19,3 +18,3 @@ /** | ||
export interface ConfigMapping { | ||
[mountPoint: string]: FileSystem | BackendConfig | keyof typeof backends | Backend; | ||
[mountPoint: string]: FileSystem | BackendConfig | Backend; | ||
} | ||
@@ -31,4 +30,8 @@ /** | ||
export declare function configure(config: Configuration): Promise<void>; | ||
export * from './backends/index.js'; | ||
export type { Backend, BackendConfig } from './backends/backend.js'; | ||
export * from './backends/AsyncMirror.js'; | ||
export * from './backends/AsyncStore.js'; | ||
export * from './backends/InMemory.js'; | ||
export * from './backends/Locked.js'; | ||
export * from './backends/Overlay.js'; | ||
export * from './backends/SyncStore.js'; | ||
@@ -35,0 +38,0 @@ export * from './ApiError.js'; |
@@ -6,3 +6,2 @@ /** | ||
import { FileSystem } from './filesystem.js'; | ||
import { backends } from './backends/index.js'; | ||
import { Cred } from './cred.js'; | ||
@@ -35,5 +34,2 @@ import { isBackend, resolveBackendConfig } from './backends/backend.js'; | ||
} | ||
if (typeof value == 'string') { | ||
value = { backend: backends[value] }; | ||
} | ||
if (isBackend(value)) { | ||
@@ -46,4 +42,7 @@ value = { backend: value }; | ||
} | ||
export * from './backends/index.js'; | ||
export * from './backends/AsyncMirror.js'; | ||
export * from './backends/AsyncStore.js'; | ||
export * from './backends/InMemory.js'; | ||
export * from './backends/Locked.js'; | ||
export * from './backends/Overlay.js'; | ||
export * from './backends/SyncStore.js'; | ||
@@ -50,0 +49,0 @@ export * from './ApiError.js'; |
@@ -1,11 +0,19 @@ | ||
import { Stats } from './stats.js'; | ||
import { Stats, type StatsLike } from './stats.js'; | ||
/** | ||
* Alias for an ino. | ||
* This will be helpful if in the future inode numbers/IDs are changed to strings or numbers. | ||
*/ | ||
export type Ino = bigint; | ||
/** | ||
* Max 32-bit integer | ||
* @hidden | ||
*/ | ||
export declare const size_max: number; | ||
/** | ||
* @internal | ||
* Room inode | ||
* @hidden | ||
*/ | ||
export declare const rootIno: Ino; | ||
/** | ||
* Generate 4 random bits at a time | ||
* | ||
* Generate a random ino | ||
* @internal | ||
@@ -17,3 +25,3 @@ */ | ||
*/ | ||
export declare class Inode { | ||
export declare class Inode implements StatsLike { | ||
readonly buffer: ArrayBufferLike; | ||
@@ -35,8 +43,10 @@ get data(): Uint8Array; | ||
set gid(value: number); | ||
get atime(): number; | ||
set atime(value: number); | ||
get mtime(): number; | ||
set mtime(value: number); | ||
get ctime(): number; | ||
set ctime(value: number); | ||
get atimeMs(): number; | ||
set atimeMs(value: number); | ||
get birthtimeMs(): number; | ||
set birthtimeMs(value: number); | ||
get mtimeMs(): number; | ||
set mtimeMs(value: number); | ||
get ctimeMs(): number; | ||
set ctimeMs(value: number); | ||
/** | ||
@@ -47,6 +57,2 @@ * Handy function that converts the Inode to a Node Stats object. | ||
/** | ||
* Get the size of this Inode, in bytes. | ||
*/ | ||
sizeof(): number; | ||
/** | ||
* Updates the Inode using information from the stats object. Used by file | ||
@@ -53,0 +59,0 @@ * systems at sync time, e.g.: |
@@ -1,18 +0,10 @@ | ||
import { S_IFMT } from './emulation/constants.js'; | ||
import { Stats, FileType } from './stats.js'; | ||
var Offset; | ||
(function (Offset) { | ||
Offset[Offset["ino"] = 0] = "ino"; | ||
Offset[Offset["size"] = 8] = "size"; | ||
Offset[Offset["mode"] = 12] = "mode"; | ||
Offset[Offset["nlink"] = 14] = "nlink"; | ||
Offset[Offset["uid"] = 18] = "uid"; | ||
Offset[Offset["gid"] = 22] = "gid"; | ||
Offset[Offset["atime"] = 26] = "atime"; | ||
Offset[Offset["mtime"] = 34] = "mtime"; | ||
Offset[Offset["ctime"] = 42] = "ctime"; | ||
})(Offset || (Offset = {})); | ||
import { Stats } from './stats.js'; | ||
/** | ||
* Max 32-bit integer | ||
* @hidden | ||
*/ | ||
export const size_max = 2 ** 32 - 1; | ||
/** | ||
* @internal | ||
* Room inode | ||
* @hidden | ||
*/ | ||
@@ -27,4 +19,3 @@ export const rootIno = 0n; | ||
/** | ||
* Generate 4 random bits at a time | ||
* | ||
* Generate a random ino | ||
* @internal | ||
@@ -36,2 +27,19 @@ */ | ||
/** | ||
* Offsets for inode members | ||
*/ | ||
var Offset; | ||
(function (Offset) { | ||
Offset[Offset["ino"] = 0] = "ino"; | ||
Offset[Offset["size"] = 8] = "size"; | ||
Offset[Offset["mode"] = 12] = "mode"; | ||
Offset[Offset["nlink"] = 14] = "nlink"; | ||
Offset[Offset["uid"] = 18] = "uid"; | ||
Offset[Offset["gid"] = 22] = "gid"; | ||
Offset[Offset["atime"] = 26] = "atime"; | ||
Offset[Offset["birthtime"] = 34] = "birthtime"; | ||
Offset[Offset["mtime"] = 42] = "mtime"; | ||
Offset[Offset["ctime"] = 50] = "ctime"; | ||
Offset[Offset["end"] = 58] = "end"; | ||
})(Offset || (Offset = {})); | ||
/** | ||
* Generic inode definition that can easily be serialized. | ||
@@ -45,3 +53,6 @@ */ | ||
const setDefaults = !buffer; | ||
buffer ?? (buffer = new ArrayBuffer(50)); | ||
buffer ?? (buffer = new ArrayBuffer(Offset.end)); | ||
if (buffer?.byteLength < Offset.end) { | ||
throw new RangeError(`Can not create an inode from a buffer less than ${Offset.end} bytes`); | ||
} | ||
this.view = new DataView(buffer); | ||
@@ -57,5 +68,6 @@ this.buffer = buffer; | ||
const now = Date.now(); | ||
this.atime = now; | ||
this.mtime = now; | ||
this.ctime = now; | ||
this.atimeMs = now; | ||
this.mtimeMs = now; | ||
this.ctimeMs = now; | ||
this.birthtimeMs = now; | ||
} | ||
@@ -98,18 +110,24 @@ get ino() { | ||
} | ||
get atime() { | ||
get atimeMs() { | ||
return this.view.getFloat64(Offset.atime, true); | ||
} | ||
set atime(value) { | ||
set atimeMs(value) { | ||
this.view.setFloat64(Offset.atime, value, true); | ||
} | ||
get mtime() { | ||
get birthtimeMs() { | ||
return this.view.getFloat64(Offset.birthtime, true); | ||
} | ||
set birthtimeMs(value) { | ||
this.view.setFloat64(Offset.birthtime, value, true); | ||
} | ||
get mtimeMs() { | ||
return this.view.getFloat64(Offset.mtime, true); | ||
} | ||
set mtime(value) { | ||
set mtimeMs(value) { | ||
this.view.setFloat64(Offset.mtime, value, true); | ||
} | ||
get ctime() { | ||
get ctimeMs() { | ||
return this.view.getFloat64(Offset.ctime, true); | ||
} | ||
set ctime(value) { | ||
set ctimeMs(value) { | ||
this.view.setFloat64(Offset.ctime, value, true); | ||
@@ -121,11 +139,5 @@ } | ||
toStats() { | ||
return new Stats((this.mode & S_IFMT) === FileType.DIRECTORY ? FileType.DIRECTORY : FileType.FILE, this.size, this.mode, this.atime, this.mtime, this.ctime, this.uid, this.gid); | ||
return new Stats(this); | ||
} | ||
/** | ||
* Get the size of this Inode, in bytes. | ||
*/ | ||
sizeof() { | ||
return this.buffer.byteLength; | ||
} | ||
/** | ||
* Updates the Inode using information from the stats object. Used by file | ||
@@ -162,12 +174,12 @@ * systems at sync time, e.g.: | ||
} | ||
if (this.atime !== stats.atimeMs) { | ||
this.atime = stats.atimeMs; | ||
if (this.atimeMs !== stats.atimeMs) { | ||
this.atimeMs = stats.atimeMs; | ||
hasChanged = true; | ||
} | ||
if (this.mtime !== stats.mtimeMs) { | ||
this.mtime = stats.mtimeMs; | ||
if (this.mtimeMs !== stats.mtimeMs) { | ||
this.mtimeMs = stats.mtimeMs; | ||
hasChanged = true; | ||
} | ||
if (this.ctime !== stats.ctimeMs) { | ||
this.ctime = stats.ctimeMs; | ||
if (this.ctimeMs !== stats.ctimeMs) { | ||
this.ctimeMs = stats.ctimeMs; | ||
hasChanged = true; | ||
@@ -174,0 +186,0 @@ } |
@@ -1,2 +0,1 @@ | ||
export type MutexCallback = () => void; | ||
/** | ||
@@ -6,3 +5,3 @@ * Non-recursive mutex | ||
*/ | ||
export default class Mutex { | ||
export declare class Mutex { | ||
private _locks; | ||
@@ -9,0 +8,0 @@ lock(path: string): Promise<void>; |
@@ -5,3 +5,3 @@ /** | ||
*/ | ||
export default class Mutex { | ||
export class Mutex { | ||
constructor() { | ||
@@ -8,0 +8,0 @@ this._locks = new Map(); |
@@ -13,5 +13,45 @@ /// <reference types="node" resolution-mode="require"/> | ||
/** | ||
* Common code used by both Stats and BigIntStats | ||
* | ||
*/ | ||
export declare abstract class StatsCommon<T extends number | bigint> implements Node.StatsBase<T> { | ||
export interface StatsLike { | ||
/** | ||
* Size of the item in bytes. | ||
* For directories/symlinks, this is normally the size of the struct that represents the item. | ||
*/ | ||
size: number | bigint; | ||
/** | ||
* Unix-style file mode (e.g. 0o644) that includes the item type | ||
* Type of the item can be FILE, DIRECTORY, SYMLINK, or SOCKET | ||
*/ | ||
mode: number | bigint; | ||
/** | ||
* time of last access, in milliseconds since epoch | ||
*/ | ||
atimeMs: number | bigint; | ||
/** | ||
* time of last modification, in milliseconds since epoch | ||
*/ | ||
mtimeMs: number | bigint; | ||
/** | ||
* time of last time file status was changed, in milliseconds since epoch | ||
*/ | ||
ctimeMs: number | bigint; | ||
/** | ||
* time of file creation, in milliseconds since epoch | ||
*/ | ||
birthtimeMs: number | bigint; | ||
/** | ||
* the id of the user that owns the file | ||
*/ | ||
uid: number | bigint; | ||
/** | ||
* the id of the group that owns the file | ||
*/ | ||
gid: number | bigint; | ||
} | ||
/** | ||
* Provides information about a particular entry in the file system. | ||
* Common code used by both Stats and BigIntStats. | ||
*/ | ||
export declare abstract class StatsCommon<T extends number | bigint> implements Node.StatsBase<T>, StatsLike { | ||
protected abstract _isBigint: boolean; | ||
@@ -22,2 +62,6 @@ protected get _typename(): string; | ||
blocks: T; | ||
/** | ||
* Unix-style file mode (e.g. 0o644) that includes the type of the item. | ||
* Type of the item can be FILE, DIRECTORY, SYMLINK, or SOCKET | ||
*/ | ||
mode: T; | ||
@@ -56,29 +100,35 @@ /** | ||
fileData?: Uint8Array; | ||
/** | ||
* time of last access, in milliseconds since epoch | ||
*/ | ||
atimeMs: T; | ||
get atime(): Date; | ||
set atime(value: Date); | ||
/** | ||
* time of last modification, in milliseconds since epoch | ||
*/ | ||
mtimeMs: T; | ||
get mtime(): Date; | ||
set mtime(value: Date); | ||
/** | ||
* time of last time file status was changed, in milliseconds since epoch | ||
*/ | ||
ctimeMs: T; | ||
get ctime(): Date; | ||
set ctime(value: Date); | ||
/** | ||
* time of file creation, in milliseconds since epoch | ||
*/ | ||
birthtimeMs: T; | ||
get birthtime(): Date; | ||
set birthtime(value: Date); | ||
/** | ||
* Size of the item in bytes. | ||
* For directories/symlinks, this is normally the size of the struct that represents the item. | ||
*/ | ||
size: T; | ||
/** | ||
* Provides information about a particular entry in the file system. | ||
* @param itemType Type of the item (FILE, DIRECTORY, SYMLINK, or SOCKET) | ||
* @param size Size of the item in bytes. For directories/symlinks, | ||
* this is normally the size of the struct that represents the item. | ||
* @param mode Unix-style file mode (e.g. 0o644) | ||
* @param atimeMs time of last access, in milliseconds since epoch | ||
* @param mtimeMs time of last modification, in milliseconds since epoch | ||
* @param ctimeMs time of last time file status was changed, in milliseconds since epoch | ||
* @param uid the id of the user that owns the file | ||
* @param gid the id of the group that owns the file | ||
* @param birthtimeMs time of file creation, in milliseconds since epoch | ||
* Creates a new stats instance from a stats-like object. Can be used to copy stats (note) | ||
*/ | ||
constructor(itemType?: FileType, size?: number | bigint, mode?: number | bigint, atimeMs?: number | bigint, mtimeMs?: number | bigint, ctimeMs?: number | bigint, uid?: number | bigint, gid?: number | bigint, birthtimeMs?: number | bigint); | ||
constructor({ atimeMs, mtimeMs, ctimeMs, birthtimeMs, uid, gid, size, mode }?: Partial<StatsLike>); | ||
/** | ||
@@ -134,8 +184,9 @@ * @returns true if this item is a file. | ||
*/ | ||
export declare class Stats extends StatsCommon<number> implements Node.Stats { | ||
export declare class Stats extends StatsCommon<number> implements Node.Stats, StatsLike { | ||
protected _isBigint: boolean; | ||
/** | ||
* Clones the stats object. | ||
* @deprecated use `new Stats(stats)` | ||
*/ | ||
static clone(s: Stats): Stats; | ||
static clone(stats: Stats): Stats; | ||
} | ||
@@ -146,3 +197,3 @@ /** | ||
*/ | ||
export declare class BigIntStats extends StatsCommon<bigint> implements Node.BigIntStats { | ||
export declare class BigIntStats extends StatsCommon<bigint> implements Node.BigIntStats, StatsLike { | ||
protected _isBigint: boolean; | ||
@@ -155,4 +206,5 @@ atimeNs: bigint; | ||
* Clone a stats object. | ||
* @deprecated use `new BigIntStats(stats)` | ||
*/ | ||
static clone(s: BigIntStats | Stats): BigIntStats; | ||
static clone(stats: BigIntStats | Stats): BigIntStats; | ||
} |
@@ -13,3 +13,4 @@ import { Cred } from './cred.js'; | ||
/** | ||
* Common code used by both Stats and BigIntStats | ||
* Provides information about a particular entry in the file system. | ||
* Common code used by both Stats and BigIntStats. | ||
*/ | ||
@@ -51,15 +52,5 @@ export class StatsCommon { | ||
/** | ||
* Provides information about a particular entry in the file system. | ||
* @param itemType Type of the item (FILE, DIRECTORY, SYMLINK, or SOCKET) | ||
* @param size Size of the item in bytes. For directories/symlinks, | ||
* this is normally the size of the struct that represents the item. | ||
* @param mode Unix-style file mode (e.g. 0o644) | ||
* @param atimeMs time of last access, in milliseconds since epoch | ||
* @param mtimeMs time of last modification, in milliseconds since epoch | ||
* @param ctimeMs time of last time file status was changed, in milliseconds since epoch | ||
* @param uid the id of the user that owns the file | ||
* @param gid the id of the group that owns the file | ||
* @param birthtimeMs time of file creation, in milliseconds since epoch | ||
* Creates a new stats instance from a stats-like object. Can be used to copy stats (note) | ||
*/ | ||
constructor(itemType = FileType.FILE, size = -1, mode, atimeMs, mtimeMs, ctimeMs, uid, gid, birthtimeMs) { | ||
constructor({ atimeMs, mtimeMs, ctimeMs, birthtimeMs, uid, gid, size, mode } = {}) { | ||
/** | ||
@@ -98,3 +89,3 @@ * ID of device containing file | ||
const currentTime = Date.now(); | ||
const resolveT = (v, def) => (typeof v == this._typename ? v : this._convert(typeof v == this._typename_inverse ? v : def)); | ||
const resolveT = (val, _default) => (typeof val == this._typename ? val : this._convert(typeof val == this._typename_inverse ? val : _default)); | ||
this.atimeMs = resolveT(atimeMs, currentTime); | ||
@@ -107,2 +98,3 @@ this.mtimeMs = resolveT(mtimeMs, currentTime); | ||
this.size = this._convert(size); | ||
const itemType = Number(mode) & S_IFMT || FileType.FILE; | ||
if (mode) { | ||
@@ -236,5 +228,6 @@ this.mode = this._convert(mode); | ||
* Clones the stats object. | ||
* @deprecated use `new Stats(stats)` | ||
*/ | ||
static clone(s) { | ||
return new Stats(s.mode & S_IFMT, s.size, s.mode & ~S_IFMT, s.atimeMs, s.mtimeMs, s.ctimeMs, s.uid, s.gid, s.birthtimeMs); | ||
static clone(stats) { | ||
return new Stats(stats); | ||
} | ||
@@ -254,7 +247,8 @@ } | ||
* Clone a stats object. | ||
* @deprecated use `new BigIntStats(stats)` | ||
*/ | ||
static clone(s) { | ||
return new BigIntStats(Number(s.mode) & S_IFMT, BigInt(s.size), BigInt(s.mode) & BigInt(~S_IFMT), BigInt(s.atimeMs), BigInt(s.mtimeMs), BigInt(s.ctimeMs), BigInt(s.uid), BigInt(s.gid), BigInt(s.birthtimeMs)); | ||
static clone(stats) { | ||
return new BigIntStats(stats); | ||
} | ||
} | ||
BigIntStats; |
@@ -10,3 +10,3 @@ /// <reference types="node" resolution-mode="require"/> | ||
* Synchronous recursive makedir. | ||
* @internal | ||
* @hidden | ||
*/ | ||
@@ -16,3 +16,3 @@ export declare function mkdirpSync(p: string, mode: number, cred: Cred, fs: FileSystem): void; | ||
* Calculates levenshtein distance. | ||
* @internal | ||
* @hidden | ||
*/ | ||
@@ -23,9 +23,4 @@ export declare function levenshtein(a: string, b: string): number; | ||
/** | ||
* Converts a callback into a promise. Assumes last parameter is the callback | ||
* @todo Look at changing resolve value from cbArgs[0] to include other callback arguments? | ||
* @hidden | ||
*/ | ||
export declare function toPromise(fn: (...fnArgs: unknown[]) => unknown): (...args: unknown[]) => Promise<unknown>; | ||
/** | ||
* @internal | ||
*/ | ||
export declare const setImmediate: (callback: () => unknown) => void; | ||
@@ -32,0 +27,0 @@ /** |
import { ApiError, ErrorCode } from './ApiError.js'; | ||
import * as path from './emulation/path.js'; | ||
import { dirname } from './emulation/path.js'; | ||
/** | ||
* Synchronous recursive makedir. | ||
* @internal | ||
* @hidden | ||
*/ | ||
export function mkdirpSync(p, mode, cred, fs) { | ||
if (!fs.existsSync(p, cred)) { | ||
mkdirpSync(path.dirname(p), mode, cred, fs); | ||
mkdirpSync(dirname(p), mode, cred, fs); | ||
fs.mkdirSync(p, mode, cred); | ||
} | ||
} | ||
/* | ||
* Levenshtein distance, from the `js-levenshtein` NPM module. | ||
* Copied here to avoid complexity of adding another CommonJS module dependency. | ||
*/ | ||
function _min(d0, d1, d2, bx, ay) { | ||
@@ -22,3 +18,3 @@ return Math.min(d0 + 1, d1 + 1, d2 + 1, bx === ay ? d1 : d1 + 1); | ||
* Calculates levenshtein distance. | ||
* @internal | ||
* @hidden | ||
*/ | ||
@@ -98,23 +94,4 @@ export function levenshtein(a, b) { | ||
/** | ||
* Converts a callback into a promise. Assumes last parameter is the callback | ||
* @todo Look at changing resolve value from cbArgs[0] to include other callback arguments? | ||
* @hidden | ||
*/ | ||
export function toPromise(fn) { | ||
return function (...args) { | ||
return new Promise((resolve, reject) => { | ||
args.push((e, ...cbArgs) => { | ||
if (e) { | ||
reject(e); | ||
} | ||
else { | ||
resolve(cbArgs[0]); | ||
} | ||
}); | ||
fn(...args); | ||
}); | ||
}; | ||
} | ||
/** | ||
* @internal | ||
*/ | ||
export const setImmediate = typeof globalThis.setImmediate == 'function' ? globalThis.setImmediate : cb => setTimeout(cb, 0); | ||
@@ -126,17 +103,41 @@ /** | ||
export function encode(input, encoding = 'utf8') { | ||
if (typeof input != 'string') { | ||
throw new ApiError(ErrorCode.EINVAL, 'Can not encode a non-string'); | ||
} | ||
switch (encoding) { | ||
case 'ascii': | ||
return new globalThis.TextEncoder().encode(input).map(v => v & 0x7f); | ||
case 'latin1': | ||
case 'binary': | ||
return new Uint8Array(Array.from(input).map(char => char.charCodeAt(0))); | ||
case 'utf8': | ||
case 'utf-8': | ||
return new Uint8Array(Array.from(input).flatMap(char => { | ||
const code = char.charCodeAt(0); | ||
if (code < 0x80) { | ||
return code; | ||
} | ||
const a = (code & 0x3f) | 0x80; | ||
if (code < 0x800) { | ||
return [(code >> 6) | 0xc0, a]; | ||
} | ||
const b = ((code >> 6) & 0x3f) | 0x80; | ||
if (code < 0x10000) { | ||
return [(code >> 12) | 0xe0, b, a]; | ||
} | ||
return [(code >> 18) | 0xf0, ((code >> 12) & 0x3f) | 0x80, b, a]; | ||
})); | ||
case 'base64': | ||
return encode(atob(input), 'utf-8'); | ||
case 'base64url': | ||
return encode(input.replace('_', '/').replace('-', '+'), 'base64'); | ||
case 'hex': | ||
return new globalThis.TextEncoder().encode(input); | ||
return new Uint8Array(input.match(/.{1,2}/g).map(e => parseInt(e, 16))); | ||
case 'utf16le': | ||
case 'ucs2': | ||
case 'ucs-2': | ||
return new globalThis.TextEncoder().encode(input).slice(0, -1); | ||
const u16 = new Uint16Array(new ArrayBuffer(input.length * 2)); | ||
for (let i = 0; i < input.length; i++) { | ||
u16[i] = input.charCodeAt(i); | ||
} | ||
return new Uint8Array(u16.buffer); | ||
default: | ||
@@ -151,10 +152,32 @@ throw new ApiError(ErrorCode.EINVAL, 'Invalid encoding: ' + encoding); | ||
export function decode(input, encoding = 'utf8') { | ||
if (!(input instanceof Uint8Array)) { | ||
throw new ApiError(ErrorCode.EINVAL, 'Can not decode a non-Uint8Array'); | ||
} | ||
switch (encoding) { | ||
case 'ascii': | ||
case 'latin1': | ||
case 'binary': | ||
return Array.from(input) | ||
.map(char => String.fromCharCode(char)) | ||
.join(''); | ||
case 'utf8': | ||
case 'utf-8': | ||
return new globalThis.TextDecoder().decode(input); | ||
case 'latin1': | ||
case 'binary': | ||
return new globalThis.TextDecoder('latin1').decode(input); | ||
let utf8String = ''; | ||
for (let i = 0; i < input.length; i++) { | ||
let code; | ||
if (input[i] < 0x80) { | ||
code = input[i]; | ||
} | ||
else if (input[i] < 0xe0) { | ||
code = ((input[i] & 0x1f) << 6) | (input[++i] & 0x3f); | ||
} | ||
else if (input[i] < 0xf0) { | ||
code = ((input[i] & 0x0f) << 12) | ((input[++i] & 0x3f) << 6) | (input[++i] & 0x3f); | ||
} | ||
else { | ||
code = ((input[i] & 0x07) << 18) | ((input[++i] & 0x3f) << 12) | ((input[++i] & 0x3f) << 6) | (input[++i] & 0x3f); | ||
} | ||
utf8String += String.fromCharCode(code); | ||
} | ||
return utf8String; | ||
case 'utf16le': | ||
@@ -170,5 +193,3 @@ case 'ucs2': | ||
case 'base64': | ||
return btoa(Array.from(input) | ||
.map(v => String.fromCharCode(v)) | ||
.join('')); | ||
return btoa(decode(input, 'utf-8')); | ||
case 'base64url': | ||
@@ -178,3 +199,3 @@ return decode(input, 'base64').replace('/', '_').replace('+', '-'); | ||
return Array.from(input) | ||
.map(e => e.toString(16)) | ||
.map(e => e.toString(16).padStart(2, '0')) | ||
.join(''); | ||
@@ -181,0 +202,0 @@ default: |
{ | ||
"name": "@zenfs/core", | ||
"version": "0.3.5", | ||
"version": "0.4.0", | ||
"description": "A filesystem in your browser", | ||
@@ -12,2 +12,5 @@ "main": "dist/index.js", | ||
], | ||
"bin": { | ||
"make-index": "./scripts/make-index.js" | ||
}, | ||
"type": "module", | ||
@@ -50,2 +53,3 @@ "homepage": "https://github.com/zen-fs/core", | ||
"@types/readable-stream": "^4.0.10", | ||
"minimatch": "^9.0.3", | ||
"readable-stream": "^4.5.2" | ||
@@ -52,0 +56,0 @@ }, |
@@ -42,3 +42,3 @@ # ZenFS | ||
#### Using different and/or different backends | ||
#### Using different and/or multiple backends | ||
@@ -54,3 +54,3 @@ A single `InMemory` backend is created by default, mounted on `/`. | ||
```js | ||
import { configure } from '@zenfs/core'; | ||
import { configure, InMemory } from '@zenfs/core'; | ||
import { IndexedDB } from '@zenfs/dom'; | ||
@@ -63,3 +63,3 @@ import { Zip } from '@zenfs/zip'; | ||
'/mnt/zip': { backend: Zip, zipData }, | ||
'/tmp': 'InMemory', | ||
'/tmp': InMemory, | ||
'/home': IndexedDB, | ||
@@ -70,3 +70,7 @@ }; | ||
> [!TIP] | ||
> When configuring a mount point, you can pass in 1. A string that maps to a built-in backend 2. A `Backend` object, if the backend has no required options 3. An object that has a `backend` property which is a `Backend` or a string that maps to a built-in backend and the options accepted by the backend | ||
> When configuring a mount point, you can pass in | ||
> | ||
> 1. A string that maps to a built-in backend | ||
> 2. A `Backend` object, if the backend has no required options | ||
> 3. An object that has the options accepted by the backend and a `backend` property which is (1) or (2) | ||
@@ -116,3 +120,3 @@ Here is an example that mounts the `Storage` backend from `@zenfs/dom` on `/`: | ||
```js | ||
import { configure, fs } from '@zenfs/core'; | ||
import { configure, fs, AsyncMirror, InMemory } from '@zenfs/core'; | ||
import { IndexedDB } from '@zenfs/dom'; | ||
@@ -122,4 +126,4 @@ | ||
'/': { | ||
backend: 'AsyncMirror', | ||
sync: 'InMemory', | ||
backend: AsyncMirror, | ||
sync: InMemory, | ||
async: IndexedDB, | ||
@@ -139,3 +143,3 @@ }, | ||
```js | ||
import { configure, createBackend } from '@zenfs/core'; | ||
import { configure, createBackend, InMemory } from '@zenfs/core'; | ||
import { IndexedDB } from '@zenfs/dom'; | ||
@@ -145,3 +149,3 @@ import { Zip } from '@zenfs/zip'; | ||
await configure({ | ||
'/tmp': 'InMemory', | ||
'/tmp': InMemory, | ||
'/home': IndexedDB, | ||
@@ -148,0 +152,0 @@ }; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1481502
11479
174
4
58
1
+ Addedminimatch@^9.0.3
+ Addedbalanced-match@1.0.2(transitive)
+ Addedbrace-expansion@2.0.1(transitive)
+ Addedminimatch@9.0.5(transitive)