stubborn-fs
Advanced tools
Comparing version 1.2.1 to 1.2.2
@@ -1,4 +0,3 @@ | ||
/// <reference types="node" /> | ||
declare const attemptifyAsync: <T extends Function>(fn: T, onError: (error: NodeJS.ErrnoException) => void) => T; | ||
declare const attemptifySync: <T extends Function>(fn: T, onError: (error: NodeJS.ErrnoException) => void) => T; | ||
declare const attemptifyAsync: <Args extends unknown[], Return>(fn: (...args: Args) => Promise<Return>, onError: (error: unknown) => undefined) => (...args: Args) => Promise<Return | undefined>; | ||
declare const attemptifySync: <Args extends unknown[], Return>(fn: (...args: Args) => Return, onError: (error: unknown) => undefined) => (...args: Args) => Return | undefined; | ||
export { attemptifyAsync, attemptifySync }; |
/* MAIN */ | ||
const attemptifyAsync = (fn, onError) => { | ||
return function attemptified() { | ||
return fn.apply(undefined, arguments).catch(onError); | ||
return function attemptified(...args) { | ||
return fn.apply(undefined, args).catch(onError); | ||
}; | ||
}; | ||
const attemptifySync = (fn, onError) => { | ||
return function attemptified() { | ||
return function attemptified(...args) { | ||
try { | ||
return fn.apply(undefined, arguments); | ||
return fn.apply(undefined, args); | ||
} | ||
@@ -12,0 +12,0 @@ catch (error) { |
declare const IS_USER_ROOT: boolean; | ||
declare const LIMIT_FILES_DESCRIPTORS = 10000; | ||
declare const NOOP: () => void; | ||
declare const NOOP: () => undefined; | ||
export { IS_USER_ROOT, LIMIT_FILES_DESCRIPTORS, NOOP }; |
@@ -0,6 +1,8 @@ | ||
/* IMPORT */ | ||
import process from 'node:process'; | ||
/* MAIN */ | ||
const IS_USER_ROOT = process.getuid ? !process.getuid() : false; | ||
const LIMIT_FILES_DESCRIPTORS = 10000; //TODO: fetch the real limit from the filesystem | ||
const NOOP = () => { }; | ||
const LIMIT_FILES_DESCRIPTORS = 10000; //TODO: Fetch the real limit from the filesystem, somehow | ||
const NOOP = () => undefined; | ||
/* EXPORT */ | ||
export { IS_USER_ROOT, LIMIT_FILES_DESCRIPTORS, NOOP }; |
/// <reference types="node" /> | ||
declare const Handlers: { | ||
isChangeErrorOk: (error: NodeJS.ErrnoException) => boolean; | ||
isRetriableError: (error: NodeJS.ErrnoException) => boolean; | ||
onChangeError: (error: NodeJS.ErrnoException) => void; | ||
isChangeErrorOk: (error: unknown) => boolean; | ||
isNodeError: (error: unknown) => error is NodeJS.ErrnoException; | ||
isRetriableError: (error: unknown) => boolean; | ||
onChangeError: (error: unknown) => undefined; | ||
}; | ||
export default Handlers; |
@@ -7,2 +7,4 @@ /* IMPORT */ | ||
isChangeErrorOk: (error) => { | ||
if (!Handlers.isNodeError(error)) | ||
return false; | ||
const { code } = error; | ||
@@ -15,3 +17,8 @@ if (code === 'ENOSYS') | ||
}, | ||
isNodeError: (error) => { | ||
return error instanceof Error; | ||
}, | ||
isRetriableError: (error) => { | ||
if (!Handlers.isNodeError(error)) | ||
return false; | ||
const { code } = error; | ||
@@ -23,2 +30,4 @@ if (code === 'EMFILE' || code === 'ENFILE' || code === 'EAGAIN' || code === 'EBUSY' || code === 'EACCESS' || code === 'EACCS' || code === 'EPERM') | ||
onChangeError: (error) => { | ||
if (!Handlers.isNodeError(error)) | ||
throw error; | ||
if (Handlers.isChangeErrorOk(error)) | ||
@@ -25,0 +34,0 @@ return; |
/// <reference types="node" /> | ||
/// <reference types="node" /> | ||
/// <reference types="node" /> | ||
import fs from 'node:fs'; | ||
declare const FS: { | ||
attempt: { | ||
chmod: typeof fs.chmod.__promisify__; | ||
chown: typeof fs.chown.__promisify__; | ||
close: typeof fs.close.__promisify__; | ||
fsync: typeof fs.fsync.__promisify__; | ||
mkdir: typeof fs.mkdir.__promisify__; | ||
realpath: typeof fs.realpath.__promisify__; | ||
stat: typeof fs.stat.__promisify__; | ||
unlink: typeof fs.unlink.__promisify__; | ||
chmodSync: typeof fs.chmodSync; | ||
chownSync: typeof fs.chownSync; | ||
closeSync: typeof fs.closeSync; | ||
existsSync: typeof fs.existsSync; | ||
fsyncSync: typeof fs.fsync; | ||
mkdirSync: typeof fs.mkdirSync; | ||
realpathSync: typeof fs.realpathSync; | ||
statSync: fs.StatSyncFn; | ||
unlinkSync: typeof fs.unlinkSync; | ||
chmod: (path: fs.PathLike, mode: fs.Mode) => Promise<void | undefined>; | ||
chown: (path: fs.PathLike, uid: number, gid: number) => Promise<void | undefined>; | ||
close: (fd: number) => Promise<void | undefined>; | ||
fsync: (fd: number) => Promise<void | undefined>; | ||
mkdir: (path: fs.PathLike, options?: fs.Mode | fs.MakeDirectoryOptions | null | undefined) => Promise<string | undefined>; | ||
realpath: (path: fs.PathLike, options?: fs.EncodingOption) => Promise<string | Buffer | undefined>; | ||
stat: (path: fs.PathLike, options?: fs.StatOptions | undefined) => Promise<fs.Stats | fs.BigIntStats | undefined>; | ||
unlink: (path: fs.PathLike) => Promise<void | undefined>; | ||
chmodSync: (path: fs.PathLike, mode: fs.Mode) => void | undefined; | ||
chownSync: (path: fs.PathLike, uid: number, gid: number) => void | undefined; | ||
closeSync: (fd: number) => void | undefined; | ||
existsSync: (path: fs.PathLike) => boolean | undefined; | ||
fsyncSync: (fd: number, callback: fs.NoParamCallback) => void | undefined; | ||
mkdirSync: (path: fs.PathLike, options?: fs.Mode | fs.MakeDirectoryOptions | null | undefined) => string | undefined; | ||
realpathSync: (path: fs.PathLike, options?: fs.EncodingOption) => string | Buffer | undefined; | ||
statSync: (path: fs.PathLike, options?: fs.StatSyncOptions | undefined) => fs.Stats | fs.BigIntStats | undefined; | ||
unlinkSync: (path: fs.PathLike) => void | undefined; | ||
}; | ||
retry: { | ||
close: (timeout: number) => typeof fs.close.__promisify__; | ||
fsync: (timeout: number) => typeof fs.fsync.__promisify__; | ||
open: (timeout: number) => typeof fs.open.__promisify__; | ||
readFile: (timeout: number) => typeof fs.readFile.__promisify__; | ||
rename: (timeout: number) => typeof fs.rename.__promisify__; | ||
stat: (timeout: number) => typeof fs.stat.__promisify__; | ||
write: (timeout: number) => typeof fs.write.__promisify__; | ||
writeFile: (timeout: number) => typeof fs.writeFile.__promisify__; | ||
closeSync: (timeout: number) => typeof fs.closeSync; | ||
fsyncSync: (timeout: number) => typeof fs.fsyncSync; | ||
openSync: (timeout: number) => typeof fs.openSync; | ||
readFileSync: (timeout: number) => typeof fs.readFileSync; | ||
renameSync: (timeout: number) => typeof fs.renameSync; | ||
statSync: (timeout: number) => fs.StatSyncFn; | ||
writeSync: (timeout: number) => typeof fs.writeSync; | ||
writeFileSync: (timeout: number) => typeof fs.writeFileSync; | ||
close: (timeout: number) => (fd: number) => Promise<void | undefined>; | ||
fsync: (timeout: number) => (fd: number) => Promise<void | undefined>; | ||
open: (timeout: number) => (path: fs.PathLike, flags: fs.OpenMode, mode?: fs.Mode | null | undefined) => Promise<number | undefined>; | ||
readFile: (timeout: number) => (path: fs.PathOrFileDescriptor, options?: BufferEncoding | (fs.ObjectEncodingOptions & { | ||
flag?: string | undefined; | ||
}) | null | undefined) => Promise<string | Buffer | undefined>; | ||
rename: (timeout: number) => (oldPath: fs.PathLike, newPath: fs.PathLike) => Promise<void | undefined>; | ||
stat: (timeout: number) => (path: fs.PathLike, options?: fs.StatOptions | undefined) => Promise<fs.Stats | fs.BigIntStats | undefined>; | ||
write: (timeout: number) => (fd: number, string: string, position?: number | null | undefined, encoding?: BufferEncoding | null | undefined) => Promise<{ | ||
bytesWritten: number; | ||
buffer: string; | ||
} | undefined>; | ||
writeFile: (timeout: number) => (path: fs.PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options?: fs.WriteFileOptions | undefined) => Promise<void | undefined>; | ||
closeSync: (timeout: number) => (fd: number) => void | undefined; | ||
fsyncSync: (timeout: number) => (fd: number) => void | undefined; | ||
openSync: (timeout: number) => (path: fs.PathLike, flags: fs.OpenMode, mode?: fs.Mode | null | undefined) => number | undefined; | ||
readFileSync: (timeout: number) => (path: fs.PathOrFileDescriptor, options?: BufferEncoding | (fs.ObjectEncodingOptions & { | ||
flag?: string | undefined; | ||
}) | null | undefined) => string | Buffer | undefined; | ||
renameSync: (timeout: number) => (oldPath: fs.PathLike, newPath: fs.PathLike) => void | undefined; | ||
statSync: (timeout: number) => (path: fs.PathLike, options?: fs.StatSyncOptions | undefined) => fs.Stats | fs.BigIntStats | undefined; | ||
writeSync: (timeout: number) => (fd: number, string: string, position?: number | null | undefined, encoding?: BufferEncoding | null | undefined) => number | undefined; | ||
writeFileSync: (timeout: number) => (file: fs.PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options?: fs.WriteFileOptions | undefined) => void | undefined; | ||
}; | ||
}; | ||
export default FS; |
@@ -11,2 +11,3 @@ /* IMPORT */ | ||
attempt: { | ||
/* ASYNC */ | ||
chmod: attemptifyAsync(promisify(fs.chmod), Handlers.onChangeError), | ||
@@ -20,2 +21,3 @@ chown: attemptifyAsync(promisify(fs.chown), Handlers.onChangeError), | ||
unlink: attemptifyAsync(promisify(fs.unlink), NOOP), | ||
/* SYNC */ | ||
chmodSync: attemptifySync(fs.chmodSync, Handlers.onChangeError), | ||
@@ -32,2 +34,3 @@ chownSync: attemptifySync(fs.chownSync, Handlers.onChangeError), | ||
retry: { | ||
/* ASYNC */ | ||
close: retryifyAsync(promisify(fs.close), Handlers.isRetriableError), | ||
@@ -41,2 +44,3 @@ fsync: retryifyAsync(promisify(fs.fsync), Handlers.isRetriableError), | ||
writeFile: retryifyAsync(promisify(fs.writeFile), Handlers.isRetriableError), | ||
/* SYNC */ | ||
closeSync: retryifySync(fs.closeSync, Handlers.isRetriableError), | ||
@@ -43,0 +47,0 @@ fsyncSync: retryifySync(fs.fsyncSync, Handlers.isRetriableError), |
@@ -1,4 +0,3 @@ | ||
/// <reference types="node" /> | ||
declare const retryifyAsync: <T extends Function>(fn: T, isRetriableError: (error: NodeJS.ErrnoException) => boolean | void) => (timeout: number) => T; | ||
declare const retryifySync: <T extends Function>(fn: T, isRetriableError: (error: NodeJS.ErrnoException) => boolean | void) => (timeout: number) => T; | ||
declare const retryifyAsync: <Args extends unknown[], Return>(fn: (...args: Args) => Promise<Return>, isRetriableError: (error: unknown) => boolean | void) => (timeout: number) => (...args: Args) => Promise<Return | undefined>; | ||
declare const retryifySync: <Args extends unknown[], Return>(fn: (...args: Args) => Return, isRetriableError: (error: unknown) => boolean | void) => (timeout: number) => (...args: Args) => Return | undefined; | ||
export { retryifyAsync, retryifySync }; |
@@ -8,7 +8,7 @@ /* IMPORT */ | ||
return RetryfyQueue.schedule().then(cleanup => { | ||
const onResolve = result => { | ||
const onResolve = (result) => { | ||
cleanup(); | ||
return result; | ||
}; | ||
const onReject = error => { | ||
const onReject = (error) => { | ||
cleanup(); | ||
@@ -15,0 +15,0 @@ if (Date.now() >= timestamp) |
@@ -5,3 +5,3 @@ { | ||
"description": "Stubborn versions of Node's fs functions that try really hard to do their job.", | ||
"version": "1.2.1", | ||
"version": "1.2.2", | ||
"type": "module", | ||
@@ -15,3 +15,3 @@ "main": "dist/index.js", | ||
"compile:watch": "tsex compile --watch", | ||
"prepublishOnly": "npm run clean && npm run compile" | ||
"prepublishOnly": "tsex prepare" | ||
}, | ||
@@ -26,6 +26,6 @@ "keywords": [ | ||
"devDependencies": { | ||
"@types/node": "^17.0.35", | ||
"tsex": "^1.1.2", | ||
"typescript": "^4.6.4" | ||
"@types/node": "^18.13.0", | ||
"tsex": "^2.1.0", | ||
"typescript": "^4.9.5" | ||
} | ||
} |
/* MAIN */ | ||
const attemptifyAsync = <T extends Function> ( fn: T, onError: (( error: NodeJS.ErrnoException ) => void) ): T => { | ||
const attemptifyAsync = <Args extends unknown[], Return> ( fn: ( ...args: Args ) => Promise<Return>, onError: (( error: unknown ) => undefined) ): (( ...args: Args ) => Promise<Return | undefined>) => { | ||
return function attemptified () { | ||
return function attemptified ( ...args: Args ): Promise<Return | undefined> { | ||
return fn.apply ( undefined, arguments ).catch ( onError ); | ||
return fn.apply ( undefined, args ).catch ( onError ); | ||
} as any; | ||
}; | ||
}; | ||
const attemptifySync = <T extends Function> ( fn: T, onError: (( error: NodeJS.ErrnoException ) => void) ): T => { | ||
const attemptifySync = <Args extends unknown[], Return> ( fn: ( ...args: Args ) => Return, onError: (( error: unknown ) => undefined) ): (( ...args: Args ) => Return | undefined) => { | ||
return function attemptified () { | ||
return function attemptified ( ...args: Args ): Return | undefined { | ||
try { | ||
return fn.apply ( undefined, arguments ); | ||
return fn.apply ( undefined, args ); | ||
} catch ( error: any ) { | ||
} catch ( error: unknown ) { | ||
@@ -28,3 +28,3 @@ return onError ( error ); | ||
} as any; | ||
}; | ||
@@ -31,0 +31,0 @@ }; |
/* IMPORT */ | ||
import process from 'node:process'; | ||
/* MAIN */ | ||
@@ -6,5 +10,5 @@ | ||
const LIMIT_FILES_DESCRIPTORS = 10000; //TODO: fetch the real limit from the filesystem | ||
const LIMIT_FILES_DESCRIPTORS = 10_000; //TODO: Fetch the real limit from the filesystem, somehow | ||
const NOOP = () => {}; | ||
const NOOP = () => undefined; | ||
@@ -11,0 +15,0 @@ /* EXPORT */ |
@@ -12,4 +12,6 @@ | ||
isChangeErrorOk: ( error: NodeJS.ErrnoException ): boolean => { //URL: https://github.com/isaacs/node-graceful-fs/blob/master/polyfills.js#L315-L342 | ||
isChangeErrorOk: ( error: unknown ): boolean => { //URL: https://github.com/isaacs/node-graceful-fs/blob/master/polyfills.js#L315-L342 | ||
if ( !Handlers.isNodeError ( error ) ) return false; | ||
const {code} = error; | ||
@@ -25,4 +27,12 @@ | ||
isRetriableError: ( error: NodeJS.ErrnoException ): boolean => { | ||
isNodeError: ( error: unknown ): error is NodeJS.ErrnoException => { | ||
return error instanceof Error; | ||
}, | ||
isRetriableError: ( error: unknown ): boolean => { | ||
if ( !Handlers.isNodeError ( error ) ) return false; | ||
const {code} = error; | ||
@@ -36,4 +46,6 @@ | ||
onChangeError: ( error: NodeJS.ErrnoException ): void => { | ||
onChangeError: ( error: unknown ): undefined => { | ||
if ( !Handlers.isNodeError ( error ) ) throw error; | ||
if ( Handlers.isChangeErrorOk ( error ) ) return; | ||
@@ -40,0 +52,0 @@ |
@@ -15,3 +15,3 @@ | ||
attempt: { | ||
/* ASYNC */ | ||
chmod: attemptifyAsync ( promisify ( fs.chmod ), Handlers.onChangeError ), | ||
@@ -25,3 +25,3 @@ chown: attemptifyAsync ( promisify ( fs.chown ), Handlers.onChangeError ), | ||
unlink: attemptifyAsync ( promisify ( fs.unlink ), NOOP ), | ||
/* SYNC */ | ||
chmodSync: attemptifySync ( fs.chmodSync, Handlers.onChangeError ), | ||
@@ -36,6 +36,5 @@ chownSync: attemptifySync ( fs.chownSync, Handlers.onChangeError ), | ||
unlinkSync: attemptifySync ( fs.unlinkSync, NOOP ) | ||
}, | ||
retry: { | ||
/* ASYNC */ | ||
close: retryifyAsync ( promisify ( fs.close ), Handlers.isRetriableError ), | ||
@@ -49,3 +48,3 @@ fsync: retryifyAsync ( promisify ( fs.fsync ), Handlers.isRetriableError ), | ||
writeFile: retryifyAsync ( promisify ( fs.writeFile ), Handlers.isRetriableError ), | ||
/* SYNC */ | ||
closeSync: retryifySync ( fs.closeSync, Handlers.isRetriableError ), | ||
@@ -59,3 +58,2 @@ fsyncSync: retryifySync ( fs.fsyncSync, Handlers.isRetriableError ), | ||
writeFileSync: retryifySync ( fs.writeFileSync, Handlers.isRetriableError ) | ||
} | ||
@@ -62,0 +60,0 @@ }; |
@@ -8,11 +8,11 @@ | ||
const retryifyAsync = <T extends Function> ( fn: T, isRetriableError: (( error: NodeJS.ErrnoException ) => boolean | void) ): (( timeout: number ) => T) => { | ||
const retryifyAsync = <Args extends unknown[], Return> ( fn: ( ...args: Args ) => Promise<Return>, isRetriableError: (( error: unknown ) => boolean | void) ): (( timeout: number ) => ( ...args: Args ) => Promise<Return | undefined>) => { | ||
return function retrified ( timestamp: number ) { | ||
return function attempt ( ...args ) { | ||
return function attempt ( ...args: Args ): Promise<Return | undefined> { | ||
return RetryfyQueue.schedule ().then ( cleanup => { | ||
const onResolve = result => { | ||
const onResolve = ( result: Return ): Return => { | ||
@@ -25,3 +25,3 @@ cleanup (); | ||
const onReject = error => { | ||
const onReject = ( error: unknown ): Promise<Return | undefined> => { | ||
@@ -49,3 +49,3 @@ cleanup (); | ||
} as any; | ||
}; | ||
@@ -56,7 +56,7 @@ }; | ||
const retryifySync = <T extends Function> ( fn: T, isRetriableError: (( error: NodeJS.ErrnoException ) => boolean | void) ): (( timeout: number ) => T) => { | ||
const retryifySync = <Args extends unknown[], Return> ( fn: ( ...args: Args ) => Return, isRetriableError: (( error: unknown ) => boolean | void) ): (( timeout: number ) => ( ...args: Args ) => Return | undefined) => { | ||
return function retrified ( timestamp: number ) { | ||
return function attempt ( ...args ) { | ||
return function attempt ( ...args: Args ): Return { | ||
@@ -67,3 +67,3 @@ try { | ||
} catch ( error: any ) { | ||
} catch ( error: unknown ) { | ||
@@ -78,3 +78,3 @@ if ( Date.now () > timestamp ) throw error; | ||
} as any; | ||
}; | ||
@@ -81,0 +81,0 @@ }; |
{ | ||
"extends": "tsex/tsconfig.json", | ||
"compilerOptions": { | ||
"noImplicitAny": false | ||
} | ||
"extends": "tsex/tsconfig.json" | ||
} |
25726
510