avancement planning
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
const spawn = require('@npmcli/promise-spawn')
|
||||
const promiseRetry = require('promise-retry')
|
||||
const { promiseRetry } = require('@gar/promise-retry')
|
||||
const { log } = require('proc-log')
|
||||
const makeError = require('./make-error.js')
|
||||
const makeOpts = require('./opts.js')
|
||||
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
The ISC License
|
||||
|
||||
Copyright (c) 2016-2022 Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
+19
-13
@@ -8,18 +8,24 @@ Windows.
|
||||
## USAGE
|
||||
|
||||
```js
|
||||
// default export is a minified version that doesn't need to
|
||||
// load more than one file. Load the 'isexe/raw' export if
|
||||
// you want the non-minified version for some reason.
|
||||
import { isexe, sync } from 'isexe'
|
||||
// or require() works too
|
||||
// const { isexe } = require('isexe')
|
||||
isexe('some-file-name').then(isExe => {
|
||||
if (isExe) {
|
||||
console.error('this thing can be run')
|
||||
} else {
|
||||
console.error('cannot be run')
|
||||
}
|
||||
}, (err) => {
|
||||
console.error('probably file doesnt exist or something')
|
||||
})
|
||||
isexe('some-file-name').then(
|
||||
isExe => {
|
||||
if (isExe) {
|
||||
console.error('this thing can be run')
|
||||
} else {
|
||||
console.error('cannot be run')
|
||||
}
|
||||
},
|
||||
err => {
|
||||
console.error('probably file doesnt exist or something')
|
||||
},
|
||||
)
|
||||
|
||||
// same thing but synchronous, throws errors
|
||||
isExe = sync('some-file-name')
|
||||
@@ -66,9 +72,9 @@ The default exported implementation will be chosen based on
|
||||
import type IsexeOptions from 'isexe'
|
||||
```
|
||||
|
||||
* `ignoreErrors` Treat all errors as "no, this is not
|
||||
- `ignoreErrors` Treat all errors as "no, this is not
|
||||
executable", but don't raise them.
|
||||
* `uid` Number to use as the user id on posix
|
||||
* `gid` Number to use as the group id on posix
|
||||
* `pathExt` List of path extensions to use instead of `PATHEXT`
|
||||
- `uid` Number to use as the user id on posix
|
||||
- `gid` Number to use as the group id on posix
|
||||
- `pathExt` List of path extensions to use instead of `PATHEXT`
|
||||
environment variable on Windows.
|
||||
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
import * as posix from './posix.js';
|
||||
import * as win32 from './win32.js';
|
||||
export * from './options.js';
|
||||
export { win32, posix };
|
||||
/**
|
||||
* Determine whether a path is executable on the current platform.
|
||||
*/
|
||||
export declare const isexe: (path: string, options?: import("./options.js").IsexeOptions) => Promise<boolean>;
|
||||
/**
|
||||
* Synchronously determine whether a path is executable on the
|
||||
* current platform.
|
||||
*/
|
||||
export declare const sync: (path: string, options?: import("./options.js").IsexeOptions) => boolean;
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,cAAc,cAAc,CAAA;AAC5B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;AAKvB;;GAEG;AACH,eAAO,MAAM,KAAK,mFAAa,CAAA;AAC/B;;;GAGG;AACH,eAAO,MAAM,IAAI,0EAAY,CAAA"}
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.sync = exports.isexe = exports.posix = exports.win32 = void 0;
|
||||
const posix = __importStar(require("./posix.js"));
|
||||
exports.posix = posix;
|
||||
const win32 = __importStar(require("./win32.js"));
|
||||
exports.win32 = win32;
|
||||
__exportStar(require("./options.js"), exports);
|
||||
const platform = process.env._ISEXE_TEST_PLATFORM_ || process.platform;
|
||||
const impl = platform === 'win32' ? win32 : posix;
|
||||
/**
|
||||
* Determine whether a path is executable on the current platform.
|
||||
*/
|
||||
exports.isexe = impl.isexe;
|
||||
/**
|
||||
* Synchronously determine whether a path is executable on the
|
||||
* current platform.
|
||||
*/
|
||||
exports.sync = impl.sync;
|
||||
//# sourceMappingURL=index.js.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,kDAAmC;AAGnB,sBAAK;AAFrB,kDAAmC;AAE1B,sBAAK;AADd,+CAA4B;AAG5B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,OAAO,CAAC,QAAQ,CAAA;AACtE,MAAM,IAAI,GAAG,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAA;AAEjD;;GAEG;AACU,QAAA,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;AAC/B;;;GAGG;AACU,QAAA,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA","sourcesContent":["import * as posix from './posix.js'\nimport * as win32 from './win32.js'\nexport * from './options.js'\nexport { win32, posix }\n\nconst platform = process.env._ISEXE_TEST_PLATFORM_ || process.platform\nconst impl = platform === 'win32' ? win32 : posix\n\n/**\n * Determine whether a path is executable on the current platform.\n */\nexport const isexe = impl.isexe\n/**\n * Synchronously determine whether a path is executable on the\n * current platform.\n */\nexport const sync = impl.sync\n"]}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
export interface IsexeOptions {
|
||||
/**
|
||||
* Ignore errors arising from attempting to get file access status
|
||||
* Note that EACCES is always ignored, because that just means
|
||||
* it's not executable. If this is not set, then attempting to check
|
||||
* the executable-ness of a nonexistent file will raise ENOENT, for
|
||||
* example.
|
||||
*/
|
||||
ignoreErrors?: boolean;
|
||||
/**
|
||||
* effective uid when checking executable mode flags on posix
|
||||
* Defaults to process.getuid()
|
||||
*/
|
||||
uid?: number;
|
||||
/**
|
||||
* effective gid when checking executable mode flags on posix
|
||||
* Defaults to process.getgid()
|
||||
*/
|
||||
gid?: number;
|
||||
/**
|
||||
* effective group ID list to use when checking executable mode flags
|
||||
* on posix
|
||||
* Defaults to process.getgroups()
|
||||
*/
|
||||
groups?: number[];
|
||||
/**
|
||||
* The ;-delimited path extension list for win32 implementation.
|
||||
* Defaults to process.env.PATHEXT
|
||||
*/
|
||||
pathExt?: string;
|
||||
}
|
||||
//# sourceMappingURL=options.d.ts.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/options.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IAEtB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IAEZ;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IAEZ;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IAEjB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB"}
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=options.js.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/options.ts"],"names":[],"mappings":"","sourcesContent":["export interface IsexeOptions {\n /**\n * Ignore errors arising from attempting to get file access status\n * Note that EACCES is always ignored, because that just means\n * it's not executable. If this is not set, then attempting to check\n * the executable-ness of a nonexistent file will raise ENOENT, for\n * example.\n */\n ignoreErrors?: boolean\n\n /**\n * effective uid when checking executable mode flags on posix\n * Defaults to process.getuid()\n */\n uid?: number\n\n /**\n * effective gid when checking executable mode flags on posix\n * Defaults to process.getgid()\n */\n gid?: number\n\n /**\n * effective group ID list to use when checking executable mode flags\n * on posix\n * Defaults to process.getgroups()\n */\n groups?: number[]\n\n /**\n * The ;-delimited path extension list for win32 implementation.\n * Defaults to process.env.PATHEXT\n */\n pathExt?: string\n}\n"]}
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"type": "commonjs"
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
* This is the Posix implementation of isexe, which uses the file
|
||||
* mode and uid/gid values.
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
import { IsexeOptions } from './options';
|
||||
/**
|
||||
* Determine whether a path is executable according to the mode and
|
||||
* current (or specified) user and group IDs.
|
||||
*/
|
||||
export declare const isexe: (path: string, options?: IsexeOptions) => Promise<boolean>;
|
||||
/**
|
||||
* Synchronously determine whether a path is executable according to
|
||||
* the mode and current (or specified) user and group IDs.
|
||||
*/
|
||||
export declare const sync: (path: string, options?: IsexeOptions) => boolean;
|
||||
//# sourceMappingURL=posix.d.ts.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"posix.d.ts","sourceRoot":"","sources":["../../src/posix.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAExC;;;GAGG;AACH,eAAO,MAAM,KAAK,SACV,MAAM,YACH,YAAY,KACpB,QAAQ,OAAO,CASjB,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,IAAI,SACT,MAAM,YACH,YAAY,KACpB,OASF,CAAA"}
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
"use strict";
|
||||
/**
|
||||
* This is the Posix implementation of isexe, which uses the file
|
||||
* mode and uid/gid values.
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.sync = exports.isexe = void 0;
|
||||
const fs_1 = require("fs");
|
||||
const promises_1 = require("fs/promises");
|
||||
/**
|
||||
* Determine whether a path is executable according to the mode and
|
||||
* current (or specified) user and group IDs.
|
||||
*/
|
||||
const isexe = async (path, options = {}) => {
|
||||
const { ignoreErrors = false } = options;
|
||||
try {
|
||||
return checkStat(await (0, promises_1.stat)(path), options);
|
||||
}
|
||||
catch (e) {
|
||||
const er = e;
|
||||
if (ignoreErrors || er.code === 'EACCES')
|
||||
return false;
|
||||
throw er;
|
||||
}
|
||||
};
|
||||
exports.isexe = isexe;
|
||||
/**
|
||||
* Synchronously determine whether a path is executable according to
|
||||
* the mode and current (or specified) user and group IDs.
|
||||
*/
|
||||
const sync = (path, options = {}) => {
|
||||
const { ignoreErrors = false } = options;
|
||||
try {
|
||||
return checkStat((0, fs_1.statSync)(path), options);
|
||||
}
|
||||
catch (e) {
|
||||
const er = e;
|
||||
if (ignoreErrors || er.code === 'EACCES')
|
||||
return false;
|
||||
throw er;
|
||||
}
|
||||
};
|
||||
exports.sync = sync;
|
||||
const checkStat = (stat, options) => stat.isFile() && checkMode(stat, options);
|
||||
const checkMode = (stat, options) => {
|
||||
const myUid = options.uid ?? process.getuid?.();
|
||||
const myGroups = options.groups ?? process.getgroups?.() ?? [];
|
||||
const myGid = options.gid ?? process.getgid?.() ?? myGroups[0];
|
||||
if (myUid === undefined || myGid === undefined) {
|
||||
throw new Error('cannot get uid or gid');
|
||||
}
|
||||
const groups = new Set([myGid, ...myGroups]);
|
||||
const mod = stat.mode;
|
||||
const uid = stat.uid;
|
||||
const gid = stat.gid;
|
||||
const u = parseInt('100', 8);
|
||||
const g = parseInt('010', 8);
|
||||
const o = parseInt('001', 8);
|
||||
const ug = u | g;
|
||||
return !!(mod & o ||
|
||||
(mod & g && groups.has(gid)) ||
|
||||
(mod & u && uid === myUid) ||
|
||||
(mod & ug && myUid === 0));
|
||||
};
|
||||
//# sourceMappingURL=posix.js.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"posix.js","sourceRoot":"","sources":["../../src/posix.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEH,2BAAoC;AACpC,0CAAkC;AAGlC;;;GAGG;AACI,MAAM,KAAK,GAAG,KAAK,EACxB,IAAY,EACZ,UAAwB,EAAE,EACR,EAAE;IACpB,MAAM,EAAE,YAAY,GAAG,KAAK,EAAE,GAAG,OAAO,CAAA;IACxC,IAAI;QACF,OAAO,SAAS,CAAC,MAAM,IAAA,eAAI,EAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAA;KAC5C;IAAC,OAAO,CAAC,EAAE;QACV,MAAM,EAAE,GAAG,CAA0B,CAAA;QACrC,IAAI,YAAY,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAA;QACtD,MAAM,EAAE,CAAA;KACT;AACH,CAAC,CAAA;AAZY,QAAA,KAAK,SAYjB;AAED;;;GAGG;AACI,MAAM,IAAI,GAAG,CAClB,IAAY,EACZ,UAAwB,EAAE,EACjB,EAAE;IACX,MAAM,EAAE,YAAY,GAAG,KAAK,EAAE,GAAG,OAAO,CAAA;IACxC,IAAI;QACF,OAAO,SAAS,CAAC,IAAA,aAAQ,EAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAA;KAC1C;IAAC,OAAO,CAAC,EAAE;QACV,MAAM,EAAE,GAAG,CAA0B,CAAA;QACrC,IAAI,YAAY,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAA;QACtD,MAAM,EAAE,CAAA;KACT;AACH,CAAC,CAAA;AAZY,QAAA,IAAI,QAYhB;AAED,MAAM,SAAS,GAAG,CAAC,IAAW,EAAE,OAAqB,EAAE,EAAE,CACvD,IAAI,CAAC,MAAM,EAAE,IAAI,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;AAE3C,MAAM,SAAS,GAAG,CAAC,IAAW,EAAE,OAAqB,EAAE,EAAE;IACvD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAA;IAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,CAAA;IAC9D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAA;IAC9D,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,EAAE;QAC9C,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAA;KACzC;IAED,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAA;IAE5C,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAA;IACrB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAA;IACpB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAA;IAEpB,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IAC5B,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IAC5B,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IAC5B,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAA;IAEhB,OAAO,CAAC,CAAC,CACP,GAAG,GAAG,CAAC;QACP,CAAC,GAAG,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,KAAK,KAAK,CAAC;QAC1B,CAAC,GAAG,GAAG,EAAE,IAAI,KAAK,KAAK,CAAC,CAAC,CAC1B,CAAA;AACH,CAAC,CAAA","sourcesContent":["/**\n * This is the Posix implementation of isexe, which uses the file\n * mode and uid/gid values.\n *\n * @module\n */\n\nimport { Stats, statSync } from 'fs'\nimport { stat } from 'fs/promises'\nimport { IsexeOptions } from './options'\n\n/**\n * Determine whether a path is executable according to the mode and\n * current (or specified) user and group IDs.\n */\nexport const isexe = async (\n path: string,\n options: IsexeOptions = {}\n): Promise<boolean> => {\n const { ignoreErrors = false } = options\n try {\n return checkStat(await stat(path), options)\n } catch (e) {\n const er = e as NodeJS.ErrnoException\n if (ignoreErrors || er.code === 'EACCES') return false\n throw er\n }\n}\n\n/**\n * Synchronously determine whether a path is executable according to\n * the mode and current (or specified) user and group IDs.\n */\nexport const sync = (\n path: string,\n options: IsexeOptions = {}\n): boolean => {\n const { ignoreErrors = false } = options\n try {\n return checkStat(statSync(path), options)\n } catch (e) {\n const er = e as NodeJS.ErrnoException\n if (ignoreErrors || er.code === 'EACCES') return false\n throw er\n }\n}\n\nconst checkStat = (stat: Stats, options: IsexeOptions) =>\n stat.isFile() && checkMode(stat, options)\n\nconst checkMode = (stat: Stats, options: IsexeOptions) => {\n const myUid = options.uid ?? process.getuid?.()\n const myGroups = options.groups ?? process.getgroups?.() ?? []\n const myGid = options.gid ?? process.getgid?.() ?? myGroups[0]\n if (myUid === undefined || myGid === undefined) {\n throw new Error('cannot get uid or gid')\n }\n\n const groups = new Set([myGid, ...myGroups])\n\n const mod = stat.mode\n const uid = stat.uid\n const gid = stat.gid\n\n const u = parseInt('100', 8)\n const g = parseInt('010', 8)\n const o = parseInt('001', 8)\n const ug = u | g\n\n return !!(\n mod & o ||\n (mod & g && groups.has(gid)) ||\n (mod & u && uid === myUid) ||\n (mod & ug && myUid === 0)\n )\n}\n"]}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
* This is the Windows implementation of isexe, which uses the file
|
||||
* extension and PATHEXT setting.
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
import { IsexeOptions } from './options';
|
||||
/**
|
||||
* Determine whether a path is executable based on the file extension
|
||||
* and PATHEXT environment variable (or specified pathExt option)
|
||||
*/
|
||||
export declare const isexe: (path: string, options?: IsexeOptions) => Promise<boolean>;
|
||||
/**
|
||||
* Synchronously determine whether a path is executable based on the file
|
||||
* extension and PATHEXT environment variable (or specified pathExt option)
|
||||
*/
|
||||
export declare const sync: (path: string, options?: IsexeOptions) => boolean;
|
||||
//# sourceMappingURL=win32.d.ts.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"win32.d.ts","sourceRoot":"","sources":["../../src/win32.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAExC;;;GAGG;AACH,eAAO,MAAM,KAAK,SACV,MAAM,YACH,YAAY,KACpB,QAAQ,OAAO,CASjB,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,IAAI,SACT,MAAM,YACH,YAAY,KACpB,OASF,CAAA"}
|
||||
-62
@@ -1,62 +0,0 @@
|
||||
"use strict";
|
||||
/**
|
||||
* This is the Windows implementation of isexe, which uses the file
|
||||
* extension and PATHEXT setting.
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.sync = exports.isexe = void 0;
|
||||
const fs_1 = require("fs");
|
||||
const promises_1 = require("fs/promises");
|
||||
/**
|
||||
* Determine whether a path is executable based on the file extension
|
||||
* and PATHEXT environment variable (or specified pathExt option)
|
||||
*/
|
||||
const isexe = async (path, options = {}) => {
|
||||
const { ignoreErrors = false } = options;
|
||||
try {
|
||||
return checkStat(await (0, promises_1.stat)(path), path, options);
|
||||
}
|
||||
catch (e) {
|
||||
const er = e;
|
||||
if (ignoreErrors || er.code === 'EACCES')
|
||||
return false;
|
||||
throw er;
|
||||
}
|
||||
};
|
||||
exports.isexe = isexe;
|
||||
/**
|
||||
* Synchronously determine whether a path is executable based on the file
|
||||
* extension and PATHEXT environment variable (or specified pathExt option)
|
||||
*/
|
||||
const sync = (path, options = {}) => {
|
||||
const { ignoreErrors = false } = options;
|
||||
try {
|
||||
return checkStat((0, fs_1.statSync)(path), path, options);
|
||||
}
|
||||
catch (e) {
|
||||
const er = e;
|
||||
if (ignoreErrors || er.code === 'EACCES')
|
||||
return false;
|
||||
throw er;
|
||||
}
|
||||
};
|
||||
exports.sync = sync;
|
||||
const checkPathExt = (path, options) => {
|
||||
const { pathExt = process.env.PATHEXT || '' } = options;
|
||||
const peSplit = pathExt.split(';');
|
||||
if (peSplit.indexOf('') !== -1) {
|
||||
return true;
|
||||
}
|
||||
for (let i = 0; i < peSplit.length; i++) {
|
||||
const p = peSplit[i].toLowerCase();
|
||||
const ext = path.substring(path.length - p.length).toLowerCase();
|
||||
if (p && ext === p) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const checkStat = (stat, path, options) => stat.isFile() && checkPathExt(path, options);
|
||||
//# sourceMappingURL=win32.js.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"win32.js","sourceRoot":"","sources":["../../src/win32.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEH,2BAAoC;AACpC,0CAAkC;AAGlC;;;GAGG;AACI,MAAM,KAAK,GAAG,KAAK,EACxB,IAAY,EACZ,UAAwB,EAAE,EACR,EAAE;IACpB,MAAM,EAAE,YAAY,GAAG,KAAK,EAAE,GAAG,OAAO,CAAA;IACxC,IAAI;QACF,OAAO,SAAS,CAAC,MAAM,IAAA,eAAI,EAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;KAClD;IAAC,OAAO,CAAC,EAAE;QACV,MAAM,EAAE,GAAG,CAA0B,CAAA;QACrC,IAAI,YAAY,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAA;QACtD,MAAM,EAAE,CAAA;KACT;AACH,CAAC,CAAA;AAZY,QAAA,KAAK,SAYjB;AAED;;;GAGG;AACI,MAAM,IAAI,GAAG,CAClB,IAAY,EACZ,UAAwB,EAAE,EACjB,EAAE;IACX,MAAM,EAAE,YAAY,GAAG,KAAK,EAAE,GAAG,OAAO,CAAA;IACxC,IAAI;QACF,OAAO,SAAS,CAAC,IAAA,aAAQ,EAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;KAChD;IAAC,OAAO,CAAC,EAAE;QACV,MAAM,EAAE,GAAG,CAA0B,CAAA;QACrC,IAAI,YAAY,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAA;QACtD,MAAM,EAAE,CAAA;KACT;AACH,CAAC,CAAA;AAZY,QAAA,IAAI,QAYhB;AAED,MAAM,YAAY,GAAG,CAAC,IAAY,EAAE,OAAqB,EAAE,EAAE;IAC3D,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,EAAE,GAAG,OAAO,CAAA;IACvD,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAClC,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE;QAC9B,OAAO,IAAI,CAAA;KACZ;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACvC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAA;QAEhE,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,EAAE;YAClB,OAAO,IAAI,CAAA;SACZ;KACF;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED,MAAM,SAAS,GAAG,CAAC,IAAW,EAAE,IAAY,EAAE,OAAqB,EAAE,EAAE,CACrE,IAAI,CAAC,MAAM,EAAE,IAAI,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA","sourcesContent":["/**\n * This is the Windows implementation of isexe, which uses the file\n * extension and PATHEXT setting.\n *\n * @module\n */\n\nimport { Stats, statSync } from 'fs'\nimport { stat } from 'fs/promises'\nimport { IsexeOptions } from './options'\n\n/**\n * Determine whether a path is executable based on the file extension\n * and PATHEXT environment variable (or specified pathExt option)\n */\nexport const isexe = async (\n path: string,\n options: IsexeOptions = {}\n): Promise<boolean> => {\n const { ignoreErrors = false } = options\n try {\n return checkStat(await stat(path), path, options)\n } catch (e) {\n const er = e as NodeJS.ErrnoException\n if (ignoreErrors || er.code === 'EACCES') return false\n throw er\n }\n}\n\n/**\n * Synchronously determine whether a path is executable based on the file\n * extension and PATHEXT environment variable (or specified pathExt option)\n */\nexport const sync = (\n path: string,\n options: IsexeOptions = {}\n): boolean => {\n const { ignoreErrors = false } = options\n try {\n return checkStat(statSync(path), path, options)\n } catch (e) {\n const er = e as NodeJS.ErrnoException\n if (ignoreErrors || er.code === 'EACCES') return false\n throw er\n }\n}\n\nconst checkPathExt = (path: string, options: IsexeOptions) => {\n const { pathExt = process.env.PATHEXT || '' } = options\n const peSplit = pathExt.split(';')\n if (peSplit.indexOf('') !== -1) {\n return true\n }\n\n for (let i = 0; i < peSplit.length; i++) {\n const p = peSplit[i].toLowerCase()\n const ext = path.substring(path.length - p.length).toLowerCase()\n\n if (p && ext === p) {\n return true\n }\n }\n return false\n}\n\nconst checkStat = (stat: Stats, path: string, options: IsexeOptions) =>\n stat.isFile() && checkPathExt(path, options)\n"]}
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
import * as posix from './posix.js';
|
||||
import * as win32 from './win32.js';
|
||||
export * from './options.js';
|
||||
export { win32, posix };
|
||||
/**
|
||||
* Determine whether a path is executable on the current platform.
|
||||
*/
|
||||
export declare const isexe: (path: string, options?: import("./options.js").IsexeOptions) => Promise<boolean>;
|
||||
/**
|
||||
* Synchronously determine whether a path is executable on the
|
||||
* current platform.
|
||||
*/
|
||||
export declare const sync: (path: string, options?: import("./options.js").IsexeOptions) => boolean;
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,cAAc,cAAc,CAAA;AAC5B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;AAKvB;;GAEG;AACH,eAAO,MAAM,KAAK,mFAAa,CAAA;AAC/B;;;GAGG;AACH,eAAO,MAAM,IAAI,0EAAY,CAAA"}
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
import * as posix from './posix.js';
|
||||
import * as win32 from './win32.js';
|
||||
export * from './options.js';
|
||||
export { win32, posix };
|
||||
const platform = process.env._ISEXE_TEST_PLATFORM_ || process.platform;
|
||||
const impl = platform === 'win32' ? win32 : posix;
|
||||
/**
|
||||
* Determine whether a path is executable on the current platform.
|
||||
*/
|
||||
export const isexe = impl.isexe;
|
||||
/**
|
||||
* Synchronously determine whether a path is executable on the
|
||||
* current platform.
|
||||
*/
|
||||
export const sync = impl.sync;
|
||||
//# sourceMappingURL=index.js.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,cAAc,cAAc,CAAA;AAC5B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;AAEvB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,OAAO,CAAC,QAAQ,CAAA;AACtE,MAAM,IAAI,GAAG,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAA;AAEjD;;GAEG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;AAC/B;;;GAGG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA","sourcesContent":["import * as posix from './posix.js'\nimport * as win32 from './win32.js'\nexport * from './options.js'\nexport { win32, posix }\n\nconst platform = process.env._ISEXE_TEST_PLATFORM_ || process.platform\nconst impl = platform === 'win32' ? win32 : posix\n\n/**\n * Determine whether a path is executable on the current platform.\n */\nexport const isexe = impl.isexe\n/**\n * Synchronously determine whether a path is executable on the\n * current platform.\n */\nexport const sync = impl.sync\n"]}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
export interface IsexeOptions {
|
||||
/**
|
||||
* Ignore errors arising from attempting to get file access status
|
||||
* Note that EACCES is always ignored, because that just means
|
||||
* it's not executable. If this is not set, then attempting to check
|
||||
* the executable-ness of a nonexistent file will raise ENOENT, for
|
||||
* example.
|
||||
*/
|
||||
ignoreErrors?: boolean;
|
||||
/**
|
||||
* effective uid when checking executable mode flags on posix
|
||||
* Defaults to process.getuid()
|
||||
*/
|
||||
uid?: number;
|
||||
/**
|
||||
* effective gid when checking executable mode flags on posix
|
||||
* Defaults to process.getgid()
|
||||
*/
|
||||
gid?: number;
|
||||
/**
|
||||
* effective group ID list to use when checking executable mode flags
|
||||
* on posix
|
||||
* Defaults to process.getgroups()
|
||||
*/
|
||||
groups?: number[];
|
||||
/**
|
||||
* The ;-delimited path extension list for win32 implementation.
|
||||
* Defaults to process.env.PATHEXT
|
||||
*/
|
||||
pathExt?: string;
|
||||
}
|
||||
//# sourceMappingURL=options.d.ts.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/options.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IAEtB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IAEZ;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IAEZ;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IAEjB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB"}
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
export {};
|
||||
//# sourceMappingURL=options.js.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/options.ts"],"names":[],"mappings":"","sourcesContent":["export interface IsexeOptions {\n /**\n * Ignore errors arising from attempting to get file access status\n * Note that EACCES is always ignored, because that just means\n * it's not executable. If this is not set, then attempting to check\n * the executable-ness of a nonexistent file will raise ENOENT, for\n * example.\n */\n ignoreErrors?: boolean\n\n /**\n * effective uid when checking executable mode flags on posix\n * Defaults to process.getuid()\n */\n uid?: number\n\n /**\n * effective gid when checking executable mode flags on posix\n * Defaults to process.getgid()\n */\n gid?: number\n\n /**\n * effective group ID list to use when checking executable mode flags\n * on posix\n * Defaults to process.getgroups()\n */\n groups?: number[]\n\n /**\n * The ;-delimited path extension list for win32 implementation.\n * Defaults to process.env.PATHEXT\n */\n pathExt?: string\n}\n"]}
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
* This is the Posix implementation of isexe, which uses the file
|
||||
* mode and uid/gid values.
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
import { IsexeOptions } from './options';
|
||||
/**
|
||||
* Determine whether a path is executable according to the mode and
|
||||
* current (or specified) user and group IDs.
|
||||
*/
|
||||
export declare const isexe: (path: string, options?: IsexeOptions) => Promise<boolean>;
|
||||
/**
|
||||
* Synchronously determine whether a path is executable according to
|
||||
* the mode and current (or specified) user and group IDs.
|
||||
*/
|
||||
export declare const sync: (path: string, options?: IsexeOptions) => boolean;
|
||||
//# sourceMappingURL=posix.d.ts.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"posix.d.ts","sourceRoot":"","sources":["../../src/posix.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAExC;;;GAGG;AACH,eAAO,MAAM,KAAK,SACV,MAAM,YACH,YAAY,KACpB,QAAQ,OAAO,CASjB,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,IAAI,SACT,MAAM,YACH,YAAY,KACpB,OASF,CAAA"}
|
||||
-62
@@ -1,62 +0,0 @@
|
||||
/**
|
||||
* This is the Posix implementation of isexe, which uses the file
|
||||
* mode and uid/gid values.
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
import { statSync } from 'fs';
|
||||
import { stat } from 'fs/promises';
|
||||
/**
|
||||
* Determine whether a path is executable according to the mode and
|
||||
* current (or specified) user and group IDs.
|
||||
*/
|
||||
export const isexe = async (path, options = {}) => {
|
||||
const { ignoreErrors = false } = options;
|
||||
try {
|
||||
return checkStat(await stat(path), options);
|
||||
}
|
||||
catch (e) {
|
||||
const er = e;
|
||||
if (ignoreErrors || er.code === 'EACCES')
|
||||
return false;
|
||||
throw er;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Synchronously determine whether a path is executable according to
|
||||
* the mode and current (or specified) user and group IDs.
|
||||
*/
|
||||
export const sync = (path, options = {}) => {
|
||||
const { ignoreErrors = false } = options;
|
||||
try {
|
||||
return checkStat(statSync(path), options);
|
||||
}
|
||||
catch (e) {
|
||||
const er = e;
|
||||
if (ignoreErrors || er.code === 'EACCES')
|
||||
return false;
|
||||
throw er;
|
||||
}
|
||||
};
|
||||
const checkStat = (stat, options) => stat.isFile() && checkMode(stat, options);
|
||||
const checkMode = (stat, options) => {
|
||||
const myUid = options.uid ?? process.getuid?.();
|
||||
const myGroups = options.groups ?? process.getgroups?.() ?? [];
|
||||
const myGid = options.gid ?? process.getgid?.() ?? myGroups[0];
|
||||
if (myUid === undefined || myGid === undefined) {
|
||||
throw new Error('cannot get uid or gid');
|
||||
}
|
||||
const groups = new Set([myGid, ...myGroups]);
|
||||
const mod = stat.mode;
|
||||
const uid = stat.uid;
|
||||
const gid = stat.gid;
|
||||
const u = parseInt('100', 8);
|
||||
const g = parseInt('010', 8);
|
||||
const o = parseInt('001', 8);
|
||||
const ug = u | g;
|
||||
return !!(mod & o ||
|
||||
(mod & g && groups.has(gid)) ||
|
||||
(mod & u && uid === myUid) ||
|
||||
(mod & ug && myUid === 0));
|
||||
};
|
||||
//# sourceMappingURL=posix.js.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"posix.js","sourceRoot":"","sources":["../../src/posix.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAS,QAAQ,EAAE,MAAM,IAAI,CAAA;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAGlC;;;GAGG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,EACxB,IAAY,EACZ,UAAwB,EAAE,EACR,EAAE;IACpB,MAAM,EAAE,YAAY,GAAG,KAAK,EAAE,GAAG,OAAO,CAAA;IACxC,IAAI;QACF,OAAO,SAAS,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAA;KAC5C;IAAC,OAAO,CAAC,EAAE;QACV,MAAM,EAAE,GAAG,CAA0B,CAAA;QACrC,IAAI,YAAY,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAA;QACtD,MAAM,EAAE,CAAA;KACT;AACH,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,IAAY,EACZ,UAAwB,EAAE,EACjB,EAAE;IACX,MAAM,EAAE,YAAY,GAAG,KAAK,EAAE,GAAG,OAAO,CAAA;IACxC,IAAI;QACF,OAAO,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAA;KAC1C;IAAC,OAAO,CAAC,EAAE;QACV,MAAM,EAAE,GAAG,CAA0B,CAAA;QACrC,IAAI,YAAY,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAA;QACtD,MAAM,EAAE,CAAA;KACT;AACH,CAAC,CAAA;AAED,MAAM,SAAS,GAAG,CAAC,IAAW,EAAE,OAAqB,EAAE,EAAE,CACvD,IAAI,CAAC,MAAM,EAAE,IAAI,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;AAE3C,MAAM,SAAS,GAAG,CAAC,IAAW,EAAE,OAAqB,EAAE,EAAE;IACvD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAA;IAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,CAAA;IAC9D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAA;IAC9D,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,EAAE;QAC9C,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAA;KACzC;IAED,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAA;IAE5C,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAA;IACrB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAA;IACpB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAA;IAEpB,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IAC5B,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IAC5B,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IAC5B,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAA;IAEhB,OAAO,CAAC,CAAC,CACP,GAAG,GAAG,CAAC;QACP,CAAC,GAAG,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,KAAK,KAAK,CAAC;QAC1B,CAAC,GAAG,GAAG,EAAE,IAAI,KAAK,KAAK,CAAC,CAAC,CAC1B,CAAA;AACH,CAAC,CAAA","sourcesContent":["/**\n * This is the Posix implementation of isexe, which uses the file\n * mode and uid/gid values.\n *\n * @module\n */\n\nimport { Stats, statSync } from 'fs'\nimport { stat } from 'fs/promises'\nimport { IsexeOptions } from './options'\n\n/**\n * Determine whether a path is executable according to the mode and\n * current (or specified) user and group IDs.\n */\nexport const isexe = async (\n path: string,\n options: IsexeOptions = {}\n): Promise<boolean> => {\n const { ignoreErrors = false } = options\n try {\n return checkStat(await stat(path), options)\n } catch (e) {\n const er = e as NodeJS.ErrnoException\n if (ignoreErrors || er.code === 'EACCES') return false\n throw er\n }\n}\n\n/**\n * Synchronously determine whether a path is executable according to\n * the mode and current (or specified) user and group IDs.\n */\nexport const sync = (\n path: string,\n options: IsexeOptions = {}\n): boolean => {\n const { ignoreErrors = false } = options\n try {\n return checkStat(statSync(path), options)\n } catch (e) {\n const er = e as NodeJS.ErrnoException\n if (ignoreErrors || er.code === 'EACCES') return false\n throw er\n }\n}\n\nconst checkStat = (stat: Stats, options: IsexeOptions) =>\n stat.isFile() && checkMode(stat, options)\n\nconst checkMode = (stat: Stats, options: IsexeOptions) => {\n const myUid = options.uid ?? process.getuid?.()\n const myGroups = options.groups ?? process.getgroups?.() ?? []\n const myGid = options.gid ?? process.getgid?.() ?? myGroups[0]\n if (myUid === undefined || myGid === undefined) {\n throw new Error('cannot get uid or gid')\n }\n\n const groups = new Set([myGid, ...myGroups])\n\n const mod = stat.mode\n const uid = stat.uid\n const gid = stat.gid\n\n const u = parseInt('100', 8)\n const g = parseInt('010', 8)\n const o = parseInt('001', 8)\n const ug = u | g\n\n return !!(\n mod & o ||\n (mod & g && groups.has(gid)) ||\n (mod & u && uid === myUid) ||\n (mod & ug && myUid === 0)\n )\n}\n"]}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
* This is the Windows implementation of isexe, which uses the file
|
||||
* extension and PATHEXT setting.
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
import { IsexeOptions } from './options';
|
||||
/**
|
||||
* Determine whether a path is executable based on the file extension
|
||||
* and PATHEXT environment variable (or specified pathExt option)
|
||||
*/
|
||||
export declare const isexe: (path: string, options?: IsexeOptions) => Promise<boolean>;
|
||||
/**
|
||||
* Synchronously determine whether a path is executable based on the file
|
||||
* extension and PATHEXT environment variable (or specified pathExt option)
|
||||
*/
|
||||
export declare const sync: (path: string, options?: IsexeOptions) => boolean;
|
||||
//# sourceMappingURL=win32.d.ts.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"win32.d.ts","sourceRoot":"","sources":["../../src/win32.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAExC;;;GAGG;AACH,eAAO,MAAM,KAAK,SACV,MAAM,YACH,YAAY,KACpB,QAAQ,OAAO,CASjB,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,IAAI,SACT,MAAM,YACH,YAAY,KACpB,OASF,CAAA"}
|
||||
-57
@@ -1,57 +0,0 @@
|
||||
/**
|
||||
* This is the Windows implementation of isexe, which uses the file
|
||||
* extension and PATHEXT setting.
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
import { statSync } from 'fs';
|
||||
import { stat } from 'fs/promises';
|
||||
/**
|
||||
* Determine whether a path is executable based on the file extension
|
||||
* and PATHEXT environment variable (or specified pathExt option)
|
||||
*/
|
||||
export const isexe = async (path, options = {}) => {
|
||||
const { ignoreErrors = false } = options;
|
||||
try {
|
||||
return checkStat(await stat(path), path, options);
|
||||
}
|
||||
catch (e) {
|
||||
const er = e;
|
||||
if (ignoreErrors || er.code === 'EACCES')
|
||||
return false;
|
||||
throw er;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Synchronously determine whether a path is executable based on the file
|
||||
* extension and PATHEXT environment variable (or specified pathExt option)
|
||||
*/
|
||||
export const sync = (path, options = {}) => {
|
||||
const { ignoreErrors = false } = options;
|
||||
try {
|
||||
return checkStat(statSync(path), path, options);
|
||||
}
|
||||
catch (e) {
|
||||
const er = e;
|
||||
if (ignoreErrors || er.code === 'EACCES')
|
||||
return false;
|
||||
throw er;
|
||||
}
|
||||
};
|
||||
const checkPathExt = (path, options) => {
|
||||
const { pathExt = process.env.PATHEXT || '' } = options;
|
||||
const peSplit = pathExt.split(';');
|
||||
if (peSplit.indexOf('') !== -1) {
|
||||
return true;
|
||||
}
|
||||
for (let i = 0; i < peSplit.length; i++) {
|
||||
const p = peSplit[i].toLowerCase();
|
||||
const ext = path.substring(path.length - p.length).toLowerCase();
|
||||
if (p && ext === p) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const checkStat = (stat, path, options) => stat.isFile() && checkPathExt(path, options);
|
||||
//# sourceMappingURL=win32.js.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"win32.js","sourceRoot":"","sources":["../../src/win32.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAS,QAAQ,EAAE,MAAM,IAAI,CAAA;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAGlC;;;GAGG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,EACxB,IAAY,EACZ,UAAwB,EAAE,EACR,EAAE;IACpB,MAAM,EAAE,YAAY,GAAG,KAAK,EAAE,GAAG,OAAO,CAAA;IACxC,IAAI;QACF,OAAO,SAAS,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;KAClD;IAAC,OAAO,CAAC,EAAE;QACV,MAAM,EAAE,GAAG,CAA0B,CAAA;QACrC,IAAI,YAAY,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAA;QACtD,MAAM,EAAE,CAAA;KACT;AACH,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,IAAY,EACZ,UAAwB,EAAE,EACjB,EAAE;IACX,MAAM,EAAE,YAAY,GAAG,KAAK,EAAE,GAAG,OAAO,CAAA;IACxC,IAAI;QACF,OAAO,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;KAChD;IAAC,OAAO,CAAC,EAAE;QACV,MAAM,EAAE,GAAG,CAA0B,CAAA;QACrC,IAAI,YAAY,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAA;QACtD,MAAM,EAAE,CAAA;KACT;AACH,CAAC,CAAA;AAED,MAAM,YAAY,GAAG,CAAC,IAAY,EAAE,OAAqB,EAAE,EAAE;IAC3D,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,EAAE,GAAG,OAAO,CAAA;IACvD,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAClC,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE;QAC9B,OAAO,IAAI,CAAA;KACZ;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACvC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAA;QAEhE,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,EAAE;YAClB,OAAO,IAAI,CAAA;SACZ;KACF;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED,MAAM,SAAS,GAAG,CAAC,IAAW,EAAE,IAAY,EAAE,OAAqB,EAAE,EAAE,CACrE,IAAI,CAAC,MAAM,EAAE,IAAI,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA","sourcesContent":["/**\n * This is the Windows implementation of isexe, which uses the file\n * extension and PATHEXT setting.\n *\n * @module\n */\n\nimport { Stats, statSync } from 'fs'\nimport { stat } from 'fs/promises'\nimport { IsexeOptions } from './options'\n\n/**\n * Determine whether a path is executable based on the file extension\n * and PATHEXT environment variable (or specified pathExt option)\n */\nexport const isexe = async (\n path: string,\n options: IsexeOptions = {}\n): Promise<boolean> => {\n const { ignoreErrors = false } = options\n try {\n return checkStat(await stat(path), path, options)\n } catch (e) {\n const er = e as NodeJS.ErrnoException\n if (ignoreErrors || er.code === 'EACCES') return false\n throw er\n }\n}\n\n/**\n * Synchronously determine whether a path is executable based on the file\n * extension and PATHEXT environment variable (or specified pathExt option)\n */\nexport const sync = (\n path: string,\n options: IsexeOptions = {}\n): boolean => {\n const { ignoreErrors = false } = options\n try {\n return checkStat(statSync(path), path, options)\n } catch (e) {\n const er = e as NodeJS.ErrnoException\n if (ignoreErrors || er.code === 'EACCES') return false\n throw er\n }\n}\n\nconst checkPathExt = (path: string, options: IsexeOptions) => {\n const { pathExt = process.env.PATHEXT || '' } = options\n const peSplit = pathExt.split(';')\n if (peSplit.indexOf('') !== -1) {\n return true\n }\n\n for (let i = 0; i < peSplit.length; i++) {\n const p = peSplit[i].toLowerCase()\n const ext = path.substring(path.length - p.length).toLowerCase()\n\n if (p && ext === p) {\n return true\n }\n }\n return false\n}\n\nconst checkStat = (stat: Stats, path: string, options: IsexeOptions) =>\n stat.isFile() && checkPathExt(path, options)\n"]}
|
||||
+52
-70
@@ -1,96 +1,78 @@
|
||||
{
|
||||
"name": "isexe",
|
||||
"version": "3.1.1",
|
||||
"version": "4.0.0",
|
||||
"description": "Minimal module to check if a file is executable.",
|
||||
"main": "./dist/cjs/index.js",
|
||||
"module": "./dist/mjs/index.js",
|
||||
"types": "./dist/cjs/index.js",
|
||||
"main": "./dist/commonjs/index.min.js",
|
||||
"module": "./dist/esm/index.min.js",
|
||||
"types": "./dist/commonjs/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"tshy": {
|
||||
"selfLink": false,
|
||||
"exports": {
|
||||
"./raw": "./src/index.ts",
|
||||
"./package.json": "./package.json",
|
||||
".": {
|
||||
"import": {
|
||||
"types": "./dist/esm/index.d.ts",
|
||||
"default": "./dist/esm/index.min.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./dist/commonjs/index.d.ts",
|
||||
"default": "./dist/commonjs/index.min.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"exports": {
|
||||
"./raw": {
|
||||
"import": {
|
||||
"types": "./dist/esm/index.d.ts",
|
||||
"default": "./dist/esm/index.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./dist/commonjs/index.d.ts",
|
||||
"default": "./dist/commonjs/index.js"
|
||||
}
|
||||
},
|
||||
"./package.json": "./package.json",
|
||||
".": {
|
||||
"import": {
|
||||
"types": "./dist/mjs/index.d.ts",
|
||||
"default": "./dist/mjs/index.js"
|
||||
"types": "./dist/esm/index.d.ts",
|
||||
"default": "./dist/esm/index.min.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./dist/cjs/index.d.ts",
|
||||
"default": "./dist/cjs/index.js"
|
||||
"types": "./dist/commonjs/index.d.ts",
|
||||
"default": "./dist/commonjs/index.min.js"
|
||||
}
|
||||
},
|
||||
"./posix": {
|
||||
"import": {
|
||||
"types": "./dist/mjs/posix.d.ts",
|
||||
"default": "./dist/mjs/posix.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./dist/cjs/posix.d.ts",
|
||||
"default": "./dist/cjs/posix.js"
|
||||
}
|
||||
},
|
||||
"./win32": {
|
||||
"import": {
|
||||
"types": "./dist/mjs/win32.d.ts",
|
||||
"default": "./dist/mjs/win32.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./dist/cjs/win32.d.ts",
|
||||
"default": "./dist/cjs/win32.js"
|
||||
}
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.4.5",
|
||||
"@types/tap": "^15.0.8",
|
||||
"c8": "^8.0.1",
|
||||
"mkdirp": "^0.5.1",
|
||||
"prettier": "^2.8.8",
|
||||
"rimraf": "^2.5.0",
|
||||
"sync-content": "^1.0.2",
|
||||
"tap": "^16.3.8",
|
||||
"ts-node": "^10.9.1",
|
||||
"typedoc": "^0.24.8",
|
||||
"typescript": "^5.1.6"
|
||||
"@types/node": "^25.2.1",
|
||||
"esbuild": "^0.27.3",
|
||||
"prettier": "^3.8.1",
|
||||
"tap": "^21.5.1",
|
||||
"tshy": "^3.1.3",
|
||||
"typedoc": "^0.28.16"
|
||||
},
|
||||
"scripts": {
|
||||
"preversion": "npm test",
|
||||
"postversion": "npm publish",
|
||||
"prepublishOnly": "git push origin --follow-tags",
|
||||
"prepare": "tsc -p tsconfig/cjs.json && tsc -p tsconfig/esm.json && bash ./scripts/fixup.sh",
|
||||
"prepare": "tshy && bash build.sh",
|
||||
"pretest": "npm run prepare",
|
||||
"presnap": "npm run prepare",
|
||||
"test": "c8 tap",
|
||||
"snap": "c8 tap",
|
||||
"format": "prettier --write . --loglevel warn --ignore-path ../../.prettierignore --cache",
|
||||
"typedoc": "typedoc --tsconfig tsconfig/esm.json ./src/*.ts"
|
||||
"test": "tap",
|
||||
"snap": "tap",
|
||||
"format": "prettier --write .",
|
||||
"typedoc": "typedoc"
|
||||
},
|
||||
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
|
||||
"license": "ISC",
|
||||
"tap": {
|
||||
"coverage": false,
|
||||
"node-arg": [
|
||||
"--enable-source-maps",
|
||||
"--no-warnings",
|
||||
"--loader",
|
||||
"ts-node/esm"
|
||||
],
|
||||
"ts": false
|
||||
},
|
||||
"prettier": {
|
||||
"semi": false,
|
||||
"printWidth": 75,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"singleQuote": true,
|
||||
"jsxSingleQuote": false,
|
||||
"bracketSameLine": true,
|
||||
"arrowParens": "avoid",
|
||||
"endOfLine": "lf"
|
||||
},
|
||||
"license": "BlueOak-1.0.0",
|
||||
"repository": "https://github.com/isaacs/isexe",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
"node": ">=20"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
||||
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
The ISC License
|
||||
|
||||
Copyright (c) 2010-2023 Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
+155
-17
@@ -57,10 +57,17 @@ const options = {
|
||||
|
||||
// for use when you need to clean up something when objects
|
||||
// are evicted from the cache
|
||||
dispose: (value, key) => {
|
||||
dispose: (value, key, reason) => {
|
||||
freeFromMemoryOrWhatever(value)
|
||||
},
|
||||
|
||||
// for use when you need to know that an item is being inserted
|
||||
// note that this does NOT allow you to prevent the insertion,
|
||||
// it just allows you to know about it.
|
||||
onInsert: (value, key, reason) => {
|
||||
logInsertionOrWhatever(key, value)
|
||||
},
|
||||
|
||||
// how long to live in ms
|
||||
ttl: 1000 * 60 * 5,
|
||||
|
||||
@@ -72,11 +79,7 @@ const options = {
|
||||
|
||||
// async method to use for cache.fetch(), for
|
||||
// stale-while-revalidate type of behavior
|
||||
fetchMethod: async (
|
||||
key,
|
||||
staleValue,
|
||||
{ options, signal, context }
|
||||
) => {},
|
||||
fetchMethod: async (key, staleValue, { options, signal, context }) => {},
|
||||
}
|
||||
|
||||
const cache = new LRUCache(options)
|
||||
@@ -154,7 +157,7 @@ const cache = {
|
||||
}
|
||||
cache.timers.set(
|
||||
k,
|
||||
setTimeout(() => cache.delete(k), ttl)
|
||||
setTimeout(() => cache.delete(k), ttl),
|
||||
)
|
||||
cache.data.set(k, v)
|
||||
},
|
||||
@@ -212,9 +215,95 @@ const myGet = (key, value) => {
|
||||
}
|
||||
```
|
||||
|
||||
## Tracing and Observability
|
||||
|
||||
Most methods can accept a `status` option, which is an
|
||||
[`LRUCache.Status`](https://isaacs.github.io/node-lru-cache/interfaces/LRUCache.LRUCache.Status.html)
|
||||
object that will be decorated along the operation with
|
||||
indications about what was done and why.
|
||||
|
||||
Additionally, this library is instrumented using the
|
||||
[`node:diagnostics_channel`](https://nodejs.org/api/diagnostics_channel.html)
|
||||
module on Node and other platforms that support it. In order to
|
||||
get diagnostics metrics, listen on the
|
||||
`channel('lru-cache:metrics')`. To get Tracing Channel traces,
|
||||
subscribe to the `tracingChannel('lru-cache')`. The
|
||||
[`LRUCache.Status`](https://isaacs.github.io/node-lru-cache/interfaces/LRUCache.LRUCache.Status.html)
|
||||
objects will be provided as the message context to those channel
|
||||
listeners.
|
||||
|
||||
For example, you could do the following to get comprehensive
|
||||
information about every LRUCache instance in your application:
|
||||
|
||||
```ts
|
||||
import { tracingChannel, subscribe } from 'node:diagnostics_channel'
|
||||
|
||||
subscribe('lru-cache:metrics', (message, name) => {
|
||||
// name will always be 'lru-cache:metrics'
|
||||
// message will be the LRUCache.Status object for whatever
|
||||
// synchronous operation was performed.
|
||||
console.error('LRUCache Metrics', message)
|
||||
})
|
||||
|
||||
tracingChannel('lru-cache').subscribe({
|
||||
start: status => {
|
||||
// a traced operation is starting
|
||||
},
|
||||
asyncStart: status => {
|
||||
// an async traced operation is starting
|
||||
},
|
||||
asyncEnd: status => {
|
||||
// an async traced operation is ending
|
||||
}
|
||||
error: status => {
|
||||
// a traced operation failed
|
||||
},
|
||||
end: status => {
|
||||
// a traced operation is complete
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
The async `cache.fetch()` and `cache.forceFetch` methods are
|
||||
covered by `tracingChannels`. All the other operations are
|
||||
covered by the `lru-cache:metrics` channel, because they are
|
||||
strictly synchronous, and thus don't have an asynchronous
|
||||
lifecycle to track.
|
||||
|
||||
Note that using `status` objects or using
|
||||
`node:diagnostics_channel` listeners _will_ impose a modest
|
||||
performance penalty. Creating data objects is not ever free; do
|
||||
not believe anyone who tells you otherwise. But it is as small as
|
||||
possible.
|
||||
|
||||
### Platform Compatibility Caveat
|
||||
|
||||
Not all platforms support the `node:diagnostics_channel` module.
|
||||
Currently, this is only available in Node, Bun, and Deno, and
|
||||
some edge computing platforms that provide a Node compatibility
|
||||
layer.
|
||||
|
||||
To work around this, if you are loading in a non-Node
|
||||
environment, the package.json exports will direct your module
|
||||
loader to pull in a version that starts out with a dummy
|
||||
implementation, then does a conditional dynamic `import` of the
|
||||
`node:diagnostics_channel` module, and then swaps out those
|
||||
dummy objects with the real thing if it succeeds. This means that
|
||||
cache metrics and tracing channels started in the first load-time
|
||||
tick of your application will _not_ be covered, except in
|
||||
environments that load using the `require` import
|
||||
condition, or both the `node` and `esm` import conditions
|
||||
together.
|
||||
|
||||
Top-level await _could_ be used to remove this caveat, but that
|
||||
feature is dead on arrival, unfortunately. See
|
||||
[#397](https://github.com/isaacs/node-lru-cache/issues/397) and
|
||||
[#398](https://github.com/isaacs/node-lru-cache/issues/398) for
|
||||
more details.
|
||||
|
||||
## Performance
|
||||
|
||||
As of January 2022, version 7 of this library is one of the most
|
||||
As of April 2026, version 11 of this library is one of the most
|
||||
performant LRU cache implementations in JavaScript.
|
||||
|
||||
Benchmarks can be extremely difficult to get right. In
|
||||
@@ -269,9 +358,9 @@ If performance matters to you:
|
||||
LRUCache](https://yomguithereal.github.io/mnemonist/lru-cache)
|
||||
which uses an Object as its data store.
|
||||
|
||||
2. Failing that, if at all possible, use short non-numeric
|
||||
strings (ie, less than 256 characters) as your keys, and use
|
||||
[mnemonist's
|
||||
2. Failing that, if you can use short non-numeric strings (ie,
|
||||
less than 256 characters) as your keys, and you do not need
|
||||
any of the other features of this library, use [mnemonist's
|
||||
LRUCache](https://yomguithereal.github.io/mnemonist/lru-cache).
|
||||
|
||||
3. If the types of your keys will be anything else, especially
|
||||
@@ -283,14 +372,63 @@ If performance matters to you:
|
||||
(like asynchronous fetching, a variety of TTL staleness
|
||||
options, and so on), then [mnemonist's
|
||||
LRUMap](https://yomguithereal.github.io/mnemonist/lru-map) is
|
||||
a very good option, and just slightly faster than this module
|
||||
(since it does considerably less).
|
||||
also a very good option, and just slightly faster than this
|
||||
module (since it does considerably less).
|
||||
|
||||
4. Do not use a `dispose` function, size tracking, or especially
|
||||
ttl behavior, unless absolutely needed. These features are
|
||||
convenient, and necessary in some use cases, and every attempt
|
||||
has been made to make the performance impact minimal, but it
|
||||
isn't nothing.
|
||||
ttl behavior or observability features, unless absolutely
|
||||
needed. These features are convenient, and necessary in some
|
||||
use cases, and every attempt has been made to make the
|
||||
performance impact minimal, but it isn't nothing.
|
||||
|
||||
## Testing
|
||||
|
||||
When writing tests that involve TTL-related functionality, note
|
||||
that this module creates an internal reference to the global
|
||||
`performance` or `Date` objects at import time. If you import it
|
||||
statically at the top level, those references cannot be mocked or
|
||||
overridden in your test environment.
|
||||
|
||||
To avoid this, dynamically import the package within your tests
|
||||
so that the references are captured after your mocks are applied.
|
||||
For example:
|
||||
|
||||
```ts
|
||||
// ❌ Not recommended
|
||||
import { LRUCache } from 'lru-cache'
|
||||
// mocking timers, e.g. jest.useFakeTimers()
|
||||
|
||||
// ✅ Recommended for TTL tests
|
||||
// mocking timers, e.g. jest.useFakeTimers()
|
||||
const { LRUCache } = await import('lru-cache')
|
||||
```
|
||||
|
||||
This ensures that your mocked timers or time sources are
|
||||
respected when testing TTL behavior.
|
||||
|
||||
Additionally, you can pass in a `perf` option when creating your
|
||||
LRUCache instance. This option accepts any object with a `now`
|
||||
method that returns a number.
|
||||
|
||||
For example, this would be a very bare-bones time-mocking system
|
||||
you could use in your tests, without any particular test
|
||||
framework:
|
||||
|
||||
```ts
|
||||
import { LRUCache } from 'lru-cache'
|
||||
|
||||
let myClockTime = 0
|
||||
|
||||
const cache = new LRUCache<string>({
|
||||
max: 10,
|
||||
ttl: 1000,
|
||||
perf: {
|
||||
now: () => myClockTime,
|
||||
},
|
||||
})
|
||||
|
||||
// run tests, updating myClockTime as needed
|
||||
```
|
||||
|
||||
## Breaking Changes in Version 7
|
||||
|
||||
|
||||
+156
-33
@@ -1,6 +1,8 @@
|
||||
/**
|
||||
* @module LRUCache
|
||||
*/
|
||||
import type { Perf } from './perf.js';
|
||||
export type { Perf } from './perf.js';
|
||||
declare const TYPE: unique symbol;
|
||||
export type PosInt = number & {
|
||||
[TYPE]: 'Positive Integer';
|
||||
@@ -75,6 +77,20 @@ export declare namespace LRUCache {
|
||||
* {@link OptionsBase.disposeAfter} options.
|
||||
*/
|
||||
type Disposer<K, V> = (value: V, key: K, reason: DisposeReason) => void;
|
||||
/**
|
||||
* The reason why an item was added to the cache, passed
|
||||
* to the {@link Inserter} methods.
|
||||
*
|
||||
* - `add`: the item was not found in the cache, and was added
|
||||
* - `update`: the item was in the cache, with the same value provided
|
||||
* - `replace`: the item was in the cache, and replaced
|
||||
*/
|
||||
type InsertReason = 'add' | 'update' | 'replace';
|
||||
/**
|
||||
* A method called upon item insertion, passed as the
|
||||
* {@link OptionsBase.insert}
|
||||
*/
|
||||
type Inserter<K, V> = (value: V, key: K, reason: InsertReason) => void;
|
||||
/**
|
||||
* A function that returns the effective calculated size
|
||||
* of an entry in the cache.
|
||||
@@ -102,8 +118,16 @@ export declare namespace LRUCache {
|
||||
*
|
||||
* The `status` option should be a plain JavaScript object. The following
|
||||
* fields will be set on it appropriately, depending on the situation.
|
||||
*
|
||||
* These objects are also the context objects passed to listeners on the
|
||||
* `lru-cache:metrics` diagnostic channel, and the `lru-cache` tracing
|
||||
* channels, in platforms that support them.
|
||||
*/
|
||||
interface Status<V> {
|
||||
interface Status<K, V, FC = unknown> {
|
||||
/**
|
||||
* The operation being performed
|
||||
*/
|
||||
op?: 'get' | 'set' | 'memo' | 'fetch' | 'delete' | 'has' | 'peek';
|
||||
/**
|
||||
* The status of a set() operation.
|
||||
*
|
||||
@@ -112,7 +136,37 @@ export declare namespace LRUCache {
|
||||
* - replace: the item was in the cache, and replaced
|
||||
* - miss: the item was not added to the cache for some reason
|
||||
*/
|
||||
set?: 'add' | 'update' | 'replace' | 'miss';
|
||||
set?: 'add' | 'update' | 'replace' | 'miss' | 'deleted';
|
||||
/**
|
||||
* The status of a delete() operation.
|
||||
*/
|
||||
delete?: LRUCache.DisposeReason;
|
||||
/**
|
||||
* The result of a peek() operation
|
||||
*
|
||||
* - hit: the item was found and returned
|
||||
* - stale: the item is in the cache, but past its ttl and not returned
|
||||
* - miss: item not in the cache
|
||||
*/
|
||||
peek?: 'hit' | 'miss' | 'stale';
|
||||
/**
|
||||
* The status of a memo() operation.
|
||||
*
|
||||
* - 'hit': the item was found in the cache and returned
|
||||
* - 'miss': the `memoMethod` function was called
|
||||
*/
|
||||
memo?: 'hit' | 'miss';
|
||||
/**
|
||||
* The `context` option provided to a memo or fetch operation
|
||||
*
|
||||
* In practice, of course, this will be the same type as the `FC`
|
||||
* fetch context param used to instantiate the LRUCache, but the
|
||||
* convolutions of threading that through would get quite complicated,
|
||||
* and preclude forcing/forbidding the passing of a `context` param
|
||||
* where it is/isn't expected, which is more valuable for error
|
||||
* prevention.
|
||||
*/
|
||||
context?: unknown;
|
||||
/**
|
||||
* the ttl stored for the item, or undefined if ttls are not used.
|
||||
*/
|
||||
@@ -143,8 +197,15 @@ export declare namespace LRUCache {
|
||||
*/
|
||||
maxEntrySizeExceeded?: true;
|
||||
/**
|
||||
* The old value, specified in the case of `set:'update'` or
|
||||
* `set:'replace'`
|
||||
* The key that was set or retrieved
|
||||
*/
|
||||
key?: K;
|
||||
/**
|
||||
* The value that was set
|
||||
*/
|
||||
value?: V;
|
||||
/**
|
||||
* The old value, specified in the case of `set:'replace'`
|
||||
*/
|
||||
oldValue?: V;
|
||||
/**
|
||||
@@ -170,6 +231,10 @@ export declare namespace LRUCache {
|
||||
* {@link FetchOptions.forceRefresh} was specified.
|
||||
*/
|
||||
fetch?: 'get' | 'inflight' | 'miss' | 'hit' | 'stale' | 'refresh';
|
||||
/**
|
||||
* `forceRefresh` option was used for either a fetch or memo operation
|
||||
*/
|
||||
forceRefresh?: boolean;
|
||||
/**
|
||||
* The {@link OptionsBase.fetchMethod} was called
|
||||
*/
|
||||
@@ -191,7 +256,7 @@ export declare namespace LRUCache {
|
||||
fetchAborted?: true;
|
||||
/**
|
||||
* The abort signal received was ignored, and the fetch was allowed to
|
||||
* continue.
|
||||
* continue in the background.
|
||||
*/
|
||||
fetchAbortIgnored?: true;
|
||||
/**
|
||||
@@ -207,15 +272,27 @@ export declare namespace LRUCache {
|
||||
*
|
||||
* - fetching: The item is currently being fetched. If a previous value
|
||||
* is present and allowed, that will be returned.
|
||||
* - stale: The item is in the cache, and is stale.
|
||||
* - stale: The item is in the cache, and is stale. If it was returned,
|
||||
* then the `returnedStale` flag will be set.
|
||||
* - stale-fetching: The value is being fetched in the background, but is
|
||||
* currently stale. If the stale value was returned, then the
|
||||
* `returnedStale` flag will be set.
|
||||
* - hit: the item is in the cache
|
||||
* - miss: the item is not in the cache
|
||||
*/
|
||||
get?: 'stale' | 'hit' | 'miss';
|
||||
get?: 'stale' | 'hit' | 'miss' | 'fetching' | 'stale-fetching';
|
||||
/**
|
||||
* A fetch or get operation returned a stale value.
|
||||
*/
|
||||
returnedStale?: true;
|
||||
/**
|
||||
* A tracingChannel trace was started for this operation
|
||||
*/
|
||||
trace?: boolean;
|
||||
/**
|
||||
* A reference to the cache instance associated with this operation
|
||||
*/
|
||||
cache?: LRUCache<K & {}, V & {}, FC>;
|
||||
}
|
||||
/**
|
||||
* options which override the options set in the LRUCache constructor
|
||||
@@ -233,7 +310,7 @@ export declare namespace LRUCache {
|
||||
* the fetchMethod is called.
|
||||
*/
|
||||
interface FetcherFetchOptions<K, V, FC = unknown> extends Pick<OptionsBase<K, V, FC>, 'allowStale' | 'updateAgeOnGet' | 'noDeleteOnStaleGet' | 'sizeCalculation' | 'ttl' | 'noDisposeOnSet' | 'noUpdateTTL' | 'noDeleteOnFetchRejection' | 'allowStaleOnFetchRejection' | 'ignoreFetchAbort' | 'allowStaleOnFetchAbort'> {
|
||||
status?: Status<V>;
|
||||
status?: Status<K, V, FC>;
|
||||
size?: Size;
|
||||
}
|
||||
/**
|
||||
@@ -255,7 +332,7 @@ export declare namespace LRUCache {
|
||||
*/
|
||||
context?: FC;
|
||||
signal?: AbortSignal;
|
||||
status?: Status<V>;
|
||||
status?: Status<K, V, FC>;
|
||||
}
|
||||
/**
|
||||
* Options provided to {@link LRUCache#fetch} when the FC type is something
|
||||
@@ -268,7 +345,7 @@ export declare namespace LRUCache {
|
||||
* Options provided to {@link LRUCache#fetch} when the FC type is
|
||||
* `undefined` or `void`
|
||||
*/
|
||||
interface FetchOptionsNoContext<K, V> extends FetchOptions<K, V, undefined> {
|
||||
interface FetchOptionsNoContext<K, V, FC extends undefined | void = undefined> extends FetchOptions<K, V, FC> {
|
||||
context?: undefined;
|
||||
}
|
||||
interface MemoOptions<K, V, FC = unknown> extends Pick<OptionsBase<K, V, FC>, 'allowStale' | 'updateAgeOnGet' | 'noDeleteOnStaleGet' | 'sizeCalculation' | 'ttl' | 'noDisposeOnSet' | 'noUpdateTTL' | 'noDeleteOnFetchRejection' | 'allowStaleOnFetchRejection' | 'ignoreFetchAbort' | 'allowStaleOnFetchAbort'> {
|
||||
@@ -286,7 +363,7 @@ export declare namespace LRUCache {
|
||||
* be required.
|
||||
*/
|
||||
context?: FC;
|
||||
status?: Status<V>;
|
||||
status?: Status<K, V, FC>;
|
||||
}
|
||||
/**
|
||||
* Options provided to {@link LRUCache#memo} when the FC type is something
|
||||
@@ -299,7 +376,7 @@ export declare namespace LRUCache {
|
||||
* Options provided to {@link LRUCache#memo} when the FC type is
|
||||
* `undefined` or `void`
|
||||
*/
|
||||
interface MemoOptionsNoContext<K, V> extends MemoOptions<K, V, undefined> {
|
||||
interface MemoOptionsNoContext<K, V, FC extends undefined | void = undefined> extends MemoOptions<K, V, FC> {
|
||||
context?: undefined;
|
||||
}
|
||||
/**
|
||||
@@ -320,7 +397,7 @@ export declare namespace LRUCache {
|
||||
*
|
||||
* This is the union of {@link GetOptions} and {@link SetOptions}, plus
|
||||
* {@link MemoOptions.forceRefresh}, and
|
||||
* {@link MemoerOptions.context}
|
||||
* {@link MemoOptions.context}
|
||||
*
|
||||
* Any of these may be modified in the {@link OptionsBase.memoMethod}
|
||||
* function, but the {@link GetOptions} fields will of course have no
|
||||
@@ -328,7 +405,7 @@ export declare namespace LRUCache {
|
||||
* the memoMethod is called.
|
||||
*/
|
||||
interface MemoizerMemoOptions<K, V, FC = unknown> extends Pick<OptionsBase<K, V, FC>, 'allowStale' | 'updateAgeOnGet' | 'noDeleteOnStaleGet' | 'sizeCalculation' | 'ttl' | 'noDisposeOnSet' | 'noUpdateTTL'> {
|
||||
status?: Status<V>;
|
||||
status?: Status<K, V, FC>;
|
||||
size?: Size;
|
||||
start?: Milliseconds;
|
||||
}
|
||||
@@ -336,18 +413,19 @@ export declare namespace LRUCache {
|
||||
* Options that may be passed to the {@link LRUCache#has} method.
|
||||
*/
|
||||
interface HasOptions<K, V, FC> extends Pick<OptionsBase<K, V, FC>, 'updateAgeOnHas'> {
|
||||
status?: Status<V>;
|
||||
status?: Status<K, V, FC>;
|
||||
}
|
||||
/**
|
||||
* Options that may be passed to the {@link LRUCache#get} method.
|
||||
*/
|
||||
interface GetOptions<K, V, FC> extends Pick<OptionsBase<K, V, FC>, 'allowStale' | 'updateAgeOnGet' | 'noDeleteOnStaleGet'> {
|
||||
status?: Status<V>;
|
||||
status?: Status<K, V, FC>;
|
||||
}
|
||||
/**
|
||||
* Options that may be passed to the {@link LRUCache#peek} method.
|
||||
*/
|
||||
interface PeekOptions<K, V, FC> extends Pick<OptionsBase<K, V, FC>, 'allowStale'> {
|
||||
status?: Status<K, V, FC>;
|
||||
}
|
||||
/**
|
||||
* Options that may be passed to the {@link LRUCache#set} method.
|
||||
@@ -368,7 +446,7 @@ export declare namespace LRUCache {
|
||||
* method is in use.
|
||||
*/
|
||||
start?: Milliseconds;
|
||||
status?: Status<V>;
|
||||
status?: Status<K, V, FC>;
|
||||
}
|
||||
/**
|
||||
* The type signature for the {@link OptionsBase.fetchMethod} option.
|
||||
@@ -555,6 +633,17 @@ export declare namespace LRUCache {
|
||||
* `cache.clear()`, or `cache.set(key, undefined)`.
|
||||
*/
|
||||
dispose?: Disposer<K, V>;
|
||||
/**
|
||||
* Function that is called when new items are inserted into the cache,
|
||||
* as `onInsert(value, key, reason)`.
|
||||
*
|
||||
* This can be useful if you need to perform actions when an item is
|
||||
* added, such as logging or tracking insertions.
|
||||
*
|
||||
* Unlike some other options, this may _not_ be overridden by passing
|
||||
* an option to `set()`, for performance and consistency reasons.
|
||||
*/
|
||||
onInsert?: Inserter<K, V>;
|
||||
/**
|
||||
* The same as {@link OptionsBase.dispose}, but called *after* the entry
|
||||
* is completely removed and the cache is once again in a clean state.
|
||||
@@ -610,6 +699,20 @@ export declare namespace LRUCache {
|
||||
* though for most cases, only minimally.
|
||||
*/
|
||||
maxSize?: Size;
|
||||
/**
|
||||
* The effective size for background fetch promises.
|
||||
*
|
||||
* This has no effect unless `maxSize` and `sizeCalculation` are used,
|
||||
* and a {@link LRUCache.OptionsBase.fetchMethod} is provided to
|
||||
* support {@link LRUCache#fetch}.
|
||||
*
|
||||
* If a stale value is present in the cache, then the effective size of
|
||||
* the background fetch is the size of the stale item it will eventually
|
||||
* replace. If not, then this value is used as its effective size.
|
||||
*
|
||||
* @default 1
|
||||
*/
|
||||
backgroundFetchSize?: number;
|
||||
/**
|
||||
* The maximum allowed size for any single item in the cache.
|
||||
*
|
||||
@@ -796,6 +899,15 @@ export declare namespace LRUCache {
|
||||
* call to {@link LRUCache#fetch}.
|
||||
*/
|
||||
ignoreFetchAbort?: boolean;
|
||||
/**
|
||||
* In some cases, you may want to swap out the performance/Date object
|
||||
* used for TTL tracking. This should almost certainly NOT be done in
|
||||
* production environments!
|
||||
*
|
||||
* This value defaults to `global.performance` if it has a `now()` method,
|
||||
* or the `global.Date` object otherwise.
|
||||
*/
|
||||
perf?: Perf;
|
||||
}
|
||||
interface OptionsMaxLimit<K, V, FC> extends OptionsBase<K, V, FC> {
|
||||
max: Count;
|
||||
@@ -837,8 +949,12 @@ export declare namespace LRUCache {
|
||||
*
|
||||
* Changing any of these will alter the defaults for subsequent method calls.
|
||||
*/
|
||||
export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implements Map<K, V> {
|
||||
export declare class LRUCache<K extends {}, V extends {}, FC = unknown> {
|
||||
#private;
|
||||
/**
|
||||
* {@link LRUCache.OptionsBase.perf}
|
||||
*/
|
||||
get perf(): Perf;
|
||||
/**
|
||||
* {@link LRUCache.OptionsBase.ttl}
|
||||
*/
|
||||
@@ -899,6 +1015,8 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
* {@link LRUCache.OptionsBase.ignoreFetchAbort}
|
||||
*/
|
||||
ignoreFetchAbort: boolean;
|
||||
/** {@link LRUCache.OptionsBase.backgroundFetchSize} */
|
||||
backgroundFetchSize: number;
|
||||
/**
|
||||
* Do not call this method unless you need to inspect the
|
||||
* inner workings of the cache. If anything returned by this
|
||||
@@ -911,6 +1029,7 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
static unsafeExposeInternals<K extends {}, V extends {}, FC extends unknown = unknown>(c: LRUCache<K, V, FC>): {
|
||||
starts: ZeroArray | undefined;
|
||||
ttls: ZeroArray | undefined;
|
||||
autopurgeTimers: (NodeJS.Timeout | undefined)[] | undefined;
|
||||
sizes: ZeroArray | undefined;
|
||||
keyMap: Map<K, number>;
|
||||
keyList: (K | undefined)[];
|
||||
@@ -920,8 +1039,8 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
readonly head: Index;
|
||||
readonly tail: Index;
|
||||
free: StackLike;
|
||||
isBackgroundFetch: (p: any) => boolean;
|
||||
backgroundFetch: (k: K, index: number | undefined, options: LRUCache.FetchOptions<K, V, FC>, context: any) => BackgroundFetch<V>;
|
||||
isBackgroundFetch: (p: unknown) => p is BackgroundFetch<V>;
|
||||
backgroundFetch: (k: K, index: number | undefined, options: LRUCache.FetchOptions<K, V, FC>, context: unknown) => BackgroundFetch<V>;
|
||||
moveToTail: (index: number) => void;
|
||||
indexes: (options?: {
|
||||
allowStale: boolean;
|
||||
@@ -956,6 +1075,10 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
* {@link LRUCache.OptionsBase.dispose} (read-only)
|
||||
*/
|
||||
get dispose(): LRUCache.Disposer<K, V> | undefined;
|
||||
/**
|
||||
* {@link LRUCache.OptionsBase.onInsert} (read-only)
|
||||
*/
|
||||
get onInsert(): LRUCache.Inserter<K, V> | undefined;
|
||||
/**
|
||||
* {@link LRUCache.OptionsBase.disposeAfter} (read-only)
|
||||
*/
|
||||
@@ -977,7 +1100,7 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
* Return a generator yielding `[key, value]` pairs,
|
||||
* in order from least recently used to most recently used.
|
||||
*/
|
||||
rentries(): Generator<(K | V | BackgroundFetch<V> | undefined)[], void, unknown>;
|
||||
rentries(): Generator<(K | V)[], void, unknown>;
|
||||
/**
|
||||
* Return a generator yielding the keys in the cache,
|
||||
* in order from most recently used to least recently used.
|
||||
@@ -1001,7 +1124,7 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
* Return a generator yielding the values in the cache,
|
||||
* in order from least recently used to most recently used.
|
||||
*/
|
||||
rvalues(): Generator<V | BackgroundFetch<V> | undefined, void, unknown>;
|
||||
rvalues(): Generator<V | undefined, void, unknown>;
|
||||
/**
|
||||
* Iterating over the cache itself yields the same results as
|
||||
* {@link LRUCache.entries}
|
||||
@@ -1029,12 +1152,12 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
*
|
||||
* Does not update age or recenty of use, or iterate over stale values.
|
||||
*/
|
||||
forEach(fn: (v: V, k: K, self: LRUCache<K, V, FC>) => any, thisp?: any): void;
|
||||
forEach(fn: (v: V, k: K, self: LRUCache<K, V, FC>) => unknown, thisp?: unknown): void;
|
||||
/**
|
||||
* The same as {@link LRUCache.forEach} but items are iterated over in
|
||||
* reverse order. (ie, less recently used items are iterated over first.)
|
||||
*/
|
||||
rforEach(fn: (v: V, k: K, self: LRUCache<K, V, FC>) => any, thisp?: any): void;
|
||||
rforEach(fn: (v: V, k: K, self: LRUCache<K, V, FC>) => unknown, thisp?: unknown): void;
|
||||
/**
|
||||
* Delete any stale entries. Returns true if anything was removed,
|
||||
* false otherwise.
|
||||
@@ -1055,7 +1178,7 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
info(key: K): LRUCache.Entry<V> | undefined;
|
||||
/**
|
||||
* Return an array of [key, {@link LRUCache.Entry}] tuples which can be
|
||||
* passed to {@link LRLUCache#load}.
|
||||
* passed to {@link LRUCache#load}.
|
||||
*
|
||||
* The `start` fields are calculated relative to a portable `Date.now()`
|
||||
* timestamp, even if `performance.now()` is available.
|
||||
@@ -1107,7 +1230,7 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
* If the value is `undefined`, then this is an alias for
|
||||
* `cache.delete(key)`. `undefined` is never stored in the cache.
|
||||
*/
|
||||
set(k: K, v: V | BackgroundFetch<V> | undefined, setOptions?: LRUCache.SetOptions<K, V, FC>): this;
|
||||
set(k: K, v: V | undefined, setOptions?: LRUCache.SetOptions<K, V, FC>): this;
|
||||
/**
|
||||
* Evict the least recently used item, returning its value or
|
||||
* `undefined` if cache is empty.
|
||||
@@ -1223,23 +1346,23 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
* the same time, because they're both waiting on the same
|
||||
* underlying fetchMethod response.
|
||||
*/
|
||||
fetch(k: K, fetchOptions: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V> : LRUCache.FetchOptionsWithContext<K, V, FC>): Promise<undefined | V>;
|
||||
fetch(k: unknown extends FC ? K : FC extends undefined | void ? K : never, fetchOptions?: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V> : never): Promise<undefined | V>;
|
||||
fetch(k: K, fetchOptions: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V, FC> : LRUCache.FetchOptionsWithContext<K, V, FC>): Promise<undefined | V>;
|
||||
fetch(k: unknown extends FC ? K : FC extends undefined | void ? K : never, fetchOptions?: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V, FC> : never): Promise<undefined | V>;
|
||||
/**
|
||||
* In some cases, `cache.fetch()` may resolve to `undefined`, either because
|
||||
* a {@link LRUCache.OptionsBase#fetchMethod} was not provided (turning
|
||||
* `cache.fetch(k)` into just an async wrapper around `cache.get(k)`) or
|
||||
* because `ignoreFetchAbort` was specified (either to the constructor or
|
||||
* in the {@link LRUCache.FetchOptions}). Also, the
|
||||
* {@link OptionsBase.fetchMethod} may return `undefined` or `void`, making
|
||||
* {@link LRUCache.OptionsBase.fetchMethod} may return `undefined` or `void`, making
|
||||
* the test even more complicated.
|
||||
*
|
||||
* Because inferring the cases where `undefined` might be returned are so
|
||||
* cumbersome, but testing for `undefined` can also be annoying, this method
|
||||
* can be used, which will reject if `this.fetch()` resolves to undefined.
|
||||
*/
|
||||
forceFetch(k: K, fetchOptions: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V> : LRUCache.FetchOptionsWithContext<K, V, FC>): Promise<V>;
|
||||
forceFetch(k: unknown extends FC ? K : FC extends undefined | void ? K : never, fetchOptions?: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V> : never): Promise<V>;
|
||||
forceFetch(k: K, fetchOptions: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V, FC> : LRUCache.FetchOptionsWithContext<K, V, FC>): Promise<V>;
|
||||
forceFetch(k: unknown extends FC ? K : FC extends undefined | void ? K : never, fetchOptions?: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V, FC> : never): Promise<V>;
|
||||
/**
|
||||
* If the key is found in the cache, then this is equivalent to
|
||||
* {@link LRUCache#get}. If not, in the cache, then calculate the value using
|
||||
@@ -1254,8 +1377,8 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
* relevant in the course of fetching the data. It is only relevant for the
|
||||
* course of a single `memo()` operation, and discarded afterwards.
|
||||
*/
|
||||
memo(k: K, memoOptions: unknown extends FC ? LRUCache.MemoOptions<K, V, FC> : FC extends undefined | void ? LRUCache.MemoOptionsNoContext<K, V> : LRUCache.MemoOptionsWithContext<K, V, FC>): V;
|
||||
memo(k: unknown extends FC ? K : FC extends undefined | void ? K : never, memoOptions?: unknown extends FC ? LRUCache.MemoOptions<K, V, FC> : FC extends undefined | void ? LRUCache.MemoOptionsNoContext<K, V> : never): V;
|
||||
memo(k: K, memoOptions: unknown extends FC ? LRUCache.MemoOptions<K, V, FC> : FC extends undefined | void ? LRUCache.MemoOptionsNoContext<K, V, FC> : LRUCache.MemoOptionsWithContext<K, V, FC>): V;
|
||||
memo(k: unknown extends FC ? K : FC extends undefined | void ? K : never, memoOptions?: unknown extends FC ? LRUCache.MemoOptions<K, V, FC> : FC extends undefined | void ? LRUCache.MemoOptionsNoContext<K, V, FC> : never): V;
|
||||
/**
|
||||
* Return a value from the cache. Will update the recency of the cache
|
||||
* entry found.
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+425
-245
File diff suppressed because it is too large
Load Diff
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+4
-4
File diff suppressed because one or more lines are too long
+156
-33
@@ -1,6 +1,8 @@
|
||||
/**
|
||||
* @module LRUCache
|
||||
*/
|
||||
import type { Perf } from './perf.js';
|
||||
export type { Perf } from './perf.js';
|
||||
declare const TYPE: unique symbol;
|
||||
export type PosInt = number & {
|
||||
[TYPE]: 'Positive Integer';
|
||||
@@ -75,6 +77,20 @@ export declare namespace LRUCache {
|
||||
* {@link OptionsBase.disposeAfter} options.
|
||||
*/
|
||||
type Disposer<K, V> = (value: V, key: K, reason: DisposeReason) => void;
|
||||
/**
|
||||
* The reason why an item was added to the cache, passed
|
||||
* to the {@link Inserter} methods.
|
||||
*
|
||||
* - `add`: the item was not found in the cache, and was added
|
||||
* - `update`: the item was in the cache, with the same value provided
|
||||
* - `replace`: the item was in the cache, and replaced
|
||||
*/
|
||||
type InsertReason = 'add' | 'update' | 'replace';
|
||||
/**
|
||||
* A method called upon item insertion, passed as the
|
||||
* {@link OptionsBase.insert}
|
||||
*/
|
||||
type Inserter<K, V> = (value: V, key: K, reason: InsertReason) => void;
|
||||
/**
|
||||
* A function that returns the effective calculated size
|
||||
* of an entry in the cache.
|
||||
@@ -102,8 +118,16 @@ export declare namespace LRUCache {
|
||||
*
|
||||
* The `status` option should be a plain JavaScript object. The following
|
||||
* fields will be set on it appropriately, depending on the situation.
|
||||
*
|
||||
* These objects are also the context objects passed to listeners on the
|
||||
* `lru-cache:metrics` diagnostic channel, and the `lru-cache` tracing
|
||||
* channels, in platforms that support them.
|
||||
*/
|
||||
interface Status<V> {
|
||||
interface Status<K, V, FC = unknown> {
|
||||
/**
|
||||
* The operation being performed
|
||||
*/
|
||||
op?: 'get' | 'set' | 'memo' | 'fetch' | 'delete' | 'has' | 'peek';
|
||||
/**
|
||||
* The status of a set() operation.
|
||||
*
|
||||
@@ -112,7 +136,37 @@ export declare namespace LRUCache {
|
||||
* - replace: the item was in the cache, and replaced
|
||||
* - miss: the item was not added to the cache for some reason
|
||||
*/
|
||||
set?: 'add' | 'update' | 'replace' | 'miss';
|
||||
set?: 'add' | 'update' | 'replace' | 'miss' | 'deleted';
|
||||
/**
|
||||
* The status of a delete() operation.
|
||||
*/
|
||||
delete?: LRUCache.DisposeReason;
|
||||
/**
|
||||
* The result of a peek() operation
|
||||
*
|
||||
* - hit: the item was found and returned
|
||||
* - stale: the item is in the cache, but past its ttl and not returned
|
||||
* - miss: item not in the cache
|
||||
*/
|
||||
peek?: 'hit' | 'miss' | 'stale';
|
||||
/**
|
||||
* The status of a memo() operation.
|
||||
*
|
||||
* - 'hit': the item was found in the cache and returned
|
||||
* - 'miss': the `memoMethod` function was called
|
||||
*/
|
||||
memo?: 'hit' | 'miss';
|
||||
/**
|
||||
* The `context` option provided to a memo or fetch operation
|
||||
*
|
||||
* In practice, of course, this will be the same type as the `FC`
|
||||
* fetch context param used to instantiate the LRUCache, but the
|
||||
* convolutions of threading that through would get quite complicated,
|
||||
* and preclude forcing/forbidding the passing of a `context` param
|
||||
* where it is/isn't expected, which is more valuable for error
|
||||
* prevention.
|
||||
*/
|
||||
context?: unknown;
|
||||
/**
|
||||
* the ttl stored for the item, or undefined if ttls are not used.
|
||||
*/
|
||||
@@ -143,8 +197,15 @@ export declare namespace LRUCache {
|
||||
*/
|
||||
maxEntrySizeExceeded?: true;
|
||||
/**
|
||||
* The old value, specified in the case of `set:'update'` or
|
||||
* `set:'replace'`
|
||||
* The key that was set or retrieved
|
||||
*/
|
||||
key?: K;
|
||||
/**
|
||||
* The value that was set
|
||||
*/
|
||||
value?: V;
|
||||
/**
|
||||
* The old value, specified in the case of `set:'replace'`
|
||||
*/
|
||||
oldValue?: V;
|
||||
/**
|
||||
@@ -170,6 +231,10 @@ export declare namespace LRUCache {
|
||||
* {@link FetchOptions.forceRefresh} was specified.
|
||||
*/
|
||||
fetch?: 'get' | 'inflight' | 'miss' | 'hit' | 'stale' | 'refresh';
|
||||
/**
|
||||
* `forceRefresh` option was used for either a fetch or memo operation
|
||||
*/
|
||||
forceRefresh?: boolean;
|
||||
/**
|
||||
* The {@link OptionsBase.fetchMethod} was called
|
||||
*/
|
||||
@@ -191,7 +256,7 @@ export declare namespace LRUCache {
|
||||
fetchAborted?: true;
|
||||
/**
|
||||
* The abort signal received was ignored, and the fetch was allowed to
|
||||
* continue.
|
||||
* continue in the background.
|
||||
*/
|
||||
fetchAbortIgnored?: true;
|
||||
/**
|
||||
@@ -207,15 +272,27 @@ export declare namespace LRUCache {
|
||||
*
|
||||
* - fetching: The item is currently being fetched. If a previous value
|
||||
* is present and allowed, that will be returned.
|
||||
* - stale: The item is in the cache, and is stale.
|
||||
* - stale: The item is in the cache, and is stale. If it was returned,
|
||||
* then the `returnedStale` flag will be set.
|
||||
* - stale-fetching: The value is being fetched in the background, but is
|
||||
* currently stale. If the stale value was returned, then the
|
||||
* `returnedStale` flag will be set.
|
||||
* - hit: the item is in the cache
|
||||
* - miss: the item is not in the cache
|
||||
*/
|
||||
get?: 'stale' | 'hit' | 'miss';
|
||||
get?: 'stale' | 'hit' | 'miss' | 'fetching' | 'stale-fetching';
|
||||
/**
|
||||
* A fetch or get operation returned a stale value.
|
||||
*/
|
||||
returnedStale?: true;
|
||||
/**
|
||||
* A tracingChannel trace was started for this operation
|
||||
*/
|
||||
trace?: boolean;
|
||||
/**
|
||||
* A reference to the cache instance associated with this operation
|
||||
*/
|
||||
cache?: LRUCache<K & {}, V & {}, FC>;
|
||||
}
|
||||
/**
|
||||
* options which override the options set in the LRUCache constructor
|
||||
@@ -233,7 +310,7 @@ export declare namespace LRUCache {
|
||||
* the fetchMethod is called.
|
||||
*/
|
||||
interface FetcherFetchOptions<K, V, FC = unknown> extends Pick<OptionsBase<K, V, FC>, 'allowStale' | 'updateAgeOnGet' | 'noDeleteOnStaleGet' | 'sizeCalculation' | 'ttl' | 'noDisposeOnSet' | 'noUpdateTTL' | 'noDeleteOnFetchRejection' | 'allowStaleOnFetchRejection' | 'ignoreFetchAbort' | 'allowStaleOnFetchAbort'> {
|
||||
status?: Status<V>;
|
||||
status?: Status<K, V, FC>;
|
||||
size?: Size;
|
||||
}
|
||||
/**
|
||||
@@ -255,7 +332,7 @@ export declare namespace LRUCache {
|
||||
*/
|
||||
context?: FC;
|
||||
signal?: AbortSignal;
|
||||
status?: Status<V>;
|
||||
status?: Status<K, V, FC>;
|
||||
}
|
||||
/**
|
||||
* Options provided to {@link LRUCache#fetch} when the FC type is something
|
||||
@@ -268,7 +345,7 @@ export declare namespace LRUCache {
|
||||
* Options provided to {@link LRUCache#fetch} when the FC type is
|
||||
* `undefined` or `void`
|
||||
*/
|
||||
interface FetchOptionsNoContext<K, V> extends FetchOptions<K, V, undefined> {
|
||||
interface FetchOptionsNoContext<K, V, FC extends undefined | void = undefined> extends FetchOptions<K, V, FC> {
|
||||
context?: undefined;
|
||||
}
|
||||
interface MemoOptions<K, V, FC = unknown> extends Pick<OptionsBase<K, V, FC>, 'allowStale' | 'updateAgeOnGet' | 'noDeleteOnStaleGet' | 'sizeCalculation' | 'ttl' | 'noDisposeOnSet' | 'noUpdateTTL' | 'noDeleteOnFetchRejection' | 'allowStaleOnFetchRejection' | 'ignoreFetchAbort' | 'allowStaleOnFetchAbort'> {
|
||||
@@ -286,7 +363,7 @@ export declare namespace LRUCache {
|
||||
* be required.
|
||||
*/
|
||||
context?: FC;
|
||||
status?: Status<V>;
|
||||
status?: Status<K, V, FC>;
|
||||
}
|
||||
/**
|
||||
* Options provided to {@link LRUCache#memo} when the FC type is something
|
||||
@@ -299,7 +376,7 @@ export declare namespace LRUCache {
|
||||
* Options provided to {@link LRUCache#memo} when the FC type is
|
||||
* `undefined` or `void`
|
||||
*/
|
||||
interface MemoOptionsNoContext<K, V> extends MemoOptions<K, V, undefined> {
|
||||
interface MemoOptionsNoContext<K, V, FC extends undefined | void = undefined> extends MemoOptions<K, V, FC> {
|
||||
context?: undefined;
|
||||
}
|
||||
/**
|
||||
@@ -320,7 +397,7 @@ export declare namespace LRUCache {
|
||||
*
|
||||
* This is the union of {@link GetOptions} and {@link SetOptions}, plus
|
||||
* {@link MemoOptions.forceRefresh}, and
|
||||
* {@link MemoerOptions.context}
|
||||
* {@link MemoOptions.context}
|
||||
*
|
||||
* Any of these may be modified in the {@link OptionsBase.memoMethod}
|
||||
* function, but the {@link GetOptions} fields will of course have no
|
||||
@@ -328,7 +405,7 @@ export declare namespace LRUCache {
|
||||
* the memoMethod is called.
|
||||
*/
|
||||
interface MemoizerMemoOptions<K, V, FC = unknown> extends Pick<OptionsBase<K, V, FC>, 'allowStale' | 'updateAgeOnGet' | 'noDeleteOnStaleGet' | 'sizeCalculation' | 'ttl' | 'noDisposeOnSet' | 'noUpdateTTL'> {
|
||||
status?: Status<V>;
|
||||
status?: Status<K, V, FC>;
|
||||
size?: Size;
|
||||
start?: Milliseconds;
|
||||
}
|
||||
@@ -336,18 +413,19 @@ export declare namespace LRUCache {
|
||||
* Options that may be passed to the {@link LRUCache#has} method.
|
||||
*/
|
||||
interface HasOptions<K, V, FC> extends Pick<OptionsBase<K, V, FC>, 'updateAgeOnHas'> {
|
||||
status?: Status<V>;
|
||||
status?: Status<K, V, FC>;
|
||||
}
|
||||
/**
|
||||
* Options that may be passed to the {@link LRUCache#get} method.
|
||||
*/
|
||||
interface GetOptions<K, V, FC> extends Pick<OptionsBase<K, V, FC>, 'allowStale' | 'updateAgeOnGet' | 'noDeleteOnStaleGet'> {
|
||||
status?: Status<V>;
|
||||
status?: Status<K, V, FC>;
|
||||
}
|
||||
/**
|
||||
* Options that may be passed to the {@link LRUCache#peek} method.
|
||||
*/
|
||||
interface PeekOptions<K, V, FC> extends Pick<OptionsBase<K, V, FC>, 'allowStale'> {
|
||||
status?: Status<K, V, FC>;
|
||||
}
|
||||
/**
|
||||
* Options that may be passed to the {@link LRUCache#set} method.
|
||||
@@ -368,7 +446,7 @@ export declare namespace LRUCache {
|
||||
* method is in use.
|
||||
*/
|
||||
start?: Milliseconds;
|
||||
status?: Status<V>;
|
||||
status?: Status<K, V, FC>;
|
||||
}
|
||||
/**
|
||||
* The type signature for the {@link OptionsBase.fetchMethod} option.
|
||||
@@ -555,6 +633,17 @@ export declare namespace LRUCache {
|
||||
* `cache.clear()`, or `cache.set(key, undefined)`.
|
||||
*/
|
||||
dispose?: Disposer<K, V>;
|
||||
/**
|
||||
* Function that is called when new items are inserted into the cache,
|
||||
* as `onInsert(value, key, reason)`.
|
||||
*
|
||||
* This can be useful if you need to perform actions when an item is
|
||||
* added, such as logging or tracking insertions.
|
||||
*
|
||||
* Unlike some other options, this may _not_ be overridden by passing
|
||||
* an option to `set()`, for performance and consistency reasons.
|
||||
*/
|
||||
onInsert?: Inserter<K, V>;
|
||||
/**
|
||||
* The same as {@link OptionsBase.dispose}, but called *after* the entry
|
||||
* is completely removed and the cache is once again in a clean state.
|
||||
@@ -610,6 +699,20 @@ export declare namespace LRUCache {
|
||||
* though for most cases, only minimally.
|
||||
*/
|
||||
maxSize?: Size;
|
||||
/**
|
||||
* The effective size for background fetch promises.
|
||||
*
|
||||
* This has no effect unless `maxSize` and `sizeCalculation` are used,
|
||||
* and a {@link LRUCache.OptionsBase.fetchMethod} is provided to
|
||||
* support {@link LRUCache#fetch}.
|
||||
*
|
||||
* If a stale value is present in the cache, then the effective size of
|
||||
* the background fetch is the size of the stale item it will eventually
|
||||
* replace. If not, then this value is used as its effective size.
|
||||
*
|
||||
* @default 1
|
||||
*/
|
||||
backgroundFetchSize?: number;
|
||||
/**
|
||||
* The maximum allowed size for any single item in the cache.
|
||||
*
|
||||
@@ -796,6 +899,15 @@ export declare namespace LRUCache {
|
||||
* call to {@link LRUCache#fetch}.
|
||||
*/
|
||||
ignoreFetchAbort?: boolean;
|
||||
/**
|
||||
* In some cases, you may want to swap out the performance/Date object
|
||||
* used for TTL tracking. This should almost certainly NOT be done in
|
||||
* production environments!
|
||||
*
|
||||
* This value defaults to `global.performance` if it has a `now()` method,
|
||||
* or the `global.Date` object otherwise.
|
||||
*/
|
||||
perf?: Perf;
|
||||
}
|
||||
interface OptionsMaxLimit<K, V, FC> extends OptionsBase<K, V, FC> {
|
||||
max: Count;
|
||||
@@ -837,8 +949,12 @@ export declare namespace LRUCache {
|
||||
*
|
||||
* Changing any of these will alter the defaults for subsequent method calls.
|
||||
*/
|
||||
export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implements Map<K, V> {
|
||||
export declare class LRUCache<K extends {}, V extends {}, FC = unknown> {
|
||||
#private;
|
||||
/**
|
||||
* {@link LRUCache.OptionsBase.perf}
|
||||
*/
|
||||
get perf(): Perf;
|
||||
/**
|
||||
* {@link LRUCache.OptionsBase.ttl}
|
||||
*/
|
||||
@@ -899,6 +1015,8 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
* {@link LRUCache.OptionsBase.ignoreFetchAbort}
|
||||
*/
|
||||
ignoreFetchAbort: boolean;
|
||||
/** {@link LRUCache.OptionsBase.backgroundFetchSize} */
|
||||
backgroundFetchSize: number;
|
||||
/**
|
||||
* Do not call this method unless you need to inspect the
|
||||
* inner workings of the cache. If anything returned by this
|
||||
@@ -911,6 +1029,7 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
static unsafeExposeInternals<K extends {}, V extends {}, FC extends unknown = unknown>(c: LRUCache<K, V, FC>): {
|
||||
starts: ZeroArray | undefined;
|
||||
ttls: ZeroArray | undefined;
|
||||
autopurgeTimers: (NodeJS.Timeout | undefined)[] | undefined;
|
||||
sizes: ZeroArray | undefined;
|
||||
keyMap: Map<K, number>;
|
||||
keyList: (K | undefined)[];
|
||||
@@ -920,8 +1039,8 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
readonly head: Index;
|
||||
readonly tail: Index;
|
||||
free: StackLike;
|
||||
isBackgroundFetch: (p: any) => boolean;
|
||||
backgroundFetch: (k: K, index: number | undefined, options: LRUCache.FetchOptions<K, V, FC>, context: any) => BackgroundFetch<V>;
|
||||
isBackgroundFetch: (p: unknown) => p is BackgroundFetch<V>;
|
||||
backgroundFetch: (k: K, index: number | undefined, options: LRUCache.FetchOptions<K, V, FC>, context: unknown) => BackgroundFetch<V>;
|
||||
moveToTail: (index: number) => void;
|
||||
indexes: (options?: {
|
||||
allowStale: boolean;
|
||||
@@ -956,6 +1075,10 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
* {@link LRUCache.OptionsBase.dispose} (read-only)
|
||||
*/
|
||||
get dispose(): LRUCache.Disposer<K, V> | undefined;
|
||||
/**
|
||||
* {@link LRUCache.OptionsBase.onInsert} (read-only)
|
||||
*/
|
||||
get onInsert(): LRUCache.Inserter<K, V> | undefined;
|
||||
/**
|
||||
* {@link LRUCache.OptionsBase.disposeAfter} (read-only)
|
||||
*/
|
||||
@@ -977,7 +1100,7 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
* Return a generator yielding `[key, value]` pairs,
|
||||
* in order from least recently used to most recently used.
|
||||
*/
|
||||
rentries(): Generator<(K | V | BackgroundFetch<V> | undefined)[], void, unknown>;
|
||||
rentries(): Generator<(K | V)[], void, unknown>;
|
||||
/**
|
||||
* Return a generator yielding the keys in the cache,
|
||||
* in order from most recently used to least recently used.
|
||||
@@ -1001,7 +1124,7 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
* Return a generator yielding the values in the cache,
|
||||
* in order from least recently used to most recently used.
|
||||
*/
|
||||
rvalues(): Generator<V | BackgroundFetch<V> | undefined, void, unknown>;
|
||||
rvalues(): Generator<V | undefined, void, unknown>;
|
||||
/**
|
||||
* Iterating over the cache itself yields the same results as
|
||||
* {@link LRUCache.entries}
|
||||
@@ -1029,12 +1152,12 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
*
|
||||
* Does not update age or recenty of use, or iterate over stale values.
|
||||
*/
|
||||
forEach(fn: (v: V, k: K, self: LRUCache<K, V, FC>) => any, thisp?: any): void;
|
||||
forEach(fn: (v: V, k: K, self: LRUCache<K, V, FC>) => unknown, thisp?: unknown): void;
|
||||
/**
|
||||
* The same as {@link LRUCache.forEach} but items are iterated over in
|
||||
* reverse order. (ie, less recently used items are iterated over first.)
|
||||
*/
|
||||
rforEach(fn: (v: V, k: K, self: LRUCache<K, V, FC>) => any, thisp?: any): void;
|
||||
rforEach(fn: (v: V, k: K, self: LRUCache<K, V, FC>) => unknown, thisp?: unknown): void;
|
||||
/**
|
||||
* Delete any stale entries. Returns true if anything was removed,
|
||||
* false otherwise.
|
||||
@@ -1055,7 +1178,7 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
info(key: K): LRUCache.Entry<V> | undefined;
|
||||
/**
|
||||
* Return an array of [key, {@link LRUCache.Entry}] tuples which can be
|
||||
* passed to {@link LRLUCache#load}.
|
||||
* passed to {@link LRUCache#load}.
|
||||
*
|
||||
* The `start` fields are calculated relative to a portable `Date.now()`
|
||||
* timestamp, even if `performance.now()` is available.
|
||||
@@ -1107,7 +1230,7 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
* If the value is `undefined`, then this is an alias for
|
||||
* `cache.delete(key)`. `undefined` is never stored in the cache.
|
||||
*/
|
||||
set(k: K, v: V | BackgroundFetch<V> | undefined, setOptions?: LRUCache.SetOptions<K, V, FC>): this;
|
||||
set(k: K, v: V | undefined, setOptions?: LRUCache.SetOptions<K, V, FC>): this;
|
||||
/**
|
||||
* Evict the least recently used item, returning its value or
|
||||
* `undefined` if cache is empty.
|
||||
@@ -1223,23 +1346,23 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
* the same time, because they're both waiting on the same
|
||||
* underlying fetchMethod response.
|
||||
*/
|
||||
fetch(k: K, fetchOptions: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V> : LRUCache.FetchOptionsWithContext<K, V, FC>): Promise<undefined | V>;
|
||||
fetch(k: unknown extends FC ? K : FC extends undefined | void ? K : never, fetchOptions?: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V> : never): Promise<undefined | V>;
|
||||
fetch(k: K, fetchOptions: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V, FC> : LRUCache.FetchOptionsWithContext<K, V, FC>): Promise<undefined | V>;
|
||||
fetch(k: unknown extends FC ? K : FC extends undefined | void ? K : never, fetchOptions?: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V, FC> : never): Promise<undefined | V>;
|
||||
/**
|
||||
* In some cases, `cache.fetch()` may resolve to `undefined`, either because
|
||||
* a {@link LRUCache.OptionsBase#fetchMethod} was not provided (turning
|
||||
* `cache.fetch(k)` into just an async wrapper around `cache.get(k)`) or
|
||||
* because `ignoreFetchAbort` was specified (either to the constructor or
|
||||
* in the {@link LRUCache.FetchOptions}). Also, the
|
||||
* {@link OptionsBase.fetchMethod} may return `undefined` or `void`, making
|
||||
* {@link LRUCache.OptionsBase.fetchMethod} may return `undefined` or `void`, making
|
||||
* the test even more complicated.
|
||||
*
|
||||
* Because inferring the cases where `undefined` might be returned are so
|
||||
* cumbersome, but testing for `undefined` can also be annoying, this method
|
||||
* can be used, which will reject if `this.fetch()` resolves to undefined.
|
||||
*/
|
||||
forceFetch(k: K, fetchOptions: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V> : LRUCache.FetchOptionsWithContext<K, V, FC>): Promise<V>;
|
||||
forceFetch(k: unknown extends FC ? K : FC extends undefined | void ? K : never, fetchOptions?: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V> : never): Promise<V>;
|
||||
forceFetch(k: K, fetchOptions: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V, FC> : LRUCache.FetchOptionsWithContext<K, V, FC>): Promise<V>;
|
||||
forceFetch(k: unknown extends FC ? K : FC extends undefined | void ? K : never, fetchOptions?: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V, FC> : never): Promise<V>;
|
||||
/**
|
||||
* If the key is found in the cache, then this is equivalent to
|
||||
* {@link LRUCache#get}. If not, in the cache, then calculate the value using
|
||||
@@ -1254,8 +1377,8 @@ export declare class LRUCache<K extends {}, V extends {}, FC = unknown> implemen
|
||||
* relevant in the course of fetching the data. It is only relevant for the
|
||||
* course of a single `memo()` operation, and discarded afterwards.
|
||||
*/
|
||||
memo(k: K, memoOptions: unknown extends FC ? LRUCache.MemoOptions<K, V, FC> : FC extends undefined | void ? LRUCache.MemoOptionsNoContext<K, V> : LRUCache.MemoOptionsWithContext<K, V, FC>): V;
|
||||
memo(k: unknown extends FC ? K : FC extends undefined | void ? K : never, memoOptions?: unknown extends FC ? LRUCache.MemoOptions<K, V, FC> : FC extends undefined | void ? LRUCache.MemoOptionsNoContext<K, V> : never): V;
|
||||
memo(k: K, memoOptions: unknown extends FC ? LRUCache.MemoOptions<K, V, FC> : FC extends undefined | void ? LRUCache.MemoOptionsNoContext<K, V, FC> : LRUCache.MemoOptionsWithContext<K, V, FC>): V;
|
||||
memo(k: unknown extends FC ? K : FC extends undefined | void ? K : never, memoOptions?: unknown extends FC ? LRUCache.MemoOptions<K, V, FC> : FC extends undefined | void ? LRUCache.MemoOptionsNoContext<K, V, FC> : never): V;
|
||||
/**
|
||||
* Return a value from the cache. Will update the recency of the cache
|
||||
* entry found.
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+425
-245
File diff suppressed because it is too large
Load Diff
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+4
-4
File diff suppressed because one or more lines are too long
+82
-44
@@ -1,10 +1,7 @@
|
||||
{
|
||||
"name": "lru-cache",
|
||||
"publishConfig": {
|
||||
"tag": "legacy-v10"
|
||||
},
|
||||
"description": "A cache object that deletes the least-recently-used items.",
|
||||
"version": "10.4.3",
|
||||
"version": "11.5.0",
|
||||
"author": "Isaac Z. Schlueter <i@izs.me>",
|
||||
"keywords": [
|
||||
"mru",
|
||||
@@ -14,7 +11,7 @@
|
||||
"sideEffects": false,
|
||||
"scripts": {
|
||||
"build": "npm run prepare",
|
||||
"prepare": "tshy && bash fixup.sh",
|
||||
"prepare": "tshy && bash scripts/build.sh",
|
||||
"pretest": "npm run prepare",
|
||||
"presnap": "npm run prepare",
|
||||
"test": "tap",
|
||||
@@ -28,89 +25,130 @@
|
||||
"prebenchmark": "npm run prepare",
|
||||
"benchmark": "make -C benchmark",
|
||||
"preprofile": "npm run prepare",
|
||||
"profile": "make -C benchmark profile"
|
||||
"profile": "make -C benchmark profile",
|
||||
"lint": "oxlint --fix src test",
|
||||
"postsnap": "npm run lint",
|
||||
"postlint": "npm run format"
|
||||
},
|
||||
"main": "./dist/commonjs/index.js",
|
||||
"main": "./dist/commonjs/index.min.js",
|
||||
"types": "./dist/commonjs/index.d.ts",
|
||||
"tshy": {
|
||||
"esmDialects": [
|
||||
"browser",
|
||||
"node"
|
||||
],
|
||||
"commonjsDialects": [
|
||||
"browser",
|
||||
"node"
|
||||
],
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./min": {
|
||||
"./raw": "./src/index.ts",
|
||||
".": {
|
||||
"import": {
|
||||
"browser": {
|
||||
"types": "./dist/esm/browser/index.d.ts",
|
||||
"default": "./dist/esm/browser/index.min.js"
|
||||
},
|
||||
"node": {
|
||||
"types": "./dist/esm/node/index.d.ts",
|
||||
"default": "./dist/esm/node/index.min.js"
|
||||
},
|
||||
"types": "./dist/esm/index.d.ts",
|
||||
"default": "./dist/esm/index.min.js"
|
||||
},
|
||||
"require": {
|
||||
"browser": {
|
||||
"types": "./dist/commonjs/browser/index.d.ts",
|
||||
"default": "./dist/commonjs/browser/index.min.js"
|
||||
},
|
||||
"node": {
|
||||
"types": "./dist/commonjs/node/index.d.ts",
|
||||
"default": "./dist/commonjs/node/index.min.js"
|
||||
},
|
||||
"types": "./dist/commonjs/index.d.ts",
|
||||
"default": "./dist/commonjs/index.min.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"selfLink": false
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/isaacs/node-lru-cache.git"
|
||||
"url": "git+ssh://git@github.com/isaacs/node-lru-cache.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.2.5",
|
||||
"@types/tap": "^15.0.6",
|
||||
"benchmark": "^2.1.4",
|
||||
"esbuild": "^0.17.11",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"esbuild": "^0.28.0",
|
||||
"marked": "^4.2.12",
|
||||
"mkdirp": "^2.1.5",
|
||||
"prettier": "^2.6.2",
|
||||
"tap": "^20.0.3",
|
||||
"tshy": "^2.0.0",
|
||||
"tslib": "^2.4.0",
|
||||
"typedoc": "^0.25.3",
|
||||
"typescript": "^5.2.2"
|
||||
"mkdirp": "^3.0.1",
|
||||
"oxlint": "^1.65.0",
|
||||
"oxlint-tsgolint": "^0.22.1",
|
||||
"prettier": "^3.8.3",
|
||||
"tap": "^21.7.4",
|
||||
"tshy": "^4.1.2",
|
||||
"typedoc": "^0.28.19"
|
||||
},
|
||||
"license": "ISC",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"prettier": {
|
||||
"semi": false,
|
||||
"printWidth": 70,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"singleQuote": true,
|
||||
"jsxSingleQuote": false,
|
||||
"bracketSameLine": true,
|
||||
"arrowParens": "avoid",
|
||||
"endOfLine": "lf"
|
||||
},
|
||||
"tap": {
|
||||
"node-arg": [
|
||||
"--expose-gc"
|
||||
],
|
||||
"plugin": [
|
||||
"@tapjs/clock"
|
||||
]
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"./raw": {
|
||||
"import": {
|
||||
"browser": {
|
||||
"types": "./dist/esm/browser/index.d.ts",
|
||||
"default": "./dist/esm/browser/index.js"
|
||||
},
|
||||
"node": {
|
||||
"types": "./dist/esm/node/index.d.ts",
|
||||
"default": "./dist/esm/node/index.js"
|
||||
},
|
||||
"types": "./dist/esm/index.d.ts",
|
||||
"default": "./dist/esm/index.js"
|
||||
},
|
||||
"require": {
|
||||
"browser": {
|
||||
"types": "./dist/commonjs/browser/index.d.ts",
|
||||
"default": "./dist/commonjs/browser/index.js"
|
||||
},
|
||||
"node": {
|
||||
"types": "./dist/commonjs/node/index.d.ts",
|
||||
"default": "./dist/commonjs/node/index.js"
|
||||
},
|
||||
"types": "./dist/commonjs/index.d.ts",
|
||||
"default": "./dist/commonjs/index.js"
|
||||
}
|
||||
},
|
||||
"./min": {
|
||||
".": {
|
||||
"import": {
|
||||
"browser": {
|
||||
"types": "./dist/esm/browser/index.d.ts",
|
||||
"default": "./dist/esm/browser/index.min.js"
|
||||
},
|
||||
"node": {
|
||||
"types": "./dist/esm/node/index.d.ts",
|
||||
"default": "./dist/esm/node/index.min.js"
|
||||
},
|
||||
"types": "./dist/esm/index.d.ts",
|
||||
"default": "./dist/esm/index.min.js"
|
||||
},
|
||||
"require": {
|
||||
"browser": {
|
||||
"types": "./dist/commonjs/browser/index.d.ts",
|
||||
"default": "./dist/commonjs/browser/index.min.js"
|
||||
},
|
||||
"node": {
|
||||
"types": "./dist/commonjs/node/index.d.ts",
|
||||
"default": "./dist/commonjs/node/index.min.js"
|
||||
},
|
||||
"types": "./dist/commonjs/index.d.ts",
|
||||
"default": "./dist/commonjs/index.min.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "module",
|
||||
"module": "./dist/esm/index.js"
|
||||
"module": "./dist/esm/index.min.js"
|
||||
}
|
||||
|
||||
+6
-6
@@ -2,7 +2,7 @@
|
||||
"author": "GitHub Inc.",
|
||||
"name": "which",
|
||||
"description": "Like which(1) unix command. Find the first instance of an executable in the PATH.",
|
||||
"version": "5.0.0",
|
||||
"version": "6.0.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/npm/node-which.git"
|
||||
@@ -13,11 +13,11 @@
|
||||
},
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"isexe": "^3.1.1"
|
||||
"isexe": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@npmcli/eslint-config": "^5.0.0",
|
||||
"@npmcli/template-oss": "4.23.3",
|
||||
"@npmcli/eslint-config": "^6.0.0",
|
||||
"@npmcli/template-oss": "4.28.1",
|
||||
"tap": "^16.3.0"
|
||||
},
|
||||
"scripts": {
|
||||
@@ -42,11 +42,11 @@
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.17.0 || >=20.5.0"
|
||||
"node": "^20.17.0 || >=22.9.0"
|
||||
},
|
||||
"templateOSS": {
|
||||
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
|
||||
"version": "4.23.3",
|
||||
"version": "4.28.1",
|
||||
"publish": "true"
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@npmcli/git",
|
||||
"version": "6.0.3",
|
||||
"version": "7.0.2",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
"bin/",
|
||||
@@ -33,22 +33,22 @@
|
||||
"devDependencies": {
|
||||
"@npmcli/eslint-config": "^5.0.0",
|
||||
"@npmcli/template-oss": "4.24.1",
|
||||
"npm-package-arg": "^12.0.1",
|
||||
"npm-package-arg": "^13.0.0",
|
||||
"slash": "^3.0.0",
|
||||
"tap": "^16.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@npmcli/promise-spawn": "^8.0.0",
|
||||
"ini": "^5.0.0",
|
||||
"lru-cache": "^10.0.1",
|
||||
"npm-pick-manifest": "^10.0.0",
|
||||
"proc-log": "^5.0.0",
|
||||
"promise-retry": "^2.0.1",
|
||||
"@gar/promise-retry": "^1.0.0",
|
||||
"@npmcli/promise-spawn": "^9.0.0",
|
||||
"ini": "^6.0.0",
|
||||
"lru-cache": "^11.2.1",
|
||||
"npm-pick-manifest": "^11.0.1",
|
||||
"proc-log": "^6.0.0",
|
||||
"semver": "^7.3.5",
|
||||
"which": "^5.0.0"
|
||||
"which": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.17.0 || >=20.5.0"
|
||||
"node": "^20.17.0 || >=22.9.0"
|
||||
},
|
||||
"templateOSS": {
|
||||
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
|
||||
|
||||
Reference in New Issue
Block a user