Download web/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js from Amitkumar001/Law_Slm: direct link, hf CLI and curl.
- Browser
- Download file 24.3 kB
-
https://huggingface.co/Amitkumar001/Law_Slm/resolve/main/web/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js
- Command line
-
hf download hf://Amitkumar001/Law_Slm/web/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js
-
curl -L -o CachedInputFileSystem.js https://huggingface.co/Amitkumar001/Law_Slm/resolve/main/web/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js
24.3 kB
| /* | |
| MIT License http://www.opensource.org/licenses/mit-license.php | |
| Author Tobias Koppers @sokra | |
| */ | |
| ; | |
| // eslint-disable-next-line n/prefer-global/process | |
| const { nextTick } = require("process"); | |
| /** @typedef {import("./Resolver").FileSystem} FileSystem */ | |
| /** @typedef {import("./Resolver").PathLike} PathLike */ | |
| /** @typedef {import("./Resolver").PathOrFileDescriptor} PathOrFileDescriptor */ | |
| /** @typedef {import("./Resolver").SyncFileSystem} SyncFileSystem */ | |
| /** @typedef {FileSystem & SyncFileSystem} BaseFileSystem */ | |
| /** | |
| * @template T | |
| * @typedef {import("./Resolver").FileSystemCallback<T>} FileSystemCallback<T> | |
| */ | |
| /** | |
| * @param {string} path path | |
| * @returns {string} dirname | |
| */ | |
| const dirname = (path) => { | |
| let idx = path.length - 1; | |
| while (idx >= 0) { | |
| const char = path.charCodeAt(idx); | |
| // slash or backslash | |
| if (char === 47 || char === 92) break; | |
| idx--; | |
| } | |
| if (idx < 0) return ""; | |
| return path.slice(0, idx); | |
| }; | |
| /** | |
| * @template T | |
| * @param {FileSystemCallback<T>[]} callbacks callbacks | |
| * @param {Error | null} err error | |
| * @param {T} result result | |
| */ | |
| const runCallbacks = (callbacks, err, result) => { | |
| if (callbacks.length === 1) { | |
| callbacks[0](err, result); | |
| callbacks.length = 0; | |
| return; | |
| } | |
| let error; | |
| for (const callback of callbacks) { | |
| try { | |
| callback(err, result); | |
| } catch (err) { | |
| if (!error) error = err; | |
| } | |
| } | |
| callbacks.length = 0; | |
| if (error) throw error; | |
| }; | |
| // eslint-disable-next-line jsdoc/reject-function-type | |
| /** @typedef {Function} EXPECTED_FUNCTION */ | |
| // eslint-disable-next-line jsdoc/reject-any-type | |
| /** @typedef {any} EXPECTED_ANY */ | |
| /** | |
| * The first pending cache hit is held in these slots (a scheduled tick is | |
| * pending iff `firstCallback` is set); later hits from the same synchronous | |
| * burst spill into `dispatchQueue` as flat [callback, err, result] triples | |
| * and are drained by the same tick. This keeps the common single-hit case | |
| * as cheap as a plain `nextTick` while bursts share one tick. | |
| * @type {FileSystemCallback<EXPECTED_ANY> | undefined} | |
| */ | |
| let firstCallback; | |
| /** @type {Error | null} */ | |
| let firstErr = null; | |
| /** @type {EXPECTED_ANY} */ | |
| let firstResult; | |
| /** @type {EXPECTED_ANY[]} */ | |
| let dispatchQueue = []; | |
| let dispatchQueueLength = 0; | |
| /** @type {EXPECTED_ANY[]} */ | |
| let spareQueue = []; | |
| // upper bound on the spill-array capacity kept alive between bursts | |
| const MAX_RETAINED_QUEUE_LENGTH = 1024; | |
| const runDispatch = () => { | |
| const callback = /** @type {FileSystemCallback<EXPECTED_ANY>} */ ( | |
| firstCallback | |
| ); | |
| const err = firstErr; | |
| const result = firstResult; | |
| // clear before calling: hits made from inside a callback start a new tick | |
| firstCallback = undefined; | |
| firstErr = null; | |
| firstResult = undefined; | |
| if (dispatchQueueLength === 0) { | |
| // single hit: no queue bookkeeping, a throw affects nobody else | |
| callback(err, result); | |
| return; | |
| } | |
| const queue = dispatchQueue; | |
| const length = dispatchQueueLength; | |
| // ping-pong the two arrays so draining never allocates | |
| dispatchQueue = spareQueue; | |
| dispatchQueueLength = 0; | |
| let i = -3; | |
| try { | |
| callback(err, result); | |
| for (i = 0; i < length; i += 3) { | |
| queue[i](queue[i + 1], queue[i + 2]); | |
| } | |
| } finally { | |
| // a throwing callback must not starve the rest: re-schedule the | |
| // remainder ahead of anything scheduled during this drain (matching | |
| // the old per-tick FIFO order) and rethrow | |
| i += 3; | |
| if (i < length) { | |
| if (firstCallback === undefined) { | |
| // no reentrant hit took the slot, so `dispatchQueue` is empty | |
| firstCallback = queue[i]; | |
| firstErr = queue[i + 1]; | |
| firstResult = queue[i + 2]; | |
| nextTick(runDispatch); | |
| for (let j = i + 3; j < length; j++) { | |
| dispatchQueue[dispatchQueueLength++] = queue[j]; | |
| } | |
| } else { | |
| // a reentrant hit claimed the slot (and scheduled the tick); | |
| // displace it behind the remainder to keep FIFO order | |
| const rest = queue.slice(i, length); | |
| rest.push(firstCallback, firstErr, firstResult); | |
| for (let j = 0; j < dispatchQueueLength; j++) { | |
| rest.push(dispatchQueue[j]); | |
| } | |
| [firstCallback, firstErr, firstResult] = rest; | |
| dispatchQueue = rest.slice(3); | |
| dispatchQueueLength = dispatchQueue.length; | |
| } | |
| } | |
| // release references but keep the backing store, so the next burst | |
| // does not have to re-grow the array from scratch | |
| for (let j = 0; j < length; j++) queue[j] = undefined; | |
| // bound the permanently retained capacity after a rare giant burst | |
| if (queue.length > MAX_RETAINED_QUEUE_LENGTH) { | |
| queue.length = MAX_RETAINED_QUEUE_LENGTH; | |
| } | |
| spareQueue = queue; | |
| } | |
| }; | |
| /** | |
| * Cache hits stay asynchronous, but all hits from the same synchronous | |
| * execution share a single `nextTick` instead of scheduling one each. | |
| * @param {FileSystemCallback<EXPECTED_ANY>} callback callback | |
| * @param {Error | null} err error | |
| * @param {EXPECTED_ANY} result result | |
| */ | |
| const scheduleDispatch = (callback, err, result) => { | |
| if (firstCallback === undefined) { | |
| firstCallback = callback; | |
| firstErr = err; | |
| firstResult = result; | |
| nextTick(runDispatch); | |
| } else { | |
| const queue = dispatchQueue; | |
| queue[dispatchQueueLength] = callback; | |
| queue[dispatchQueueLength + 1] = err; | |
| queue[dispatchQueueLength + 2] = result; | |
| dispatchQueueLength += 3; | |
| } | |
| }; | |
| class OperationMergerBackend { | |
| /** | |
| * @param {EXPECTED_FUNCTION | undefined} provider async method in filesystem | |
| * @param {EXPECTED_FUNCTION | undefined} syncProvider sync method in filesystem | |
| * @param {BaseFileSystem} providerContext call context for the provider methods | |
| */ | |
| constructor(provider, syncProvider, providerContext) { | |
| this._provider = provider; | |
| this._syncProvider = syncProvider; | |
| this._providerContext = providerContext; | |
| this._activeAsyncOperations = new Map(); | |
| this.provide = this._provider | |
| ? // Comment to align jsdoc | |
| /** | |
| * @param {PathLike | PathOrFileDescriptor} path path | |
| * @param {object | FileSystemCallback<EXPECTED_ANY> | undefined} options options | |
| * @param {FileSystemCallback<EXPECTED_ANY>=} callback callback | |
| * @returns {EXPECTED_ANY} result | |
| */ | |
| (path, options, callback) => { | |
| if (typeof options === "function") { | |
| callback = | |
| /** @type {FileSystemCallback<EXPECTED_ANY>} */ | |
| (options); | |
| options = undefined; | |
| } | |
| if ( | |
| typeof path !== "string" && | |
| !Buffer.isBuffer(path) && | |
| !(path instanceof URL) && | |
| typeof path !== "number" | |
| ) { | |
| /** @type {EXPECTED_FUNCTION} */ | |
| (callback)( | |
| new TypeError("path must be a string, Buffer, URL or number"), | |
| ); | |
| return; | |
| } | |
| if (options) { | |
| return /** @type {EXPECTED_FUNCTION} */ (this._provider).call( | |
| this._providerContext, | |
| path, | |
| options, | |
| callback, | |
| ); | |
| } | |
| let callbacks = this._activeAsyncOperations.get(path); | |
| if (callbacks) { | |
| callbacks.push(callback); | |
| return; | |
| } | |
| this._activeAsyncOperations.set(path, (callbacks = [callback])); | |
| /** @type {EXPECTED_FUNCTION} */ | |
| (provider)( | |
| path, | |
| /** | |
| * @param {Error} err error | |
| * @param {EXPECTED_ANY} result result | |
| */ | |
| (err, result) => { | |
| this._activeAsyncOperations.delete(path); | |
| runCallbacks(callbacks, err, result); | |
| }, | |
| ); | |
| } | |
| : null; | |
| this.provideSync = this._syncProvider | |
| ? // Comment to align jsdoc | |
| /** | |
| * @param {PathLike | PathOrFileDescriptor} path path | |
| * @param {object=} options options | |
| * @returns {EXPECTED_ANY} result | |
| */ | |
| (path, options) => | |
| /** @type {EXPECTED_FUNCTION} */ (this._syncProvider).call( | |
| this._providerContext, | |
| path, | |
| options, | |
| ) | |
| : null; | |
| } | |
| purge() {} | |
| purgeParent() {} | |
| } | |
| /* | |
| IDLE: | |
| insert data: goto SYNC | |
| SYNC: | |
| before provide: run ticks | |
| event loop tick: goto ASYNC_ACTIVE | |
| ASYNC: | |
| timeout: run tick, goto ASYNC_PASSIVE | |
| ASYNC_PASSIVE: | |
| before provide: run ticks | |
| IDLE --[insert data]--> SYNC --[event loop tick]--> ASYNC_ACTIVE --[interval tick]-> ASYNC_PASSIVE | |
| ^ | | |
| +---------[insert data]-------+ | |
| */ | |
| const STORAGE_MODE_IDLE = 0; | |
| const STORAGE_MODE_SYNC = 1; | |
| const STORAGE_MODE_ASYNC = 2; | |
| /** | |
| * @callback Provide | |
| * @param {PathLike | PathOrFileDescriptor} path path | |
| * @param {EXPECTED_ANY} options options | |
| * @param {FileSystemCallback<EXPECTED_ANY>} callback callback | |
| * @returns {void} | |
| */ | |
| class CacheBackend { | |
| /** | |
| * @param {number} duration max cache duration of items | |
| * @param {EXPECTED_FUNCTION | undefined} provider async method | |
| * @param {EXPECTED_FUNCTION | undefined} syncProvider sync method | |
| * @param {BaseFileSystem} providerContext call context for the provider methods | |
| */ | |
| constructor(duration, provider, syncProvider, providerContext) { | |
| this._duration = duration; | |
| this._provider = provider; | |
| this._syncProvider = syncProvider; | |
| this._providerContext = providerContext; | |
| /** @type {Map<string, FileSystemCallback<EXPECTED_ANY>[]>} */ | |
| this._activeAsyncOperations = new Map(); | |
| /** @type {Map<string, { err: Error | null, result?: EXPECTED_ANY, level: Set<string> }>} */ | |
| this._data = new Map(); | |
| /** @type {Set<string>[]} */ | |
| this._levels = []; | |
| for (let i = 0; i < 10; i++) this._levels.push(new Set()); | |
| if (duration !== Infinity) { | |
| for (let i = 5000; i < duration; i += 500) { | |
| this._levels.push(new Set()); | |
| } | |
| } | |
| this._currentLevel = 0; | |
| this._tickInterval = Math.floor(duration / this._levels.length); | |
| /** @type {STORAGE_MODE_IDLE | STORAGE_MODE_SYNC | STORAGE_MODE_ASYNC} */ | |
| this._mode = STORAGE_MODE_IDLE; | |
| /** @type {NodeJS.Timeout | undefined} */ | |
| this._timeout = undefined; | |
| /** @type {number | undefined} */ | |
| this._nextDecay = undefined; | |
| // eslint-disable-next-line no-warning-comments | |
| // @ts-ignore | |
| this.provide = provider ? this.provide.bind(this) : null; | |
| // eslint-disable-next-line no-warning-comments | |
| // @ts-ignore | |
| this.provideSync = syncProvider ? this.provideSync.bind(this) : null; | |
| } | |
| /** | |
| * @param {PathLike | PathOrFileDescriptor} path path | |
| * @param {EXPECTED_ANY} options options | |
| * @param {FileSystemCallback<EXPECTED_ANY>} callback callback | |
| * @returns {void} | |
| */ | |
| provide(path, options, callback) { | |
| if (typeof options === "function") { | |
| callback = options; | |
| options = undefined; | |
| } | |
| if ( | |
| typeof path !== "string" && | |
| !Buffer.isBuffer(path) && | |
| !(path instanceof URL) && | |
| typeof path !== "number" | |
| ) { | |
| callback(new TypeError("path must be a string, Buffer, URL or number")); | |
| return; | |
| } | |
| const strPath = typeof path !== "string" ? path.toString() : path; | |
| if (options) { | |
| return /** @type {EXPECTED_FUNCTION} */ (this._provider).call( | |
| this._providerContext, | |
| path, | |
| options, | |
| callback, | |
| ); | |
| } | |
| // When in sync mode we can move to async mode | |
| if (this._mode === STORAGE_MODE_SYNC) { | |
| this._enterAsyncMode(); | |
| } | |
| // Check in cache | |
| const cacheEntry = this._data.get(strPath); | |
| if (cacheEntry !== undefined) { | |
| if (cacheEntry.err) { | |
| return scheduleDispatch(callback, cacheEntry.err, undefined); | |
| } | |
| return scheduleDispatch(callback, null, cacheEntry.result); | |
| } | |
| // Check if there is already the same operation running | |
| let callbacks = this._activeAsyncOperations.get(strPath); | |
| if (callbacks !== undefined) { | |
| callbacks.push(callback); | |
| return; | |
| } | |
| this._activeAsyncOperations.set(strPath, (callbacks = [callback])); | |
| // Run the operation | |
| /** @type {EXPECTED_FUNCTION} */ | |
| (this._provider).call( | |
| this._providerContext, | |
| path, | |
| /** | |
| * @param {Error | null} err error | |
| * @param {EXPECTED_ANY=} result result | |
| */ | |
| (err, result) => { | |
| this._activeAsyncOperations.delete(strPath); | |
| this._storeResult(strPath, err, result); | |
| // Enter async mode if not yet done | |
| this._enterAsyncMode(); | |
| runCallbacks( | |
| /** @type {FileSystemCallback<EXPECTED_ANY>[]} */ (callbacks), | |
| err, | |
| result, | |
| ); | |
| }, | |
| ); | |
| } | |
| /** | |
| * @param {PathLike | PathOrFileDescriptor} path path | |
| * @param {EXPECTED_ANY} options options | |
| * @returns {EXPECTED_ANY} result | |
| */ | |
| provideSync(path, options) { | |
| if ( | |
| typeof path !== "string" && | |
| !Buffer.isBuffer(path) && | |
| !(path instanceof URL) && | |
| typeof path !== "number" | |
| ) { | |
| throw new TypeError("path must be a string"); | |
| } | |
| const strPath = typeof path !== "string" ? path.toString() : path; | |
| if (options) { | |
| return /** @type {EXPECTED_FUNCTION} */ (this._syncProvider).call( | |
| this._providerContext, | |
| path, | |
| options, | |
| ); | |
| } | |
| // In sync mode we may have to decay some cache items | |
| if (this._mode === STORAGE_MODE_SYNC) { | |
| this._runDecays(); | |
| } | |
| // Check in cache | |
| const cacheEntry = this._data.get(strPath); | |
| if (cacheEntry !== undefined) { | |
| if (cacheEntry.err) throw cacheEntry.err; | |
| return cacheEntry.result; | |
| } | |
| // Get all active async operations | |
| // This sync operation will also complete them | |
| const callbacks = this._activeAsyncOperations.get(strPath); | |
| this._activeAsyncOperations.delete(strPath); | |
| // Run the operation | |
| // When in idle mode, we will enter sync mode | |
| let result; | |
| try { | |
| result = /** @type {EXPECTED_FUNCTION} */ (this._syncProvider).call( | |
| this._providerContext, | |
| path, | |
| ); | |
| } catch (err) { | |
| this._storeResult(strPath, /** @type {Error} */ (err), undefined); | |
| this._enterSyncModeWhenIdle(); | |
| if (callbacks) { | |
| runCallbacks(callbacks, /** @type {Error} */ (err), undefined); | |
| } | |
| throw err; | |
| } | |
| this._storeResult(strPath, null, result); | |
| this._enterSyncModeWhenIdle(); | |
| if (callbacks) { | |
| runCallbacks(callbacks, null, result); | |
| } | |
| return result; | |
| } | |
| /** | |
| * @param {(string | Buffer | URL | number | (string | URL | Buffer | number)[] | Set<string | URL | Buffer | number>)=} what what to purge | |
| * @param {{ exact?: boolean }=} options options; `exact: true` removes only entries whose key matches `what` exactly instead of any entry whose key starts with `what` | |
| */ | |
| purge(what, options) { | |
| if (what === undefined || what === null) { | |
| if (this._mode !== STORAGE_MODE_IDLE) { | |
| this._data.clear(); | |
| for (const level of this._levels) { | |
| level.clear(); | |
| } | |
| this._enterIdleMode(); | |
| } | |
| return; | |
| } | |
| const exact = | |
| options !== undefined && options !== null && options.exact === true; | |
| if (exact) { | |
| if ( | |
| typeof what === "string" || | |
| Buffer.isBuffer(what) || | |
| what instanceof URL || | |
| typeof what === "number" | |
| ) { | |
| const strWhat = typeof what !== "string" ? what.toString() : what; | |
| const data = this._data.get(strWhat); | |
| if (data !== undefined) { | |
| this._data.delete(strWhat); | |
| data.level.delete(strWhat); | |
| } | |
| } else { | |
| for (const item of what) { | |
| const strItem = typeof item !== "string" ? item.toString() : item; | |
| const data = this._data.get(strItem); | |
| if (data !== undefined) { | |
| this._data.delete(strItem); | |
| data.level.delete(strItem); | |
| } | |
| } | |
| } | |
| if (this._data.size === 0) { | |
| this._enterIdleMode(); | |
| } | |
| return; | |
| } | |
| if ( | |
| typeof what === "string" || | |
| Buffer.isBuffer(what) || | |
| what instanceof URL || | |
| typeof what === "number" | |
| ) { | |
| const strWhat = typeof what !== "string" ? what.toString() : what; | |
| if (strWhat === "") { | |
| // empty string is a prefix of every key — short-circuit the O(n) scan | |
| if (this._mode !== STORAGE_MODE_IDLE) { | |
| this._data.clear(); | |
| for (const level of this._levels) { | |
| level.clear(); | |
| } | |
| this._enterIdleMode(); | |
| } | |
| return; | |
| } | |
| for (const [key, data] of this._data) { | |
| if (key.startsWith(strWhat)) { | |
| this._data.delete(key); | |
| data.level.delete(key); | |
| } | |
| } | |
| if (this._data.size === 0) { | |
| this._enterIdleMode(); | |
| } | |
| } else { | |
| for (const [key, data] of this._data) { | |
| for (const item of what) { | |
| const strItem = typeof item !== "string" ? item.toString() : item; | |
| if (key.startsWith(strItem)) { | |
| this._data.delete(key); | |
| data.level.delete(key); | |
| break; | |
| } | |
| } | |
| } | |
| if (this._data.size === 0) { | |
| this._enterIdleMode(); | |
| } | |
| } | |
| } | |
| /** | |
| * @param {(string | Buffer | URL | number | (string | URL | Buffer | number)[] | Set<string | URL | Buffer | number>)=} what what to purge | |
| */ | |
| purgeParent(what) { | |
| if (what === undefined || what === null) { | |
| this.purge(); | |
| } else if ( | |
| typeof what === "string" || | |
| Buffer.isBuffer(what) || | |
| what instanceof URL || | |
| typeof what === "number" | |
| ) { | |
| const strWhat = typeof what !== "string" ? what.toString() : what; | |
| this.purge(dirname(strWhat)); | |
| } else { | |
| const set = new Set(); | |
| for (const item of what) { | |
| const strItem = typeof item !== "string" ? item.toString() : item; | |
| set.add(dirname(strItem)); | |
| } | |
| this.purge(set); | |
| } | |
| } | |
| /** | |
| * @param {string} path path | |
| * @param {Error | null} err error | |
| * @param {EXPECTED_ANY} result result | |
| */ | |
| _storeResult(path, err, result) { | |
| if (this._data.has(path)) return; | |
| const level = this._levels[this._currentLevel]; | |
| this._data.set(path, { err, result, level }); | |
| level.add(path); | |
| } | |
| _decayLevel() { | |
| const nextLevel = (this._currentLevel + 1) % this._levels.length; | |
| const decay = this._levels[nextLevel]; | |
| this._currentLevel = nextLevel; | |
| for (const item of decay) { | |
| this._data.delete(item); | |
| } | |
| decay.clear(); | |
| if (this._data.size === 0) { | |
| this._enterIdleMode(); | |
| } else { | |
| /** @type {number} */ | |
| (this._nextDecay) += this._tickInterval; | |
| } | |
| } | |
| _runDecays() { | |
| while ( | |
| /** @type {number} */ (this._nextDecay) <= Date.now() && | |
| this._mode !== STORAGE_MODE_IDLE | |
| ) { | |
| this._decayLevel(); | |
| } | |
| } | |
| _enterAsyncMode() { | |
| let timeout = 0; | |
| switch (this._mode) { | |
| case STORAGE_MODE_ASYNC: | |
| return; | |
| case STORAGE_MODE_IDLE: | |
| this._nextDecay = Date.now() + this._tickInterval; | |
| timeout = this._tickInterval; | |
| break; | |
| case STORAGE_MODE_SYNC: | |
| this._runDecays(); | |
| // _runDecays may change the mode | |
| if ( | |
| /** @type {STORAGE_MODE_IDLE | STORAGE_MODE_SYNC | STORAGE_MODE_ASYNC} */ | |
| (this._mode) === STORAGE_MODE_IDLE | |
| ) { | |
| return; | |
| } | |
| timeout = Math.max( | |
| 0, | |
| /** @type {number} */ (this._nextDecay) - Date.now(), | |
| ); | |
| break; | |
| } | |
| this._mode = STORAGE_MODE_ASYNC; | |
| // When duration is Infinity, cache entries never expire, so there | |
| // is no need to schedule a decay timer. | |
| if (this._duration === Infinity) { | |
| return; | |
| } | |
| const ref = setTimeout(() => { | |
| this._mode = STORAGE_MODE_SYNC; | |
| this._runDecays(); | |
| }, timeout); | |
| if (ref.unref) ref.unref(); | |
| this._timeout = ref; | |
| } | |
| _enterSyncModeWhenIdle() { | |
| if (this._mode === STORAGE_MODE_IDLE) { | |
| this._mode = STORAGE_MODE_SYNC; | |
| this._nextDecay = Date.now() + this._tickInterval; | |
| } | |
| } | |
| _enterIdleMode() { | |
| this._mode = STORAGE_MODE_IDLE; | |
| this._nextDecay = undefined; | |
| if (this._timeout) clearTimeout(this._timeout); | |
| } | |
| } | |
| /** | |
| * @template {EXPECTED_FUNCTION} Provider | |
| * @template {EXPECTED_FUNCTION} AsyncProvider | |
| * @template FileSystem | |
| * @param {number} duration duration in ms files are cached | |
| * @param {Provider | undefined} provider provider | |
| * @param {AsyncProvider | undefined} syncProvider sync provider | |
| * @param {BaseFileSystem} providerContext provider context | |
| * @returns {OperationMergerBackend | CacheBackend} backend | |
| */ | |
| const createBackend = (duration, provider, syncProvider, providerContext) => { | |
| if (duration > 0) { | |
| return new CacheBackend(duration, provider, syncProvider, providerContext); | |
| } | |
| return new OperationMergerBackend(provider, syncProvider, providerContext); | |
| }; | |
| module.exports = class CachedInputFileSystem { | |
| /** | |
| * @param {BaseFileSystem} fileSystem file system | |
| * @param {number} duration duration in ms files are cached | |
| */ | |
| constructor(fileSystem, duration) { | |
| this.fileSystem = fileSystem; | |
| this._lstatBackend = createBackend( | |
| duration, | |
| this.fileSystem.lstat, | |
| this.fileSystem.lstatSync, | |
| this.fileSystem, | |
| ); | |
| const lstat = this._lstatBackend.provide; | |
| this.lstat = /** @type {FileSystem["lstat"]} */ (lstat); | |
| const lstatSync = this._lstatBackend.provideSync; | |
| this.lstatSync = /** @type {SyncFileSystem["lstatSync"]} */ (lstatSync); | |
| this._statBackend = createBackend( | |
| duration, | |
| this.fileSystem.stat, | |
| this.fileSystem.statSync, | |
| this.fileSystem, | |
| ); | |
| const stat = this._statBackend.provide; | |
| this.stat = /** @type {FileSystem["stat"]} */ (stat); | |
| const statSync = this._statBackend.provideSync; | |
| this.statSync = /** @type {SyncFileSystem["statSync"]} */ (statSync); | |
| this._readdirBackend = createBackend( | |
| duration, | |
| this.fileSystem.readdir, | |
| this.fileSystem.readdirSync, | |
| this.fileSystem, | |
| ); | |
| const readdir = this._readdirBackend.provide; | |
| this.readdir = /** @type {FileSystem["readdir"]} */ (readdir); | |
| const readdirSync = this._readdirBackend.provideSync; | |
| this.readdirSync = /** @type {SyncFileSystem["readdirSync"]} */ ( | |
| readdirSync | |
| ); | |
| this._readFileBackend = createBackend( | |
| duration, | |
| this.fileSystem.readFile, | |
| this.fileSystem.readFileSync, | |
| this.fileSystem, | |
| ); | |
| const readFile = this._readFileBackend.provide; | |
| this.readFile = /** @type {FileSystem["readFile"]} */ (readFile); | |
| const readFileSync = this._readFileBackend.provideSync; | |
| this.readFileSync = /** @type {SyncFileSystem["readFileSync"]} */ ( | |
| readFileSync | |
| ); | |
| this._readJsonBackend = createBackend( | |
| duration, | |
| // prettier-ignore | |
| this.fileSystem.readJson || | |
| (this.readFile && | |
| ( | |
| /** | |
| * @param {string} path path | |
| * @param {FileSystemCallback<EXPECTED_ANY>} callback callback | |
| */ | |
| (path, callback) => { | |
| this.readFile(path, (err, buffer) => { | |
| if (err) return callback(err); | |
| if (!buffer || buffer.length === 0) | |
| {return callback(new Error("No file content"));} | |
| let data; | |
| try { | |
| data = JSON.parse(buffer.toString("utf8")); | |
| } catch (err_) { | |
| return callback(/** @type {Error} */ (err_)); | |
| } | |
| callback(null, data); | |
| }); | |
| }) | |
| ), | |
| // prettier-ignore | |
| this.fileSystem.readJsonSync || | |
| (this.readFileSync && | |
| ( | |
| /** | |
| * @param {string} path path | |
| * @returns {EXPECTED_ANY} result | |
| */ | |
| (path) => { | |
| const buffer = this.readFileSync(path); | |
| const data = JSON.parse(buffer.toString("utf8")); | |
| return data; | |
| } | |
| )), | |
| this.fileSystem, | |
| ); | |
| const readJson = this._readJsonBackend.provide; | |
| this.readJson = /** @type {FileSystem["readJson"]} */ (readJson); | |
| const readJsonSync = this._readJsonBackend.provideSync; | |
| this.readJsonSync = /** @type {SyncFileSystem["readJsonSync"]} */ ( | |
| readJsonSync | |
| ); | |
| this._readlinkBackend = createBackend( | |
| duration, | |
| this.fileSystem.readlink, | |
| this.fileSystem.readlinkSync, | |
| this.fileSystem, | |
| ); | |
| const readlink = this._readlinkBackend.provide; | |
| this.readlink = /** @type {FileSystem["readlink"]} */ (readlink); | |
| const readlinkSync = this._readlinkBackend.provideSync; | |
| this.readlinkSync = /** @type {SyncFileSystem["readlinkSync"]} */ ( | |
| readlinkSync | |
| ); | |
| this._realpathBackend = createBackend( | |
| duration, | |
| this.fileSystem.realpath, | |
| this.fileSystem.realpathSync, | |
| this.fileSystem, | |
| ); | |
| const realpath = this._realpathBackend.provide; | |
| this.realpath = /** @type {FileSystem["realpath"]} */ (realpath); | |
| const realpathSync = this._realpathBackend.provideSync; | |
| this.realpathSync = /** @type {SyncFileSystem["realpathSync"]} */ ( | |
| realpathSync | |
| ); | |
| } | |
| /** | |
| * @param {(string | Buffer | URL | number | (string | URL | Buffer | number)[] | Set<string | URL | Buffer | number>)=} what what to purge | |
| * @param {{ exact?: boolean }=} options options; `exact: true` removes only cache entries whose key matches `what` exactly instead of any entry whose key starts with `what` | |
| */ | |
| purge(what, options) { | |
| this._statBackend.purge(what, options); | |
| this._lstatBackend.purge(what, options); | |
| if (options !== undefined && options !== null && options.exact === true) { | |
| this._readdirBackend.purge(what, options); | |
| } else { | |
| this._readdirBackend.purgeParent(what); | |
| } | |
| this._readFileBackend.purge(what, options); | |
| this._readlinkBackend.purge(what, options); | |
| this._readJsonBackend.purge(what, options); | |
| this._realpathBackend.purge(what, options); | |
| } | |
| }; | |