avancement planning

This commit is contained in:
2026-05-26 11:58:39 +02:00
parent 619a2b240a
commit 150b97cd2e
4892 changed files with 99214 additions and 429382 deletions
+2 -2
View File
@@ -10,7 +10,7 @@ const Pipeline = require('minipass-pipeline')
const Flush = require('minipass-flush')
const path = require('path')
const ssri = require('ssri')
const uniqueFilename = require('unique-filename')
const { tmpName } = require('../util/tmp')
const fsm = require('fs-minipass')
module.exports = write
@@ -152,7 +152,7 @@ async function pipeToTmp (inputStream, cache, tmpTarget, opts) {
}
async function makeTmp (cache, opts) {
const tmpTarget = uniqueFilename(path.join(cache, 'tmp'), opts.tmpPrefix)
const tmpTarget = tmpName(cache, opts.tmpPrefix)
await fs.mkdir(path.dirname(tmpTarget), { recursive: true })
return {
target: tmpTarget,
+2 -2
View File
@@ -12,7 +12,7 @@ const {
const { Minipass } = require('minipass')
const path = require('path')
const ssri = require('ssri')
const uniqueFilename = require('unique-filename')
const { tmpName } = require('./util/tmp')
const contentPath = require('./content/path')
const hashToSegments = require('./util/hash-to-segments')
@@ -69,7 +69,7 @@ async function compact (cache, key, matchFn, opts = {}) {
}).join('\n')
const setup = async () => {
const target = uniqueFilename(path.join(cache, 'tmp'), opts.tmpPrefix)
const target = tmpName(cache, opts.tmpPrefix)
await mkdir(path.dirname(target), { recursive: true })
return {
target,
+6
View File
@@ -1,11 +1,17 @@
'use strict'
const crypto = require('crypto')
const { withTempDir } = require('@npmcli/fs')
const fs = require('fs/promises')
const path = require('path')
module.exports.mkdir = mktmpdir
module.exports.tmpName = function tmpName (cache, tmpPrefix) {
const id = crypto.randomUUID()
return path.join(cache, 'tmp', tmpPrefix ? `${tmpPrefix}-${id}` : id)
}
async function mktmpdir (cache, opts = {}) {
const { tmpPrefix } = opts
const tmpDir = path.join(cache, 'tmp')
-63
View File
@@ -1,63 +0,0 @@
All packages under `src/` are licensed according to the terms in
their respective `LICENSE` or `LICENSE.md` files.
The remainder of this project is licensed under the Blue Oak
Model License, as follows:
-----
# Blue Oak Model License
Version 1.0.0
## Purpose
This license gives everyone as much permission to work with
this software as possible, while protecting contributors
from liability.
## Acceptance
In order to receive this license, you must agree to its
rules. The rules of this license are both obligations
under that agreement and conditions to your license.
You must not do anything with this software that triggers
a rule that you cannot or will not follow.
## Copyright
Each contributor licenses you to do everything with this
software that would otherwise infringe that contributor's
copyright in it.
## Notices
You must ensure that everyone who gets a copy of
any part of this software from you, with or without
changes, also gets the text of this license or a link to
<https://blueoakcouncil.org/license/1.0.0>.
## Excuse
If anyone notifies you in writing that you have not
complied with [Notices](#notices), you can keep your
license by taking all practical steps to comply within 30
days after the notice. If you do not do so, your license
ends immediately.
## Patent
Each contributor licenses you to do everything with this
software that would otherwise infringe any patent claims
they can license or become able to license.
## Reliability
No contributor can revoke this license.
## No Liability
***As far as the law allows, this software comes as is,
without any warranty or condition, and no contributor
will be liable to anyone for any damages related to this
software or this license, under any kind of legal claim.***
-3
View File
@@ -1,3 +0,0 @@
Like `chown -R`.
Takes the same arguments as `fs.chown()`
-3
View File
@@ -1,3 +0,0 @@
export declare const chownr: (p: string, uid: number, gid: number, cb: (er?: unknown) => any) => void;
export declare const chownrSync: (p: string, uid: number, gid: number) => void;
//# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AA0CA,eAAO,MAAM,MAAM,MACd,MAAM,OACJ,MAAM,OACN,MAAM,YACD,OAAO,KAAK,GAAG,SA0B1B,CAAA;AAcD,eAAO,MAAM,UAAU,MAAO,MAAM,OAAO,MAAM,OAAO,MAAM,SAiB7D,CAAA"}
-93
View File
@@ -1,93 +0,0 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.chownrSync = exports.chownr = void 0;
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const lchownSync = (path, uid, gid) => {
try {
return node_fs_1.default.lchownSync(path, uid, gid);
}
catch (er) {
if (er?.code !== 'ENOENT')
throw er;
}
};
const chown = (cpath, uid, gid, cb) => {
node_fs_1.default.lchown(cpath, uid, gid, er => {
// Skip ENOENT error
cb(er && er?.code !== 'ENOENT' ? er : null);
});
};
const chownrKid = (p, child, uid, gid, cb) => {
if (child.isDirectory()) {
(0, exports.chownr)(node_path_1.default.resolve(p, child.name), uid, gid, (er) => {
if (er)
return cb(er);
const cpath = node_path_1.default.resolve(p, child.name);
chown(cpath, uid, gid, cb);
});
}
else {
const cpath = node_path_1.default.resolve(p, child.name);
chown(cpath, uid, gid, cb);
}
};
const chownr = (p, uid, gid, cb) => {
node_fs_1.default.readdir(p, { withFileTypes: true }, (er, children) => {
// any error other than ENOTDIR or ENOTSUP means it's not readable,
// or doesn't exist. give up.
if (er) {
if (er.code === 'ENOENT')
return cb();
else if (er.code !== 'ENOTDIR' && er.code !== 'ENOTSUP')
return cb(er);
}
if (er || !children.length)
return chown(p, uid, gid, cb);
let len = children.length;
let errState = null;
const then = (er) => {
/* c8 ignore start */
if (errState)
return;
/* c8 ignore stop */
if (er)
return cb((errState = er));
if (--len === 0)
return chown(p, uid, gid, cb);
};
for (const child of children) {
chownrKid(p, child, uid, gid, then);
}
});
};
exports.chownr = chownr;
const chownrKidSync = (p, child, uid, gid) => {
if (child.isDirectory())
(0, exports.chownrSync)(node_path_1.default.resolve(p, child.name), uid, gid);
lchownSync(node_path_1.default.resolve(p, child.name), uid, gid);
};
const chownrSync = (p, uid, gid) => {
let children;
try {
children = node_fs_1.default.readdirSync(p, { withFileTypes: true });
}
catch (er) {
const e = er;
if (e?.code === 'ENOENT')
return;
else if (e?.code === 'ENOTDIR' || e?.code === 'ENOTSUP')
return lchownSync(p, uid, gid);
else
throw e;
}
for (const child of children) {
chownrKidSync(p, child, uid, gid);
}
return lchownSync(p, uid, gid);
};
exports.chownrSync = chownrSync;
//# sourceMappingURL=index.js.map
File diff suppressed because one or more lines are too long
-3
View File
@@ -1,3 +0,0 @@
{
"type": "commonjs"
}
-3
View File
@@ -1,3 +0,0 @@
export declare const chownr: (p: string, uid: number, gid: number, cb: (er?: unknown) => any) => void;
export declare const chownrSync: (p: string, uid: number, gid: number) => void;
//# sourceMappingURL=index.d.ts.map
-1
View File
@@ -1 +0,0 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AA0CA,eAAO,MAAM,MAAM,MACd,MAAM,OACJ,MAAM,OACN,MAAM,YACD,OAAO,KAAK,GAAG,SA0B1B,CAAA;AAcD,eAAO,MAAM,UAAU,MAAO,MAAM,OAAO,MAAM,OAAO,MAAM,SAiB7D,CAAA"}
-85
View File
@@ -1,85 +0,0 @@
import fs from 'node:fs';
import path from 'node:path';
const lchownSync = (path, uid, gid) => {
try {
return fs.lchownSync(path, uid, gid);
}
catch (er) {
if (er?.code !== 'ENOENT')
throw er;
}
};
const chown = (cpath, uid, gid, cb) => {
fs.lchown(cpath, uid, gid, er => {
// Skip ENOENT error
cb(er && er?.code !== 'ENOENT' ? er : null);
});
};
const chownrKid = (p, child, uid, gid, cb) => {
if (child.isDirectory()) {
chownr(path.resolve(p, child.name), uid, gid, (er) => {
if (er)
return cb(er);
const cpath = path.resolve(p, child.name);
chown(cpath, uid, gid, cb);
});
}
else {
const cpath = path.resolve(p, child.name);
chown(cpath, uid, gid, cb);
}
};
export const chownr = (p, uid, gid, cb) => {
fs.readdir(p, { withFileTypes: true }, (er, children) => {
// any error other than ENOTDIR or ENOTSUP means it's not readable,
// or doesn't exist. give up.
if (er) {
if (er.code === 'ENOENT')
return cb();
else if (er.code !== 'ENOTDIR' && er.code !== 'ENOTSUP')
return cb(er);
}
if (er || !children.length)
return chown(p, uid, gid, cb);
let len = children.length;
let errState = null;
const then = (er) => {
/* c8 ignore start */
if (errState)
return;
/* c8 ignore stop */
if (er)
return cb((errState = er));
if (--len === 0)
return chown(p, uid, gid, cb);
};
for (const child of children) {
chownrKid(p, child, uid, gid, then);
}
});
};
const chownrKidSync = (p, child, uid, gid) => {
if (child.isDirectory())
chownrSync(path.resolve(p, child.name), uid, gid);
lchownSync(path.resolve(p, child.name), uid, gid);
};
export const chownrSync = (p, uid, gid) => {
let children;
try {
children = fs.readdirSync(p, { withFileTypes: true });
}
catch (er) {
const e = er;
if (e?.code === 'ENOENT')
return;
else if (e?.code === 'ENOTDIR' || e?.code === 'ENOTSUP')
return lchownSync(p, uid, gid);
else
throw e;
}
for (const child of children) {
chownrKidSync(p, child, uid, gid);
}
return lchownSync(p, uid, gid);
};
//# sourceMappingURL=index.js.map
File diff suppressed because one or more lines are too long
-3
View File
@@ -1,3 +0,0 @@
{
"type": "module"
}
-69
View File
@@ -1,69 +0,0 @@
{
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
"name": "chownr",
"description": "like `chown -R`",
"version": "3.0.0",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/chownr.git"
},
"files": [
"dist"
],
"devDependencies": {
"@types/node": "^20.12.5",
"mkdirp": "^3.0.1",
"prettier": "^3.2.5",
"rimraf": "^5.0.5",
"tap": "^18.7.2",
"tshy": "^1.13.1",
"typedoc": "^0.25.12"
},
"scripts": {
"prepare": "tshy",
"pretest": "npm run prepare",
"test": "tap",
"preversion": "npm test",
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags",
"format": "prettier --write . --loglevel warn",
"typedoc": "typedoc --tsconfig .tshy/esm.json ./src/*.ts"
},
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=18"
},
"tshy": {
"exports": {
"./package.json": "./package.json",
".": "./src/index.ts"
}
},
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"types": "./dist/esm/index.d.ts",
"default": "./dist/esm/index.js"
},
"require": {
"types": "./dist/commonjs/index.d.ts",
"default": "./dist/commonjs/index.js"
}
}
},
"main": "./dist/commonjs/index.js",
"types": "./dist/commonjs/index.d.ts",
"type": "module",
"prettier": {
"semi": false,
"printWidth": 75,
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"jsxSingleQuote": false,
"bracketSameLine": true,
"arrowParens": "avoid",
"endOfLine": "lf"
}
}
-15
View File
@@ -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
View File
@@ -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
View File
@@ -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.
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+156 -33
View File
@@ -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.
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+82 -44
View File
@@ -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"
}
-55
View File
@@ -1,55 +0,0 @@
# Blue Oak Model License
Version 1.0.0
## Purpose
This license gives everyone as much permission to work with
this software as possible, while protecting contributors
from liability.
## Acceptance
In order to receive this license, you must agree to its
rules. The rules of this license are both obligations
under that agreement and conditions to your license.
You must not do anything with this software that triggers
a rule that you cannot or will not follow.
## Copyright
Each contributor licenses you to do everything with this
software that would otherwise infringe that contributor's
copyright in it.
## Notices
You must ensure that everyone who gets a copy of
any part of this software from you, with or without
changes, also gets the text of this license or a link to
<https://blueoakcouncil.org/license/1.0.0>.
## Excuse
If anyone notifies you in writing that you have not
complied with [Notices](#notices), you can keep your
license by taking all practical steps to comply within 30
days after the notice. If you do not do so, your license
ends immediately.
## Patent
Each contributor licenses you to do everything with this
software that would otherwise infringe any patent claims
they can license or become able to license.
## Reliability
No contributor can revoke this license.
## No Liability
***As far as the law allows, this software comes as is,
without any warranty or condition, and no contributor
will be liable to anyone for any damages related to this
software or this license, under any kind of legal claim.***
-1145
View File
File diff suppressed because it is too large Load Diff
-3
View File
@@ -1,3 +0,0 @@
import { Pack, PackSync } from './pack.js';
export declare const create: import("./make-command.js").TarCommand<Pack, PackSync>;
//# sourceMappingURL=create.d.ts.map
-1
View File
@@ -1 +0,0 @@
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/create.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AA8E1C,eAAO,MAAM,MAAM,wDAUlB,CAAA"}
-83
View File
@@ -1,83 +0,0 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.create = void 0;
const fs_minipass_1 = require("@isaacs/fs-minipass");
const node_path_1 = __importDefault(require("node:path"));
const list_js_1 = require("./list.js");
const make_command_js_1 = require("./make-command.js");
const pack_js_1 = require("./pack.js");
const createFileSync = (opt, files) => {
const p = new pack_js_1.PackSync(opt);
const stream = new fs_minipass_1.WriteStreamSync(opt.file, {
mode: opt.mode || 0o666,
});
p.pipe(stream);
addFilesSync(p, files);
};
const createFile = (opt, files) => {
const p = new pack_js_1.Pack(opt);
const stream = new fs_minipass_1.WriteStream(opt.file, {
mode: opt.mode || 0o666,
});
p.pipe(stream);
const promise = new Promise((res, rej) => {
stream.on('error', rej);
stream.on('close', res);
p.on('error', rej);
});
addFilesAsync(p, files);
return promise;
};
const addFilesSync = (p, files) => {
files.forEach(file => {
if (file.charAt(0) === '@') {
(0, list_js_1.list)({
file: node_path_1.default.resolve(p.cwd, file.slice(1)),
sync: true,
noResume: true,
onReadEntry: entry => p.add(entry),
});
}
else {
p.add(file);
}
});
p.end();
};
const addFilesAsync = async (p, files) => {
for (let i = 0; i < files.length; i++) {
const file = String(files[i]);
if (file.charAt(0) === '@') {
await (0, list_js_1.list)({
file: node_path_1.default.resolve(String(p.cwd), file.slice(1)),
noResume: true,
onReadEntry: entry => {
p.add(entry);
},
});
}
else {
p.add(file);
}
}
p.end();
};
const createSync = (opt, files) => {
const p = new pack_js_1.PackSync(opt);
addFilesSync(p, files);
return p;
};
const createAsync = (opt, files) => {
const p = new pack_js_1.Pack(opt);
addFilesAsync(p, files);
return p;
};
exports.create = (0, make_command_js_1.makeCommand)(createFileSync, createFile, createSync, createAsync, (_opt, files) => {
if (!files?.length) {
throw new TypeError('no paths specified to add to archive');
}
});
//# sourceMappingURL=create.js.map
File diff suppressed because one or more lines are too long
-8
View File
@@ -1,8 +0,0 @@
export declare class CwdError extends Error {
path: string;
code: string;
syscall: 'chdir';
constructor(path: string, code: string);
get name(): string;
}
//# sourceMappingURL=cwd-error.d.ts.map
@@ -1 +0,0 @@
{"version":3,"file":"cwd-error.d.ts","sourceRoot":"","sources":["../../src/cwd-error.ts"],"names":[],"mappings":"AAAA,qBAAa,QAAS,SAAQ,KAAK;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,OAAO,CAAU;gBAEd,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAMtC,IAAI,IAAI,WAEP;CACF"}
-18
View File
@@ -1,18 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CwdError = void 0;
class CwdError extends Error {
path;
code;
syscall = 'chdir';
constructor(path, code) {
super(`${code}: Cannot cd into '${path}'`);
this.path = path;
this.code = code;
}
get name() {
return 'CwdError';
}
}
exports.CwdError = CwdError;
//# sourceMappingURL=cwd-error.js.map
-1
View File
@@ -1 +0,0 @@
{"version":3,"file":"cwd-error.js","sourceRoot":"","sources":["../../src/cwd-error.ts"],"names":[],"mappings":";;;AAAA,MAAa,QAAS,SAAQ,KAAK;IACjC,IAAI,CAAQ;IACZ,IAAI,CAAQ;IACZ,OAAO,GAAY,OAAO,CAAA;IAE1B,YAAY,IAAY,EAAE,IAAY;QACpC,KAAK,CAAC,GAAG,IAAI,qBAAqB,IAAI,GAAG,CAAC,CAAA;QAC1C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,UAAU,CAAA;IACnB,CAAC;CACF;AAdD,4BAcC","sourcesContent":["export class CwdError extends Error {\n path: string\n code: string\n syscall: 'chdir' = 'chdir'\n\n constructor(path: string, code: string) {\n super(`${code}: Cannot cd into '${path}'`)\n this.path = path\n this.code = code\n }\n\n get name() {\n return 'CwdError'\n }\n}\n"]}
-3
View File
@@ -1,3 +0,0 @@
import { Unpack, UnpackSync } from './unpack.js';
export declare const extract: import("./make-command.js").TarCommand<Unpack, UnpackSync>;
//# sourceMappingURL=extract.d.ts.map
-1
View File
@@ -1 +0,0 @@
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/extract.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AA2ChD,eAAO,MAAM,OAAO,4DAQnB,CAAA"}
-78
View File
@@ -1,78 +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 __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.extract = void 0;
// tar -x
const fsm = __importStar(require("@isaacs/fs-minipass"));
const node_fs_1 = __importDefault(require("node:fs"));
const list_js_1 = require("./list.js");
const make_command_js_1 = require("./make-command.js");
const unpack_js_1 = require("./unpack.js");
const extractFileSync = (opt) => {
const u = new unpack_js_1.UnpackSync(opt);
const file = opt.file;
const stat = node_fs_1.default.statSync(file);
// This trades a zero-byte read() syscall for a stat
// However, it will usually result in less memory allocation
const readSize = opt.maxReadSize || 16 * 1024 * 1024;
const stream = new fsm.ReadStreamSync(file, {
readSize: readSize,
size: stat.size,
});
stream.pipe(u);
};
const extractFile = (opt, _) => {
const u = new unpack_js_1.Unpack(opt);
const readSize = opt.maxReadSize || 16 * 1024 * 1024;
const file = opt.file;
const p = new Promise((resolve, reject) => {
u.on('error', reject);
u.on('close', resolve);
// This trades a zero-byte read() syscall for a stat
// However, it will usually result in less memory allocation
node_fs_1.default.stat(file, (er, stat) => {
if (er) {
reject(er);
}
else {
const stream = new fsm.ReadStream(file, {
readSize: readSize,
size: stat.size,
});
stream.on('error', reject);
stream.pipe(u);
}
});
});
return p;
};
exports.extract = (0, make_command_js_1.makeCommand)(extractFileSync, extractFile, opt => new unpack_js_1.UnpackSync(opt), opt => new unpack_js_1.Unpack(opt), (opt, files) => {
if (files?.length)
(0, list_js_1.filesFilter)(opt, files);
});
//# sourceMappingURL=extract.js.map
-1
View File
@@ -1 +0,0 @@
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/extract.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS;AACT,yDAA0C;AAC1C,sDAAwB;AACxB,uCAAuC;AACvC,uDAA+C;AAE/C,2CAAgD;AAEhD,MAAM,eAAe,GAAG,CAAC,GAAuB,EAAE,EAAE;IAClD,MAAM,CAAC,GAAG,IAAI,sBAAU,CAAC,GAAG,CAAC,CAAA;IAC7B,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAA;IACrB,MAAM,IAAI,GAAG,iBAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC9B,oDAAoD;IACpD,4DAA4D;IAC5D,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,IAAI,EAAE,GAAG,IAAI,GAAG,IAAI,CAAA;IACpD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE;QAC1C,QAAQ,EAAE,QAAQ;QAClB,IAAI,EAAE,IAAI,CAAC,IAAI;KAChB,CAAC,CAAA;IACF,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AAChB,CAAC,CAAA;AAED,MAAM,WAAW,GAAG,CAAC,GAAmB,EAAE,CAAY,EAAE,EAAE;IACxD,MAAM,CAAC,GAAG,IAAI,kBAAM,CAAC,GAAG,CAAC,CAAA;IACzB,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,IAAI,EAAE,GAAG,IAAI,GAAG,IAAI,CAAA;IAEpD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAA;IACrB,MAAM,CAAC,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC9C,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QACrB,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QAEtB,oDAAoD;QACpD,4DAA4D;QAC5D,iBAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE;YACzB,IAAI,EAAE,EAAE,CAAC;gBACP,MAAM,CAAC,EAAE,CAAC,CAAA;YACZ,CAAC;iBAAM,CAAC;gBACN,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE;oBACtC,QAAQ,EAAE,QAAQ;oBAClB,IAAI,EAAE,IAAI,CAAC,IAAI;iBAChB,CAAC,CAAA;gBACF,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;gBAC1B,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YAChB,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IACF,OAAO,CAAC,CAAA;AACV,CAAC,CAAA;AAEY,QAAA,OAAO,GAAG,IAAA,6BAAW,EAChC,eAAe,EACf,WAAW,EACX,GAAG,CAAC,EAAE,CAAC,IAAI,sBAAU,CAAC,GAAG,CAAC,EAC1B,GAAG,CAAC,EAAE,CAAC,IAAI,kBAAM,CAAC,GAAG,CAAC,EACtB,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;IACb,IAAI,KAAK,EAAE,MAAM;QAAE,IAAA,qBAAW,EAAC,GAAG,EAAE,KAAK,CAAC,CAAA;AAC5C,CAAC,CACF,CAAA","sourcesContent":["// tar -x\nimport * as fsm from '@isaacs/fs-minipass'\nimport fs from 'node:fs'\nimport { filesFilter } from './list.js'\nimport { makeCommand } from './make-command.js'\nimport { TarOptionsFile, TarOptionsSyncFile } from './options.js'\nimport { Unpack, UnpackSync } from './unpack.js'\n\nconst extractFileSync = (opt: TarOptionsSyncFile) => {\n const u = new UnpackSync(opt)\n const file = opt.file\n const stat = fs.statSync(file)\n // This trades a zero-byte read() syscall for a stat\n // However, it will usually result in less memory allocation\n const readSize = opt.maxReadSize || 16 * 1024 * 1024\n const stream = new fsm.ReadStreamSync(file, {\n readSize: readSize,\n size: stat.size,\n })\n stream.pipe(u)\n}\n\nconst extractFile = (opt: TarOptionsFile, _?: string[]) => {\n const u = new Unpack(opt)\n const readSize = opt.maxReadSize || 16 * 1024 * 1024\n\n const file = opt.file\n const p = new Promise<void>((resolve, reject) => {\n u.on('error', reject)\n u.on('close', resolve)\n\n // This trades a zero-byte read() syscall for a stat\n // However, it will usually result in less memory allocation\n fs.stat(file, (er, stat) => {\n if (er) {\n reject(er)\n } else {\n const stream = new fsm.ReadStream(file, {\n readSize: readSize,\n size: stat.size,\n })\n stream.on('error', reject)\n stream.pipe(u)\n }\n })\n })\n return p\n}\n\nexport const extract = makeCommand<Unpack, UnpackSync>(\n extractFileSync,\n extractFile,\n opt => new UnpackSync(opt),\n opt => new Unpack(opt),\n (opt, files) => {\n if (files?.length) filesFilter(opt, files)\n },\n)\n"]}
@@ -1,2 +0,0 @@
export declare const getWriteFlag: (() => string) | ((size: number) => number | "w");
//# sourceMappingURL=get-write-flag.d.ts.map
@@ -1 +0,0 @@
{"version":3,"file":"get-write-flag.d.ts","sourceRoot":"","sources":["../../src/get-write-flag.ts"],"names":[],"mappings":"AAwBA,eAAO,MAAM,YAAY,2BAGd,MAAM,kBAAwC,CAAA"}
-29
View File
@@ -1,29 +0,0 @@
"use strict";
// Get the appropriate flag to use for creating files
// We use fmap on Windows platforms for files less than
// 512kb. This is a fairly low limit, but avoids making
// things slower in some cases. Since most of what this
// library is used for is extracting tarballs of many
// relatively small files in npm packages and the like,
// it can be a big boost on Windows platforms.
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getWriteFlag = void 0;
const fs_1 = __importDefault(require("fs"));
const platform = process.env.__FAKE_PLATFORM__ || process.platform;
const isWindows = platform === 'win32';
/* c8 ignore start */
const { O_CREAT, O_TRUNC, O_WRONLY } = fs_1.default.constants;
const UV_FS_O_FILEMAP = Number(process.env.__FAKE_FS_O_FILENAME__) ||
fs_1.default.constants.UV_FS_O_FILEMAP ||
0;
/* c8 ignore stop */
const fMapEnabled = isWindows && !!UV_FS_O_FILEMAP;
const fMapLimit = 512 * 1024;
const fMapFlag = UV_FS_O_FILEMAP | O_TRUNC | O_CREAT | O_WRONLY;
exports.getWriteFlag = !fMapEnabled ?
() => 'w'
: (size) => (size < fMapLimit ? fMapFlag : 'w');
//# sourceMappingURL=get-write-flag.js.map
@@ -1 +0,0 @@
{"version":3,"file":"get-write-flag.js","sourceRoot":"","sources":["../../src/get-write-flag.ts"],"names":[],"mappings":";AAAA,qDAAqD;AACrD,uDAAuD;AACvD,wDAAwD;AACxD,wDAAwD;AACxD,qDAAqD;AACrD,uDAAuD;AACvD,8CAA8C;;;;;;AAE9C,4CAAmB;AAEnB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,OAAO,CAAC,QAAQ,CAAA;AAClE,MAAM,SAAS,GAAG,QAAQ,KAAK,OAAO,CAAA;AAEtC,qBAAqB;AACrB,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,YAAE,CAAC,SAAS,CAAA;AACnD,MAAM,eAAe,GACnB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;IAC1C,YAAE,CAAC,SAAS,CAAC,eAAe;IAC5B,CAAC,CAAA;AACH,oBAAoB;AAEpB,MAAM,WAAW,GAAG,SAAS,IAAI,CAAC,CAAC,eAAe,CAAA;AAClD,MAAM,SAAS,GAAG,GAAG,GAAG,IAAI,CAAA;AAC5B,MAAM,QAAQ,GAAG,eAAe,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAA;AAClD,QAAA,YAAY,GACvB,CAAC,WAAW,CAAC,CAAC;IACZ,GAAG,EAAE,CAAC,GAAG;IACX,CAAC,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA","sourcesContent":["// Get the appropriate flag to use for creating files\n// We use fmap on Windows platforms for files less than\n// 512kb. This is a fairly low limit, but avoids making\n// things slower in some cases. Since most of what this\n// library is used for is extracting tarballs of many\n// relatively small files in npm packages and the like,\n// it can be a big boost on Windows platforms.\n\nimport fs from 'fs'\n\nconst platform = process.env.__FAKE_PLATFORM__ || process.platform\nconst isWindows = platform === 'win32'\n\n/* c8 ignore start */\nconst { O_CREAT, O_TRUNC, O_WRONLY } = fs.constants\nconst UV_FS_O_FILEMAP =\n Number(process.env.__FAKE_FS_O_FILENAME__) ||\n fs.constants.UV_FS_O_FILEMAP ||\n 0\n/* c8 ignore stop */\n\nconst fMapEnabled = isWindows && !!UV_FS_O_FILEMAP\nconst fMapLimit = 512 * 1024\nconst fMapFlag = UV_FS_O_FILEMAP | O_TRUNC | O_CREAT | O_WRONLY\nexport const getWriteFlag =\n !fMapEnabled ?\n () => 'w'\n : (size: number) => (size < fMapLimit ? fMapFlag : 'w')\n"]}
-55
View File
@@ -1,55 +0,0 @@
/// <reference types="node" />
/// <reference types="node" />
import type { EntryTypeCode, EntryTypeName } from './types.js';
export type HeaderData = {
path?: string;
mode?: number;
uid?: number;
gid?: number;
size?: number;
cksum?: number;
type?: EntryTypeName | 'Unsupported';
linkpath?: string;
uname?: string;
gname?: string;
devmaj?: number;
devmin?: number;
atime?: Date;
ctime?: Date;
mtime?: Date;
charset?: string;
comment?: string;
dev?: number;
ino?: number;
nlink?: number;
};
export declare class Header implements HeaderData {
#private;
cksumValid: boolean;
needPax: boolean;
nullBlock: boolean;
block?: Buffer;
path?: string;
mode?: number;
uid?: number;
gid?: number;
size?: number;
cksum?: number;
linkpath?: string;
uname?: string;
gname?: string;
devmaj: number;
devmin: number;
atime?: Date;
ctime?: Date;
mtime?: Date;
charset?: string;
comment?: string;
constructor(data?: Buffer | HeaderData, off?: number, ex?: HeaderData, gex?: HeaderData);
decode(buf: Buffer, off: number, ex?: HeaderData, gex?: HeaderData): void;
encode(buf?: Buffer, off?: number): boolean;
get type(): EntryTypeName;
get typeKey(): EntryTypeCode | 'Unsupported';
set type(type: EntryTypeCode | EntryTypeName | 'Unsupported');
}
//# sourceMappingURL=header.d.ts.map
-1
View File
@@ -1 +0,0 @@
{"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../src/header.ts"],"names":[],"mappings":";;AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAG9D,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,aAAa,GAAG,aAAa,CAAA;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,IAAI,CAAA;IACZ,KAAK,CAAC,EAAE,IAAI,CAAA;IACZ,KAAK,CAAC,EAAE,IAAI,CAAA;IAIZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,qBAAa,MAAO,YAAW,UAAU;;IACvC,UAAU,EAAE,OAAO,CAAQ;IAC3B,OAAO,EAAE,OAAO,CAAQ;IACxB,SAAS,EAAE,OAAO,CAAQ;IAE1B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAI;IAClB,MAAM,EAAE,MAAM,CAAI;IAClB,KAAK,CAAC,EAAE,IAAI,CAAA;IACZ,KAAK,CAAC,EAAE,IAAI,CAAA;IACZ,KAAK,CAAC,EAAE,IAAI,CAAA;IAEZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;gBAGd,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,EAC1B,GAAG,GAAE,MAAU,EACf,EAAE,CAAC,EAAE,UAAU,EACf,GAAG,CAAC,EAAE,UAAU;IASlB,MAAM,CACJ,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,EAAE,CAAC,EAAE,UAAU,EACf,GAAG,CAAC,EAAE,UAAU;IA+GlB,MAAM,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,GAAE,MAAU;IAwEpC,IAAI,IAAI,IAAI,aAAa,CAKxB;IAED,IAAI,OAAO,IAAI,aAAa,GAAG,aAAa,CAE3C;IAED,IAAI,IAAI,CAAC,IAAI,EAAE,aAAa,GAAG,aAAa,GAAG,aAAa,EAS3D;CACF"}
-315
View File
@@ -1,315 +0,0 @@
"use strict";
// parse a 512-byte header block to a data object, or vice-versa
// encode returns `true` if a pax extended header is needed, because
// the data could not be faithfully encoded in a simple header.
// (Also, check header.needPax to see if it needs a pax header.)
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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Header = void 0;
const node_path_1 = require("node:path");
const large = __importStar(require("./large-numbers.js"));
const types = __importStar(require("./types.js"));
class Header {
cksumValid = false;
needPax = false;
nullBlock = false;
block;
path;
mode;
uid;
gid;
size;
cksum;
#type = 'Unsupported';
linkpath;
uname;
gname;
devmaj = 0;
devmin = 0;
atime;
ctime;
mtime;
charset;
comment;
constructor(data, off = 0, ex, gex) {
if (Buffer.isBuffer(data)) {
this.decode(data, off || 0, ex, gex);
}
else if (data) {
this.#slurp(data);
}
}
decode(buf, off, ex, gex) {
if (!off) {
off = 0;
}
if (!buf || !(buf.length >= off + 512)) {
throw new Error('need 512 bytes for header');
}
this.path = ex?.path ?? decString(buf, off, 100);
this.mode = ex?.mode ?? gex?.mode ?? decNumber(buf, off + 100, 8);
this.uid = ex?.uid ?? gex?.uid ?? decNumber(buf, off + 108, 8);
this.gid = ex?.gid ?? gex?.gid ?? decNumber(buf, off + 116, 8);
this.size = ex?.size ?? gex?.size ?? decNumber(buf, off + 124, 12);
this.mtime =
ex?.mtime ?? gex?.mtime ?? decDate(buf, off + 136, 12);
this.cksum = decNumber(buf, off + 148, 12);
// if we have extended or global extended headers, apply them now
// See https://github.com/npm/node-tar/pull/187
// Apply global before local, so it overrides
if (gex)
this.#slurp(gex, true);
if (ex)
this.#slurp(ex);
// old tar versions marked dirs as a file with a trailing /
const t = decString(buf, off + 156, 1);
if (types.isCode(t)) {
this.#type = t || '0';
}
if (this.#type === '0' && this.path.slice(-1) === '/') {
this.#type = '5';
}
// tar implementations sometimes incorrectly put the stat(dir).size
// as the size in the tarball, even though Directory entries are
// not able to have any body at all. In the very rare chance that
// it actually DOES have a body, we weren't going to do anything with
// it anyway, and it'll just be a warning about an invalid header.
if (this.#type === '5') {
this.size = 0;
}
this.linkpath = decString(buf, off + 157, 100);
if (buf.subarray(off + 257, off + 265).toString() ===
'ustar\u000000') {
/* c8 ignore start */
this.uname =
ex?.uname ?? gex?.uname ?? decString(buf, off + 265, 32);
this.gname =
ex?.gname ?? gex?.gname ?? decString(buf, off + 297, 32);
this.devmaj =
ex?.devmaj ?? gex?.devmaj ?? decNumber(buf, off + 329, 8) ?? 0;
this.devmin =
ex?.devmin ?? gex?.devmin ?? decNumber(buf, off + 337, 8) ?? 0;
/* c8 ignore stop */
if (buf[off + 475] !== 0) {
// definitely a prefix, definitely >130 chars.
const prefix = decString(buf, off + 345, 155);
this.path = prefix + '/' + this.path;
}
else {
const prefix = decString(buf, off + 345, 130);
if (prefix) {
this.path = prefix + '/' + this.path;
}
/* c8 ignore start */
this.atime =
ex?.atime ?? gex?.atime ?? decDate(buf, off + 476, 12);
this.ctime =
ex?.ctime ?? gex?.ctime ?? decDate(buf, off + 488, 12);
/* c8 ignore stop */
}
}
let sum = 8 * 0x20;
for (let i = off; i < off + 148; i++) {
sum += buf[i];
}
for (let i = off + 156; i < off + 512; i++) {
sum += buf[i];
}
this.cksumValid = sum === this.cksum;
if (this.cksum === undefined && sum === 8 * 0x20) {
this.nullBlock = true;
}
}
#slurp(ex, gex = false) {
Object.assign(this, Object.fromEntries(Object.entries(ex).filter(([k, v]) => {
// we slurp in everything except for the path attribute in
// a global extended header, because that's weird. Also, any
// null/undefined values are ignored.
return !(v === null ||
v === undefined ||
(k === 'path' && gex) ||
(k === 'linkpath' && gex) ||
k === 'global');
})));
}
encode(buf, off = 0) {
if (!buf) {
buf = this.block = Buffer.alloc(512);
}
if (this.#type === 'Unsupported') {
this.#type = '0';
}
if (!(buf.length >= off + 512)) {
throw new Error('need 512 bytes for header');
}
const prefixSize = this.ctime || this.atime ? 130 : 155;
const split = splitPrefix(this.path || '', prefixSize);
const path = split[0];
const prefix = split[1];
this.needPax = !!split[2];
this.needPax = encString(buf, off, 100, path) || this.needPax;
this.needPax =
encNumber(buf, off + 100, 8, this.mode) || this.needPax;
this.needPax =
encNumber(buf, off + 108, 8, this.uid) || this.needPax;
this.needPax =
encNumber(buf, off + 116, 8, this.gid) || this.needPax;
this.needPax =
encNumber(buf, off + 124, 12, this.size) || this.needPax;
this.needPax =
encDate(buf, off + 136, 12, this.mtime) || this.needPax;
buf[off + 156] = this.#type.charCodeAt(0);
this.needPax =
encString(buf, off + 157, 100, this.linkpath) || this.needPax;
buf.write('ustar\u000000', off + 257, 8);
this.needPax =
encString(buf, off + 265, 32, this.uname) || this.needPax;
this.needPax =
encString(buf, off + 297, 32, this.gname) || this.needPax;
this.needPax =
encNumber(buf, off + 329, 8, this.devmaj) || this.needPax;
this.needPax =
encNumber(buf, off + 337, 8, this.devmin) || this.needPax;
this.needPax =
encString(buf, off + 345, prefixSize, prefix) || this.needPax;
if (buf[off + 475] !== 0) {
this.needPax =
encString(buf, off + 345, 155, prefix) || this.needPax;
}
else {
this.needPax =
encString(buf, off + 345, 130, prefix) || this.needPax;
this.needPax =
encDate(buf, off + 476, 12, this.atime) || this.needPax;
this.needPax =
encDate(buf, off + 488, 12, this.ctime) || this.needPax;
}
let sum = 8 * 0x20;
for (let i = off; i < off + 148; i++) {
sum += buf[i];
}
for (let i = off + 156; i < off + 512; i++) {
sum += buf[i];
}
this.cksum = sum;
encNumber(buf, off + 148, 8, this.cksum);
this.cksumValid = true;
return this.needPax;
}
get type() {
return (this.#type === 'Unsupported' ?
this.#type
: types.name.get(this.#type));
}
get typeKey() {
return this.#type;
}
set type(type) {
const c = String(types.code.get(type));
if (types.isCode(c) || c === 'Unsupported') {
this.#type = c;
}
else if (types.isCode(type)) {
this.#type = type;
}
else {
throw new TypeError('invalid entry type: ' + type);
}
}
}
exports.Header = Header;
const splitPrefix = (p, prefixSize) => {
const pathSize = 100;
let pp = p;
let prefix = '';
let ret = undefined;
const root = node_path_1.posix.parse(p).root || '.';
if (Buffer.byteLength(pp) < pathSize) {
ret = [pp, prefix, false];
}
else {
// first set prefix to the dir, and path to the base
prefix = node_path_1.posix.dirname(pp);
pp = node_path_1.posix.basename(pp);
do {
if (Buffer.byteLength(pp) <= pathSize &&
Buffer.byteLength(prefix) <= prefixSize) {
// both fit!
ret = [pp, prefix, false];
}
else if (Buffer.byteLength(pp) > pathSize &&
Buffer.byteLength(prefix) <= prefixSize) {
// prefix fits in prefix, but path doesn't fit in path
ret = [pp.slice(0, pathSize - 1), prefix, true];
}
else {
// make path take a bit from prefix
pp = node_path_1.posix.join(node_path_1.posix.basename(prefix), pp);
prefix = node_path_1.posix.dirname(prefix);
}
} while (prefix !== root && ret === undefined);
// at this point, found no resolution, just truncate
if (!ret) {
ret = [p.slice(0, pathSize - 1), '', true];
}
}
return ret;
};
const decString = (buf, off, size) => buf
.subarray(off, off + size)
.toString('utf8')
.replace(/\0.*/, '');
const decDate = (buf, off, size) => numToDate(decNumber(buf, off, size));
const numToDate = (num) => num === undefined ? undefined : new Date(num * 1000);
const decNumber = (buf, off, size) => Number(buf[off]) & 0x80 ?
large.parse(buf.subarray(off, off + size))
: decSmallNumber(buf, off, size);
const nanUndef = (value) => (isNaN(value) ? undefined : value);
const decSmallNumber = (buf, off, size) => nanUndef(parseInt(buf
.subarray(off, off + size)
.toString('utf8')
.replace(/\0.*$/, '')
.trim(), 8));
// the maximum encodable as a null-terminated octal, by field size
const MAXNUM = {
12: 0o77777777777,
8: 0o7777777,
};
const encNumber = (buf, off, size, num) => num === undefined ? false
: num > MAXNUM[size] || num < 0 ?
(large.encode(num, buf.subarray(off, off + size)), true)
: (encSmallNumber(buf, off, size, num), false);
const encSmallNumber = (buf, off, size, num) => buf.write(octalString(num, size), off, size, 'ascii');
const octalString = (num, size) => padOctal(Math.floor(num).toString(8), size);
const padOctal = (str, size) => (str.length === size - 1 ?
str
: new Array(size - str.length - 1).join('0') + str + ' ') + '\0';
const encDate = (buf, off, size, date) => date === undefined ? false : (encNumber(buf, off, size, date.getTime() / 1000));
// enough to fill the longest string we've got
const NULLS = new Array(156).join('\0');
// pad with nulls, return true if it's longer or non-ascii
const encString = (buf, off, size, str) => str === undefined ? false : ((buf.write(str + NULLS, off, size, 'utf8'),
str.length !== Buffer.byteLength(str) || str.length > size));
//# sourceMappingURL=header.js.map
File diff suppressed because one or more lines are too long
-20
View File
@@ -1,20 +0,0 @@
export { type TarOptionsWithAliasesAsync, type TarOptionsWithAliasesAsyncFile, type TarOptionsWithAliasesAsyncNoFile, type TarOptionsWithAliasesSyncNoFile, type TarOptionsWithAliases, type TarOptionsWithAliasesFile, type TarOptionsWithAliasesSync, type TarOptionsWithAliasesSyncFile, } from './options.js';
export * from './create.js';
export { create as c } from './create.js';
export * from './extract.js';
export { extract as x } from './extract.js';
export * from './header.js';
export * from './list.js';
export { list as t } from './list.js';
export * from './pack.js';
export * from './parse.js';
export * from './pax.js';
export * from './read-entry.js';
export * from './replace.js';
export { replace as r } from './replace.js';
export * as types from './types.js';
export * from './unpack.js';
export * from './update.js';
export { update as u } from './update.js';
export * from './write-entry.js';
//# sourceMappingURL=index.d.ts.map
-1
View File
@@ -1 +0,0 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,8BAA8B,EACnC,KAAK,gCAAgC,EACrC,KAAK,+BAA+B,EACpC,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,yBAAyB,EAC9B,KAAK,6BAA6B,GACnC,MAAM,cAAc,CAAA;AAErB,cAAc,aAAa,CAAA;AAC3B,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,aAAa,CAAA;AACzC,cAAc,cAAc,CAAA;AAC5B,OAAO,EAAE,OAAO,IAAI,CAAC,EAAE,MAAM,cAAc,CAAA;AAC3C,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,OAAO,EAAE,IAAI,IAAI,CAAC,EAAE,MAAM,WAAW,CAAA;AAErC,cAAc,WAAW,CAAA;AACzB,cAAc,YAAY,CAAA;AAC1B,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,OAAO,EAAE,OAAO,IAAI,CAAC,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,aAAa,CAAA;AACzC,cAAc,kBAAkB,CAAA"}
-54
View File
@@ -1,54 +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 __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);
};
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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.u = exports.types = exports.r = exports.t = exports.x = exports.c = void 0;
__exportStar(require("./create.js"), exports);
var create_js_1 = require("./create.js");
Object.defineProperty(exports, "c", { enumerable: true, get: function () { return create_js_1.create; } });
__exportStar(require("./extract.js"), exports);
var extract_js_1 = require("./extract.js");
Object.defineProperty(exports, "x", { enumerable: true, get: function () { return extract_js_1.extract; } });
__exportStar(require("./header.js"), exports);
__exportStar(require("./list.js"), exports);
var list_js_1 = require("./list.js");
Object.defineProperty(exports, "t", { enumerable: true, get: function () { return list_js_1.list; } });
// classes
__exportStar(require("./pack.js"), exports);
__exportStar(require("./parse.js"), exports);
__exportStar(require("./pax.js"), exports);
__exportStar(require("./read-entry.js"), exports);
__exportStar(require("./replace.js"), exports);
var replace_js_1 = require("./replace.js");
Object.defineProperty(exports, "r", { enumerable: true, get: function () { return replace_js_1.replace; } });
exports.types = __importStar(require("./types.js"));
__exportStar(require("./unpack.js"), exports);
__exportStar(require("./update.js"), exports);
var update_js_1 = require("./update.js");
Object.defineProperty(exports, "u", { enumerable: true, get: function () { return update_js_1.update; } });
__exportStar(require("./write-entry.js"), exports);
//# sourceMappingURL=index.js.map
-1
View File
@@ -1 +0,0 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,8CAA2B;AAC3B,yCAAyC;AAAhC,8FAAA,MAAM,OAAK;AACpB,+CAA4B;AAC5B,2CAA2C;AAAlC,+FAAA,OAAO,OAAK;AACrB,8CAA2B;AAC3B,4CAAyB;AACzB,qCAAqC;AAA5B,4FAAA,IAAI,OAAK;AAClB,UAAU;AACV,4CAAyB;AACzB,6CAA0B;AAC1B,2CAAwB;AACxB,kDAA+B;AAC/B,+CAA4B;AAC5B,2CAA2C;AAAlC,+FAAA,OAAO,OAAK;AACrB,oDAAmC;AACnC,8CAA2B;AAC3B,8CAA2B;AAC3B,yCAAyC;AAAhC,8FAAA,MAAM,OAAK;AACpB,mDAAgC","sourcesContent":["export {\n type TarOptionsWithAliasesAsync,\n type TarOptionsWithAliasesAsyncFile,\n type TarOptionsWithAliasesAsyncNoFile,\n type TarOptionsWithAliasesSyncNoFile,\n type TarOptionsWithAliases,\n type TarOptionsWithAliasesFile,\n type TarOptionsWithAliasesSync,\n type TarOptionsWithAliasesSyncFile,\n} from './options.js'\n\nexport * from './create.js'\nexport { create as c } from './create.js'\nexport * from './extract.js'\nexport { extract as x } from './extract.js'\nexport * from './header.js'\nexport * from './list.js'\nexport { list as t } from './list.js'\n// classes\nexport * from './pack.js'\nexport * from './parse.js'\nexport * from './pax.js'\nexport * from './read-entry.js'\nexport * from './replace.js'\nexport { replace as r } from './replace.js'\nexport * as types from './types.js'\nexport * from './unpack.js'\nexport * from './update.js'\nexport { update as u } from './update.js'\nexport * from './write-entry.js'\n"]}
@@ -1,5 +0,0 @@
/// <reference types="node" />
/// <reference types="node" />
export declare const encode: (num: number, buf: Buffer) => Buffer;
export declare const parse: (buf: Buffer) => number;
//# sourceMappingURL=large-numbers.d.ts.map
@@ -1 +0,0 @@
{"version":3,"file":"large-numbers.d.ts","sourceRoot":"","sources":["../../src/large-numbers.ts"],"names":[],"mappings":";;AAGA,eAAO,MAAM,MAAM,QAAS,MAAM,OAAO,MAAM,WAa9C,CAAA;AA6BD,eAAO,MAAM,KAAK,QAAS,MAAM,WAmBhC,CAAA"}
-99
View File
@@ -1,99 +0,0 @@
"use strict";
// Tar can encode large and negative numbers using a leading byte of
// 0xff for negative, and 0x80 for positive.
Object.defineProperty(exports, "__esModule", { value: true });
exports.parse = exports.encode = void 0;
const encode = (num, buf) => {
if (!Number.isSafeInteger(num)) {
// The number is so large that javascript cannot represent it with integer
// precision.
throw Error('cannot encode number outside of javascript safe integer range');
}
else if (num < 0) {
encodeNegative(num, buf);
}
else {
encodePositive(num, buf);
}
return buf;
};
exports.encode = encode;
const encodePositive = (num, buf) => {
buf[0] = 0x80;
for (var i = buf.length; i > 1; i--) {
buf[i - 1] = num & 0xff;
num = Math.floor(num / 0x100);
}
};
const encodeNegative = (num, buf) => {
buf[0] = 0xff;
var flipped = false;
num = num * -1;
for (var i = buf.length; i > 1; i--) {
var byte = num & 0xff;
num = Math.floor(num / 0x100);
if (flipped) {
buf[i - 1] = onesComp(byte);
}
else if (byte === 0) {
buf[i - 1] = 0;
}
else {
flipped = true;
buf[i - 1] = twosComp(byte);
}
}
};
const parse = (buf) => {
const pre = buf[0];
const value = pre === 0x80 ? pos(buf.subarray(1, buf.length))
: pre === 0xff ? twos(buf)
: null;
if (value === null) {
throw Error('invalid base256 encoding');
}
if (!Number.isSafeInteger(value)) {
// The number is so large that javascript cannot represent it with integer
// precision.
throw Error('parsed number outside of javascript safe integer range');
}
return value;
};
exports.parse = parse;
const twos = (buf) => {
var len = buf.length;
var sum = 0;
var flipped = false;
for (var i = len - 1; i > -1; i--) {
var byte = Number(buf[i]);
var f;
if (flipped) {
f = onesComp(byte);
}
else if (byte === 0) {
f = byte;
}
else {
flipped = true;
f = twosComp(byte);
}
if (f !== 0) {
sum -= f * Math.pow(256, len - i - 1);
}
}
return sum;
};
const pos = (buf) => {
var len = buf.length;
var sum = 0;
for (var i = len - 1; i > -1; i--) {
var byte = Number(buf[i]);
if (byte !== 0) {
sum += byte * Math.pow(256, len - i - 1);
}
}
return sum;
};
const onesComp = (byte) => (0xff ^ byte) & 0xff;
const twosComp = (byte) => ((0xff ^ byte) + 1) & 0xff;
//# sourceMappingURL=large-numbers.js.map
File diff suppressed because one or more lines are too long
-7
View File
@@ -1,7 +0,0 @@
import { TarOptions } from './options.js';
import { Parser } from './parse.js';
export declare const filesFilter: (opt: TarOptions, files: string[]) => void;
export declare const list: import("./make-command.js").TarCommand<Parser, Parser & {
sync: true;
}>;
//# sourceMappingURL=list.d.ts.map
-1
View File
@@ -1 +0,0 @@
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/list.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,UAAU,EAGX,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAgBnC,eAAO,MAAM,WAAW,QAAS,UAAU,SAAS,MAAM,EAAE,SA4B3D,CAAA;AA+DD,eAAO,MAAM,IAAI;UAG4B,IAAI;EAMhD,CAAA"}
-140
View File
@@ -1,140 +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 __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.list = exports.filesFilter = void 0;
// tar -t
const fsm = __importStar(require("@isaacs/fs-minipass"));
const node_fs_1 = __importDefault(require("node:fs"));
const path_1 = require("path");
const make_command_js_1 = require("./make-command.js");
const parse_js_1 = require("./parse.js");
const strip_trailing_slashes_js_1 = require("./strip-trailing-slashes.js");
const onReadEntryFunction = (opt) => {
const onReadEntry = opt.onReadEntry;
opt.onReadEntry =
onReadEntry ?
e => {
onReadEntry(e);
e.resume();
}
: e => e.resume();
};
// construct a filter that limits the file entries listed
// include child entries if a dir is included
const filesFilter = (opt, files) => {
const map = new Map(files.map(f => [(0, strip_trailing_slashes_js_1.stripTrailingSlashes)(f), true]));
const filter = opt.filter;
const mapHas = (file, r = '') => {
const root = r || (0, path_1.parse)(file).root || '.';
let ret;
if (file === root)
ret = false;
else {
const m = map.get(file);
if (m !== undefined) {
ret = m;
}
else {
ret = mapHas((0, path_1.dirname)(file), root);
}
}
map.set(file, ret);
return ret;
};
opt.filter =
filter ?
(file, entry) => filter(file, entry) && mapHas((0, strip_trailing_slashes_js_1.stripTrailingSlashes)(file))
: file => mapHas((0, strip_trailing_slashes_js_1.stripTrailingSlashes)(file));
};
exports.filesFilter = filesFilter;
const listFileSync = (opt) => {
const p = new parse_js_1.Parser(opt);
const file = opt.file;
let fd;
try {
fd = node_fs_1.default.openSync(file, 'r');
const stat = node_fs_1.default.fstatSync(fd);
const readSize = opt.maxReadSize || 16 * 1024 * 1024;
if (stat.size < readSize) {
const buf = Buffer.allocUnsafe(stat.size);
const read = node_fs_1.default.readSync(fd, buf, 0, stat.size, 0);
p.end(read === buf.byteLength ? buf : buf.subarray(0, read));
}
else {
let pos = 0;
const buf = Buffer.allocUnsafe(readSize);
while (pos < stat.size) {
const bytesRead = node_fs_1.default.readSync(fd, buf, 0, readSize, pos);
if (bytesRead === 0)
break;
pos += bytesRead;
p.write(buf.subarray(0, bytesRead));
}
p.end();
}
}
finally {
if (typeof fd === 'number') {
try {
node_fs_1.default.closeSync(fd);
/* c8 ignore next */
}
catch (er) { }
}
}
};
const listFile = (opt, _files) => {
const parse = new parse_js_1.Parser(opt);
const readSize = opt.maxReadSize || 16 * 1024 * 1024;
const file = opt.file;
const p = new Promise((resolve, reject) => {
parse.on('error', reject);
parse.on('end', resolve);
node_fs_1.default.stat(file, (er, stat) => {
if (er) {
reject(er);
}
else {
const stream = new fsm.ReadStream(file, {
readSize: readSize,
size: stat.size,
});
stream.on('error', reject);
stream.pipe(parse);
}
});
});
return p;
};
exports.list = (0, make_command_js_1.makeCommand)(listFileSync, listFile, opt => new parse_js_1.Parser(opt), opt => new parse_js_1.Parser(opt), (opt, files) => {
if (files?.length)
(0, exports.filesFilter)(opt, files);
if (!opt.noResume)
onReadEntryFunction(opt);
});
//# sourceMappingURL=list.js.map
File diff suppressed because one or more lines are too long
-49
View File
@@ -1,49 +0,0 @@
import { TarOptions, TarOptionsAsyncFile, TarOptionsAsyncNoFile, TarOptionsSyncFile, TarOptionsSyncNoFile, TarOptionsWithAliases, TarOptionsWithAliasesAsync, TarOptionsWithAliasesAsyncFile, TarOptionsWithAliasesAsyncNoFile, TarOptionsWithAliasesFile, TarOptionsWithAliasesNoFile, TarOptionsWithAliasesSync, TarOptionsWithAliasesSyncFile, TarOptionsWithAliasesSyncNoFile } from './options.js';
export type CB = (er?: Error) => any;
export type TarCommand<AsyncClass, SyncClass extends {
sync: true;
}> = {
(): AsyncClass;
(opt: TarOptionsWithAliasesAsyncNoFile): AsyncClass;
(entries: string[]): AsyncClass;
(opt: TarOptionsWithAliasesAsyncNoFile, entries: string[]): AsyncClass;
} & {
(opt: TarOptionsWithAliasesSyncNoFile): SyncClass;
(opt: TarOptionsWithAliasesSyncNoFile, entries: string[]): SyncClass;
} & {
(opt: TarOptionsWithAliasesAsyncFile): Promise<void>;
(opt: TarOptionsWithAliasesAsyncFile, entries: string[]): Promise<void>;
(opt: TarOptionsWithAliasesAsyncFile, cb: CB): Promise<void>;
(opt: TarOptionsWithAliasesAsyncFile, entries: string[], cb: CB): Promise<void>;
} & {
(opt: TarOptionsWithAliasesSyncFile): void;
(opt: TarOptionsWithAliasesSyncFile, entries: string[]): void;
} & {
(opt: TarOptionsWithAliasesSync): typeof opt extends (TarOptionsWithAliasesFile) ? void : typeof opt extends TarOptionsWithAliasesNoFile ? SyncClass : void | SyncClass;
(opt: TarOptionsWithAliasesSync, entries: string[]): typeof opt extends TarOptionsWithAliasesFile ? void : typeof opt extends TarOptionsWithAliasesNoFile ? SyncClass : void | SyncClass;
} & {
(opt: TarOptionsWithAliasesAsync): typeof opt extends (TarOptionsWithAliasesFile) ? Promise<void> : typeof opt extends TarOptionsWithAliasesNoFile ? AsyncClass : Promise<void> | AsyncClass;
(opt: TarOptionsWithAliasesAsync, entries: string[]): typeof opt extends TarOptionsWithAliasesFile ? Promise<void> : typeof opt extends TarOptionsWithAliasesNoFile ? AsyncClass : Promise<void> | AsyncClass;
(opt: TarOptionsWithAliasesAsync, cb: CB): Promise<void>;
(opt: TarOptionsWithAliasesAsync, entries: string[], cb: CB): typeof opt extends TarOptionsWithAliasesFile ? Promise<void> : typeof opt extends TarOptionsWithAliasesNoFile ? never : Promise<void>;
} & {
(opt: TarOptionsWithAliasesFile): Promise<void> | void;
(opt: TarOptionsWithAliasesFile, entries: string[]): typeof opt extends TarOptionsWithAliasesSync ? void : typeof opt extends TarOptionsWithAliasesAsync ? Promise<void> : Promise<void> | void;
(opt: TarOptionsWithAliasesFile, cb: CB): Promise<void>;
(opt: TarOptionsWithAliasesFile, entries: string[], cb: CB): typeof opt extends TarOptionsWithAliasesSync ? never : typeof opt extends TarOptionsWithAliasesAsync ? Promise<void> : Promise<void>;
} & {
(opt: TarOptionsWithAliasesNoFile): typeof opt extends (TarOptionsWithAliasesSync) ? SyncClass : typeof opt extends TarOptionsWithAliasesAsync ? AsyncClass : SyncClass | AsyncClass;
(opt: TarOptionsWithAliasesNoFile, entries: string[]): typeof opt extends TarOptionsWithAliasesSync ? SyncClass : typeof opt extends TarOptionsWithAliasesAsync ? AsyncClass : SyncClass | AsyncClass;
} & {
(opt: TarOptionsWithAliases): typeof opt extends (TarOptionsWithAliasesFile) ? typeof opt extends TarOptionsWithAliasesSync ? void : typeof opt extends TarOptionsWithAliasesAsync ? Promise<void> : void | Promise<void> : typeof opt extends TarOptionsWithAliasesNoFile ? typeof opt extends TarOptionsWithAliasesSync ? SyncClass : typeof opt extends TarOptionsWithAliasesAsync ? AsyncClass : SyncClass | AsyncClass : typeof opt extends TarOptionsWithAliasesSync ? SyncClass | void : typeof opt extends TarOptionsWithAliasesAsync ? AsyncClass | Promise<void> : SyncClass | void | AsyncClass | Promise<void>;
} & {
syncFile: (opt: TarOptionsSyncFile, entries: string[]) => void;
asyncFile: (opt: TarOptionsAsyncFile, entries: string[], cb?: CB) => Promise<void>;
syncNoFile: (opt: TarOptionsSyncNoFile, entries: string[]) => SyncClass;
asyncNoFile: (opt: TarOptionsAsyncNoFile, entries: string[]) => AsyncClass;
validate?: (opt: TarOptions, entries?: string[]) => void;
};
export declare const makeCommand: <AsyncClass, SyncClass extends {
sync: true;
}>(syncFile: (opt: TarOptionsSyncFile, entries: string[]) => void, asyncFile: (opt: TarOptionsAsyncFile, entries: string[], cb?: CB) => Promise<void>, syncNoFile: (opt: TarOptionsSyncNoFile, entries: string[]) => SyncClass, asyncNoFile: (opt: TarOptionsAsyncNoFile, entries: string[]) => AsyncClass, validate?: (opt: TarOptions, entries?: string[]) => void) => TarCommand<AsyncClass, SyncClass>;
//# sourceMappingURL=make-command.d.ts.map
@@ -1 +0,0 @@
{"version":3,"file":"make-command.d.ts","sourceRoot":"","sources":["../../src/make-command.ts"],"names":[],"mappings":"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"}
-61
View File
@@ -1,61 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeCommand = void 0;
const options_js_1 = require("./options.js");
const makeCommand = (syncFile, asyncFile, syncNoFile, asyncNoFile, validate) => {
return Object.assign((opt_ = [], entries, cb) => {
if (Array.isArray(opt_)) {
entries = opt_;
opt_ = {};
}
if (typeof entries === 'function') {
cb = entries;
entries = undefined;
}
if (!entries) {
entries = [];
}
else {
entries = Array.from(entries);
}
const opt = (0, options_js_1.dealias)(opt_);
validate?.(opt, entries);
if ((0, options_js_1.isSyncFile)(opt)) {
if (typeof cb === 'function') {
throw new TypeError('callback not supported for sync tar functions');
}
return syncFile(opt, entries);
}
else if ((0, options_js_1.isAsyncFile)(opt)) {
const p = asyncFile(opt, entries);
// weirdness to make TS happy
const c = cb ? cb : undefined;
return c ? p.then(() => c(), c) : p;
}
else if ((0, options_js_1.isSyncNoFile)(opt)) {
if (typeof cb === 'function') {
throw new TypeError('callback not supported for sync tar functions');
}
return syncNoFile(opt, entries);
}
else if ((0, options_js_1.isAsyncNoFile)(opt)) {
if (typeof cb === 'function') {
throw new TypeError('callback only supported with file option');
}
return asyncNoFile(opt, entries);
/* c8 ignore start */
}
else {
throw new Error('impossible options??');
}
/* c8 ignore stop */
}, {
syncFile,
asyncFile,
syncNoFile,
asyncNoFile,
validate,
});
};
exports.makeCommand = makeCommand;
//# sourceMappingURL=make-command.js.map
File diff suppressed because one or more lines are too long
-26
View File
@@ -1,26 +0,0 @@
/// <reference types="node" />
import { CwdError } from './cwd-error.js';
import { SymlinkError } from './symlink-error.js';
export type MkdirOptions = {
uid?: number;
gid?: number;
processUid?: number;
processGid?: number;
umask?: number;
preserve: boolean;
unlink: boolean;
cwd: string;
mode: number;
};
export type MkdirError = NodeJS.ErrnoException | CwdError | SymlinkError;
/**
* Wrapper around fs/promises.mkdir for tar's needs.
*
* The main purpose is to avoid creating directories if we know that
* they already exist (and track which ones exist for this purpose),
* and prevent entries from being extracted into symlinked folders,
* if `preservePaths` is not set.
*/
export declare const mkdir: (dir: string, opt: MkdirOptions, cb: (er?: null | MkdirError, made?: string) => void) => void | Promise<void>;
export declare const mkdirSync: (dir: string, opt: MkdirOptions) => void | SymlinkError;
//# sourceMappingURL=mkdir.d.ts.map
-1
View File
@@ -1 +0,0 @@
{"version":3,"file":"mkdir.d.ts","sourceRoot":"","sources":["../../src/mkdir.ts"],"names":[],"mappings":";AAIA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjD,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,OAAO,CAAA;IACjB,MAAM,EAAE,OAAO,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,UAAU,GAClB,MAAM,CAAC,cAAc,GACrB,QAAQ,GACR,YAAY,CAAA;AAiBhB;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,QACX,MAAM,OACN,YAAY,MACb,CAAC,EAAE,CAAC,EAAE,IAAI,GAAG,UAAU,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,yBAoDpD,CAAA;AAiFD,eAAO,MAAM,SAAS,QAAS,MAAM,OAAO,YAAY,wBAqEvD,CAAA"}
-188
View File
@@ -1,188 +0,0 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.mkdirSync = exports.mkdir = void 0;
const chownr_1 = require("chownr");
const node_fs_1 = __importDefault(require("node:fs"));
const promises_1 = __importDefault(require("node:fs/promises"));
const node_path_1 = __importDefault(require("node:path"));
const cwd_error_js_1 = require("./cwd-error.js");
const normalize_windows_path_js_1 = require("./normalize-windows-path.js");
const symlink_error_js_1 = require("./symlink-error.js");
const checkCwd = (dir, cb) => {
node_fs_1.default.stat(dir, (er, st) => {
if (er || !st.isDirectory()) {
er = new cwd_error_js_1.CwdError(dir, er?.code || 'ENOTDIR');
}
cb(er);
});
};
/**
* Wrapper around fs/promises.mkdir for tar's needs.
*
* The main purpose is to avoid creating directories if we know that
* they already exist (and track which ones exist for this purpose),
* and prevent entries from being extracted into symlinked folders,
* if `preservePaths` is not set.
*/
const mkdir = (dir, opt, cb) => {
dir = (0, normalize_windows_path_js_1.normalizeWindowsPath)(dir);
// if there's any overlap between mask and mode,
// then we'll need an explicit chmod
/* c8 ignore next */
const umask = opt.umask ?? 0o22;
const mode = opt.mode | 0o0700;
const needChmod = (mode & umask) !== 0;
const uid = opt.uid;
const gid = opt.gid;
const doChown = typeof uid === 'number' &&
typeof gid === 'number' &&
(uid !== opt.processUid || gid !== opt.processGid);
const preserve = opt.preserve;
const unlink = opt.unlink;
const cwd = (0, normalize_windows_path_js_1.normalizeWindowsPath)(opt.cwd);
const done = (er, created) => {
if (er) {
cb(er);
}
else {
if (created && doChown) {
(0, chownr_1.chownr)(created, uid, gid, er => done(er));
}
else if (needChmod) {
node_fs_1.default.chmod(dir, mode, cb);
}
else {
cb();
}
}
};
if (dir === cwd) {
return checkCwd(dir, done);
}
if (preserve) {
return promises_1.default.mkdir(dir, { mode, recursive: true }).then(made => done(null, made ?? undefined), // oh, ts
done);
}
const sub = (0, normalize_windows_path_js_1.normalizeWindowsPath)(node_path_1.default.relative(cwd, dir));
const parts = sub.split('/');
mkdir_(cwd, parts, mode, unlink, cwd, undefined, done);
};
exports.mkdir = mkdir;
const mkdir_ = (base, parts, mode, unlink, cwd, created, cb) => {
if (!parts.length) {
return cb(null, created);
}
const p = parts.shift();
const part = (0, normalize_windows_path_js_1.normalizeWindowsPath)(node_path_1.default.resolve(base + '/' + p));
node_fs_1.default.mkdir(part, mode, onmkdir(part, parts, mode, unlink, cwd, created, cb));
};
const onmkdir = (part, parts, mode, unlink, cwd, created, cb) => (er) => {
if (er) {
node_fs_1.default.lstat(part, (statEr, st) => {
if (statEr) {
statEr.path =
statEr.path && (0, normalize_windows_path_js_1.normalizeWindowsPath)(statEr.path);
cb(statEr);
}
else if (st.isDirectory()) {
mkdir_(part, parts, mode, unlink, cwd, created, cb);
}
else if (unlink) {
node_fs_1.default.unlink(part, er => {
if (er) {
return cb(er);
}
node_fs_1.default.mkdir(part, mode, onmkdir(part, parts, mode, unlink, cwd, created, cb));
});
}
else if (st.isSymbolicLink()) {
return cb(new symlink_error_js_1.SymlinkError(part, part + '/' + parts.join('/')));
}
else {
cb(er);
}
});
}
else {
created = created || part;
mkdir_(part, parts, mode, unlink, cwd, created, cb);
}
};
const checkCwdSync = (dir) => {
let ok = false;
let code = undefined;
try {
ok = node_fs_1.default.statSync(dir).isDirectory();
}
catch (er) {
code = er?.code;
}
finally {
if (!ok) {
throw new cwd_error_js_1.CwdError(dir, code ?? 'ENOTDIR');
}
}
};
const mkdirSync = (dir, opt) => {
dir = (0, normalize_windows_path_js_1.normalizeWindowsPath)(dir);
// if there's any overlap between mask and mode,
// then we'll need an explicit chmod
/* c8 ignore next */
const umask = opt.umask ?? 0o22;
const mode = opt.mode | 0o700;
const needChmod = (mode & umask) !== 0;
const uid = opt.uid;
const gid = opt.gid;
const doChown = typeof uid === 'number' &&
typeof gid === 'number' &&
(uid !== opt.processUid || gid !== opt.processGid);
const preserve = opt.preserve;
const unlink = opt.unlink;
const cwd = (0, normalize_windows_path_js_1.normalizeWindowsPath)(opt.cwd);
const done = (created) => {
if (created && doChown) {
(0, chownr_1.chownrSync)(created, uid, gid);
}
if (needChmod) {
node_fs_1.default.chmodSync(dir, mode);
}
};
if (dir === cwd) {
checkCwdSync(cwd);
return done();
}
if (preserve) {
return done(node_fs_1.default.mkdirSync(dir, { mode, recursive: true }) ?? undefined);
}
const sub = (0, normalize_windows_path_js_1.normalizeWindowsPath)(node_path_1.default.relative(cwd, dir));
const parts = sub.split('/');
let created = undefined;
for (let p = parts.shift(), part = cwd; p && (part += '/' + p); p = parts.shift()) {
part = (0, normalize_windows_path_js_1.normalizeWindowsPath)(node_path_1.default.resolve(part));
try {
node_fs_1.default.mkdirSync(part, mode);
created = created || part;
}
catch (er) {
const st = node_fs_1.default.lstatSync(part);
if (st.isDirectory()) {
continue;
}
else if (unlink) {
node_fs_1.default.unlinkSync(part);
node_fs_1.default.mkdirSync(part, mode);
created = created || part;
continue;
}
else if (st.isSymbolicLink()) {
return new symlink_error_js_1.SymlinkError(part, part + '/' + parts.join('/'));
}
}
}
return done(created);
};
exports.mkdirSync = mkdirSync;
//# sourceMappingURL=mkdir.js.map
File diff suppressed because one or more lines are too long
-2
View File
@@ -1,2 +0,0 @@
export declare const modeFix: (mode: number, isDir: boolean, portable: boolean) => number;
//# sourceMappingURL=mode-fix.d.ts.map
@@ -1 +0,0 @@
{"version":3,"file":"mode-fix.d.ts","sourceRoot":"","sources":["../../src/mode-fix.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,SACZ,MAAM,SACL,OAAO,YACJ,OAAO,WA0BlB,CAAA"}
-29
View File
@@ -1,29 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.modeFix = void 0;
const modeFix = (mode, isDir, portable) => {
mode &= 0o7777;
// in portable mode, use the minimum reasonable umask
// if this system creates files with 0o664 by default
// (as some linux distros do), then we'll write the
// archive with 0o644 instead. Also, don't ever create
// a file that is not readable/writable by the owner.
if (portable) {
mode = (mode | 0o600) & ~0o22;
}
// if dirs are readable, then they should be listable
if (isDir) {
if (mode & 0o400) {
mode |= 0o100;
}
if (mode & 0o40) {
mode |= 0o10;
}
if (mode & 0o4) {
mode |= 0o1;
}
}
return mode;
};
exports.modeFix = modeFix;
//# sourceMappingURL=mode-fix.js.map
-1
View File
@@ -1 +0,0 @@
{"version":3,"file":"mode-fix.js","sourceRoot":"","sources":["../../src/mode-fix.ts"],"names":[],"mappings":";;;AAAO,MAAM,OAAO,GAAG,CACrB,IAAY,EACZ,KAAc,EACd,QAAiB,EACjB,EAAE;IACF,IAAI,IAAI,MAAM,CAAA;IAEd,qDAAqD;IACrD,qDAAqD;IACrD,mDAAmD;IACnD,uDAAuD;IACvD,qDAAqD;IACrD,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAA;IAC/B,CAAC;IAED,qDAAqD;IACrD,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;YACjB,IAAI,IAAI,KAAK,CAAA;QACf,CAAC;QACD,IAAI,IAAI,GAAG,IAAI,EAAE,CAAC;YAChB,IAAI,IAAI,IAAI,CAAA;QACd,CAAC;QACD,IAAI,IAAI,GAAG,GAAG,EAAE,CAAC;YACf,IAAI,IAAI,GAAG,CAAA;QACb,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC,CAAA;AA7BY,QAAA,OAAO,WA6BnB","sourcesContent":["export const modeFix = (\n mode: number,\n isDir: boolean,\n portable: boolean,\n) => {\n mode &= 0o7777\n\n // in portable mode, use the minimum reasonable umask\n // if this system creates files with 0o664 by default\n // (as some linux distros do), then we'll write the\n // archive with 0o644 instead. Also, don't ever create\n // a file that is not readable/writable by the owner.\n if (portable) {\n mode = (mode | 0o600) & ~0o22\n }\n\n // if dirs are readable, then they should be listable\n if (isDir) {\n if (mode & 0o400) {\n mode |= 0o100\n }\n if (mode & 0o40) {\n mode |= 0o10\n }\n if (mode & 0o4) {\n mode |= 0o1\n }\n }\n return mode\n}\n"]}
@@ -1,2 +0,0 @@
export declare const normalizeUnicode: (s: string) => string;
//# sourceMappingURL=normalize-unicode.d.ts.map
@@ -1 +0,0 @@
{"version":3,"file":"normalize-unicode.d.ts","sourceRoot":"","sources":["../../src/normalize-unicode.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,gBAAgB,MAAO,MAAM,KAAG,MAqB5C,CAAA"}
@@ -1,34 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.normalizeUnicode = void 0;
// warning: extremely hot code path.
// This has been meticulously optimized for use
// within npm install on large package trees.
// Do not edit without careful benchmarking.
const normalizeCache = Object.create(null);
// Limit the size of this. Very low-sophistication LRU cache
const MAX = 10000;
const cache = new Set();
const normalizeUnicode = (s) => {
if (!cache.has(s)) {
normalizeCache[s] = s.normalize('NFD');
}
else {
cache.delete(s);
}
cache.add(s);
const ret = normalizeCache[s];
let i = cache.size - MAX;
// only prune when we're 10% over the max
if (i > MAX / 10) {
for (const s of cache) {
cache.delete(s);
delete normalizeCache[s];
if (--i <= 0)
break;
}
}
return ret;
};
exports.normalizeUnicode = normalizeUnicode;
//# sourceMappingURL=normalize-unicode.js.map
@@ -1 +0,0 @@
{"version":3,"file":"normalize-unicode.js","sourceRoot":"","sources":["../../src/normalize-unicode.ts"],"names":[],"mappings":";;;AAAA,oCAAoC;AACpC,+CAA+C;AAC/C,6CAA6C;AAC7C,4CAA4C;AAC5C,MAAM,cAAc,GAA2B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;AAElE,4DAA4D;AAC5D,MAAM,GAAG,GAAG,KAAK,CAAA;AACjB,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAA;AACxB,MAAM,gBAAgB,GAAG,CAAC,CAAS,EAAU,EAAE;IACpD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAClB,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IACxC,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IAEZ,MAAM,GAAG,GAAG,cAAc,CAAC,CAAC,CAAW,CAAA;IAEvC,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,GAAG,GAAG,CAAA;IACxB,yCAAyC;IACzC,IAAI,CAAC,GAAG,GAAG,GAAG,EAAE,EAAE,CAAC;QACjB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;YACf,OAAO,cAAc,CAAC,CAAC,CAAC,CAAA;YACxB,IAAI,EAAE,CAAC,IAAI,CAAC;gBAAE,MAAK;QACrB,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA;AArBY,QAAA,gBAAgB,oBAqB5B","sourcesContent":["// warning: extremely hot code path.\n// This has been meticulously optimized for use\n// within npm install on large package trees.\n// Do not edit without careful benchmarking.\nconst normalizeCache: Record<string, string> = Object.create(null)\n\n// Limit the size of this. Very low-sophistication LRU cache\nconst MAX = 10000\nconst cache = new Set<string>()\nexport const normalizeUnicode = (s: string): string => {\n if (!cache.has(s)) {\n normalizeCache[s] = s.normalize('NFD')\n } else {\n cache.delete(s)\n }\n cache.add(s)\n\n const ret = normalizeCache[s] as string\n\n let i = cache.size - MAX\n // only prune when we're 10% over the max\n if (i > MAX / 10) {\n for (const s of cache) {\n cache.delete(s)\n delete normalizeCache[s]\n if (--i <= 0) break\n }\n }\n\n return ret\n}\n"]}
@@ -1,2 +0,0 @@
export declare const normalizeWindowsPath: (p: string) => string;
//# sourceMappingURL=normalize-windows-path.d.ts.map
@@ -1 +0,0 @@
{"version":3,"file":"normalize-windows-path.d.ts","sourceRoot":"","sources":["../../src/normalize-windows-path.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,oBAAoB,MAEzB,MAAM,WAC+B,CAAA"}
@@ -1,12 +0,0 @@
"use strict";
// on windows, either \ or / are valid directory separators.
// on unix, \ is a valid character in filenames.
// so, on windows, and only on windows, we replace all \ chars with /,
// so that we can use / as our one and only directory separator char.
Object.defineProperty(exports, "__esModule", { value: true });
exports.normalizeWindowsPath = void 0;
const platform = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform;
exports.normalizeWindowsPath = platform !== 'win32' ?
(p) => p
: (p) => p && p.replace(/\\/g, '/');
//# sourceMappingURL=normalize-windows-path.js.map
@@ -1 +0,0 @@
{"version":3,"file":"normalize-windows-path.js","sourceRoot":"","sources":["../../src/normalize-windows-path.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,gDAAgD;AAChD,sEAAsE;AACtE,qEAAqE;;;AAErE,MAAM,QAAQ,GACZ,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,OAAO,CAAC,QAAQ,CAAA;AAE9C,QAAA,oBAAoB,GAC/B,QAAQ,KAAK,OAAO,CAAC,CAAC;IACpB,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA","sourcesContent":["// on windows, either \\ or / are valid directory separators.\n// on unix, \\ is a valid character in filenames.\n// so, on windows, and only on windows, we replace all \\ chars with /,\n// so that we can use / as our one and only directory separator char.\n\nconst platform =\n process.env.TESTING_TAR_FAKE_PLATFORM || process.platform\n\nexport const normalizeWindowsPath =\n platform !== 'win32' ?\n (p: string) => p\n : (p: string) => p && p.replace(/\\\\/g, '/')\n"]}
-621
View File
@@ -1,621 +0,0 @@
/// <reference types="node" />
import { type GzipOptions, type ZlibOptions } from 'minizlib';
import { type Stats } from 'node:fs';
import { type ReadEntry } from './read-entry.js';
import { type WarnData } from './warn-method.js';
import { WriteEntry } from './write-entry.js';
/**
* The options that can be provided to tar commands.
*
* Note that some of these are only relevant for certain commands, since
* they are specific to reading or writing.
*
* Aliases are provided in the {@link TarOptionsWithAliases} type.
*/
export interface TarOptions {
/**
* Perform all I/O operations synchronously. If the stream is ended
* immediately, then it will be processed entirely synchronously.
*/
sync?: boolean;
/**
* The tar file to be read and/or written. When this is set, a stream
* is not returned. Asynchronous commands will return a promise indicating
* when the operation is completed, and synchronous commands will return
* immediately.
*/
file?: string;
/**
* Treat warnings as crash-worthy errors. Defaults false.
*/
strict?: boolean;
/**
* The effective current working directory for this tar command
*/
cwd?: string;
/**
* When creating a tar archive, this can be used to compress it as well.
* Set to `true` to use the default gzip options, or customize them as
* needed.
*
* When reading, if this is unset, then the compression status will be
* inferred from the archive data. This is generally best, unless you are
* sure of the compression settings in use to create the archive, and want to
* fail if the archive doesn't match expectations.
*/
gzip?: boolean | GzipOptions;
/**
* When creating archives, preserve absolute and `..` paths in the archive,
* rather than sanitizing them under the cwd.
*
* When extracting, allow absolute paths, paths containing `..`, and
* extracting through symbolic links. By default, the root `/` is stripped
* from absolute paths (eg, turning `/x/y/z` into `x/y/z`), paths containing
* `..` are not extracted, and any file whose location would be modified by a
* symbolic link is not extracted.
*
* **WARNING** This is almost always unsafe, and must NEVER be used on
* archives from untrusted sources, such as user input, and every entry must
* be validated to ensure it is safe to write. Even if the input is not
* malicious, mistakes can cause a lot of damage!
*/
preservePaths?: boolean;
/**
* When extracting, do not set the `mtime` value for extracted entries to
* match the `mtime` in the archive.
*
* When creating archives, do not store the `mtime` value in the entry. Note
* that this prevents properly using other mtime-based features (such as
* `tar.update` or the `newer` option) with the resulting archive.
*/
noMtime?: boolean;
/**
* Set to `true` or an object with settings for `zlib.BrotliCompress()` to
* create a brotli-compressed archive
*
* When extracting, this will cause the archive to be treated as a
* brotli-compressed file if set to `true` or a ZlibOptions object.
*
* If set `false`, then brotli options will not be used.
*
* If this, the `gzip`, and `zstd` options are left `undefined`, then tar
* will attempt to infer the brotli compression status, but can only do so
* based on the filename. If the filename ends in `.tbr` or `.tar.br`, and
* the first 512 bytes are not a valid tar header, then brotli decompression
* will be attempted.
*/
brotli?: boolean | ZlibOptions;
/**
* Set to `true` or an object with settings for `zstd.compress()` to
* create a zstd-compressed archive
*
* When extracting, this will cause the archive to be treated as a
* zstd-compressed file if set to `true` or a ZlibOptions object.
*
* If set `false`, then zstd options will not be used.
*
* If this, the `gzip`, and `brotli` options are left `undefined`, then tar
* will attempt to infer the zstd compression status, but can only do so
* based on the filename. If the filename ends in `.tzst` or `.tar.zst`, and
* the first 512 bytes are not a valid tar header, then zstd decompression
* will be attempted.
*/
zstd?: boolean | ZlibOptions;
/**
* A function that is called with `(path, stat)` when creating an archive, or
* `(path, entry)` when extracting. Return true to process the file/entry, or
* false to exclude it.
*/
filter?: (path: string, entry: Stats | ReadEntry) => boolean;
/**
* A function that gets called for any warning encountered.
*
* Note: if `strict` is set, then the warning will throw, and this method
* will not be called.
*/
onwarn?: (code: string, message: string, data: WarnData) => any;
/**
* When extracting, unlink files before creating them. Without this option,
* tar overwrites existing files, which preserves existing hardlinks. With
* this option, existing hardlinks will be broken, as will any symlink that
* would affect the location of an extracted file.
*/
unlink?: boolean;
/**
* When extracting, strip the specified number of path portions from the
* entry path. For example, with `{strip: 2}`, the entry `a/b/c/d` would be
* extracted to `{cwd}/c/d`.
*
* Any entry whose entire path is stripped will be excluded.
*/
strip?: number;
/**
* When extracting, keep the existing file on disk if it's newer than the
* file in the archive.
*/
newer?: boolean;
/**
* When extracting, do not overwrite existing files at all.
*/
keep?: boolean;
/**
* When extracting, set the `uid` and `gid` of extracted entries to the `uid`
* and `gid` fields in the archive. Defaults to true when run as root, and
* false otherwise.
*
* If false, then files and directories will be set with the owner and group
* of the user running the process. This is similar to `-p` in `tar(1)`, but
* ACLs and other system-specific data is never unpacked in this
* implementation, and modes are set by default already.
*/
preserveOwner?: boolean;
/**
* The maximum depth of subfolders to extract into. This defaults to 1024.
* Anything deeper than the limit will raise a warning and skip the entry.
* Set to `Infinity` to remove the limitation.
*/
maxDepth?: number;
/**
* When extracting, force all created files and directories, and all
* implicitly created directories, to be owned by the specified user id,
* regardless of the `uid` field in the archive.
*
* Cannot be used along with `preserveOwner`. Requires also setting the `gid`
* option.
*/
uid?: number;
/**
* When extracting, force all created files and directories, and all
* implicitly created directories, to be owned by the specified group id,
* regardless of the `gid` field in the archive.
*
* Cannot be used along with `preserveOwner`. Requires also setting the `uid`
* option.
*/
gid?: number;
/**
* When extracting, provide a function that takes an `entry` object, and
* returns a stream, or any falsey value. If a stream is provided, then that
* stream's data will be written instead of the contents of the archive
* entry. If a falsey value is provided, then the entry is written to disk as
* normal.
*
* To exclude items from extraction, use the `filter` option.
*
* Note that using an asynchronous stream type with the `transform` option
* will cause undefined behavior in synchronous extractions.
* [MiniPass](http://npm.im/minipass)-based streams are designed for this use
* case.
*/
transform?: (entry: ReadEntry) => any;
/**
* Call `chmod()` to ensure that extracted files match the entry's mode
* field. Without this field set, all mode fields in archive entries are a
* best effort attempt only.
*
* Setting this necessitates a call to the deprecated `process.umask()`
* method to determine the default umask value, unless a `processUmask`
* config is provided as well.
*
* If not set, tar will attempt to create file system entries with whatever
* mode is provided, and let the implicit process `umask` apply normally, but
* if a file already exists to be written to, then its existing mode will not
* be modified.
*
* When setting `chmod: true`, it is highly recommend to set the
* {@link TarOptions#processUmask} option as well, to avoid the call to the
* deprecated (and thread-unsafe) `process.umask()` method.
*/
chmod?: boolean;
/**
* When setting the {@link TarOptions#chmod} option to `true`, you may
* provide a value here to avoid having to call the deprecated and
* thread-unsafe `process.umask()` method.
*
* This has no effect with `chmod` is not set to true, as mode values are not
* set explicitly anyway. If `chmod` is set to `true`, and a value is not
* provided here, then `process.umask()` must be called, which will result in
* deprecation warnings.
*
* The most common values for this are `0o22` (resulting in directories
* created with mode `0o755` and files with `0o644` by default) and `0o2`
* (resulting in directores created with mode `0o775` and files `0o664`, so
* they are group-writable).
*/
processUmask?: number;
/**
* When parsing/listing archives, `entry` streams are by default resumed
* (set into "flowing" mode) immediately after the call to `onReadEntry()`.
* Set `noResume: true` to suppress this behavior.
*
* Note that when this is set, the stream will never complete until the
* data is consumed somehow.
*
* Set automatically in extract operations, since the entry is piped to
* a file system entry right away. Only relevant when parsing.
*/
noResume?: boolean;
/**
* When creating, updating, or replacing within archives, this method will
* be called with each WriteEntry that is created.
*/
onWriteEntry?: (entry: WriteEntry) => any;
/**
* When extracting or listing archives, this method will be called with
* each entry that is not excluded by a `filter`.
*
* Important when listing archives synchronously from a file, because there
* is otherwise no way to interact with the data!
*/
onReadEntry?: (entry: ReadEntry) => any;
/**
* Pack the targets of symbolic links rather than the link itself.
*/
follow?: boolean;
/**
* When creating archives, omit any metadata that is system-specific:
* `ctime`, `atime`, `uid`, `gid`, `uname`, `gname`, `dev`, `ino`, and
* `nlink`. Note that `mtime` is still included, because this is necessary
* for other time-based operations such as `tar.update`. Additionally, `mode`
* is set to a "reasonable default" for mose unix systems, based on an
* effective `umask` of `0o22`.
*
* This also defaults the `portable` option in the gzip configs when creating
* a compressed archive, in order to produce deterministic archives that are
* not operating-system specific.
*/
portable?: boolean;
/**
* When creating archives, do not recursively archive the contents of
* directories. By default, archiving a directory archives all of its
* contents as well.
*/
noDirRecurse?: boolean;
/**
* Suppress Pax extended headers when creating archives. Note that this means
* long paths and linkpaths will be truncated, and large or negative numeric
* values may be interpreted incorrectly.
*/
noPax?: boolean;
/**
* Set to a `Date` object to force a specific `mtime` value for everything
* written to an archive.
*
* This is useful when creating archives that are intended to be
* deterministic based on their contents, irrespective of the file's last
* modification time.
*
* Overridden by `noMtime`.
*/
mtime?: Date;
/**
* A path portion to prefix onto the entries added to an archive.
*/
prefix?: string;
/**
* The mode to set on any created file archive, defaults to 0o666
* masked by the process umask, often resulting in 0o644.
*
* This does *not* affect the mode fields of individual entries, or the
* mode status of extracted entries on the filesystem.
*/
mode?: number;
/**
* A cache of mtime values, to avoid having to stat the same file repeatedly.
*
* @internal
*/
mtimeCache?: Map<string, Date>;
/**
* maximum buffer size for `fs.read()` operations.
*
* @internal
*/
maxReadSize?: number;
/**
* Filter modes of entries being unpacked, like `process.umask()`
*
* @internal
*/
umask?: number;
/**
* Default mode for directories. Used for all implicitly created directories,
* and any directories in the archive that do not have a mode field.
*
* @internal
*/
dmode?: number;
/**
* default mode for files
*
* @internal
*/
fmode?: number;
/**
* Map that tracks which directories already exist, for extraction
*
* @internal
*/
dirCache?: Map<string, boolean>;
/**
* maximum supported size of meta entries. Defaults to 1MB
*
* @internal
*/
maxMetaEntrySize?: number;
/**
* A Map object containing the device and inode value for any file whose
* `nlink` value is greater than 1, to identify hard links when creating
* archives.
*
* @internal
*/
linkCache?: Map<LinkCacheKey, string>;
/**
* A map object containing the results of `fs.readdir()` calls.
*
* @internal
*/
readdirCache?: Map<string, string[]>;
/**
* A cache of all `lstat` results, for use in creating archives.
*
* @internal
*/
statCache?: Map<string, Stats>;
/**
* Number of concurrent jobs to run when creating archives.
*
* Defaults to 4.
*
* @internal
*/
jobs?: number;
/**
* Automatically set to true on Windows systems.
*
* When extracting, causes behavior where filenames containing `<|>?:`
* characters are converted to windows-compatible escape sequences in the
* created filesystem entries.
*
* When packing, causes behavior where paths replace `\` with `/`, and
* filenames containing the windows-compatible escaped forms of `<|>?:` are
* converted to actual `<|>?:` characters in the archive.
*
* @internal
*/
win32?: boolean;
/**
* For `WriteEntry` objects, the absolute path to the entry on the
* filesystem. By default, this is `resolve(cwd, entry.path)`, but it can be
* overridden explicitly.
*
* @internal
*/
absolute?: string;
/**
* Used with Parser stream interface, to attach and take over when the
* stream is completely parsed. If this is set, then the prefinish,
* finish, and end events will not fire, and are the responsibility of
* the ondone method to emit properly.
*
* @internal
*/
ondone?: () => void;
/**
* Mostly for testing, but potentially useful in some cases.
* Forcibly trigger a chown on every entry, no matter what.
*/
forceChown?: boolean;
/**
* ambiguous deprecated name for {@link onReadEntry}
*
* @deprecated
*/
onentry?: (entry: ReadEntry) => any;
}
export type TarOptionsSync = TarOptions & {
sync: true;
};
export type TarOptionsAsync = TarOptions & {
sync?: false;
};
export type TarOptionsFile = TarOptions & {
file: string;
};
export type TarOptionsNoFile = TarOptions & {
file?: undefined;
};
export type TarOptionsSyncFile = TarOptionsSync & TarOptionsFile;
export type TarOptionsAsyncFile = TarOptionsAsync & TarOptionsFile;
export type TarOptionsSyncNoFile = TarOptionsSync & TarOptionsNoFile;
export type TarOptionsAsyncNoFile = TarOptionsAsync & TarOptionsNoFile;
export type LinkCacheKey = `${number}:${number}`;
export interface TarOptionsWithAliases extends TarOptions {
/**
* The effective current working directory for this tar command
*/
C?: TarOptions['cwd'];
/**
* The tar file to be read and/or written. When this is set, a stream
* is not returned. Asynchronous commands will return a promise indicating
* when the operation is completed, and synchronous commands will return
* immediately.
*/
f?: TarOptions['file'];
/**
* When creating a tar archive, this can be used to compress it as well.
* Set to `true` to use the default gzip options, or customize them as
* needed.
*
* When reading, if this is unset, then the compression status will be
* inferred from the archive data. This is generally best, unless you are
* sure of the compression settings in use to create the archive, and want to
* fail if the archive doesn't match expectations.
*/
z?: TarOptions['gzip'];
/**
* When creating archives, preserve absolute and `..` paths in the archive,
* rather than sanitizing them under the cwd.
*
* When extracting, allow absolute paths, paths containing `..`, and
* extracting through symbolic links. By default, the root `/` is stripped
* from absolute paths (eg, turning `/x/y/z` into `x/y/z`), paths containing
* `..` are not extracted, and any file whose location would be modified by a
* symbolic link is not extracted.
*
* **WARNING** This is almost always unsafe, and must NEVER be used on
* archives from untrusted sources, such as user input, and every entry must
* be validated to ensure it is safe to write. Even if the input is not
* malicious, mistakes can cause a lot of damage!
*/
P?: TarOptions['preservePaths'];
/**
* When extracting, unlink files before creating them. Without this option,
* tar overwrites existing files, which preserves existing hardlinks. With
* this option, existing hardlinks will be broken, as will any symlink that
* would affect the location of an extracted file.
*/
U?: TarOptions['unlink'];
/**
* When extracting, strip the specified number of path portions from the
* entry path. For example, with `{strip: 2}`, the entry `a/b/c/d` would be
* extracted to `{cwd}/c/d`.
*/
'strip-components'?: TarOptions['strip'];
/**
* When extracting, strip the specified number of path portions from the
* entry path. For example, with `{strip: 2}`, the entry `a/b/c/d` would be
* extracted to `{cwd}/c/d`.
*/
stripComponents?: TarOptions['strip'];
/**
* When extracting, keep the existing file on disk if it's newer than the
* file in the archive.
*/
'keep-newer'?: TarOptions['newer'];
/**
* When extracting, keep the existing file on disk if it's newer than the
* file in the archive.
*/
keepNewer?: TarOptions['newer'];
/**
* When extracting, keep the existing file on disk if it's newer than the
* file in the archive.
*/
'keep-newer-files'?: TarOptions['newer'];
/**
* When extracting, keep the existing file on disk if it's newer than the
* file in the archive.
*/
keepNewerFiles?: TarOptions['newer'];
/**
* When extracting, do not overwrite existing files at all.
*/
k?: TarOptions['keep'];
/**
* When extracting, do not overwrite existing files at all.
*/
'keep-existing'?: TarOptions['keep'];
/**
* When extracting, do not overwrite existing files at all.
*/
keepExisting?: TarOptions['keep'];
/**
* When extracting, do not set the `mtime` value for extracted entries to
* match the `mtime` in the archive.
*
* When creating archives, do not store the `mtime` value in the entry. Note
* that this prevents properly using other mtime-based features (such as
* `tar.update` or the `newer` option) with the resulting archive.
*/
m?: TarOptions['noMtime'];
/**
* When extracting, do not set the `mtime` value for extracted entries to
* match the `mtime` in the archive.
*
* When creating archives, do not store the `mtime` value in the entry. Note
* that this prevents properly using other mtime-based features (such as
* `tar.update` or the `newer` option) with the resulting archive.
*/
'no-mtime'?: TarOptions['noMtime'];
/**
* When extracting, set the `uid` and `gid` of extracted entries to the `uid`
* and `gid` fields in the archive. Defaults to true when run as root, and
* false otherwise.
*
* If false, then files and directories will be set with the owner and group
* of the user running the process. This is similar to `-p` in `tar(1)`, but
* ACLs and other system-specific data is never unpacked in this
* implementation, and modes are set by default already.
*/
p?: TarOptions['preserveOwner'];
/**
* Pack the targets of symbolic links rather than the link itself.
*/
L?: TarOptions['follow'];
/**
* Pack the targets of symbolic links rather than the link itself.
*/
h?: TarOptions['follow'];
/**
* Deprecated option. Set explicitly false to set `chmod: true`. Ignored
* if {@link TarOptions#chmod} is set to any boolean value.
*
* @deprecated
*/
noChmod?: boolean;
}
export type TarOptionsWithAliasesSync = TarOptionsWithAliases & {
sync: true;
};
export type TarOptionsWithAliasesAsync = TarOptionsWithAliases & {
sync?: false;
};
export type TarOptionsWithAliasesFile = (TarOptionsWithAliases & {
file: string;
}) | (TarOptionsWithAliases & {
f: string;
});
export type TarOptionsWithAliasesSyncFile = TarOptionsWithAliasesSync & TarOptionsWithAliasesFile;
export type TarOptionsWithAliasesAsyncFile = TarOptionsWithAliasesAsync & TarOptionsWithAliasesFile;
export type TarOptionsWithAliasesNoFile = TarOptionsWithAliases & {
f?: undefined;
file?: undefined;
};
export type TarOptionsWithAliasesSyncNoFile = TarOptionsWithAliasesSync & TarOptionsWithAliasesNoFile;
export type TarOptionsWithAliasesAsyncNoFile = TarOptionsWithAliasesAsync & TarOptionsWithAliasesNoFile;
export declare const isSyncFile: <O extends TarOptions>(o: O) => o is O & TarOptions & {
sync: true;
} & {
file: string;
};
export declare const isAsyncFile: <O extends TarOptions>(o: O) => o is O & TarOptions & {
sync?: false | undefined;
} & {
file: string;
};
export declare const isSyncNoFile: <O extends TarOptions>(o: O) => o is O & TarOptions & {
sync: true;
} & {
file?: undefined;
};
export declare const isAsyncNoFile: <O extends TarOptions>(o: O) => o is O & TarOptions & {
sync?: false | undefined;
} & {
file?: undefined;
};
export declare const isSync: <O extends TarOptions>(o: O) => o is O & TarOptions & {
sync: true;
};
export declare const isAsync: <O extends TarOptions>(o: O) => o is O & TarOptions & {
sync?: false | undefined;
};
export declare const isFile: <O extends TarOptions>(o: O) => o is O & TarOptions & {
file: string;
};
export declare const isNoFile: <O extends TarOptions>(o: O) => o is O & TarOptions & {
file?: undefined;
};
export declare const dealias: (opt?: TarOptionsWithAliases) => TarOptions;
//# sourceMappingURL=options.d.ts.map
File diff suppressed because one or more lines are too long
-66
View File
@@ -1,66 +0,0 @@
"use strict";
// turn tar(1) style args like `C` into the more verbose things like `cwd`
Object.defineProperty(exports, "__esModule", { value: true });
exports.dealias = exports.isNoFile = exports.isFile = exports.isAsync = exports.isSync = exports.isAsyncNoFile = exports.isSyncNoFile = exports.isAsyncFile = exports.isSyncFile = void 0;
const argmap = new Map([
['C', 'cwd'],
['f', 'file'],
['z', 'gzip'],
['P', 'preservePaths'],
['U', 'unlink'],
['strip-components', 'strip'],
['stripComponents', 'strip'],
['keep-newer', 'newer'],
['keepNewer', 'newer'],
['keep-newer-files', 'newer'],
['keepNewerFiles', 'newer'],
['k', 'keep'],
['keep-existing', 'keep'],
['keepExisting', 'keep'],
['m', 'noMtime'],
['no-mtime', 'noMtime'],
['p', 'preserveOwner'],
['L', 'follow'],
['h', 'follow'],
['onentry', 'onReadEntry'],
]);
const isSyncFile = (o) => !!o.sync && !!o.file;
exports.isSyncFile = isSyncFile;
const isAsyncFile = (o) => !o.sync && !!o.file;
exports.isAsyncFile = isAsyncFile;
const isSyncNoFile = (o) => !!o.sync && !o.file;
exports.isSyncNoFile = isSyncNoFile;
const isAsyncNoFile = (o) => !o.sync && !o.file;
exports.isAsyncNoFile = isAsyncNoFile;
const isSync = (o) => !!o.sync;
exports.isSync = isSync;
const isAsync = (o) => !o.sync;
exports.isAsync = isAsync;
const isFile = (o) => !!o.file;
exports.isFile = isFile;
const isNoFile = (o) => !o.file;
exports.isNoFile = isNoFile;
const dealiasKey = (k) => {
const d = argmap.get(k);
if (d)
return d;
return k;
};
const dealias = (opt = {}) => {
if (!opt)
return {};
const result = {};
for (const [key, v] of Object.entries(opt)) {
// TS doesn't know that aliases are going to always be the same type
const k = dealiasKey(key);
result[k] = v;
}
// affordance for deprecated noChmod -> chmod
if (result.chmod === undefined && result.noChmod === false) {
result.chmod = true;
}
delete result.noChmod;
return result;
};
exports.dealias = dealias;
//# sourceMappingURL=options.js.map
File diff suppressed because one or more lines are too long
-103
View File
@@ -1,103 +0,0 @@
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
import { type Stats } from 'fs';
import { WriteEntry, WriteEntrySync, WriteEntryTar } from './write-entry.js';
export declare class PackJob {
path: string;
absolute: string;
entry?: WriteEntry | WriteEntryTar;
stat?: Stats;
readdir?: string[];
pending: boolean;
ignore: boolean;
piped: boolean;
constructor(path: string, absolute: string);
}
import { Minipass } from 'minipass';
import * as zlib from 'minizlib';
import { Yallist } from 'yallist';
import { ReadEntry } from './read-entry.js';
import { WarnEvent, type WarnData, type Warner } from './warn-method.js';
declare const ONSTAT: unique symbol;
declare const ENDED: unique symbol;
declare const QUEUE: unique symbol;
declare const CURRENT: unique symbol;
declare const PROCESS: unique symbol;
declare const PROCESSING: unique symbol;
declare const PROCESSJOB: unique symbol;
declare const JOBS: unique symbol;
declare const JOBDONE: unique symbol;
declare const ADDFSENTRY: unique symbol;
declare const ADDTARENTRY: unique symbol;
declare const STAT: unique symbol;
declare const READDIR: unique symbol;
declare const ONREADDIR: unique symbol;
declare const PIPE: unique symbol;
declare const ENTRY: unique symbol;
declare const ENTRYOPT: unique symbol;
declare const WRITEENTRYCLASS: unique symbol;
declare const WRITE: unique symbol;
declare const ONDRAIN: unique symbol;
import { TarOptions } from './options.js';
export declare class Pack extends Minipass<Buffer, ReadEntry | string, WarnEvent<Buffer>> implements Warner {
opt: TarOptions;
cwd: string;
maxReadSize?: number;
preservePaths: boolean;
strict: boolean;
noPax: boolean;
prefix: string;
linkCache: Exclude<TarOptions['linkCache'], undefined>;
statCache: Exclude<TarOptions['statCache'], undefined>;
file: string;
portable: boolean;
zip?: zlib.BrotliCompress | zlib.Gzip | zlib.ZstdCompress;
readdirCache: Exclude<TarOptions['readdirCache'], undefined>;
noDirRecurse: boolean;
follow: boolean;
noMtime: boolean;
mtime?: Date;
filter: Exclude<TarOptions['filter'], undefined>;
jobs: number;
[WRITEENTRYCLASS]: typeof WriteEntry | typeof WriteEntrySync;
onWriteEntry?: (entry: WriteEntry) => void;
[QUEUE]: Yallist<PackJob>;
[JOBS]: number;
[PROCESSING]: boolean;
[ENDED]: boolean;
constructor(opt?: TarOptions);
[WRITE](chunk: Buffer): boolean;
add(path: string | ReadEntry): this;
end(cb?: () => void): this;
end(path: string | ReadEntry, cb?: () => void): this;
end(path: string | ReadEntry, encoding?: Minipass.Encoding, cb?: () => void): this;
write(path: string | ReadEntry): boolean;
[ADDTARENTRY](p: ReadEntry): void;
[ADDFSENTRY](p: string): void;
[STAT](job: PackJob): void;
[ONSTAT](job: PackJob, stat: Stats): void;
[READDIR](job: PackJob): void;
[ONREADDIR](job: PackJob, entries: string[]): void;
[PROCESS](): void;
get [CURRENT](): PackJob | undefined;
[JOBDONE](_job: PackJob): void;
[PROCESSJOB](job: PackJob): void;
[ENTRYOPT](job: PackJob): TarOptions;
[ENTRY](job: PackJob): WriteEntry | undefined;
[ONDRAIN](): void;
[PIPE](job: PackJob): void;
pause(): void;
warn(code: string, message: string | Error, data?: WarnData): void;
}
export declare class PackSync extends Pack {
sync: true;
constructor(opt: TarOptions);
pause(): void;
resume(): void;
[STAT](job: PackJob): void;
[READDIR](job: PackJob): void;
[PIPE](job: PackJob): void;
}
export {};
//# sourceMappingURL=pack.d.ts.map
-1
View File
@@ -1 +0,0 @@
{"version":3,"file":"pack.d.ts","sourceRoot":"","sources":["../../src/pack.ts"],"names":[],"mappings":"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"}
-494
View File
@@ -1,494 +0,0 @@
"use strict";
// A readable tar stream creator
// Technically, this is a transform stream that you write paths into,
// and tar format comes out of.
// The `add()` method is like `write()` but returns this,
// and end() return `this` as well, so you can
// do `new Pack(opt).add('files').add('dir').end().pipe(output)
// You could also do something like:
// streamOfPaths().pipe(new Pack()).pipe(new fs.WriteStream('out.tar'))
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 __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PackSync = exports.Pack = exports.PackJob = void 0;
const fs_1 = __importDefault(require("fs"));
const write_entry_js_1 = require("./write-entry.js");
class PackJob {
path;
absolute;
entry;
stat;
readdir;
pending = false;
ignore = false;
piped = false;
constructor(path, absolute) {
this.path = path || './';
this.absolute = absolute;
}
}
exports.PackJob = PackJob;
const minipass_1 = require("minipass");
const zlib = __importStar(require("minizlib"));
const yallist_1 = require("yallist");
const read_entry_js_1 = require("./read-entry.js");
const warn_method_js_1 = require("./warn-method.js");
const EOF = Buffer.alloc(1024);
const ONSTAT = Symbol('onStat');
const ENDED = Symbol('ended');
const QUEUE = Symbol('queue');
const CURRENT = Symbol('current');
const PROCESS = Symbol('process');
const PROCESSING = Symbol('processing');
const PROCESSJOB = Symbol('processJob');
const JOBS = Symbol('jobs');
const JOBDONE = Symbol('jobDone');
const ADDFSENTRY = Symbol('addFSEntry');
const ADDTARENTRY = Symbol('addTarEntry');
const STAT = Symbol('stat');
const READDIR = Symbol('readdir');
const ONREADDIR = Symbol('onreaddir');
const PIPE = Symbol('pipe');
const ENTRY = Symbol('entry');
const ENTRYOPT = Symbol('entryOpt');
const WRITEENTRYCLASS = Symbol('writeEntryClass');
const WRITE = Symbol('write');
const ONDRAIN = Symbol('ondrain');
const path_1 = __importDefault(require("path"));
const normalize_windows_path_js_1 = require("./normalize-windows-path.js");
class Pack extends minipass_1.Minipass {
opt;
cwd;
maxReadSize;
preservePaths;
strict;
noPax;
prefix;
linkCache;
statCache;
file;
portable;
zip;
readdirCache;
noDirRecurse;
follow;
noMtime;
mtime;
filter;
jobs;
[WRITEENTRYCLASS];
onWriteEntry;
// Note: we actually DO need a linked list here, because we
// shift() to update the head of the list where we start, but still
// while that happens, need to know what the next item in the queue
// will be. Since we do multiple jobs in parallel, it's not as simple
// as just an Array.shift(), since that would lose the information about
// the next job in the list. We could add a .next field on the PackJob
// class, but then we'd have to be tracking the tail of the queue the
// whole time, and Yallist just does that for us anyway.
[QUEUE];
[JOBS] = 0;
[PROCESSING] = false;
[ENDED] = false;
constructor(opt = {}) {
//@ts-ignore
super();
this.opt = opt;
this.file = opt.file || '';
this.cwd = opt.cwd || process.cwd();
this.maxReadSize = opt.maxReadSize;
this.preservePaths = !!opt.preservePaths;
this.strict = !!opt.strict;
this.noPax = !!opt.noPax;
this.prefix = (0, normalize_windows_path_js_1.normalizeWindowsPath)(opt.prefix || '');
this.linkCache = opt.linkCache || new Map();
this.statCache = opt.statCache || new Map();
this.readdirCache = opt.readdirCache || new Map();
this.onWriteEntry = opt.onWriteEntry;
this[WRITEENTRYCLASS] = write_entry_js_1.WriteEntry;
if (typeof opt.onwarn === 'function') {
this.on('warn', opt.onwarn);
}
this.portable = !!opt.portable;
if (opt.gzip || opt.brotli || opt.zstd) {
if ((opt.gzip ? 1 : 0) +
(opt.brotli ? 1 : 0) +
(opt.zstd ? 1 : 0) >
1) {
throw new TypeError('gzip, brotli, zstd are mutually exclusive');
}
if (opt.gzip) {
if (typeof opt.gzip !== 'object') {
opt.gzip = {};
}
if (this.portable) {
opt.gzip.portable = true;
}
this.zip = new zlib.Gzip(opt.gzip);
}
if (opt.brotli) {
if (typeof opt.brotli !== 'object') {
opt.brotli = {};
}
this.zip = new zlib.BrotliCompress(opt.brotli);
}
if (opt.zstd) {
if (typeof opt.zstd !== 'object') {
opt.zstd = {};
}
this.zip = new zlib.ZstdCompress(opt.zstd);
}
/* c8 ignore next */
if (!this.zip)
throw new Error('impossible');
const zip = this.zip;
zip.on('data', chunk => super.write(chunk));
zip.on('end', () => super.end());
zip.on('drain', () => this[ONDRAIN]());
this.on('resume', () => zip.resume());
}
else {
this.on('drain', this[ONDRAIN]);
}
this.noDirRecurse = !!opt.noDirRecurse;
this.follow = !!opt.follow;
this.noMtime = !!opt.noMtime;
if (opt.mtime)
this.mtime = opt.mtime;
this.filter =
typeof opt.filter === 'function' ? opt.filter : () => true;
this[QUEUE] = new yallist_1.Yallist();
this[JOBS] = 0;
this.jobs = Number(opt.jobs) || 4;
this[PROCESSING] = false;
this[ENDED] = false;
}
[WRITE](chunk) {
return super.write(chunk);
}
add(path) {
this.write(path);
return this;
}
end(path, encoding, cb) {
/* c8 ignore start */
if (typeof path === 'function') {
cb = path;
path = undefined;
}
if (typeof encoding === 'function') {
cb = encoding;
encoding = undefined;
}
/* c8 ignore stop */
if (path) {
this.add(path);
}
this[ENDED] = true;
this[PROCESS]();
/* c8 ignore next */
if (cb)
cb();
return this;
}
write(path) {
if (this[ENDED]) {
throw new Error('write after end');
}
if (path instanceof read_entry_js_1.ReadEntry) {
this[ADDTARENTRY](path);
}
else {
this[ADDFSENTRY](path);
}
return this.flowing;
}
[ADDTARENTRY](p) {
const absolute = (0, normalize_windows_path_js_1.normalizeWindowsPath)(path_1.default.resolve(this.cwd, p.path));
// in this case, we don't have to wait for the stat
if (!this.filter(p.path, p)) {
p.resume();
}
else {
const job = new PackJob(p.path, absolute);
job.entry = new write_entry_js_1.WriteEntryTar(p, this[ENTRYOPT](job));
job.entry.on('end', () => this[JOBDONE](job));
this[JOBS] += 1;
this[QUEUE].push(job);
}
this[PROCESS]();
}
[ADDFSENTRY](p) {
const absolute = (0, normalize_windows_path_js_1.normalizeWindowsPath)(path_1.default.resolve(this.cwd, p));
this[QUEUE].push(new PackJob(p, absolute));
this[PROCESS]();
}
[STAT](job) {
job.pending = true;
this[JOBS] += 1;
const stat = this.follow ? 'stat' : 'lstat';
fs_1.default[stat](job.absolute, (er, stat) => {
job.pending = false;
this[JOBS] -= 1;
if (er) {
this.emit('error', er);
}
else {
this[ONSTAT](job, stat);
}
});
}
[ONSTAT](job, stat) {
this.statCache.set(job.absolute, stat);
job.stat = stat;
// now we have the stat, we can filter it.
if (!this.filter(job.path, stat)) {
job.ignore = true;
}
this[PROCESS]();
}
[READDIR](job) {
job.pending = true;
this[JOBS] += 1;
fs_1.default.readdir(job.absolute, (er, entries) => {
job.pending = false;
this[JOBS] -= 1;
if (er) {
return this.emit('error', er);
}
this[ONREADDIR](job, entries);
});
}
[ONREADDIR](job, entries) {
this.readdirCache.set(job.absolute, entries);
job.readdir = entries;
this[PROCESS]();
}
[PROCESS]() {
if (this[PROCESSING]) {
return;
}
this[PROCESSING] = true;
for (let w = this[QUEUE].head; !!w && this[JOBS] < this.jobs; w = w.next) {
this[PROCESSJOB](w.value);
if (w.value.ignore) {
const p = w.next;
this[QUEUE].removeNode(w);
w.next = p;
}
}
this[PROCESSING] = false;
if (this[ENDED] && !this[QUEUE].length && this[JOBS] === 0) {
if (this.zip) {
this.zip.end(EOF);
}
else {
super.write(EOF);
super.end();
}
}
}
get [CURRENT]() {
return this[QUEUE] && this[QUEUE].head && this[QUEUE].head.value;
}
[JOBDONE](_job) {
this[QUEUE].shift();
this[JOBS] -= 1;
this[PROCESS]();
}
[PROCESSJOB](job) {
if (job.pending) {
return;
}
if (job.entry) {
if (job === this[CURRENT] && !job.piped) {
this[PIPE](job);
}
return;
}
if (!job.stat) {
const sc = this.statCache.get(job.absolute);
if (sc) {
this[ONSTAT](job, sc);
}
else {
this[STAT](job);
}
}
if (!job.stat) {
return;
}
// filtered out!
if (job.ignore) {
return;
}
if (!this.noDirRecurse &&
job.stat.isDirectory() &&
!job.readdir) {
const rc = this.readdirCache.get(job.absolute);
if (rc) {
this[ONREADDIR](job, rc);
}
else {
this[READDIR](job);
}
if (!job.readdir) {
return;
}
}
// we know it doesn't have an entry, because that got checked above
job.entry = this[ENTRY](job);
if (!job.entry) {
job.ignore = true;
return;
}
if (job === this[CURRENT] && !job.piped) {
this[PIPE](job);
}
}
[ENTRYOPT](job) {
return {
onwarn: (code, msg, data) => this.warn(code, msg, data),
noPax: this.noPax,
cwd: this.cwd,
absolute: job.absolute,
preservePaths: this.preservePaths,
maxReadSize: this.maxReadSize,
strict: this.strict,
portable: this.portable,
linkCache: this.linkCache,
statCache: this.statCache,
noMtime: this.noMtime,
mtime: this.mtime,
prefix: this.prefix,
onWriteEntry: this.onWriteEntry,
};
}
[ENTRY](job) {
this[JOBS] += 1;
try {
const e = new this[WRITEENTRYCLASS](job.path, this[ENTRYOPT](job));
return e
.on('end', () => this[JOBDONE](job))
.on('error', er => this.emit('error', er));
}
catch (er) {
this.emit('error', er);
}
}
[ONDRAIN]() {
if (this[CURRENT] && this[CURRENT].entry) {
this[CURRENT].entry.resume();
}
}
// like .pipe() but using super, because our write() is special
[PIPE](job) {
job.piped = true;
if (job.readdir) {
job.readdir.forEach(entry => {
const p = job.path;
const base = p === './' ? '' : p.replace(/\/*$/, '/');
this[ADDFSENTRY](base + entry);
});
}
const source = job.entry;
const zip = this.zip;
/* c8 ignore start */
if (!source)
throw new Error('cannot pipe without source');
/* c8 ignore stop */
if (zip) {
source.on('data', chunk => {
if (!zip.write(chunk)) {
source.pause();
}
});
}
else {
source.on('data', chunk => {
if (!super.write(chunk)) {
source.pause();
}
});
}
}
pause() {
if (this.zip) {
this.zip.pause();
}
return super.pause();
}
warn(code, message, data = {}) {
(0, warn_method_js_1.warnMethod)(this, code, message, data);
}
}
exports.Pack = Pack;
class PackSync extends Pack {
sync = true;
constructor(opt) {
super(opt);
this[WRITEENTRYCLASS] = write_entry_js_1.WriteEntrySync;
}
// pause/resume are no-ops in sync streams.
pause() { }
resume() { }
[STAT](job) {
const stat = this.follow ? 'statSync' : 'lstatSync';
this[ONSTAT](job, fs_1.default[stat](job.absolute));
}
[READDIR](job) {
this[ONREADDIR](job, fs_1.default.readdirSync(job.absolute));
}
// gotta get it all in this tick
[PIPE](job) {
const source = job.entry;
const zip = this.zip;
if (job.readdir) {
job.readdir.forEach(entry => {
const p = job.path;
const base = p === './' ? '' : p.replace(/\/*$/, '/');
this[ADDFSENTRY](base + entry);
});
}
/* c8 ignore start */
if (!source)
throw new Error('Cannot pipe without source');
/* c8 ignore stop */
if (zip) {
source.on('data', chunk => {
zip.write(chunk);
});
}
else {
source.on('data', chunk => {
super[WRITE](chunk);
});
}
}
}
exports.PackSync = PackSync;
//# sourceMappingURL=pack.js.map
File diff suppressed because one or more lines are too long
-3
View File
@@ -1,3 +0,0 @@
{
"type": "commonjs"
}
-88
View File
@@ -1,88 +0,0 @@
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
import { EventEmitter as EE } from 'events';
import { BrotliDecompress, Unzip, ZstdDecompress } from 'minizlib';
import { TarOptions } from './options.js';
import { Pax } from './pax.js';
import { ReadEntry } from './read-entry.js';
import { type WarnData, type Warner } from './warn-method.js';
declare const STATE: unique symbol;
declare const WRITEENTRY: unique symbol;
declare const READENTRY: unique symbol;
declare const NEXTENTRY: unique symbol;
declare const PROCESSENTRY: unique symbol;
declare const EX: unique symbol;
declare const GEX: unique symbol;
declare const META: unique symbol;
declare const EMITMETA: unique symbol;
declare const BUFFER: unique symbol;
declare const QUEUE: unique symbol;
declare const ENDED: unique symbol;
declare const EMITTEDEND: unique symbol;
declare const EMIT: unique symbol;
declare const UNZIP: unique symbol;
declare const CONSUMECHUNK: unique symbol;
declare const CONSUMECHUNKSUB: unique symbol;
declare const CONSUMEBODY: unique symbol;
declare const CONSUMEMETA: unique symbol;
declare const CONSUMEHEADER: unique symbol;
declare const CONSUMING: unique symbol;
declare const BUFFERCONCAT: unique symbol;
declare const MAYBEEND: unique symbol;
declare const WRITING: unique symbol;
declare const ABORTED: unique symbol;
declare const SAW_VALID_ENTRY: unique symbol;
declare const SAW_NULL_BLOCK: unique symbol;
declare const SAW_EOF: unique symbol;
declare const CLOSESTREAM: unique symbol;
export type State = 'begin' | 'header' | 'ignore' | 'meta' | 'body';
export declare class Parser extends EE implements Warner {
file: string;
strict: boolean;
maxMetaEntrySize: number;
filter: Exclude<TarOptions['filter'], undefined>;
brotli?: TarOptions['brotli'];
zstd?: TarOptions['zstd'];
writable: true;
readable: false;
[QUEUE]: (ReadEntry | [string | symbol, any, any])[];
[BUFFER]?: Buffer;
[READENTRY]?: ReadEntry;
[WRITEENTRY]?: ReadEntry;
[STATE]: State;
[META]: string;
[EX]?: Pax;
[GEX]?: Pax;
[ENDED]: boolean;
[UNZIP]?: false | Unzip | BrotliDecompress | ZstdDecompress;
[ABORTED]: boolean;
[SAW_VALID_ENTRY]?: boolean;
[SAW_NULL_BLOCK]: boolean;
[SAW_EOF]: boolean;
[WRITING]: boolean;
[CONSUMING]: boolean;
[EMITTEDEND]: boolean;
constructor(opt?: TarOptions);
warn(code: string, message: string | Error, data?: WarnData): void;
[CONSUMEHEADER](chunk: Buffer, position: number): void;
[CLOSESTREAM](): void;
[PROCESSENTRY](entry?: ReadEntry | [string | symbol, any, any]): boolean;
[NEXTENTRY](): void;
[CONSUMEBODY](chunk: Buffer, position: number): number;
[CONSUMEMETA](chunk: Buffer, position: number): number;
[EMIT](ev: string | symbol, data?: any, extra?: any): void;
[EMITMETA](entry: ReadEntry): void;
abort(error: Error): void;
write(buffer: Uint8Array | string, cb?: (err?: Error | null) => void): boolean;
write(str: string, encoding?: BufferEncoding, cb?: (err?: Error | null) => void): boolean;
[BUFFERCONCAT](c: Buffer): void;
[MAYBEEND](): void;
[CONSUMECHUNK](chunk?: Buffer): void;
[CONSUMECHUNKSUB](chunk: Buffer): void;
end(cb?: () => void): this;
end(data: string | Buffer, cb?: () => void): this;
end(str: string, encoding?: BufferEncoding, cb?: () => void): this;
}
export {};
//# sourceMappingURL=parse.d.ts.map
-1
View File
@@ -1 +0,0 @@
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/parse.ts"],"names":[],"mappings":"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"}
-620
View File
@@ -1,620 +0,0 @@
"use strict";
// this[BUFFER] is the remainder of a chunk if we're waiting for
// the full 512 bytes of a header to come in. We will Buffer.concat()
// it to the next write(), which is a mem copy, but a small one.
//
// this[QUEUE] is a list of entries that haven't been emitted
// yet this can only get filled up if the user keeps write()ing after
// a write() returns false, or does a write() with more than one entry
//
// We don't buffer chunks, we always parse them and either create an
// entry, or push it into the active entry. The ReadEntry class knows
// to throw data away if .ignore=true
//
// Shift entry off the buffer when it emits 'end', and emit 'entry' for
// the next one in the list.
//
// At any time, we're pushing body chunks into the entry at WRITEENTRY,
// and waiting for 'end' on the entry at READENTRY
//
// ignored entries get .resume() called on them straight away
Object.defineProperty(exports, "__esModule", { value: true });
exports.Parser = void 0;
const events_1 = require("events");
const minizlib_1 = require("minizlib");
const header_js_1 = require("./header.js");
const pax_js_1 = require("./pax.js");
const read_entry_js_1 = require("./read-entry.js");
const warn_method_js_1 = require("./warn-method.js");
const maxMetaEntrySize = 1024 * 1024;
const gzipHeader = Buffer.from([0x1f, 0x8b]);
const zstdHeader = Buffer.from([0x28, 0xb5, 0x2f, 0xfd]);
const ZIP_HEADER_LEN = Math.max(gzipHeader.length, zstdHeader.length);
const STATE = Symbol('state');
const WRITEENTRY = Symbol('writeEntry');
const READENTRY = Symbol('readEntry');
const NEXTENTRY = Symbol('nextEntry');
const PROCESSENTRY = Symbol('processEntry');
const EX = Symbol('extendedHeader');
const GEX = Symbol('globalExtendedHeader');
const META = Symbol('meta');
const EMITMETA = Symbol('emitMeta');
const BUFFER = Symbol('buffer');
const QUEUE = Symbol('queue');
const ENDED = Symbol('ended');
const EMITTEDEND = Symbol('emittedEnd');
const EMIT = Symbol('emit');
const UNZIP = Symbol('unzip');
const CONSUMECHUNK = Symbol('consumeChunk');
const CONSUMECHUNKSUB = Symbol('consumeChunkSub');
const CONSUMEBODY = Symbol('consumeBody');
const CONSUMEMETA = Symbol('consumeMeta');
const CONSUMEHEADER = Symbol('consumeHeader');
const CONSUMING = Symbol('consuming');
const BUFFERCONCAT = Symbol('bufferConcat');
const MAYBEEND = Symbol('maybeEnd');
const WRITING = Symbol('writing');
const ABORTED = Symbol('aborted');
const DONE = Symbol('onDone');
const SAW_VALID_ENTRY = Symbol('sawValidEntry');
const SAW_NULL_BLOCK = Symbol('sawNullBlock');
const SAW_EOF = Symbol('sawEOF');
const CLOSESTREAM = Symbol('closeStream');
const noop = () => true;
class Parser extends events_1.EventEmitter {
file;
strict;
maxMetaEntrySize;
filter;
brotli;
zstd;
writable = true;
readable = false;
[QUEUE] = [];
[BUFFER];
[READENTRY];
[WRITEENTRY];
[STATE] = 'begin';
[META] = '';
[EX];
[GEX];
[ENDED] = false;
[UNZIP];
[ABORTED] = false;
[SAW_VALID_ENTRY];
[SAW_NULL_BLOCK] = false;
[SAW_EOF] = false;
[WRITING] = false;
[CONSUMING] = false;
[EMITTEDEND] = false;
constructor(opt = {}) {
super();
this.file = opt.file || '';
// these BADARCHIVE errors can't be detected early. listen on DONE.
this.on(DONE, () => {
if (this[STATE] === 'begin' ||
this[SAW_VALID_ENTRY] === false) {
// either less than 1 block of data, or all entries were invalid.
// Either way, probably not even a tarball.
this.warn('TAR_BAD_ARCHIVE', 'Unrecognized archive format');
}
});
if (opt.ondone) {
this.on(DONE, opt.ondone);
}
else {
this.on(DONE, () => {
this.emit('prefinish');
this.emit('finish');
this.emit('end');
});
}
this.strict = !!opt.strict;
this.maxMetaEntrySize = opt.maxMetaEntrySize || maxMetaEntrySize;
this.filter = typeof opt.filter === 'function' ? opt.filter : noop;
// Unlike gzip, brotli doesn't have any magic bytes to identify it
// Users need to explicitly tell us they're extracting a brotli file
// Or we infer from the file extension
const isTBR = opt.file &&
(opt.file.endsWith('.tar.br') || opt.file.endsWith('.tbr'));
// if it's a tbr file it MIGHT be brotli, but we don't know until
// we look at it and verify it's not a valid tar file.
this.brotli =
!(opt.gzip || opt.zstd) && opt.brotli !== undefined ? opt.brotli
: isTBR ? undefined
: false;
// zstd has magic bytes to identify it, but we also support explicit options
// and file extension detection
const isTZST = opt.file &&
(opt.file.endsWith('.tar.zst') || opt.file.endsWith('.tzst'));
this.zstd =
!(opt.gzip || opt.brotli) && opt.zstd !== undefined ? opt.zstd
: isTZST ? true
: undefined;
// have to set this so that streams are ok piping into it
this.on('end', () => this[CLOSESTREAM]());
if (typeof opt.onwarn === 'function') {
this.on('warn', opt.onwarn);
}
if (typeof opt.onReadEntry === 'function') {
this.on('entry', opt.onReadEntry);
}
}
warn(code, message, data = {}) {
(0, warn_method_js_1.warnMethod)(this, code, message, data);
}
[CONSUMEHEADER](chunk, position) {
if (this[SAW_VALID_ENTRY] === undefined) {
this[SAW_VALID_ENTRY] = false;
}
let header;
try {
header = new header_js_1.Header(chunk, position, this[EX], this[GEX]);
}
catch (er) {
return this.warn('TAR_ENTRY_INVALID', er);
}
if (header.nullBlock) {
if (this[SAW_NULL_BLOCK]) {
this[SAW_EOF] = true;
// ending an archive with no entries. pointless, but legal.
if (this[STATE] === 'begin') {
this[STATE] = 'header';
}
this[EMIT]('eof');
}
else {
this[SAW_NULL_BLOCK] = true;
this[EMIT]('nullBlock');
}
}
else {
this[SAW_NULL_BLOCK] = false;
if (!header.cksumValid) {
this.warn('TAR_ENTRY_INVALID', 'checksum failure', { header });
}
else if (!header.path) {
this.warn('TAR_ENTRY_INVALID', 'path is required', { header });
}
else {
const type = header.type;
if (/^(Symbolic)?Link$/.test(type) && !header.linkpath) {
this.warn('TAR_ENTRY_INVALID', 'linkpath required', {
header,
});
}
else if (!/^(Symbolic)?Link$/.test(type) &&
!/^(Global)?ExtendedHeader$/.test(type) &&
header.linkpath) {
this.warn('TAR_ENTRY_INVALID', 'linkpath forbidden', {
header,
});
}
else {
const entry = (this[WRITEENTRY] = new read_entry_js_1.ReadEntry(header, this[EX], this[GEX]));
// we do this for meta & ignored entries as well, because they
// are still valid tar, or else we wouldn't know to ignore them
if (!this[SAW_VALID_ENTRY]) {
if (entry.remain) {
// this might be the one!
const onend = () => {
if (!entry.invalid) {
this[SAW_VALID_ENTRY] = true;
}
};
entry.on('end', onend);
}
else {
this[SAW_VALID_ENTRY] = true;
}
}
if (entry.meta) {
if (entry.size > this.maxMetaEntrySize) {
entry.ignore = true;
this[EMIT]('ignoredEntry', entry);
this[STATE] = 'ignore';
entry.resume();
}
else if (entry.size > 0) {
this[META] = '';
entry.on('data', c => (this[META] += c));
this[STATE] = 'meta';
}
}
else {
this[EX] = undefined;
entry.ignore =
entry.ignore || !this.filter(entry.path, entry);
if (entry.ignore) {
// probably valid, just not something we care about
this[EMIT]('ignoredEntry', entry);
this[STATE] = entry.remain ? 'ignore' : 'header';
entry.resume();
}
else {
if (entry.remain) {
this[STATE] = 'body';
}
else {
this[STATE] = 'header';
entry.end();
}
if (!this[READENTRY]) {
this[QUEUE].push(entry);
this[NEXTENTRY]();
}
else {
this[QUEUE].push(entry);
}
}
}
}
}
}
}
[CLOSESTREAM]() {
queueMicrotask(() => this.emit('close'));
}
[PROCESSENTRY](entry) {
let go = true;
if (!entry) {
this[READENTRY] = undefined;
go = false;
}
else if (Array.isArray(entry)) {
const [ev, ...args] = entry;
this.emit(ev, ...args);
}
else {
this[READENTRY] = entry;
this.emit('entry', entry);
if (!entry.emittedEnd) {
entry.on('end', () => this[NEXTENTRY]());
go = false;
}
}
return go;
}
[NEXTENTRY]() {
do { } while (this[PROCESSENTRY](this[QUEUE].shift()));
if (!this[QUEUE].length) {
// At this point, there's nothing in the queue, but we may have an
// entry which is being consumed (readEntry).
// If we don't, then we definitely can handle more data.
// If we do, and either it's flowing, or it has never had any data
// written to it, then it needs more.
// The only other possibility is that it has returned false from a
// write() call, so we wait for the next drain to continue.
const re = this[READENTRY];
const drainNow = !re || re.flowing || re.size === re.remain;
if (drainNow) {
if (!this[WRITING]) {
this.emit('drain');
}
}
else {
re.once('drain', () => this.emit('drain'));
}
}
}
[CONSUMEBODY](chunk, position) {
// write up to but no more than writeEntry.blockRemain
const entry = this[WRITEENTRY];
/* c8 ignore start */
if (!entry) {
throw new Error('attempt to consume body without entry??');
}
const br = entry.blockRemain ?? 0;
/* c8 ignore stop */
const c = br >= chunk.length && position === 0 ?
chunk
: chunk.subarray(position, position + br);
entry.write(c);
if (!entry.blockRemain) {
this[STATE] = 'header';
this[WRITEENTRY] = undefined;
entry.end();
}
return c.length;
}
[CONSUMEMETA](chunk, position) {
const entry = this[WRITEENTRY];
const ret = this[CONSUMEBODY](chunk, position);
// if we finished, then the entry is reset
if (!this[WRITEENTRY] && entry) {
this[EMITMETA](entry);
}
return ret;
}
[EMIT](ev, data, extra) {
if (!this[QUEUE].length && !this[READENTRY]) {
this.emit(ev, data, extra);
}
else {
this[QUEUE].push([ev, data, extra]);
}
}
[EMITMETA](entry) {
this[EMIT]('meta', this[META]);
switch (entry.type) {
case 'ExtendedHeader':
case 'OldExtendedHeader':
this[EX] = pax_js_1.Pax.parse(this[META], this[EX], false);
break;
case 'GlobalExtendedHeader':
this[GEX] = pax_js_1.Pax.parse(this[META], this[GEX], true);
break;
case 'NextFileHasLongPath':
case 'OldGnuLongPath': {
const ex = this[EX] ?? Object.create(null);
this[EX] = ex;
ex.path = this[META].replace(/\0.*/, '');
break;
}
case 'NextFileHasLongLinkpath': {
const ex = this[EX] || Object.create(null);
this[EX] = ex;
ex.linkpath = this[META].replace(/\0.*/, '');
break;
}
/* c8 ignore start */
default:
throw new Error('unknown meta: ' + entry.type);
/* c8 ignore stop */
}
}
abort(error) {
this[ABORTED] = true;
this.emit('abort', error);
// always throws, even in non-strict mode
this.warn('TAR_ABORT', error, { recoverable: false });
}
write(chunk, encoding, cb) {
if (typeof encoding === 'function') {
cb = encoding;
encoding = undefined;
}
if (typeof chunk === 'string') {
chunk = Buffer.from(chunk,
/* c8 ignore next */
typeof encoding === 'string' ? encoding : 'utf8');
}
if (this[ABORTED]) {
/* c8 ignore next */
cb?.();
return false;
}
// first write, might be gzipped, zstd, or brotli compressed
const needSniff = this[UNZIP] === undefined ||
(this.brotli === undefined && this[UNZIP] === false);
if (needSniff && chunk) {
if (this[BUFFER]) {
chunk = Buffer.concat([this[BUFFER], chunk]);
this[BUFFER] = undefined;
}
if (chunk.length < ZIP_HEADER_LEN) {
this[BUFFER] = chunk;
/* c8 ignore next */
cb?.();
return true;
}
// look for gzip header
for (let i = 0; this[UNZIP] === undefined && i < gzipHeader.length; i++) {
if (chunk[i] !== gzipHeader[i]) {
this[UNZIP] = false;
}
}
// look for zstd header if gzip header not found
let isZstd = false;
if (this[UNZIP] === false && this.zstd !== false) {
isZstd = true;
for (let i = 0; i < zstdHeader.length; i++) {
if (chunk[i] !== zstdHeader[i]) {
isZstd = false;
break;
}
}
}
const maybeBrotli = this.brotli === undefined && !isZstd;
if (this[UNZIP] === false && maybeBrotli) {
// read the first header to see if it's a valid tar file. If so,
// we can safely assume that it's not actually brotli, despite the
// .tbr or .tar.br file extension.
// if we ended before getting a full chunk, yes, def brotli
if (chunk.length < 512) {
if (this[ENDED]) {
this.brotli = true;
}
else {
this[BUFFER] = chunk;
/* c8 ignore next */
cb?.();
return true;
}
}
else {
// if it's tar, it's pretty reliably not brotli, chances of
// that happening are astronomical.
try {
new header_js_1.Header(chunk.subarray(0, 512));
this.brotli = false;
}
catch (_) {
this.brotli = true;
}
}
}
if (this[UNZIP] === undefined ||
(this[UNZIP] === false && (this.brotli || isZstd))) {
const ended = this[ENDED];
this[ENDED] = false;
this[UNZIP] =
this[UNZIP] === undefined ? new minizlib_1.Unzip({})
: isZstd ? new minizlib_1.ZstdDecompress({})
: new minizlib_1.BrotliDecompress({});
this[UNZIP].on('data', chunk => this[CONSUMECHUNK](chunk));
this[UNZIP].on('error', er => this.abort(er));
this[UNZIP].on('end', () => {
this[ENDED] = true;
this[CONSUMECHUNK]();
});
this[WRITING] = true;
const ret = !!this[UNZIP][ended ? 'end' : 'write'](chunk);
this[WRITING] = false;
cb?.();
return ret;
}
}
this[WRITING] = true;
if (this[UNZIP]) {
this[UNZIP].write(chunk);
}
else {
this[CONSUMECHUNK](chunk);
}
this[WRITING] = false;
// return false if there's a queue, or if the current entry isn't flowing
const ret = this[QUEUE].length ? false
: this[READENTRY] ? this[READENTRY].flowing
: true;
// if we have no queue, then that means a clogged READENTRY
if (!ret && !this[QUEUE].length) {
this[READENTRY]?.once('drain', () => this.emit('drain'));
}
/* c8 ignore next */
cb?.();
return ret;
}
[BUFFERCONCAT](c) {
if (c && !this[ABORTED]) {
this[BUFFER] =
this[BUFFER] ? Buffer.concat([this[BUFFER], c]) : c;
}
}
[MAYBEEND]() {
if (this[ENDED] &&
!this[EMITTEDEND] &&
!this[ABORTED] &&
!this[CONSUMING]) {
this[EMITTEDEND] = true;
const entry = this[WRITEENTRY];
if (entry && entry.blockRemain) {
// truncated, likely a damaged file
const have = this[BUFFER] ? this[BUFFER].length : 0;
this.warn('TAR_BAD_ARCHIVE', `Truncated input (needed ${entry.blockRemain} more bytes, only ${have} available)`, { entry });
if (this[BUFFER]) {
entry.write(this[BUFFER]);
}
entry.end();
}
this[EMIT](DONE);
}
}
[CONSUMECHUNK](chunk) {
if (this[CONSUMING] && chunk) {
this[BUFFERCONCAT](chunk);
}
else if (!chunk && !this[BUFFER]) {
this[MAYBEEND]();
}
else if (chunk) {
this[CONSUMING] = true;
if (this[BUFFER]) {
this[BUFFERCONCAT](chunk);
const c = this[BUFFER];
this[BUFFER] = undefined;
this[CONSUMECHUNKSUB](c);
}
else {
this[CONSUMECHUNKSUB](chunk);
}
while (this[BUFFER] &&
this[BUFFER]?.length >= 512 &&
!this[ABORTED] &&
!this[SAW_EOF]) {
const c = this[BUFFER];
this[BUFFER] = undefined;
this[CONSUMECHUNKSUB](c);
}
this[CONSUMING] = false;
}
if (!this[BUFFER] || this[ENDED]) {
this[MAYBEEND]();
}
}
[CONSUMECHUNKSUB](chunk) {
// we know that we are in CONSUMING mode, so anything written goes into
// the buffer. Advance the position and put any remainder in the buffer.
let position = 0;
const length = chunk.length;
while (position + 512 <= length &&
!this[ABORTED] &&
!this[SAW_EOF]) {
switch (this[STATE]) {
case 'begin':
case 'header':
this[CONSUMEHEADER](chunk, position);
position += 512;
break;
case 'ignore':
case 'body':
position += this[CONSUMEBODY](chunk, position);
break;
case 'meta':
position += this[CONSUMEMETA](chunk, position);
break;
/* c8 ignore start */
default:
throw new Error('invalid state: ' + this[STATE]);
/* c8 ignore stop */
}
}
if (position < length) {
if (this[BUFFER]) {
this[BUFFER] = Buffer.concat([
chunk.subarray(position),
this[BUFFER],
]);
}
else {
this[BUFFER] = chunk.subarray(position);
}
}
}
end(chunk, encoding, cb) {
if (typeof chunk === 'function') {
cb = chunk;
encoding = undefined;
chunk = undefined;
}
if (typeof encoding === 'function') {
cb = encoding;
encoding = undefined;
}
if (typeof chunk === 'string') {
chunk = Buffer.from(chunk, encoding);
}
if (cb)
this.once('finish', cb);
if (!this[ABORTED]) {
if (this[UNZIP]) {
/* c8 ignore start */
if (chunk)
this[UNZIP].write(chunk);
/* c8 ignore stop */
this[UNZIP].end();
}
else {
this[ENDED] = true;
if (this.brotli === undefined || this.zstd === undefined)
chunk = chunk || Buffer.alloc(0);
if (chunk)
this.write(chunk);
this[MAYBEEND]();
}
}
return this;
}
}
exports.Parser = Parser;
//# sourceMappingURL=parse.js.map
File diff suppressed because one or more lines are too long
@@ -1,11 +0,0 @@
export type Reservation = {
paths: string[];
dirs: Set<string>;
};
export type Handler = (clear: () => void) => void;
export declare class PathReservations {
#private;
reserve(paths: string[], fn: Handler): boolean;
check(fn: Handler): boolean;
}
//# sourceMappingURL=path-reservations.d.ts.map
@@ -1 +0,0 @@
{"version":3,"file":"path-reservations.d.ts","sourceRoot":"","sources":["../../src/path-reservations.ts"],"names":[],"mappings":"AAgBA,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE,MAAM,IAAI,KAAK,IAAI,CAAA;AAmBjD,qBAAa,gBAAgB;;IAY3B,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,OAAO;IAgEpC,KAAK,CAAC,EAAE,EAAE,OAAO;CA8ElB"}

Some files were not shown because too many files have changed in this diff Show More