fyn 3.2.3 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -31
- package/dist/fs-worker.mjs +5477 -0
- package/dist/fyn.mjs +1587 -487
- package/docs/reference.md +659 -0
- package/package.json +11 -8
package/dist/fyn.mjs
CHANGED
|
@@ -17,7 +17,7 @@ import os$1 from "os";
|
|
|
17
17
|
import * as util$5 from "util";
|
|
18
18
|
import Util from "util";
|
|
19
19
|
import EventEmitter$1, { EventEmitter, once } from "events";
|
|
20
|
-
import { fileURLToPath } from "node:url";
|
|
20
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
21
21
|
import Pr, { basename, join, posix, win32 } from "node:path";
|
|
22
22
|
import { pipeline } from "stream/promises";
|
|
23
23
|
import * as Fs from "node:fs";
|
|
@@ -30,13 +30,14 @@ import { Buffer as Buffer$1 } from "buffer";
|
|
|
30
30
|
import * as Ps$1 from "zlib";
|
|
31
31
|
import en from "zlib";
|
|
32
32
|
import co from "node:assert";
|
|
33
|
-
import { randomBytes } from "node:crypto";
|
|
33
|
+
import Crypto$1, { randomBytes } from "node:crypto";
|
|
34
34
|
import * as FsPromises from "node:fs/promises";
|
|
35
35
|
import ro from "node:fs/promises";
|
|
36
|
+
import { Worker } from "node:worker_threads";
|
|
36
37
|
import { URL as URL$1, fileURLToPath as fileURLToPath$1 } from "url";
|
|
37
38
|
import childProcess from "child_process";
|
|
38
39
|
import fs$1 from "fs/promises";
|
|
39
|
-
import { PassThrough } from "stream";
|
|
40
|
+
import { PassThrough, Readable } from "stream";
|
|
40
41
|
import * as dns from "dns";
|
|
41
42
|
import * as net$3 from "net";
|
|
42
43
|
import * as tls$1 from "tls";
|
|
@@ -680,7 +681,9 @@ var TimeoutRunner = class {
|
|
|
680
681
|
this.defer = makeDefer(options.Promise);
|
|
681
682
|
this.ThePromise = options.Promise;
|
|
682
683
|
this.TimeoutError = options.TimeoutError;
|
|
683
|
-
|
|
684
|
+
const msg = rejectMsg || "xaa TimeoutRunner operation timed out";
|
|
685
|
+
this.timeout = setTimeout(() => this.defer.reject(new this.TimeoutError(msg)), maxMs);
|
|
686
|
+
this.defer.promise.catch(() => {});
|
|
684
687
|
}
|
|
685
688
|
/**
|
|
686
689
|
* check if runner has failed with error
|
|
@@ -787,6 +790,19 @@ function createMapContext(array) {
|
|
|
787
790
|
};
|
|
788
791
|
}
|
|
789
792
|
/**
|
|
793
|
+
* attach partial results to a map error
|
|
794
|
+
*
|
|
795
|
+
* Thrown values can be primitives or frozen, so a failed assignment is ignored.
|
|
796
|
+
*
|
|
797
|
+
* @param err - the thrown value
|
|
798
|
+
* @param partial - results mapped so far
|
|
799
|
+
*/
|
|
800
|
+
function addPartial(err, partial) {
|
|
801
|
+
try {
|
|
802
|
+
err.partial = partial;
|
|
803
|
+
} catch (_a) {}
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
790
806
|
* async map for array that supports concurrency
|
|
791
807
|
*
|
|
792
808
|
* Use by xaa.map internally.
|
|
@@ -798,7 +814,7 @@ function createMapContext(array) {
|
|
|
798
814
|
*/
|
|
799
815
|
function multiMap(array, func, options) {
|
|
800
816
|
const awaited = new Array(array.length);
|
|
801
|
-
let
|
|
817
|
+
let failed = false;
|
|
802
818
|
let completedCount = 0;
|
|
803
819
|
let freeSlots = options.concurrency;
|
|
804
820
|
let index = 0;
|
|
@@ -808,15 +824,15 @@ function multiMap(array, func, options) {
|
|
|
808
824
|
const defer = makeDefer();
|
|
809
825
|
const fail = (err) => {
|
|
810
826
|
context.failed = true;
|
|
811
|
-
if (!
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
defer.reject(
|
|
827
|
+
if (!failed) {
|
|
828
|
+
failed = true;
|
|
829
|
+
addPartial(err, awaited);
|
|
830
|
+
defer.reject(err);
|
|
815
831
|
}
|
|
816
832
|
};
|
|
817
833
|
const mapNext = () => {
|
|
818
|
-
if (!
|
|
819
|
-
if (
|
|
834
|
+
if (!failed && completedCount === totalCount) return defer.resolve(awaited);
|
|
835
|
+
if (failed || freeSlots <= 0 || index >= totalCount) return null;
|
|
820
836
|
const ir = iterator && iterator.next();
|
|
821
837
|
/* c8 ignore next 7 */
|
|
822
838
|
if (ir && ir.done) {
|
|
@@ -840,15 +856,16 @@ function multiMap(array, func, options) {
|
|
|
840
856
|
return mapNext();
|
|
841
857
|
} else return save(res);
|
|
842
858
|
};
|
|
859
|
+
const callFunc = (val) => {
|
|
860
|
+
try {
|
|
861
|
+
return handleRet(func.call(options.thisArg, val, pendingIx, context));
|
|
862
|
+
} catch (err) {
|
|
863
|
+
return fail(err);
|
|
864
|
+
}
|
|
865
|
+
};
|
|
843
866
|
const item = ir ? ir.value : array[pendingIx];
|
|
844
|
-
if (isPromise$1(item)) return item.then(
|
|
845
|
-
|
|
846
|
-
}, fail);
|
|
847
|
-
else try {
|
|
848
|
-
return handleRet(func.call(options.thisArg, item, pendingIx, context));
|
|
849
|
-
} catch (err) {
|
|
850
|
-
return fail(err);
|
|
851
|
-
}
|
|
867
|
+
if (isPromise$1(item)) return item.then(callFunc, fail);
|
|
868
|
+
else return callFunc(item);
|
|
852
869
|
};
|
|
853
870
|
mapNext();
|
|
854
871
|
return defer.promise;
|
|
@@ -865,7 +882,7 @@ async function mapSeries(array, func, options) {
|
|
|
865
882
|
}
|
|
866
883
|
} catch (err) {
|
|
867
884
|
context.failed = true;
|
|
868
|
-
err
|
|
885
|
+
addPartial(err, awaited);
|
|
869
886
|
throw err;
|
|
870
887
|
}
|
|
871
888
|
return awaited;
|
|
@@ -1223,13 +1240,15 @@ function cleanErrorStack(error, { replacePath = `${process.cwd()}/`, ignorePathF
|
|
|
1223
1240
|
if (!stack) return String(stack);
|
|
1224
1241
|
return stack.split("\n").map((line) => {
|
|
1225
1242
|
if (!line.match(/ {4,}at/)) return line;
|
|
1226
|
-
const match = line.match(/( {4,}at)([
|
|
1227
|
-
|
|
1228
|
-
|
|
1243
|
+
const match = line.match(/( {4,}at )(?:([^(]*\()(.+)(\).*)|(.+))/);
|
|
1244
|
+
const [, at, name = "", location = match === null || match === void 0 ? void 0 : match[5], tail = ""] = match || [];
|
|
1245
|
+
if (!location || !location.match(/[^:]+:\/\//) && !Path.isAbsolute(location)) return false;
|
|
1246
|
+
const path = location.replace(/\\/g, "/");
|
|
1229
1247
|
if (defaultPathFilter.concat(ignorePathFilter).find((s) => s && (s instanceof RegExp ? path.match(s) : path.includes(s)))) return false;
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1248
|
+
let path2 = path;
|
|
1249
|
+
if (replacePath && replacePath.length > 1) path2 = path.startsWith(`file://${replacePath}`) ? path.slice(`file://${replacePath}`.length) : path.replace(replacePath, "");
|
|
1250
|
+
return `${at}${name}${path2}${tail}`;
|
|
1251
|
+
}).filter((x) => x !== false).join("\n");
|
|
1233
1252
|
}
|
|
1234
1253
|
/**
|
|
1235
1254
|
* Build stack of aggregate errors
|
|
@@ -1250,16 +1269,17 @@ function aggregateStack(stack, errors) {
|
|
|
1250
1269
|
* @returns aggregate stack
|
|
1251
1270
|
*/
|
|
1252
1271
|
function aggregateErrorStack(error) {
|
|
1253
|
-
return aggregateStack(error.__stack || error.message || String(error), error.errors);
|
|
1272
|
+
return aggregateStack(error.__stack || (error instanceof AggregateError$1 ? "" : error.stack) || error.message || String(error), error.errors);
|
|
1254
1273
|
}
|
|
1255
1274
|
/**
|
|
1256
1275
|
* AggregateError
|
|
1257
1276
|
* - https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-aggregate-error-objects
|
|
1258
1277
|
*/
|
|
1259
1278
|
var AggregateError$1 = class extends globalThis.AggregateError {
|
|
1260
|
-
constructor(errors, msg) {
|
|
1279
|
+
constructor(errors, msg, options) {
|
|
1261
1280
|
if (!errors || !(errors[Symbol.iterator] instanceof Function)) throw new TypeError(`input errors must be iterable but it's ${typeof errors}`);
|
|
1262
|
-
|
|
1281
|
+
const list = Array.from(errors);
|
|
1282
|
+
super(list, msg, options);
|
|
1263
1283
|
Object.defineProperty(this, "name", { value: "AggregateError" });
|
|
1264
1284
|
let aggStack;
|
|
1265
1285
|
Object.defineProperties(this, {
|
|
@@ -1267,7 +1287,7 @@ var AggregateError$1 = class extends globalThis.AggregateError {
|
|
|
1267
1287
|
configurable: true,
|
|
1268
1288
|
enumerable: false,
|
|
1269
1289
|
writable: true,
|
|
1270
|
-
value:
|
|
1290
|
+
value: list
|
|
1271
1291
|
},
|
|
1272
1292
|
__stack: {
|
|
1273
1293
|
enumerable: false,
|
|
@@ -1540,6 +1560,22 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1540
1560
|
constructor(executor) {
|
|
1541
1561
|
super(executor);
|
|
1542
1562
|
}
|
|
1563
|
+
catch(...args) {
|
|
1564
|
+
if (args.length <= 1) return super.catch(args[0]);
|
|
1565
|
+
const handler = args.pop();
|
|
1566
|
+
if (typeof handler !== "function") throw new TypeError("The last argument to .catch() must be a function, got " + String(handler));
|
|
1567
|
+
const filters = args;
|
|
1568
|
+
return super.catch((err) => {
|
|
1569
|
+
for (const f of filters) if (f === Error || f != null && f.prototype instanceof Error) {
|
|
1570
|
+
if (err instanceof f) return handler(err);
|
|
1571
|
+
} else if (typeof f === "function") {
|
|
1572
|
+
if (f(err)) return handler(err);
|
|
1573
|
+
} else if (err !== null && (typeof err === "object" || typeof err === "function")) {
|
|
1574
|
+
if (Object.keys(f).every((k) => f[k] == err[k])) return handler(err);
|
|
1575
|
+
}
|
|
1576
|
+
throw err;
|
|
1577
|
+
});
|
|
1578
|
+
}
|
|
1543
1579
|
/**
|
|
1544
1580
|
* Bluebird-style tap() method that lets you perform side effects in a chain
|
|
1545
1581
|
* Similar to Bluebird's Promise.prototype.tap()
|
|
@@ -1559,7 +1595,16 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1559
1595
|
* @returns Promise that resolves with the filtered array
|
|
1560
1596
|
*/
|
|
1561
1597
|
filter(fn) {
|
|
1562
|
-
return this.then((value) =>
|
|
1598
|
+
return this.then(async (value) => {
|
|
1599
|
+
const arr = toArray$1(value);
|
|
1600
|
+
const len = arr.length;
|
|
1601
|
+
const result = [];
|
|
1602
|
+
for (let i = 0; i < len; i++) {
|
|
1603
|
+
const x = isPromise(arr[i]) ? await arr[i] : arr[i];
|
|
1604
|
+
if (await fn(x, i, len)) result.push(x);
|
|
1605
|
+
}
|
|
1606
|
+
return result;
|
|
1607
|
+
});
|
|
1563
1608
|
}
|
|
1564
1609
|
/**
|
|
1565
1610
|
* Bluebird-style map() method for array operations
|
|
@@ -1568,7 +1613,11 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1568
1613
|
* @returns Promise that resolves with the mapped array
|
|
1569
1614
|
*/
|
|
1570
1615
|
map(fn, options = { concurrency: 50 }) {
|
|
1571
|
-
return this.then((value) =>
|
|
1616
|
+
return this.then((value) => {
|
|
1617
|
+
const arr = toArray$1(value);
|
|
1618
|
+
const len = arr.length;
|
|
1619
|
+
return map$1(arr, (item, index) => fn(item, index, len), options);
|
|
1620
|
+
});
|
|
1572
1621
|
}
|
|
1573
1622
|
/**
|
|
1574
1623
|
* Bluebird-style mapSeries() method for array operations
|
|
@@ -1605,7 +1654,7 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1605
1654
|
*/
|
|
1606
1655
|
each(fn) {
|
|
1607
1656
|
return this.then(async (value) => {
|
|
1608
|
-
const arr = value;
|
|
1657
|
+
const arr = toArray$1(value);
|
|
1609
1658
|
const result = [];
|
|
1610
1659
|
for (let i = 0; i < arr.length; i++) {
|
|
1611
1660
|
let x = arr[i];
|
|
@@ -1675,7 +1724,7 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1675
1724
|
reduce(fn, initialValue) {
|
|
1676
1725
|
const hasInitial = arguments.length > 1;
|
|
1677
1726
|
return this.then(async (array) => {
|
|
1678
|
-
const arr = array;
|
|
1727
|
+
const arr = toArray$1(array);
|
|
1679
1728
|
const len = arr.length;
|
|
1680
1729
|
let value;
|
|
1681
1730
|
let idx;
|
|
@@ -1750,8 +1799,9 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1750
1799
|
if (typeof fn !== "function") return AveAzul.reject(/* @__PURE__ */ new TypeError("expecting a function but got " + fn));
|
|
1751
1800
|
return this.then(async (args) => {
|
|
1752
1801
|
if (Array.isArray(args)) {
|
|
1753
|
-
|
|
1754
|
-
|
|
1802
|
+
const values = args.slice();
|
|
1803
|
+
for (let i = 0; i < values.length; i++) if (isPromise(values[i])) values[i] = await values[i];
|
|
1804
|
+
return fn(...values);
|
|
1755
1805
|
} else return fn(args);
|
|
1756
1806
|
});
|
|
1757
1807
|
}
|
|
@@ -1931,6 +1981,15 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1931
1981
|
return AveAzul.resolve(items).each(fn);
|
|
1932
1982
|
}
|
|
1933
1983
|
/**
|
|
1984
|
+
* Bluebird-style filter() for array filtering
|
|
1985
|
+
* @param items - Array or iterable to filter
|
|
1986
|
+
* @param fn - Filter function (item, index, length)
|
|
1987
|
+
* @returns Promise that resolves with the items that passed the filter
|
|
1988
|
+
*/
|
|
1989
|
+
static filter(items, fn) {
|
|
1990
|
+
return AveAzul.resolve(items).filter(fn);
|
|
1991
|
+
}
|
|
1992
|
+
/**
|
|
1934
1993
|
* Bluebird-style reduce() for array reduction
|
|
1935
1994
|
* @param array - Array to reduce
|
|
1936
1995
|
* @param fn - Reducer function (value, item, index, length)
|
|
@@ -1990,7 +2049,7 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1990
2049
|
* @returns Promise that resolves with handler result
|
|
1991
2050
|
*/
|
|
1992
2051
|
static using(resources, ...args) {
|
|
1993
|
-
if (args.length === 0) throw new TypeError("
|
|
2052
|
+
if (args.length === 0) throw new TypeError("resources and handler function required");
|
|
1994
2053
|
if (Array.isArray(resources)) {
|
|
1995
2054
|
if (args.length > 1) throw new TypeError("only two arguments are allowed when passing an array of resources");
|
|
1996
2055
|
return using(resources, args[0], AveAzul, true);
|
|
@@ -2118,7 +2177,7 @@ var require_signal_exit = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
2118
2177
|
/* istanbul ignore if */
|
|
2119
2178
|
if (!processOk(global.process)) return function() {};
|
|
2120
2179
|
assert$3.equal(typeof cb, "function", "a callback must be provided for exit handler");
|
|
2121
|
-
if (loaded === false) load$
|
|
2180
|
+
if (loaded === false) load$2();
|
|
2122
2181
|
var ev = "exit";
|
|
2123
2182
|
if (opts && opts.alwaysLast) ev = "afterexit";
|
|
2124
2183
|
var remove = function() {
|
|
@@ -2168,7 +2227,7 @@ var require_signal_exit = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
2168
2227
|
return signals$1;
|
|
2169
2228
|
};
|
|
2170
2229
|
var loaded = false;
|
|
2171
|
-
var load$
|
|
2230
|
+
var load$2 = function load() {
|
|
2172
2231
|
if (loaded || !processOk(global.process)) return;
|
|
2173
2232
|
loaded = true;
|
|
2174
2233
|
emitter.count += 1;
|
|
@@ -2183,7 +2242,7 @@ var require_signal_exit = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
2183
2242
|
process.emit = processEmit;
|
|
2184
2243
|
process.reallyExit = processReallyExit;
|
|
2185
2244
|
};
|
|
2186
|
-
module.exports.load = load$
|
|
2245
|
+
module.exports.load = load$2;
|
|
2187
2246
|
var originalProcessReallyExit = process.reallyExit;
|
|
2188
2247
|
var processReallyExit = function processReallyExit(code) {
|
|
2189
2248
|
/* istanbul ignore if */
|
|
@@ -21628,7 +21687,7 @@ var SignalExit = class extends SignalExitBase {
|
|
|
21628
21687
|
}
|
|
21629
21688
|
};
|
|
21630
21689
|
const process$3 = globalThis.process;
|
|
21631
|
-
const { onExit, load, unload } = signalExitWrap(processOk(process$3) ? new SignalExit(process$3) : new SignalExitFallback());
|
|
21690
|
+
const { onExit, load: load$1, unload } = signalExitWrap(processOk(process$3) ? new SignalExit(process$3) : new SignalExitFallback());
|
|
21632
21691
|
|
|
21633
21692
|
//#endregion
|
|
21634
21693
|
//#region node_modules/restore-cursor/index.js
|
|
@@ -24034,11 +24093,16 @@ const LogItemTypes = {
|
|
|
24034
24093
|
none: 0
|
|
24035
24094
|
};
|
|
24036
24095
|
const DEFAULT_SPINNER_INTERVAL = 100;
|
|
24096
|
+
function levelValue(level) {
|
|
24097
|
+
if (!Object.prototype.hasOwnProperty.call(Levels, level)) throw new TypeError(`VisualLogger unknown log level: ${String(level)}`);
|
|
24098
|
+
return Levels[level];
|
|
24099
|
+
}
|
|
24037
24100
|
const SPIN_OFF = 0;
|
|
24038
24101
|
const SPIN_STARTED = 1;
|
|
24039
24102
|
const SPIN_RUNNING = 2;
|
|
24040
24103
|
var VisualLogger = class VisualLogger {
|
|
24041
24104
|
constructor(options = {}) {
|
|
24105
|
+
var _a;
|
|
24042
24106
|
options = {
|
|
24043
24107
|
renderFps: 30,
|
|
24044
24108
|
...options
|
|
@@ -24047,7 +24111,7 @@ var VisualLogger = class VisualLogger {
|
|
|
24047
24111
|
this._items = [];
|
|
24048
24112
|
this._itemOptions = {};
|
|
24049
24113
|
this._lines = [];
|
|
24050
|
-
this._logLevel =
|
|
24114
|
+
this._logLevel = levelValue((_a = options.logLevel) !== null && _a !== void 0 ? _a : "info");
|
|
24051
24115
|
this._itemType = LogItemTypes.normal;
|
|
24052
24116
|
this._logData = [];
|
|
24053
24117
|
this._output = options.output || defaultOutput$1;
|
|
@@ -24076,6 +24140,12 @@ var VisualLogger = class VisualLogger {
|
|
|
24076
24140
|
this._color = enable;
|
|
24077
24141
|
this.setPrefix();
|
|
24078
24142
|
}
|
|
24143
|
+
get logLevel() {
|
|
24144
|
+
return Object.keys(Levels).find((k) => Levels[k] === this._logLevel);
|
|
24145
|
+
}
|
|
24146
|
+
set logLevel(level) {
|
|
24147
|
+
this._logLevel = levelValue(level);
|
|
24148
|
+
}
|
|
24079
24149
|
static get spinners() {
|
|
24080
24150
|
return [
|
|
24081
24151
|
"|/-\\",
|
|
@@ -24210,7 +24280,10 @@ var VisualLogger = class VisualLogger {
|
|
|
24210
24280
|
this._renderLineMsg(options, data);
|
|
24211
24281
|
const updateData = typeof data === "string" ? {} : data;
|
|
24212
24282
|
if (options.save !== false && updateData._save !== false) this._save(options._msg);
|
|
24213
|
-
if (updateData._render === false)
|
|
24283
|
+
if (updateData._render === false) {
|
|
24284
|
+
this._lines[itemIdx] = this._shouldLogItem() ? this._renderLine(options) : options._msg;
|
|
24285
|
+
return this;
|
|
24286
|
+
}
|
|
24214
24287
|
}
|
|
24215
24288
|
if (this._shouldLogItem()) {
|
|
24216
24289
|
if (data === void 0 && !this._nextSpin(options)) return this;
|
|
@@ -26695,6 +26768,7 @@ var InflightStore = class {
|
|
|
26695
26768
|
//#endregion
|
|
26696
26769
|
//#region node_modules/item-queue/dist/item-queue.js
|
|
26697
26770
|
const PAUSE_ITEM = Symbol("pause");
|
|
26771
|
+
const PAUSE_CALL = Symbol("pauseCall");
|
|
26698
26772
|
const RESUME_ITEM = Symbol("resume");
|
|
26699
26773
|
const NOOP_ITEM = Symbol("NOOP");
|
|
26700
26774
|
const WATCH_PERIOD = 500;
|
|
@@ -26705,6 +26779,8 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
26705
26779
|
constructor(options) {
|
|
26706
26780
|
assert(options && typeof options.processItem === "function", "ItemQueue: must provide options.processItem callback");
|
|
26707
26781
|
super();
|
|
26782
|
+
/** bumped by an immediate pause(), so a resume() tick scheduled earlier skips itself */
|
|
26783
|
+
this._pauseSeq = 0;
|
|
26708
26784
|
this.Promise = options.Promise || ItemQueue.Promise;
|
|
26709
26785
|
assert(this.Promise, "ItemQueue: No Promise implementation available");
|
|
26710
26786
|
this._pending = new InflightStore();
|
|
@@ -26714,7 +26790,7 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
26714
26790
|
this._processItem = options.processItem;
|
|
26715
26791
|
this._stopOnError = options.stopOnError;
|
|
26716
26792
|
this._failed = false;
|
|
26717
|
-
this._timeout = options.timeout;
|
|
26793
|
+
this._timeout = options.timeout > 0 ? options.timeout : 0;
|
|
26718
26794
|
this._watchPeriod = options.watchPeriod || WATCH_PERIOD;
|
|
26719
26795
|
this._watchTime = options.watchTime;
|
|
26720
26796
|
this._id = 1;
|
|
@@ -26731,19 +26807,18 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
26731
26807
|
* @returns promise that wait for queue to finish
|
|
26732
26808
|
*/
|
|
26733
26809
|
wait() {
|
|
26734
|
-
if (this._failed) return this.Promise.reject(this.
|
|
26810
|
+
if (this._failed) return this.Promise.reject(this._failError);
|
|
26735
26811
|
if (this.isPending) return new this.Promise((resolve, reject) => {
|
|
26736
|
-
const
|
|
26737
|
-
|
|
26738
|
-
|
|
26739
|
-
|
|
26740
|
-
|
|
26741
|
-
|
|
26742
|
-
|
|
26743
|
-
}
|
|
26812
|
+
const onDone = (data) => {
|
|
26813
|
+
this.removeListener("fail", onFail);
|
|
26814
|
+
resolve(data);
|
|
26815
|
+
};
|
|
26816
|
+
const onFail = (data) => {
|
|
26817
|
+
this.removeListener("done", onDone);
|
|
26818
|
+
reject(data.error);
|
|
26744
26819
|
};
|
|
26745
|
-
this.once("done",
|
|
26746
|
-
this.once("fail",
|
|
26820
|
+
this.once("done", onDone);
|
|
26821
|
+
this.once("fail", onFail);
|
|
26747
26822
|
});
|
|
26748
26823
|
return this.Promise.resolve();
|
|
26749
26824
|
}
|
|
@@ -26831,7 +26906,15 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
26831
26906
|
* @returns instance self
|
|
26832
26907
|
*/
|
|
26833
26908
|
pause() {
|
|
26834
|
-
this._itemQ.unshift(
|
|
26909
|
+
if (this._processing || !this._pending.isEmpty) this._itemQ.unshift({
|
|
26910
|
+
item: void 0,
|
|
26911
|
+
_control: PAUSE_CALL
|
|
26912
|
+
});
|
|
26913
|
+
else {
|
|
26914
|
+
this._pause = true;
|
|
26915
|
+
this._pauseSeq++;
|
|
26916
|
+
process.nextTick(() => this.emit("pause"));
|
|
26917
|
+
}
|
|
26835
26918
|
return this;
|
|
26836
26919
|
}
|
|
26837
26920
|
/**
|
|
@@ -26854,7 +26937,10 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
26854
26937
|
* @returns instance self
|
|
26855
26938
|
*/
|
|
26856
26939
|
resume() {
|
|
26940
|
+
this._itemQ = this._itemQ.filter((x) => x._control !== PAUSE_CALL);
|
|
26941
|
+
const pauseSeq = this._pauseSeq;
|
|
26857
26942
|
process.nextTick(() => {
|
|
26943
|
+
if (pauseSeq !== this._pauseSeq) return;
|
|
26858
26944
|
this.unpause();
|
|
26859
26945
|
if (this._itemQ.length === 0) this._itemQ.push(this._wrap(RESUME_ITEM));
|
|
26860
26946
|
this._process();
|
|
@@ -26872,7 +26958,7 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
26872
26958
|
return this.resume();
|
|
26873
26959
|
}
|
|
26874
26960
|
_wrap(item, stopOnError) {
|
|
26875
|
-
if (
|
|
26961
|
+
if (item === PAUSE_ITEM || item === RESUME_ITEM) return {
|
|
26876
26962
|
item: void 0,
|
|
26877
26963
|
_control: item
|
|
26878
26964
|
};
|
|
@@ -26884,14 +26970,15 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
26884
26970
|
_emit(evt, data) {
|
|
26885
26971
|
this.emit(evt, data);
|
|
26886
26972
|
}
|
|
26887
|
-
_handleQueueItemDone(data) {
|
|
26973
|
+
_handleQueueItemDone(data, failed) {
|
|
26888
26974
|
if (data.id > 0) this._pending.remove(data.id);
|
|
26889
26975
|
if (this._failed) return;
|
|
26890
26976
|
if (!data._control && data.id > 0) {
|
|
26891
|
-
if (
|
|
26977
|
+
if (failed) {
|
|
26892
26978
|
this._emit("failItem", data);
|
|
26893
26979
|
if (data.stopOnError !== false && this._stopOnError) {
|
|
26894
|
-
this._failed =
|
|
26980
|
+
this._failed = true;
|
|
26981
|
+
this._failError = data.error;
|
|
26895
26982
|
this._emit("fail", data);
|
|
26896
26983
|
return;
|
|
26897
26984
|
}
|
|
@@ -26963,25 +27050,60 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
26963
27050
|
}
|
|
26964
27051
|
this._watchTimer = setTimeout(() => this._pendingWatcher(), this._watchPeriod).unref();
|
|
26965
27052
|
}
|
|
27053
|
+
/**
|
|
27054
|
+
* Fail the item if it doesn't settle within `options.timeout`. The first outcome wins,
|
|
27055
|
+
* so a result that arrives after the timeout is ignored.
|
|
27056
|
+
*/
|
|
27057
|
+
_withTimeout(promise, abort) {
|
|
27058
|
+
return new this.Promise((resolve, reject) => {
|
|
27059
|
+
const timer = setTimeout(() => {
|
|
27060
|
+
const error = Object.assign(/* @__PURE__ */ new Error(`item-queue: item timed out after ${this._timeout}ms`), { code: "ETIMEDOUT" });
|
|
27061
|
+
abort.abort(error);
|
|
27062
|
+
reject(error);
|
|
27063
|
+
}, this._timeout);
|
|
27064
|
+
promise.then((res) => {
|
|
27065
|
+
clearTimeout(timer);
|
|
27066
|
+
resolve(res);
|
|
27067
|
+
}, (err) => {
|
|
27068
|
+
clearTimeout(timer);
|
|
27069
|
+
reject(err);
|
|
27070
|
+
});
|
|
27071
|
+
});
|
|
27072
|
+
}
|
|
26966
27073
|
_setupWatch() {
|
|
26967
27074
|
if (!this._watchTimer && this._watchTime) process.nextTick(() => this._pendingWatcher());
|
|
26968
27075
|
}
|
|
27076
|
+
/**
|
|
27077
|
+
* A failed queue never runs queued items. Report each one as a failed item
|
|
27078
|
+
* with the queue's error, so callers waiting on a `failItem` don't hang.
|
|
27079
|
+
*/
|
|
27080
|
+
_failQueued() {
|
|
27081
|
+
const queued = this._itemQ;
|
|
27082
|
+
this._itemQ = [];
|
|
27083
|
+
for (const wrapped of queued) if (!wrapped._control) this._emit("failItem", {
|
|
27084
|
+
id: this._id++,
|
|
27085
|
+
error: this._failError,
|
|
27086
|
+
...wrapped
|
|
27087
|
+
});
|
|
27088
|
+
return 0;
|
|
27089
|
+
}
|
|
26969
27090
|
_process() {
|
|
26970
27091
|
if (this._startTime === void 0) this._startTime = Date.now();
|
|
27092
|
+
if (this._failed) return this._failQueued();
|
|
26971
27093
|
if (this._processing || this._pause || this._itemQ.length === 0) return 0;
|
|
26972
27094
|
this._processing = true;
|
|
26973
27095
|
let count = 0;
|
|
26974
27096
|
let i = this._pending.count;
|
|
26975
27097
|
for (; this._itemQ.length > 0 && i < this._concurrency; i++) {
|
|
26976
27098
|
const wrapped = this._itemQ.shift();
|
|
26977
|
-
if (wrapped._control === PAUSE_ITEM) {
|
|
27099
|
+
if (wrapped._control === PAUSE_ITEM || wrapped._control === PAUSE_CALL) {
|
|
26978
27100
|
this._pause = true;
|
|
26979
27101
|
if (this._pending.isEmpty) process.nextTick(() => {
|
|
26980
27102
|
this._handleQueueItemDone({
|
|
26981
27103
|
id: 0,
|
|
26982
27104
|
item: void 0,
|
|
26983
27105
|
_control: NOOP_ITEM
|
|
26984
|
-
});
|
|
27106
|
+
}, false);
|
|
26985
27107
|
});
|
|
26986
27108
|
break;
|
|
26987
27109
|
}
|
|
@@ -26989,12 +27111,16 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
26989
27111
|
const id = this._id++;
|
|
26990
27112
|
let promise;
|
|
26991
27113
|
if (wrapped._control === RESUME_ITEM) promise = this.Promise.resolve({});
|
|
26992
|
-
else
|
|
26993
|
-
const
|
|
26994
|
-
|
|
26995
|
-
|
|
26996
|
-
|
|
26997
|
-
|
|
27114
|
+
else {
|
|
27115
|
+
const abort = this._timeout ? new AbortController() : void 0;
|
|
27116
|
+
try {
|
|
27117
|
+
const res = this._processItem(wrapped.item, id, abort === null || abort === void 0 ? void 0 : abort.signal);
|
|
27118
|
+
if (res && res.then) promise = res;
|
|
27119
|
+
else promise = this.Promise.resolve(res);
|
|
27120
|
+
} catch (err) {
|
|
27121
|
+
promise = this.Promise.reject(err);
|
|
27122
|
+
}
|
|
27123
|
+
if (abort) promise = this._withTimeout(promise, abort);
|
|
26998
27124
|
}
|
|
26999
27125
|
this._pending.add(id, {
|
|
27000
27126
|
item: wrapped.item,
|
|
@@ -27002,12 +27128,12 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
27002
27128
|
id,
|
|
27003
27129
|
res,
|
|
27004
27130
|
...wrapped
|
|
27005
|
-
}), (error) => {
|
|
27131
|
+
}, false), (error) => {
|
|
27006
27132
|
this._handleQueueItemDone({
|
|
27007
27133
|
id,
|
|
27008
27134
|
error,
|
|
27009
27135
|
...wrapped
|
|
27010
|
-
});
|
|
27136
|
+
}, true);
|
|
27011
27137
|
})
|
|
27012
27138
|
});
|
|
27013
27139
|
}
|
|
@@ -27192,7 +27318,7 @@ function makeExtrasData(file, fullFile, path, stat, files, options) {
|
|
|
27192
27318
|
* @param extras
|
|
27193
27319
|
*/
|
|
27194
27320
|
function addResult(result, options, extras) {
|
|
27195
|
-
const group =
|
|
27321
|
+
const group = options.grouping && (typeof result === "string" ? result : result.group) || "files";
|
|
27196
27322
|
if (!options.result[group]) options.result[group] = [];
|
|
27197
27323
|
if (result.formatName !== void 0) options.result[group].push(result.formatName);
|
|
27198
27324
|
else options.result[group].push(options.prependCwd ? extras.fullFile : extras.dirFile);
|
|
@@ -27234,10 +27360,10 @@ function processFile(options, extras) {
|
|
|
27234
27360
|
}
|
|
27235
27361
|
return false;
|
|
27236
27362
|
}
|
|
27237
|
-
function acceptEntry(options, entry, path, gitignore) {
|
|
27363
|
+
function acceptEntry(options, entry, path, gitignore, fsPath) {
|
|
27238
27364
|
const isDirectory = entry.isDirectory();
|
|
27239
27365
|
if (isDirectory && options._ignoreDirs.has(entry.name)) return false;
|
|
27240
|
-
if (gitignore === null || gitignore === void 0 ? void 0 : gitignore.ignores(Path.resolve(options.dir,
|
|
27366
|
+
if (gitignore === null || gitignore === void 0 ? void 0 : gitignore.ignores(Path.resolve(options.dir, fsPath, entry.name), isDirectory)) return false;
|
|
27241
27367
|
if (options.prefilter && !options.prefilter(entry.name, path, entry)) return false;
|
|
27242
27368
|
if (isDirectory) return true;
|
|
27243
27369
|
if (options.ignoreExt.length || options.filterExt.length) {
|
|
@@ -27280,7 +27406,7 @@ function releaseDirectory(options) {
|
|
|
27280
27406
|
* @param level
|
|
27281
27407
|
* @returns
|
|
27282
27408
|
*/
|
|
27283
|
-
async function walk(path, options, level = 0, parentRules) {
|
|
27409
|
+
async function walk(path, options, level = 0, parentRules, fsPath = path) {
|
|
27284
27410
|
let promises = [];
|
|
27285
27411
|
let hasSlot = false;
|
|
27286
27412
|
try {
|
|
@@ -27290,7 +27416,9 @@ async function walk(path, options, level = 0, parentRules) {
|
|
|
27290
27416
|
hasSlot = true;
|
|
27291
27417
|
}
|
|
27292
27418
|
if (options._stopped) return void 0;
|
|
27293
|
-
const dir = Path.join(options.dir,
|
|
27419
|
+
const dir = Path.join(options.dir, fsPath);
|
|
27420
|
+
const posixSep = options._sep === "/";
|
|
27421
|
+
const outDir = posixSep ? dir : join2(options._sep, options._outCwd, path);
|
|
27294
27422
|
const gitignore = options.gitignore ? await GitignoreRules.load(Path.resolve(dir), options.gitignore, parentRules) : void 0;
|
|
27295
27423
|
let files = await asyncReaddir(dir, options.readdirOpts);
|
|
27296
27424
|
if (options.sortFiles) {
|
|
@@ -27301,16 +27429,16 @@ async function walk(path, options, level = 0, parentRules) {
|
|
|
27301
27429
|
const extrasFiles = options.fullStat && options._earlyFilter && (options.filter || options.filterDir) ? files.map((entry) => entry.name) : files;
|
|
27302
27430
|
for (let ix = 0; !options._stopped && ix < files.length; ix++) {
|
|
27303
27431
|
const file = files[ix];
|
|
27304
|
-
if (options._earlyFilter && !acceptEntry(options, file, path, gitignore)) continue;
|
|
27432
|
+
if (options._earlyFilter && !acceptEntry(options, file, path, gitignore, fsPath)) continue;
|
|
27305
27433
|
let extras;
|
|
27306
27434
|
if (options.fullStat) {
|
|
27307
27435
|
const name = options._earlyFilter ? file.name : file;
|
|
27308
|
-
const fullFile = join2(options._sep,
|
|
27309
|
-
const stat = await asyncLStat(fullFile);
|
|
27436
|
+
const fullFile = join2(options._sep, outDir, name);
|
|
27437
|
+
const stat = await asyncLStat(posixSep ? fullFile : join2("/", dir, name));
|
|
27310
27438
|
if (options._stopped) break;
|
|
27311
27439
|
extras = makeExtrasData(name, fullFile, path, stat, extrasFiles, options);
|
|
27312
27440
|
} else {
|
|
27313
|
-
const fullFile = join2(options._sep,
|
|
27441
|
+
const fullFile = join2(options._sep, outDir, file.name);
|
|
27314
27442
|
extras = makeExtrasData(file.name, fullFile, path, file, files, options);
|
|
27315
27443
|
}
|
|
27316
27444
|
if (extras.stat.isDirectory()) dirs.push(extras);
|
|
@@ -27328,7 +27456,8 @@ async function walk(path, options, level = 0, parentRules) {
|
|
|
27328
27456
|
break;
|
|
27329
27457
|
}
|
|
27330
27458
|
if (!flags.skip && level < options.maxLevel) {
|
|
27331
|
-
const
|
|
27459
|
+
const childFsPath = posixSep ? extras.dirFile : join2("/", fsPath, extras.file);
|
|
27460
|
+
const walkP = walk(extras.dirFile, options, level + 1, gitignore, childFsPath);
|
|
27332
27461
|
if (options.concurrency > 1) {
|
|
27333
27462
|
promises.push(walkP);
|
|
27334
27463
|
if (promises.length >= options.concurrency) {
|
|
@@ -27357,8 +27486,15 @@ async function walk(path, options, level = 0, parentRules) {
|
|
|
27357
27486
|
* @returns
|
|
27358
27487
|
*/
|
|
27359
27488
|
function makeOptions(opts) {
|
|
27360
|
-
const
|
|
27489
|
+
const input = typeof opts === "string" ? { cwd: opts } : opts;
|
|
27490
|
+
const options = {};
|
|
27491
|
+
for (const key of Object.keys(input)) if (input[key] !== void 0) options[key] = input[key];
|
|
27361
27492
|
if (options.prefilter && options.fullStat === false) throw new TypeError("prefilter requires fullStat: true");
|
|
27493
|
+
for (const name of [
|
|
27494
|
+
"filter",
|
|
27495
|
+
"filterDir",
|
|
27496
|
+
"prefilter"
|
|
27497
|
+
]) if (Object.prototype.toString.call(options[name]) === "[object AsyncFunction]") throw new TypeError(`${name} must return a result synchronously, not a promise`);
|
|
27362
27498
|
const sep = options.pathSep || Path.posix.sep;
|
|
27363
27499
|
let cwd = options.cwd || options.dir || process.cwd();
|
|
27364
27500
|
if (!options.hasOwnProperty("pathSep") && cwd.includes("\\")) cwd = cwd.replace(/\\/g, "/");
|
|
@@ -27380,6 +27516,7 @@ function makeOptions(opts) {
|
|
|
27380
27516
|
grouping: void 0
|
|
27381
27517
|
}, options, {
|
|
27382
27518
|
dir: cwd,
|
|
27519
|
+
_outCwd: Path.join(cwd),
|
|
27383
27520
|
fullStat: options.fullStat === void 0 ? true : options.fullStat,
|
|
27384
27521
|
result: Object.create(null),
|
|
27385
27522
|
ignoreExt: [].concat(options.ignoreExt).map(cleanExt).filter((x) => x),
|
|
@@ -27469,6 +27606,8 @@ const commaPattern = /\\,/g;
|
|
|
27469
27606
|
const periodPattern = /\\\./g;
|
|
27470
27607
|
const EXPANSION_MAX = 1e5;
|
|
27471
27608
|
const EXPANSION_MAX_LENGTH = 4e6;
|
|
27609
|
+
const EXPANSION_MAX_DEPTH = 1e3;
|
|
27610
|
+
const EXPANSION_MAX_REWRITES = 1e3;
|
|
27472
27611
|
function numeric(str) {
|
|
27473
27612
|
return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
|
|
27474
27613
|
}
|
|
@@ -27478,32 +27617,43 @@ function escapeBraces(str) {
|
|
|
27478
27617
|
function unescapeBraces(str) {
|
|
27479
27618
|
return str.replace(escSlashPattern, "\\").replace(escOpenPattern, "{").replace(escClosePattern, "}").replace(escCommaPattern, ",").replace(escPeriodPattern, ".");
|
|
27480
27619
|
}
|
|
27620
|
+
function pushAll(target, items) {
|
|
27621
|
+
for (let i = 0; i < items.length; i++) target.push(items[i]);
|
|
27622
|
+
}
|
|
27481
27623
|
/**
|
|
27482
27624
|
* Basically just str.split(","), but handling cases
|
|
27483
27625
|
* where we have nested braced sections, which should be
|
|
27484
27626
|
* treated as individual members, like {a,{b,c},d}
|
|
27485
27627
|
*/
|
|
27486
27628
|
function parseCommaParts(str) {
|
|
27487
|
-
if (!str) return [""];
|
|
27488
27629
|
const parts = [];
|
|
27489
|
-
|
|
27490
|
-
|
|
27491
|
-
|
|
27492
|
-
|
|
27493
|
-
|
|
27494
|
-
|
|
27495
|
-
|
|
27496
|
-
|
|
27497
|
-
|
|
27498
|
-
|
|
27499
|
-
|
|
27500
|
-
|
|
27630
|
+
let carry = "";
|
|
27631
|
+
for (;;) {
|
|
27632
|
+
const m = balanced("{", "}", str);
|
|
27633
|
+
if (!m) {
|
|
27634
|
+
const tail = str.split(",");
|
|
27635
|
+
tail[0] = carry + tail[0];
|
|
27636
|
+
pushAll(parts, tail);
|
|
27637
|
+
return parts;
|
|
27638
|
+
}
|
|
27639
|
+
const { pre, body, post } = m;
|
|
27640
|
+
const p = pre.split(",");
|
|
27641
|
+
p[0] = carry + p[0];
|
|
27642
|
+
p[p.length - 1] += "{" + body + "}";
|
|
27643
|
+
if (!post.length) {
|
|
27644
|
+
pushAll(parts, p);
|
|
27645
|
+
return parts;
|
|
27646
|
+
}
|
|
27647
|
+
carry = p.pop();
|
|
27648
|
+
pushAll(parts, p);
|
|
27649
|
+
str = post;
|
|
27650
|
+
}
|
|
27501
27651
|
}
|
|
27502
27652
|
function expand(str, options = {}) {
|
|
27503
27653
|
if (!str) return [];
|
|
27504
|
-
const { max = EXPANSION_MAX, maxLength = EXPANSION_MAX_LENGTH } = options;
|
|
27654
|
+
const { max = EXPANSION_MAX, maxLength = EXPANSION_MAX_LENGTH, maxDepth = EXPANSION_MAX_DEPTH, maxRewrites = EXPANSION_MAX_REWRITES } = options;
|
|
27505
27655
|
if (str.slice(0, 2) === "{}") str = "\\{\\}" + str.slice(2);
|
|
27506
|
-
return expand_(escapeBraces(str), max, maxLength, true).map(unescapeBraces);
|
|
27656
|
+
return expand_(escapeBraces(str), max, maxLength, maxDepth, 0, maxRewrites, true).map(unescapeBraces);
|
|
27507
27657
|
}
|
|
27508
27658
|
function embrace(str) {
|
|
27509
27659
|
return "{" + str + "}";
|
|
@@ -27569,8 +27719,10 @@ function expandSequence(body, isAlphaSequence, max, maxLength) {
|
|
|
27569
27719
|
}
|
|
27570
27720
|
return N;
|
|
27571
27721
|
}
|
|
27572
|
-
function expand_(str, max, maxLength, isTop) {
|
|
27722
|
+
function expand_(str, max, maxLength, maxDepth, depth, maxRewrites, isTop) {
|
|
27723
|
+
if (depth > maxDepth) return [str];
|
|
27573
27724
|
let acc = [""];
|
|
27725
|
+
let rewrites = 0;
|
|
27574
27726
|
let dropEmpties = false;
|
|
27575
27727
|
let firstGroup = true;
|
|
27576
27728
|
for (;;) {
|
|
@@ -27589,7 +27741,8 @@ function expand_(str, max, maxLength, isTop) {
|
|
|
27589
27741
|
const isSequence = isNumericSequence || isAlphaSequence;
|
|
27590
27742
|
const isOptions = m.body.indexOf(",") >= 0;
|
|
27591
27743
|
if (!isSequence && !isOptions) {
|
|
27592
|
-
if (m.post.match(/,(?!,).*\}/)) {
|
|
27744
|
+
if (rewrites < maxRewrites && m.post.match(/,(?!,).*\}/)) {
|
|
27745
|
+
rewrites++;
|
|
27593
27746
|
str = m.pre + "{" + m.body + escClose + m.post;
|
|
27594
27747
|
isTop = true;
|
|
27595
27748
|
continue;
|
|
@@ -27605,7 +27758,7 @@ function expand_(str, max, maxLength, isTop) {
|
|
|
27605
27758
|
else {
|
|
27606
27759
|
let n = parseCommaParts(m.body);
|
|
27607
27760
|
if (n.length === 1 && n[0] !== void 0) {
|
|
27608
|
-
n = expand_(n[0], max, maxLength, false).map(embrace);
|
|
27761
|
+
n = expand_(n[0], max, maxLength, maxDepth, depth + 1, maxRewrites, false).map(embrace);
|
|
27609
27762
|
/* c8 ignore start */
|
|
27610
27763
|
if (n.length === 1) {
|
|
27611
27764
|
acc = combine(acc, pre + n[0], [""], max, maxLength, dropEmpties && !m.post.length);
|
|
@@ -27619,7 +27772,7 @@ function expand_(str, max, maxLength, isTop) {
|
|
|
27619
27772
|
values = [];
|
|
27620
27773
|
let valuesLength = 0;
|
|
27621
27774
|
outer: for (let j = 0; j < n.length; j++) {
|
|
27622
|
-
const expanded = expand_(n[j], max, maxLength, false);
|
|
27775
|
+
const expanded = expand_(n[j], max, maxLength, maxDepth, depth + 1, maxRewrites, false);
|
|
27623
27776
|
for (let k = 0; k < expanded.length; k++) {
|
|
27624
27777
|
const v = expanded[k];
|
|
27625
27778
|
if (dropsEmpties && !v) continue;
|
|
@@ -29724,14 +29877,14 @@ var PackageRef = class {
|
|
|
29724
29877
|
* @param ref package string reference
|
|
29725
29878
|
*/
|
|
29726
29879
|
parseRef(ref) {
|
|
29727
|
-
const
|
|
29728
|
-
if (
|
|
29729
|
-
const tmp =
|
|
29880
|
+
const colonIx = ref.indexOf(":");
|
|
29881
|
+
if (colonIx >= 0) {
|
|
29882
|
+
const tmp = ref.substring(0, colonIx).trim();
|
|
29730
29883
|
if (tmp === "id" || tmp === "path" || tmp === "name") this.type = tmp;
|
|
29731
29884
|
else throw new Error(`package ref '${ref}' has unknown type '${tmp}' - must be 'id', 'path', or 'name'`);
|
|
29732
|
-
this.value =
|
|
29885
|
+
this.value = ref.substring(colonIx + 1).trim();
|
|
29733
29886
|
} else {
|
|
29734
|
-
this.value =
|
|
29887
|
+
this.value = ref.trim();
|
|
29735
29888
|
if (this.value.lastIndexOf("@") > 0) this.type = "id";
|
|
29736
29889
|
else this.type = "name";
|
|
29737
29890
|
}
|
|
@@ -29745,6 +29898,7 @@ var PackageRef = class {
|
|
|
29745
29898
|
} else if (this.type === "path") this.mm = new Minimatch(this.value);
|
|
29746
29899
|
}
|
|
29747
29900
|
match(pkgInfo) {
|
|
29901
|
+
if (this.regex) this.regex.lastIndex = 0;
|
|
29748
29902
|
if (this.type === "path") return this.regex ? this.regex.exec(pkgInfo.path) !== null : this.mm.match(pkgInfo.path);
|
|
29749
29903
|
else if (this.type === "id") return this.regex ? this.regex.exec(pkgInfoId(pkgInfo)) !== null : this.value === pkgInfoId(pkgInfo);
|
|
29750
29904
|
else return this.regex ? this.regex.exec(pkgInfo.name) !== null : this.value === pkgInfo.name;
|
|
@@ -29776,6 +29930,24 @@ function resolvePackage(semver, packages, fallbackToFirst = true) {
|
|
|
29776
29930
|
if (fallbackToFirst) return packages[0];
|
|
29777
29931
|
}
|
|
29778
29932
|
/**
|
|
29933
|
+
* Widen a local dep's semver per `localDepAutoSemver`, same as fyn's getAutoSemver.
|
|
29934
|
+
*
|
|
29935
|
+
* @param semver semver string
|
|
29936
|
+
* @param autoSemver the `localDepAutoSemver` setting
|
|
29937
|
+
* @returns the semver to match local versions with
|
|
29938
|
+
*/
|
|
29939
|
+
function localAutoSemver(semver, autoSemver) {
|
|
29940
|
+
if (autoSemver) {
|
|
29941
|
+
const parsedSv = import_semver.default.coerce(semver);
|
|
29942
|
+
if (parsedSv && parsedSv.raw) switch (autoSemver) {
|
|
29943
|
+
case "patch": return `~${parsedSv.raw}`;
|
|
29944
|
+
case "minor": return `^${parsedSv.raw}`;
|
|
29945
|
+
case "major": return "*";
|
|
29946
|
+
}
|
|
29947
|
+
}
|
|
29948
|
+
return semver;
|
|
29949
|
+
}
|
|
29950
|
+
/**
|
|
29779
29951
|
* Make a package ID from basic info by joining name and version into a single string.
|
|
29780
29952
|
*
|
|
29781
29953
|
* @param info package basic info
|
|
@@ -29949,6 +30121,7 @@ var FynpoDepGraph = class {
|
|
|
29949
30121
|
});
|
|
29950
30122
|
files.push(scanned);
|
|
29951
30123
|
}
|
|
30124
|
+
this.packages.byName = Object.create(null);
|
|
29952
30125
|
const filesByDepth = [...[].concat(...files)].sort((a, b) => {
|
|
29953
30126
|
const depth = (file) => posixify$2(Path.dirname(file)).split("/").length;
|
|
29954
30127
|
return depth(a) - depth(b) || a.localeCompare(b);
|
|
@@ -30115,16 +30288,17 @@ var FynpoDepGraph = class {
|
|
|
30115
30288
|
if (this.checkNoFynLocal(pkgInfo, name)) continue;
|
|
30116
30289
|
const semId = pkgId$1(name, semver);
|
|
30117
30290
|
const resolveId = this.resolvedCache[semId];
|
|
30118
|
-
|
|
30119
|
-
|
|
30120
|
-
|
|
30291
|
+
if (resolveId === "") continue;
|
|
30292
|
+
let depPkg = resolveId ? byId[resolveId] : void 0;
|
|
30293
|
+
if (!depPkg) {
|
|
30294
|
+
const localSemver = localAutoSemver(semver, this._options.localDepAutoSemver);
|
|
30295
|
+
depPkg = resolvePackage(localSemver, byName[name], !import_semver.default.validRange(localSemver));
|
|
30296
|
+
this.resolvedCache[semId] = depPkg ? pkgInfoId(depPkg) : "";
|
|
30297
|
+
}
|
|
30298
|
+
if (depPkg) this.addDep(pkgInfo, depPkg, section);
|
|
30121
30299
|
}
|
|
30122
30300
|
};
|
|
30123
|
-
for (const path in byPath)
|
|
30124
|
-
pkgInfo: byPath[path],
|
|
30125
|
-
localDepsByPath: Object.create(null),
|
|
30126
|
-
dependentsByPath: Object.create(null)
|
|
30127
|
-
};
|
|
30301
|
+
for (const path in byPath) this.getDepData(byPath[path]);
|
|
30128
30302
|
for (const path in byPath) {
|
|
30129
30303
|
const pkgInfo = byPath[path];
|
|
30130
30304
|
const depData = depMapByPath[pkgInfo.path];
|
|
@@ -30134,6 +30308,21 @@ var FynpoDepGraph = class {
|
|
|
30134
30308
|
}
|
|
30135
30309
|
}
|
|
30136
30310
|
/**
|
|
30311
|
+
* Get the dep data of a package, creating an empty one if it doesn't exist yet
|
|
30312
|
+
*
|
|
30313
|
+
* @param pkgInfo package info
|
|
30314
|
+
* @returns dep data
|
|
30315
|
+
*/
|
|
30316
|
+
getDepData(pkgInfo) {
|
|
30317
|
+
let depData = this.depMapByPath[pkgInfo.path];
|
|
30318
|
+
if (!depData) depData = this.depMapByPath[pkgInfo.path] = {
|
|
30319
|
+
pkgInfo,
|
|
30320
|
+
localDepsByPath: Object.create(null),
|
|
30321
|
+
dependentsByPath: Object.create(null)
|
|
30322
|
+
};
|
|
30323
|
+
return depData;
|
|
30324
|
+
}
|
|
30325
|
+
/**
|
|
30137
30326
|
* Add a dependency relation by package paths
|
|
30138
30327
|
*
|
|
30139
30328
|
* @param from - path of package depend from
|
|
@@ -30198,8 +30387,8 @@ var FynpoDepGraph = class {
|
|
|
30198
30387
|
*/
|
|
30199
30388
|
addDep(pkgInfo, depPkg, depSection, indirectSteps) {
|
|
30200
30389
|
if (pkgInfo.path === depPkg.path) return false;
|
|
30201
|
-
const dataPkg = this.
|
|
30202
|
-
const dataDep = this.
|
|
30390
|
+
const dataPkg = this.getDepData(pkgInfo);
|
|
30391
|
+
const dataDep = this.getDepData(depPkg);
|
|
30203
30392
|
if (dataPkg.localDepsByPath[depPkg.path]) return false;
|
|
30204
30393
|
dataPkg.localDepsByPath[depPkg.path] = {
|
|
30205
30394
|
name: depPkg.name,
|
|
@@ -30367,7 +30556,7 @@ let defaultLog$1 = consoleLog;
|
|
|
30367
30556
|
const ERR_MODULE_NOT_FOUND = "ERR_MODULE_NOT_FOUND";
|
|
30368
30557
|
const ERR_PACKAGE_PATH_NOT_EXPORTED = "ERR_PACKAGE_PATH_NOT_EXPORTED";
|
|
30369
30558
|
function normalizeOpts(optsOrMsg) {
|
|
30370
|
-
if (optsOrMsg
|
|
30559
|
+
if (optsOrMsg == null) return {};
|
|
30371
30560
|
if (optsOrMsg === true || typeof optsOrMsg === "string") return { message: optsOrMsg };
|
|
30372
30561
|
return optsOrMsg;
|
|
30373
30562
|
}
|
|
@@ -30852,7 +31041,8 @@ const fyntil = {
|
|
|
30852
31041
|
const graph = new FynpoDepGraph({
|
|
30853
31042
|
cwd: fcm.topDir,
|
|
30854
31043
|
packages: config.packages,
|
|
30855
|
-
noFynLocal: config.noFynLocal
|
|
31044
|
+
noFynLocal: config.noFynLocal,
|
|
31045
|
+
localDepAutoSemver: config.localDepAutoSemver
|
|
30856
31046
|
});
|
|
30857
31047
|
await graph.resolve();
|
|
30858
31048
|
return fyntil.fynpoConfig = {
|
|
@@ -30942,14 +31132,15 @@ const fyntil = {
|
|
|
30942
31132
|
if (!Path.isAbsolute(rel) && !rel.startsWith(".")) return `.${Path.sep}${rel}`;
|
|
30943
31133
|
return shouldPosixify ? posixify$2(rel) : rel;
|
|
30944
31134
|
},
|
|
30945
|
-
|
|
31135
|
+
/** @param pkgJsonStr - package.json's content, when the caller has it already */
|
|
31136
|
+
async readPkgJson(dirOrFile, keepRaw = false, packageFyn = false, pkgJsonStr) {
|
|
30946
31137
|
const dir = !dirOrFile.endsWith(".json") ? dirOrFile : Path.dirname(dirOrFile);
|
|
30947
31138
|
const files = ["package.json", packageFyn && "package-fyn.json"].filter(Boolean);
|
|
30948
31139
|
const finalJson = {};
|
|
30949
31140
|
for (const fname of files) {
|
|
30950
31141
|
const file = Path.join(dir, fname);
|
|
30951
31142
|
try {
|
|
30952
|
-
const str = await file_ops_default.readFile(file, "utf8");
|
|
31143
|
+
const str = fname === "package.json" && pkgJsonStr !== void 0 ? pkgJsonStr : await file_ops_default.readFile(file, "utf8");
|
|
30953
31144
|
const json = JSON.parse(str.trim());
|
|
30954
31145
|
merge(finalJson, json);
|
|
30955
31146
|
if (keepRaw && fname !== "package-fyn.json") finalJson[PACKAGE_RAW_INFO] = {
|
|
@@ -35966,15 +36157,114 @@ var To = (s) => {
|
|
|
35966
36157
|
s.mtimeCache || (s.mtimeCache = /* @__PURE__ */ new Map()), s.filter = t ? (e, i) => t(e, i) && !((s.mtimeCache?.get(e) ?? i.mtime ?? 0) > (i.mtime ?? 0)) : (e, i) => !((s.mtimeCache?.get(e) ?? i.mtime ?? 0) > (i.mtime ?? 0));
|
|
35967
36158
|
};
|
|
35968
36159
|
|
|
36160
|
+
//#endregion
|
|
36161
|
+
//#region lib/util/fs-worker-pool.ts
|
|
36162
|
+
/** One worker less than the CPUs, for the main thread, and at most 8 */
|
|
36163
|
+
const POOL_SIZE = Math.max(1, Math.min(8, os.availableParallelism() - 1));
|
|
36164
|
+
/**
|
|
36165
|
+
* A downloaded Buffer is often a view into a much bigger ArrayBuffer, and postMessage copies the
|
|
36166
|
+
* whole ArrayBuffer. So the message gets a copy of just the view, transferred. The caller's
|
|
36167
|
+
* Buffer stays usable.
|
|
36168
|
+
*/
|
|
36169
|
+
function postJob(worker, id, { op, job }) {
|
|
36170
|
+
const { data } = job;
|
|
36171
|
+
if (!data) {
|
|
36172
|
+
worker.postMessage({
|
|
36173
|
+
id,
|
|
36174
|
+
op,
|
|
36175
|
+
job
|
|
36176
|
+
});
|
|
36177
|
+
return;
|
|
36178
|
+
}
|
|
36179
|
+
const copy = new Uint8Array(data.byteLength);
|
|
36180
|
+
copy.set(data);
|
|
36181
|
+
worker.postMessage({
|
|
36182
|
+
id,
|
|
36183
|
+
op,
|
|
36184
|
+
job: {
|
|
36185
|
+
...job,
|
|
36186
|
+
data: copy
|
|
36187
|
+
}
|
|
36188
|
+
}, [copy.buffer]);
|
|
36189
|
+
}
|
|
36190
|
+
var FsWorkerPool = class {
|
|
36191
|
+
_file;
|
|
36192
|
+
_workers = [];
|
|
36193
|
+
_queue = [];
|
|
36194
|
+
_nextId = 0;
|
|
36195
|
+
constructor(file) {
|
|
36196
|
+
this._file = file;
|
|
36197
|
+
}
|
|
36198
|
+
run(op, job) {
|
|
36199
|
+
return new Promise((resolve, reject) => {
|
|
36200
|
+
this._queue.push({
|
|
36201
|
+
job: {
|
|
36202
|
+
op,
|
|
36203
|
+
job
|
|
36204
|
+
},
|
|
36205
|
+
resolve,
|
|
36206
|
+
reject
|
|
36207
|
+
});
|
|
36208
|
+
this._dispatch();
|
|
36209
|
+
});
|
|
36210
|
+
}
|
|
36211
|
+
_dispatch() {
|
|
36212
|
+
while (this._queue.length > 0) {
|
|
36213
|
+
let pw = this._workers.find((w) => !w.busy);
|
|
36214
|
+
if (!pw) {
|
|
36215
|
+
if (this._workers.length >= POOL_SIZE) return;
|
|
36216
|
+
pw = this._start();
|
|
36217
|
+
}
|
|
36218
|
+
const pending = this._queue.shift();
|
|
36219
|
+
pw.busy = pending;
|
|
36220
|
+
pw.worker.ref();
|
|
36221
|
+
postJob(pw.worker, this._nextId++, pending.job);
|
|
36222
|
+
}
|
|
36223
|
+
}
|
|
36224
|
+
_start() {
|
|
36225
|
+
const pw = { worker: new Worker(this._file) };
|
|
36226
|
+
pw.worker.on("message", (msg) => {
|
|
36227
|
+
const pending = pw.busy;
|
|
36228
|
+
pw.busy = void 0;
|
|
36229
|
+
pw.worker.unref();
|
|
36230
|
+
if (msg.error) pending.reject(Object.assign(new Error(msg.error.message), msg.error));
|
|
36231
|
+
else pending.resolve(msg.result);
|
|
36232
|
+
this._dispatch();
|
|
36233
|
+
});
|
|
36234
|
+
pw.worker.on("error", (err) => {
|
|
36235
|
+
this._workers = this._workers.filter((w) => w !== pw);
|
|
36236
|
+
pw.busy?.reject(err);
|
|
36237
|
+
pw.busy = void 0;
|
|
36238
|
+
this._dispatch();
|
|
36239
|
+
});
|
|
36240
|
+
this._workers.push(pw);
|
|
36241
|
+
return pw;
|
|
36242
|
+
}
|
|
36243
|
+
};
|
|
36244
|
+
let pool;
|
|
36245
|
+
/**
|
|
36246
|
+
* The pool, or undefined when there's no built worker next to this module, which is the case
|
|
36247
|
+
* when running from source. Callers then do the work in-thread.
|
|
36248
|
+
*/
|
|
36249
|
+
function getFsWorkerPool() {
|
|
36250
|
+
if (pool === void 0) {
|
|
36251
|
+
const file = fileURLToPath(new URL("./fs-worker.mjs", import.meta.url));
|
|
36252
|
+
pool = Br.existsSync(file) && new FsWorkerPool(file);
|
|
36253
|
+
logger$1.debug(pool ? `fs workers: up to ${POOL_SIZE} from ${file}` : "fs workers: none built, working in-thread");
|
|
36254
|
+
}
|
|
36255
|
+
return pool || void 0;
|
|
36256
|
+
}
|
|
36257
|
+
|
|
35969
36258
|
//#endregion
|
|
35970
36259
|
//#region lib/pkg-dist-extractor.ts
|
|
35971
36260
|
const { retry, missPipe: missPipe$2 } = fyntil;
|
|
36261
|
+
const isStoreJob = (result) => typeof result?.store === "function";
|
|
35972
36262
|
var PkgDistExtractor = class {
|
|
35973
36263
|
_promiseQ;
|
|
35974
36264
|
_fyn;
|
|
35975
36265
|
constructor(options) {
|
|
35976
36266
|
this._promiseQ = new promise_queue_default({
|
|
35977
|
-
concurrency: 4,
|
|
36267
|
+
concurrency: options.fyn.extractConcurrency || Math.min(4, POOL_SIZE + 1),
|
|
35978
36268
|
stopOnError: true,
|
|
35979
36269
|
processItem: (x, id) => this.processItem(x, id)
|
|
35980
36270
|
});
|
|
@@ -36024,6 +36314,7 @@ var PkgDistExtractor = class {
|
|
|
36024
36314
|
const { pkg } = data;
|
|
36025
36315
|
const promotedOpt = defaults$1({ promoted }, pick(pkg, "promoted"));
|
|
36026
36316
|
const fullOutDir = this._fyn.getInstalledPkgDir(pkg.name, pkg.version, promotedOpt);
|
|
36317
|
+
let placed;
|
|
36027
36318
|
if (pkg.extracted && pkg.extracted === fullOutDir) {
|
|
36028
36319
|
logger$1.debug(`package ${pkg.name} ${pkg.version} has already been extracted to ${pkg.extracted}`);
|
|
36029
36320
|
if (this._fyn.isNormalLayout && pkg.promoted && !promotedOpt.promoted) await this.movePromotedPkgFromFV(pkg, fullOutDir);
|
|
@@ -36036,18 +36327,24 @@ var PkgDistExtractor = class {
|
|
|
36036
36327
|
}
|
|
36037
36328
|
return json;
|
|
36038
36329
|
}
|
|
36039
|
-
|
|
36040
|
-
|
|
36330
|
+
const job = data.result;
|
|
36331
|
+
if (isStoreJob(job) && !await job.store(!data.listener && !data.deferred)) {
|
|
36332
|
+
data.deferred = true;
|
|
36333
|
+
this._promiseQ.addItem(data);
|
|
36334
|
+
return;
|
|
36335
|
+
}
|
|
36336
|
+
const result = isStoreJob(job) ? job.integrity : job;
|
|
36041
36337
|
let act;
|
|
36042
36338
|
let retrieve;
|
|
36043
36339
|
if (typeof result === "string") {
|
|
36044
36340
|
act = "hardlink";
|
|
36045
|
-
retrieve = () => {
|
|
36046
|
-
|
|
36341
|
+
retrieve = async () => {
|
|
36342
|
+
placed = await this._fyn.central.replicate(result, fullOutDir, () => this._fyn.createPkgOutDir(fullOutDir));
|
|
36047
36343
|
};
|
|
36048
36344
|
} else {
|
|
36049
36345
|
act = "extract";
|
|
36050
|
-
retrieve = () => {
|
|
36346
|
+
retrieve = async () => {
|
|
36347
|
+
await this._fyn.createPkgOutDir(fullOutDir);
|
|
36051
36348
|
const untarStream = So({
|
|
36052
36349
|
strip: 1,
|
|
36053
36350
|
strict: true,
|
|
@@ -36063,7 +36360,7 @@ var PkgDistExtractor = class {
|
|
|
36063
36360
|
logger$1.updateItem(LOAD_PACKAGE, `${act}ed ${msg}`);
|
|
36064
36361
|
}
|
|
36065
36362
|
let retries = 0;
|
|
36066
|
-
return retry(() => this._fyn.loadJsonForPkg(pkg, fullOutDir), () => {
|
|
36363
|
+
return retry(() => this._fyn.loadJsonForPkg(pkg, fullOutDir, placed), () => {
|
|
36067
36364
|
retries++;
|
|
36068
36365
|
logger$1.warn(`retrying ${retries} reading package.json`, fullOutDir);
|
|
36069
36366
|
return true;
|
|
@@ -38464,7 +38761,7 @@ var require_commonjs$8 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
38464
38761
|
//#region node_modules/brace-expansion/dist/commonjs/index.js
|
|
38465
38762
|
var require_commonjs$7 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
38466
38763
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38467
|
-
exports.EXPANSION_MAX_LENGTH = exports.EXPANSION_MAX = void 0;
|
|
38764
|
+
exports.EXPANSION_MAX_REWRITES = exports.EXPANSION_MAX_DEPTH = exports.EXPANSION_MAX_LENGTH = exports.EXPANSION_MAX = void 0;
|
|
38468
38765
|
exports.expand = expand;
|
|
38469
38766
|
const balanced_match_1 = require_commonjs$8();
|
|
38470
38767
|
const escSlash = "\0SLASH" + Math.random() + "\0";
|
|
@@ -38484,6 +38781,8 @@ var require_commonjs$7 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
38484
38781
|
const periodPattern = /\\\./g;
|
|
38485
38782
|
exports.EXPANSION_MAX = 1e5;
|
|
38486
38783
|
exports.EXPANSION_MAX_LENGTH = 4e6;
|
|
38784
|
+
exports.EXPANSION_MAX_DEPTH = 1e3;
|
|
38785
|
+
exports.EXPANSION_MAX_REWRITES = 1e3;
|
|
38487
38786
|
function numeric(str) {
|
|
38488
38787
|
return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
|
|
38489
38788
|
}
|
|
@@ -38493,32 +38792,43 @@ var require_commonjs$7 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
38493
38792
|
function unescapeBraces(str) {
|
|
38494
38793
|
return str.replace(escSlashPattern, "\\").replace(escOpenPattern, "{").replace(escClosePattern, "}").replace(escCommaPattern, ",").replace(escPeriodPattern, ".");
|
|
38495
38794
|
}
|
|
38795
|
+
function pushAll(target, items) {
|
|
38796
|
+
for (let i = 0; i < items.length; i++) target.push(items[i]);
|
|
38797
|
+
}
|
|
38496
38798
|
/**
|
|
38497
38799
|
* Basically just str.split(","), but handling cases
|
|
38498
38800
|
* where we have nested braced sections, which should be
|
|
38499
38801
|
* treated as individual members, like {a,{b,c},d}
|
|
38500
38802
|
*/
|
|
38501
38803
|
function parseCommaParts(str) {
|
|
38502
|
-
if (!str) return [""];
|
|
38503
38804
|
const parts = [];
|
|
38504
|
-
|
|
38505
|
-
|
|
38506
|
-
|
|
38507
|
-
|
|
38508
|
-
|
|
38509
|
-
|
|
38510
|
-
|
|
38511
|
-
|
|
38512
|
-
|
|
38805
|
+
let carry = "";
|
|
38806
|
+
for (;;) {
|
|
38807
|
+
const m = (0, balanced_match_1.balanced)("{", "}", str);
|
|
38808
|
+
if (!m) {
|
|
38809
|
+
const tail = str.split(",");
|
|
38810
|
+
tail[0] = carry + tail[0];
|
|
38811
|
+
pushAll(parts, tail);
|
|
38812
|
+
return parts;
|
|
38813
|
+
}
|
|
38814
|
+
const { pre, body, post } = m;
|
|
38815
|
+
const p = pre.split(",");
|
|
38816
|
+
p[0] = carry + p[0];
|
|
38817
|
+
p[p.length - 1] += "{" + body + "}";
|
|
38818
|
+
if (!post.length) {
|
|
38819
|
+
pushAll(parts, p);
|
|
38820
|
+
return parts;
|
|
38821
|
+
}
|
|
38822
|
+
carry = p.pop();
|
|
38823
|
+
pushAll(parts, p);
|
|
38824
|
+
str = post;
|
|
38513
38825
|
}
|
|
38514
|
-
parts.push.apply(parts, p);
|
|
38515
|
-
return parts;
|
|
38516
38826
|
}
|
|
38517
38827
|
function expand(str, options = {}) {
|
|
38518
38828
|
if (!str) return [];
|
|
38519
|
-
const { max = exports.EXPANSION_MAX, maxLength = exports.EXPANSION_MAX_LENGTH } = options;
|
|
38829
|
+
const { max = exports.EXPANSION_MAX, maxLength = exports.EXPANSION_MAX_LENGTH, maxDepth = exports.EXPANSION_MAX_DEPTH, maxRewrites = exports.EXPANSION_MAX_REWRITES } = options;
|
|
38520
38830
|
if (str.slice(0, 2) === "{}") str = "\\{\\}" + str.slice(2);
|
|
38521
|
-
return expand_(escapeBraces(str), max, maxLength, true).map(unescapeBraces);
|
|
38831
|
+
return expand_(escapeBraces(str), max, maxLength, maxDepth, 0, maxRewrites, true).map(unescapeBraces);
|
|
38522
38832
|
}
|
|
38523
38833
|
function embrace(str) {
|
|
38524
38834
|
return "{" + str + "}";
|
|
@@ -38584,8 +38894,10 @@ var require_commonjs$7 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
38584
38894
|
}
|
|
38585
38895
|
return N;
|
|
38586
38896
|
}
|
|
38587
|
-
function expand_(str, max, maxLength, isTop) {
|
|
38897
|
+
function expand_(str, max, maxLength, maxDepth, depth, maxRewrites, isTop) {
|
|
38898
|
+
if (depth > maxDepth) return [str];
|
|
38588
38899
|
let acc = [""];
|
|
38900
|
+
let rewrites = 0;
|
|
38589
38901
|
let dropEmpties = false;
|
|
38590
38902
|
let firstGroup = true;
|
|
38591
38903
|
for (;;) {
|
|
@@ -38604,7 +38916,8 @@ var require_commonjs$7 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
38604
38916
|
const isSequence = isNumericSequence || isAlphaSequence;
|
|
38605
38917
|
const isOptions = m.body.indexOf(",") >= 0;
|
|
38606
38918
|
if (!isSequence && !isOptions) {
|
|
38607
|
-
if (m.post.match(/,(?!,).*\}/)) {
|
|
38919
|
+
if (rewrites < maxRewrites && m.post.match(/,(?!,).*\}/)) {
|
|
38920
|
+
rewrites++;
|
|
38608
38921
|
str = m.pre + "{" + m.body + escClose + m.post;
|
|
38609
38922
|
isTop = true;
|
|
38610
38923
|
continue;
|
|
@@ -38620,7 +38933,7 @@ var require_commonjs$7 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
38620
38933
|
else {
|
|
38621
38934
|
let n = parseCommaParts(m.body);
|
|
38622
38935
|
if (n.length === 1 && n[0] !== void 0) {
|
|
38623
|
-
n = expand_(n[0], max, maxLength, false).map(embrace);
|
|
38936
|
+
n = expand_(n[0], max, maxLength, maxDepth, depth + 1, maxRewrites, false).map(embrace);
|
|
38624
38937
|
/* c8 ignore start */
|
|
38625
38938
|
if (n.length === 1) {
|
|
38626
38939
|
acc = combine(acc, pre + n[0], [""], max, maxLength, dropEmpties && !m.post.length);
|
|
@@ -38634,7 +38947,7 @@ var require_commonjs$7 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
38634
38947
|
values = [];
|
|
38635
38948
|
let valuesLength = 0;
|
|
38636
38949
|
outer: for (let j = 0; j < n.length; j++) {
|
|
38637
|
-
const expanded = expand_(n[j], max, maxLength, false);
|
|
38950
|
+
const expanded = expand_(n[j], max, maxLength, maxDepth, depth + 1, maxRewrites, false);
|
|
38638
38951
|
for (let k = 0; k < expanded.length; k++) {
|
|
38639
38952
|
const v = expanded[k];
|
|
38640
38953
|
if (dropsEmpties && !v) continue;
|
|
@@ -45425,7 +45738,7 @@ var require_normalize_data = /* @__PURE__ */ __commonJSMin(((exports, module) =>
|
|
|
45425
45738
|
}));
|
|
45426
45739
|
|
|
45427
45740
|
//#endregion
|
|
45428
|
-
//#region node_modules
|
|
45741
|
+
//#region node_modules/isexe/dist/commonjs/index.min.js
|
|
45429
45742
|
var require_index_min$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
45430
45743
|
var a = (t, e) => () => (e || t((e = { exports: {} }).exports, e), e.exports);
|
|
45431
45744
|
var _ = a((i) => {
|
|
@@ -50375,12 +50688,18 @@ var require_cache_dir$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
50375
50688
|
# This file is a cache directory tag created by cacache.
|
|
50376
50689
|
# For information about cache directory tags, see https://bford.info/cachedir/
|
|
50377
50690
|
`;
|
|
50378
|
-
|
|
50379
|
-
|
|
50380
|
-
|
|
50381
|
-
|
|
50382
|
-
|
|
50383
|
-
|
|
50691
|
+
const made = /* @__PURE__ */ new Map();
|
|
50692
|
+
function mkdir(cache) {
|
|
50693
|
+
let p = made.get(cache);
|
|
50694
|
+
if (!p) {
|
|
50695
|
+
p = fs$15.mkdir(cache, {
|
|
50696
|
+
recursive: true,
|
|
50697
|
+
owner: "inherit"
|
|
50698
|
+
}).then(() => writeTag(cache));
|
|
50699
|
+
made.set(cache, p);
|
|
50700
|
+
p.catch(() => made.delete(cache));
|
|
50701
|
+
}
|
|
50702
|
+
return p;
|
|
50384
50703
|
}
|
|
50385
50704
|
async function writeTag(cache) {
|
|
50386
50705
|
try {
|
|
@@ -58967,11 +59286,14 @@ var require_http_cache_semantics = /* @__PURE__ */ __commonJSMin(((exports, modu
|
|
|
58967
59286
|
}
|
|
58968
59287
|
/**
|
|
58969
59288
|
* @param {{headers: Record<string, string>, synchronous: boolean}|undefined} revalidation - Revalidation information, if any.
|
|
58970
|
-
* @returns {{response:
|
|
59289
|
+
* @returns {{response: HttpResponse, revalidation: {headers: Record<string, string>, synchronous: boolean}|undefined}} An object with a cached response headers and revalidation info.
|
|
58971
59290
|
*/
|
|
58972
59291
|
_evaluateRequestHitResult(revalidation) {
|
|
58973
59292
|
return {
|
|
58974
|
-
response: {
|
|
59293
|
+
response: {
|
|
59294
|
+
headers: this.responseHeaders(),
|
|
59295
|
+
status: this._status
|
|
59296
|
+
},
|
|
58975
59297
|
revalidation
|
|
58976
59298
|
};
|
|
58977
59299
|
}
|
|
@@ -59015,9 +59337,9 @@ var require_http_cache_semantics = /* @__PURE__ */ __commonJSMin(((exports, modu
|
|
|
59015
59337
|
* }
|
|
59016
59338
|
* ```
|
|
59017
59339
|
* @param {HttpRequest} req - new incoming HTTP request
|
|
59018
|
-
* @returns {{response:
|
|
59340
|
+
* @returns {{response: HttpResponse|undefined, revalidation: {headers: Record<string, string>, synchronous: boolean}|undefined}} An object containing keys:
|
|
59019
59341
|
* - revalidation: { headers: Record<string, string>, synchronous: boolean } Set if you should send this to the origin server
|
|
59020
|
-
* - response:
|
|
59342
|
+
* - response: HttpResponse Set if you can respond to the client with these cached headers
|
|
59021
59343
|
*/
|
|
59022
59344
|
evaluateRequest(req) {
|
|
59023
59345
|
this._assertRequestHasHeaders(req);
|
|
@@ -59056,9 +59378,11 @@ var require_http_cache_semantics = /* @__PURE__ */ __commonJSMin(((exports, modu
|
|
|
59056
59378
|
*/
|
|
59057
59379
|
_varyMatches(req) {
|
|
59058
59380
|
if (!this._resHeaders.vary) return true;
|
|
59059
|
-
if (this._resHeaders.vary === "*") return false;
|
|
59060
59381
|
const fields = this._resHeaders.vary.trim().toLowerCase().split(/\s*,\s*/);
|
|
59061
|
-
for (const name of fields)
|
|
59382
|
+
for (const name of fields) {
|
|
59383
|
+
if (name === "*") return false;
|
|
59384
|
+
if ((Object.prototype.hasOwnProperty.call(req.headers, name) && req.headers[name]) !== (Object.prototype.hasOwnProperty.call(this._reqHeaders, name) && this._reqHeaders[name])) return false;
|
|
59385
|
+
}
|
|
59062
59386
|
return true;
|
|
59063
59387
|
}
|
|
59064
59388
|
/**
|
|
@@ -59100,6 +59424,13 @@ var require_http_cache_semantics = /* @__PURE__ */ __commonJSMin(((exports, modu
|
|
|
59100
59424
|
return headers;
|
|
59101
59425
|
}
|
|
59102
59426
|
/**
|
|
59427
|
+
* Returns the status code of the cached response.
|
|
59428
|
+
* @returns {number} The response status code.
|
|
59429
|
+
*/
|
|
59430
|
+
status() {
|
|
59431
|
+
return this._status;
|
|
59432
|
+
}
|
|
59433
|
+
/**
|
|
59103
59434
|
* Returns the Date header value from the response or the current time if invalid.
|
|
59104
59435
|
* @returns {number} Timestamp (in milliseconds) representing the Date header or response time.
|
|
59105
59436
|
*/
|
|
@@ -62205,8 +62536,14 @@ var require_common = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
62205
62536
|
* {@link isInSubnet} when classifying a single address — notably when the
|
|
62206
62537
|
* address came from untrusted input and the result backs a trust-boundary
|
|
62207
62538
|
* decision such as an SSRF allow/deny filter.
|
|
62539
|
+
*
|
|
62540
|
+
* An address of one family is never inside a network of the other, so an
|
|
62541
|
+
* `Address4` against an `Address6` (or the reverse) is `false`. To compare
|
|
62542
|
+
* across families, convert first: `Address6.fromAddress4()`, `to4()`, or
|
|
62543
|
+
* `toAddress4Nat64()`.
|
|
62208
62544
|
*/
|
|
62209
62545
|
function isHostInSubnet(address) {
|
|
62546
|
+
if (this.binaryZeroPad().length !== address.binaryZeroPad().length) return false;
|
|
62210
62547
|
return this.mask(address.subnetMask) === address.mask();
|
|
62211
62548
|
}
|
|
62212
62549
|
/**
|
|
@@ -62493,7 +62830,9 @@ var require_ipv4 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
62493
62830
|
*/
|
|
62494
62831
|
this.isCorrect = isCorrect4;
|
|
62495
62832
|
/**
|
|
62496
|
-
* Returns true if the given address is in the subnet of the current address
|
|
62833
|
+
* Returns true if the given address is in the subnet of the current address.
|
|
62834
|
+
* An `Address6` is never in the subnet of an `Address4`; convert with
|
|
62835
|
+
* `to4()` or `Address6.fromAddress4()` to compare across families.
|
|
62497
62836
|
* @returns {boolean}
|
|
62498
62837
|
*/
|
|
62499
62838
|
this.isInSubnet = common.isInSubnet;
|
|
@@ -62503,6 +62842,8 @@ var require_ipv4 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
62503
62842
|
* when classifying a single address, so the answer doesn't change with the
|
|
62504
62843
|
* CIDR suffix the caller happened to write — notably when the address came
|
|
62505
62844
|
* from untrusted input and the result backs a trust-boundary decision.
|
|
62845
|
+
* An `Address6` is never in the subnet of an `Address4`; convert with
|
|
62846
|
+
* `to4()` or `Address6.fromAddress4()` to compare across families.
|
|
62506
62847
|
* @returns {boolean}
|
|
62507
62848
|
*/
|
|
62508
62849
|
this.isHostInSubnet = common.isHostInSubnet;
|
|
@@ -62515,6 +62856,8 @@ var require_ipv4 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
62515
62856
|
if (this.subnetMask < 0 || this.subnetMask > constants.BITS) throw new address_error_1.AddressError("Invalid subnet mask.");
|
|
62516
62857
|
address = address.replace(constants.RE_SUBNET_STRING, "");
|
|
62517
62858
|
}
|
|
62859
|
+
const longest = constants.GROUPS * 4 - 1;
|
|
62860
|
+
if (address.length > longest) throw new address_error_1.AddressError(`IPv4 addresses are at most ${longest} characters.`);
|
|
62518
62861
|
this.addressMinusSuffix = address;
|
|
62519
62862
|
this.parsedAddress = this.parse(address);
|
|
62520
62863
|
}
|
|
@@ -62631,15 +62974,20 @@ var require_ipv4 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
62631
62974
|
return Address4.fromHex(integer.toString(16).padStart(8, "0"));
|
|
62632
62975
|
}
|
|
62633
62976
|
/**
|
|
62634
|
-
* Return an address from in-addr.arpa form
|
|
62977
|
+
* Return an address from in-addr.arpa form: the four octets reversed, with
|
|
62978
|
+
* or without the `.in-addr.arpa` suffix and root dot, in any case. Throws
|
|
62979
|
+
* `AddressError` unless the reversed labels form a valid IPv4 address, so
|
|
62980
|
+
* `fromArpa(x.reverseForm())` round-trips {@link reverseForm}.
|
|
62635
62981
|
* @param {string} arpaFormAddress - an 'in-addr.arpa' form ipv4 address
|
|
62636
62982
|
* @returns {Adress4}
|
|
62637
62983
|
* @example
|
|
62638
|
-
* var address = Address4.fromArpa(42.2.0.192.in-addr.arpa.)
|
|
62984
|
+
* var address = Address4.fromArpa('42.2.0.192.in-addr.arpa.')
|
|
62639
62985
|
* address.correctForm(); // '192.0.2.42'
|
|
62640
62986
|
*/
|
|
62641
62987
|
static fromArpa(arpaFormAddress) {
|
|
62642
|
-
const
|
|
62988
|
+
const longest = constants.GROUPS * 4 - 1 + 3 + 14;
|
|
62989
|
+
if (arpaFormAddress.length > longest) throw new address_error_1.AddressError(`in-addr.arpa names are at most ${longest} characters.`);
|
|
62990
|
+
const address = arpaFormAddress.replace(/(\.in-addr\.arpa)?\.?$/i, "").split(".").reverse().join(".");
|
|
62643
62991
|
return new Address4(address);
|
|
62644
62992
|
}
|
|
62645
62993
|
/**
|
|
@@ -63420,7 +63768,9 @@ var require_ipv6 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
63420
63768
|
this.v4 = false;
|
|
63421
63769
|
this.zone = "";
|
|
63422
63770
|
/**
|
|
63423
|
-
* Returns true if the given address is in the subnet of the current address
|
|
63771
|
+
* Returns true if the given address is in the subnet of the current address.
|
|
63772
|
+
* An `Address4` is never in the subnet of an `Address6`; convert with
|
|
63773
|
+
* `Address6.fromAddress4()` or `to4()` to compare across families.
|
|
63424
63774
|
* @returns {boolean}
|
|
63425
63775
|
*/
|
|
63426
63776
|
this.isInSubnet = common.isInSubnet;
|
|
@@ -63430,6 +63780,8 @@ var require_ipv6 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
63430
63780
|
* when classifying a single address, so the answer doesn't change with the
|
|
63431
63781
|
* CIDR suffix the caller happened to write — notably when the address came
|
|
63432
63782
|
* from untrusted input and the result backs a trust-boundary decision.
|
|
63783
|
+
* An `Address4` is never in the subnet of an `Address6`; convert with
|
|
63784
|
+
* `Address6.fromAddress4()` or `to4()` to compare across families.
|
|
63433
63785
|
* @returns {boolean}
|
|
63434
63786
|
*/
|
|
63435
63787
|
this.isHostInSubnet = common.isHostInSubnet;
|
|
@@ -63455,6 +63807,8 @@ var require_ipv6 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
63455
63807
|
this.zone = zone[0];
|
|
63456
63808
|
address = address.replace(constants6.RE_ZONE_STRING, "");
|
|
63457
63809
|
}
|
|
63810
|
+
const longest = this.groups * 5 + 5;
|
|
63811
|
+
if (address.length > longest) throw new address_error_1.AddressError(`IPv6 addresses are at most ${longest} characters.`);
|
|
63458
63812
|
this.addressMinusSuffix = address;
|
|
63459
63813
|
this.parsedAddress = this.parse(this.addressMinusSuffix);
|
|
63460
63814
|
}
|
|
@@ -63640,7 +63994,7 @@ var require_ipv6 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
63640
63994
|
* Address6.fromArpa('8.b.d.0.1.0.0.2.ip6.arpa.').networkForm(); // '2001:db8::/32'
|
|
63641
63995
|
*/
|
|
63642
63996
|
static fromArpa(arpaFormAddress) {
|
|
63643
|
-
const nibbles = arpaFormAddress.replace(/(\.ip6\.arpa)
|
|
63997
|
+
const nibbles = arpaFormAddress.replace(/(\.ip6\.arpa)?\.?$/i, "");
|
|
63644
63998
|
if (!/^[0-9a-f](\.[0-9a-f]){0,31}$/i.test(nibbles)) throw new address_error_1.AddressError("Invalid 'ip6.arpa' form.");
|
|
63645
63999
|
const reversed = nibbles.split(".").reverse();
|
|
63646
64000
|
const subnetMask = reversed.length * 4;
|
|
@@ -65801,6 +66155,7 @@ var require_lib$14 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
65801
66155
|
});
|
|
65802
66156
|
if (agentCache.has(cacheKey)) return agentCache.get(cacheKey);
|
|
65803
66157
|
const newAgent = new Agent(normalizedOptions);
|
|
66158
|
+
newAgent.protocol = url.protocol;
|
|
65804
66159
|
agentCache.set(cacheKey, newAgent);
|
|
65805
66160
|
return newAgent;
|
|
65806
66161
|
};
|
|
@@ -65892,7 +66247,7 @@ var require_package$5 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
65892
66247
|
"publish": "true"
|
|
65893
66248
|
},
|
|
65894
66249
|
"_fyn": {},
|
|
65895
|
-
"_from": "make-fetch-happen@^16.0.
|
|
66250
|
+
"_from": "make-fetch-happen@^16.0.1",
|
|
65896
66251
|
"_id": "make-fetch-happen@16.0.1"
|
|
65897
66252
|
};
|
|
65898
66253
|
}));
|
|
@@ -86762,7 +87117,7 @@ var require_package_extensions = /* @__PURE__ */ __commonJSMin(((exports, module
|
|
|
86762
87117
|
var require_npm_extension = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
86763
87118
|
const { resolve: resolve$9, sep: sep$3 } = __require("node:path");
|
|
86764
87119
|
const { readFileSync, existsSync: existsSync$3 } = __require("node:fs");
|
|
86765
|
-
const { pathToFileURL } = __require("node:url");
|
|
87120
|
+
const { pathToFileURL: pathToFileURL$1 } = __require("node:url");
|
|
86766
87121
|
const { isDeepStrictEqual } = __require("node:util");
|
|
86767
87122
|
const { log } = require_lib$38();
|
|
86768
87123
|
const ssri = require_lib$23();
|
|
@@ -86831,7 +87186,7 @@ var require_npm_extension = /* @__PURE__ */ __commonJSMin(((exports, module) =>
|
|
|
86831
87186
|
async load() {
|
|
86832
87187
|
if (!this.present) return;
|
|
86833
87188
|
let mod;
|
|
86834
|
-
if (this.format === "mjs") mod = await import(`${pathToFileURL(this.path).href}?h=${this.hash}`);
|
|
87189
|
+
if (this.format === "mjs") mod = await import(`${pathToFileURL$1(this.path).href}?h=${this.hash}`);
|
|
86835
87190
|
else {
|
|
86836
87191
|
delete __require.cache[__require.resolve(this.path)];
|
|
86837
87192
|
mod = __require(this.path);
|
|
@@ -92175,10 +92530,11 @@ async function copyFile(srcFp, destFp) {
|
|
|
92175
92530
|
*
|
|
92176
92531
|
* @param {*} srcFp - source file path
|
|
92177
92532
|
* @param {*} destFp - destination file path
|
|
92533
|
+
* @param {*} noCopy - fail instead of falling back to a copy (always fails on macOS)
|
|
92178
92534
|
* @returns
|
|
92179
92535
|
*/
|
|
92180
|
-
async function cloneFile(srcFp, destFp) {
|
|
92181
|
-
return copyNew(srcFp, destFp, fs.constants.COPYFILE_FICLONE);
|
|
92536
|
+
async function cloneFile(srcFp, destFp, noCopy = false) {
|
|
92537
|
+
return copyNew(srcFp, destFp, noCopy ? fs.constants.COPYFILE_FICLONE_FORCE : fs.constants.COPYFILE_FICLONE);
|
|
92182
92538
|
}
|
|
92183
92539
|
async function prepDestDir(dest) {
|
|
92184
92540
|
const statDest = await tryCatch(() => file_ops_default.lstat(dest));
|
|
@@ -92679,6 +93035,15 @@ function getBucketPath(cache, key) {
|
|
|
92679
93035
|
return Path.join(cache, `index-v${indexV}`, hashed.slice(0, 2), hashed.slice(2, 4), hashed.slice(4));
|
|
92680
93036
|
}
|
|
92681
93037
|
/**
|
|
93038
|
+
* Get the content file path for an integrity that cacache matched, such as the `sri` from
|
|
93039
|
+
* `get.hasContent`. Same layout as cacache: the algorithm, then the hex digest in segments.
|
|
93040
|
+
*/
|
|
93041
|
+
function getContentPath(cache, sri) {
|
|
93042
|
+
const hex = sri.hexDigest();
|
|
93043
|
+
const contentV = import_package.default["cache-version"].content;
|
|
93044
|
+
return Path.join(cache, `content-v${contentV}`, sri.algorithm, hex.slice(0, 2), hex.slice(2, 4), hex.slice(4));
|
|
93045
|
+
}
|
|
93046
|
+
/**
|
|
92682
93047
|
* Update cache entry refresh timestamp by modifying bucket file mtime.
|
|
92683
93048
|
* Does not modify file contents, only filesystem metadata.
|
|
92684
93049
|
* Errors are silently ignored (cache refresh is non-critical).
|
|
@@ -92714,7 +93079,7 @@ async function getCacheInfoWithRefreshTime(cache, key) {
|
|
|
92714
93079
|
//#endregion
|
|
92715
93080
|
//#region lib/util/trimmed-packument.ts
|
|
92716
93081
|
/** Bump when the kept fields change, so files from older versions are rebuilt. */
|
|
92717
|
-
const TRIMMED_FORMAT =
|
|
93082
|
+
const TRIMMED_FORMAT = 2;
|
|
92718
93083
|
/**
|
|
92719
93084
|
* The version fields fyn reads from a registry packument. Code that starts reading another
|
|
92720
93085
|
* field from `meta.versions[v]` must add it here and bump TRIMMED_FORMAT.
|
|
@@ -92731,6 +93096,7 @@ const KEEP_VERSION_FIELDS = [
|
|
|
92731
93096
|
"cpu",
|
|
92732
93097
|
"deprecated",
|
|
92733
93098
|
"_hasShrinkwrap",
|
|
93099
|
+
"_shrinkwrap",
|
|
92734
93100
|
"fyn"
|
|
92735
93101
|
];
|
|
92736
93102
|
/** Only the install hooks are read from `scripts`. */
|
|
@@ -92762,7 +93128,7 @@ function trimPackument(packument) {
|
|
|
92762
93128
|
versions[version] = trimmed;
|
|
92763
93129
|
}
|
|
92764
93130
|
return {
|
|
92765
|
-
$format:
|
|
93131
|
+
$format: 2,
|
|
92766
93132
|
name: packument.name,
|
|
92767
93133
|
"dist-tags": packument["dist-tags"],
|
|
92768
93134
|
time: packument.time,
|
|
@@ -92775,33 +93141,68 @@ function trimmedPackumentFile(dir, packumentUrl) {
|
|
|
92775
93141
|
return Path.join(dir, `${hash}.json`);
|
|
92776
93142
|
}
|
|
92777
93143
|
/**
|
|
92778
|
-
* Read a trimmed packument
|
|
92779
|
-
* unreadable, or from another format, so the caller falls back to the full copy.
|
|
93144
|
+
* Read a trimmed packument, its refresh time, and its validators. Resolves undefined when the
|
|
93145
|
+
* file is missing, unreadable, or from another format, so the caller falls back to the full copy.
|
|
92780
93146
|
*/
|
|
92781
93147
|
async function readTrimmedPackument(file) {
|
|
92782
93148
|
try {
|
|
92783
93149
|
const [data, stat] = await Promise.all([fs.promises.readFile(file), fs.promises.stat(file)]);
|
|
92784
|
-
const
|
|
92785
|
-
|
|
92786
|
-
|
|
92787
|
-
return {
|
|
92788
|
-
packument,
|
|
93150
|
+
const parsed = parseTrimmed(data.toString());
|
|
93151
|
+
return parsed && {
|
|
93152
|
+
...parsed,
|
|
92789
93153
|
refreshTime: stat.mtimeMs
|
|
92790
93154
|
};
|
|
92791
93155
|
} catch {
|
|
92792
93156
|
return;
|
|
92793
93157
|
}
|
|
92794
93158
|
}
|
|
93159
|
+
/** Parse a trimmed copy's JSON into the packument and its validators. Undefined for another format. */
|
|
93160
|
+
function parseTrimmed(json) {
|
|
93161
|
+
const packument = JSON.parse(json);
|
|
93162
|
+
if (packument.$format !== 2) return void 0;
|
|
93163
|
+
const { $etag: etag, $lastModified: lastModified, $corgi: corgi } = packument;
|
|
93164
|
+
delete packument.$format;
|
|
93165
|
+
delete packument.$etag;
|
|
93166
|
+
delete packument.$lastModified;
|
|
93167
|
+
delete packument.$corgi;
|
|
93168
|
+
return {
|
|
93169
|
+
packument,
|
|
93170
|
+
etag,
|
|
93171
|
+
lastModified,
|
|
93172
|
+
corgi
|
|
93173
|
+
};
|
|
93174
|
+
}
|
|
93175
|
+
/** Mark a trimmed packument as refreshed now, after the registry said it hasn't changed */
|
|
93176
|
+
async function touchTrimmedPackument(file) {
|
|
93177
|
+
const now = /* @__PURE__ */ new Date();
|
|
93178
|
+
await fs.promises.utimes(file, now, now).catch(() => void 0);
|
|
93179
|
+
}
|
|
92795
93180
|
/**
|
|
92796
93181
|
* Write a trimmed copy of a packument. The write goes to a temp file renamed over the target,
|
|
92797
93182
|
* so concurrent installs never read half a file. `refreshTime` sets the mtime when the copy is
|
|
92798
|
-
* made from an existing cache entry rather than a fresh fetch. Failures are ignored: the
|
|
92799
|
-
*
|
|
93183
|
+
* made from an existing cache entry rather than a fresh fetch. Failures are ignored: the next
|
|
93184
|
+
* install fetches the packument again.
|
|
92800
93185
|
*/
|
|
92801
|
-
async function writeTrimmedPackument(file, packument, refreshTime) {
|
|
93186
|
+
async function writeTrimmedPackument(file, packument, refreshTime, validators) {
|
|
93187
|
+
let json;
|
|
93188
|
+
try {
|
|
93189
|
+
json = trimmedJson(trimPackument(packument), validators);
|
|
93190
|
+
} catch {
|
|
93191
|
+
return;
|
|
93192
|
+
}
|
|
93193
|
+
await writeTrimmed(file, json, refreshTime);
|
|
93194
|
+
}
|
|
93195
|
+
function trimmedJson(trimmed, validators) {
|
|
93196
|
+
return JSON.stringify({
|
|
93197
|
+
...trimmed,
|
|
93198
|
+
$etag: validators?.etag,
|
|
93199
|
+
$lastModified: validators?.lastModified,
|
|
93200
|
+
$corgi: validators?.corgi || void 0
|
|
93201
|
+
});
|
|
93202
|
+
}
|
|
93203
|
+
async function writeTrimmed(file, data, refreshTime) {
|
|
92802
93204
|
const tmp = `${file}.${process.pid}.${Crypto.randomBytes(4).toString("hex")}.tmp`;
|
|
92803
93205
|
try {
|
|
92804
|
-
const data = JSON.stringify(trimPackument(packument));
|
|
92805
93206
|
try {
|
|
92806
93207
|
await fs.promises.writeFile(tmp, data);
|
|
92807
93208
|
} catch (err) {
|
|
@@ -92818,9 +93219,160 @@ async function writeTrimmedPackument(file, packument, refreshTime) {
|
|
|
92818
93219
|
await fs.promises.rm(tmp, { force: true }).catch(() => void 0);
|
|
92819
93220
|
}
|
|
92820
93221
|
}
|
|
93222
|
+
/** Parse a registry response body, as sent with `encoding` */
|
|
93223
|
+
function decodePackument(data, encoding) {
|
|
93224
|
+
const json = encoding === "gzip" || encoding === "x-gzip" || encoding === "deflate" ? en.unzipSync(data) : encoding === "br" ? en.brotliDecompressSync(data) : data;
|
|
93225
|
+
return JSON.parse(Buffer.from(json.buffer, json.byteOffset, json.byteLength).toString());
|
|
93226
|
+
}
|
|
93227
|
+
/**
|
|
93228
|
+
* Decode a packument response and write its trimmed copy. The abbreviated form only flags that
|
|
93229
|
+
* a version has install scripts, and fyn records which ones, so one with any isn't saved. This
|
|
93230
|
+
* is the CPU-heavy part of a packument fetch, so an fs worker runs it when fyn has them built.
|
|
93231
|
+
*/
|
|
93232
|
+
async function savePackument(job) {
|
|
93233
|
+
const packument = decodePackument(job.data, job.encoding);
|
|
93234
|
+
if (job.corgi && Object.values(packument.versions || {}).some((v) => v.hasInstallScript)) return { needFull: true };
|
|
93235
|
+
return { json: await saveTrimmed(job.file, packument, job) };
|
|
93236
|
+
}
|
|
93237
|
+
/** Trim a packument and write it with its validators. @returns the JSON written */
|
|
93238
|
+
async function saveTrimmed(file, packument, validators) {
|
|
93239
|
+
const text = trimmedJson(trimPackument(packument), validators);
|
|
93240
|
+
await writeTrimmed(file, text);
|
|
93241
|
+
return text;
|
|
93242
|
+
}
|
|
93243
|
+
|
|
93244
|
+
//#endregion
|
|
93245
|
+
//#region lib/util/registry-get.ts
|
|
93246
|
+
let load;
|
|
93247
|
+
const loadRegistryFetch = () => load ??= Promise.all([Promise.resolve().then(() => /* @__PURE__ */ __toESM(require_lib$13(), 1)), Promise.resolve().then(() => /* @__PURE__ */ __toESM(require_lib$12(), 1))]).then(([mfh, nrf]) => ({
|
|
93248
|
+
fetch: mfh.default,
|
|
93249
|
+
getAuth: nrf.default.getAuth
|
|
93250
|
+
}));
|
|
93251
|
+
/** The plain values of `opts`, which is all auth needs and all that can go to a worker */
|
|
93252
|
+
function pickRegistryOpts(opts) {
|
|
93253
|
+
const out = {};
|
|
93254
|
+
for (const [k, v] of Object.entries(opts)) if (v === void 0 || [
|
|
93255
|
+
"string",
|
|
93256
|
+
"number",
|
|
93257
|
+
"boolean"
|
|
93258
|
+
].includes(typeof v)) out[k] = v;
|
|
93259
|
+
return out;
|
|
93260
|
+
}
|
|
93261
|
+
/** getAuth results, per opts, by authCacheKey */
|
|
93262
|
+
const authCaches = /* @__PURE__ */ new WeakMap();
|
|
93263
|
+
/**
|
|
93264
|
+
* What getAuth's result for `url` depends on. It walks up the URL's path for the longest
|
|
93265
|
+
* `//host/path` that has auth configured, and without one, falls back to the registry's auth.
|
|
93266
|
+
* So it's the longest configured prefix that matches, else the host.
|
|
93267
|
+
*/
|
|
93268
|
+
function authCacheKey(url, prefixes) {
|
|
93269
|
+
const m = /^[a-z]+:(\/\/[^/?#]+)([^?#]*)/i.exec(url);
|
|
93270
|
+
if (!m) return void 0;
|
|
93271
|
+
const full = m[1] + m[2];
|
|
93272
|
+
let best = "";
|
|
93273
|
+
for (const p of prefixes) if (p.length > best.length && full.startsWith(p) && (p.endsWith("/") || full.length === p.length || full[p.length] === "/")) best = p;
|
|
93274
|
+
return best || `host ${m[1]}`;
|
|
93275
|
+
}
|
|
93276
|
+
function cachedAuth(getAuth, url, opts) {
|
|
93277
|
+
if (opts.forceAuth) return getAuth(url, opts);
|
|
93278
|
+
let cache = authCaches.get(opts);
|
|
93279
|
+
if (!cache) {
|
|
93280
|
+
cache = {
|
|
93281
|
+
prefixes: Object.keys(opts).map((k) => /^(\/\/.+):(_authToken|_auth|username|_password|certfile|keyfile)$/.exec(k)?.[1]).filter((p) => Boolean(p)),
|
|
93282
|
+
auths: /* @__PURE__ */ new Map()
|
|
93283
|
+
};
|
|
93284
|
+
authCaches.set(opts, cache);
|
|
93285
|
+
}
|
|
93286
|
+
const key = authCacheKey(url, cache.prefixes);
|
|
93287
|
+
if (key === void 0) return getAuth(url, opts);
|
|
93288
|
+
let auth = cache.auths.get(key);
|
|
93289
|
+
if (!auth) cache.auths.set(key, auth = getAuth(url, opts));
|
|
93290
|
+
return auth;
|
|
93291
|
+
}
|
|
93292
|
+
/** Statuses from 400 up throw */
|
|
93293
|
+
async function registryGet(url, extraHeaders, opts) {
|
|
93294
|
+
const { fetch, getAuth } = await loadRegistryFetch();
|
|
93295
|
+
const auth = cachedAuth(getAuth, url, opts);
|
|
93296
|
+
const headers = {
|
|
93297
|
+
"user-agent": `fyn node/${process.version}`,
|
|
93298
|
+
...extraHeaders
|
|
93299
|
+
};
|
|
93300
|
+
if (auth.token) headers.authorization = `Bearer ${auth.token}`;
|
|
93301
|
+
else if (auth.auth) headers.authorization = `Basic ${auth.auth}`;
|
|
93302
|
+
const res = await fetch(url, {
|
|
93303
|
+
headers,
|
|
93304
|
+
compress: false,
|
|
93305
|
+
cert: auth.cert,
|
|
93306
|
+
key: auth.key,
|
|
93307
|
+
maxSockets: opts.maxSockets,
|
|
93308
|
+
noProxy: process.env.NOPROXY,
|
|
93309
|
+
retry: { retries: 3 },
|
|
93310
|
+
timeout: 3e5
|
|
93311
|
+
});
|
|
93312
|
+
if (res.status >= 400) {
|
|
93313
|
+
res.body.resume();
|
|
93314
|
+
throw Object.assign(/* @__PURE__ */ new Error(`${res.status} ${res.statusText} - GET ${url}`), {
|
|
93315
|
+
code: `E${res.status}`,
|
|
93316
|
+
statusCode: res.status
|
|
93317
|
+
});
|
|
93318
|
+
}
|
|
93319
|
+
return res;
|
|
93320
|
+
}
|
|
93321
|
+
/** npm's abbreviated install metadata, about a third the size of a full packument */
|
|
93322
|
+
const CORGI_DOC = "application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*";
|
|
93323
|
+
/**
|
|
93324
|
+
* The request headers for a packument, with validators so the registry can answer 304.
|
|
93325
|
+
*
|
|
93326
|
+
* @param full - ask for the full packument, not the abbreviated one
|
|
93327
|
+
*/
|
|
93328
|
+
function packumentHeaders(validators, full) {
|
|
93329
|
+
const headers = {
|
|
93330
|
+
accept: full ? "application/json" : CORGI_DOC,
|
|
93331
|
+
"accept-encoding": "gzip"
|
|
93332
|
+
};
|
|
93333
|
+
if (validators?.etag) headers["if-none-match"] = validators.etag;
|
|
93334
|
+
if (validators?.lastModified) headers["if-modified-since"] = validators.lastModified;
|
|
93335
|
+
return headers;
|
|
93336
|
+
}
|
|
93337
|
+
/**
|
|
93338
|
+
* Fetch a packument and write fyn's trimmed copy of it. It starts with the abbreviated form, and
|
|
93339
|
+
* gets the full one when `save` finds that abbreviated isn't enough.
|
|
93340
|
+
*
|
|
93341
|
+
* @param get - does the GET, registryGet with the job's opts by default
|
|
93342
|
+
* @param save - decodes and writes the response; an fs worker can run it
|
|
93343
|
+
*/
|
|
93344
|
+
async function fetchPackument(job, get, save = savePackument) {
|
|
93345
|
+
const doGet = get || ((url, headers) => registryGet(url, headers, job.opts || {}));
|
|
93346
|
+
const request = async (headers) => {
|
|
93347
|
+
const res = await doGet(job.url, headers);
|
|
93348
|
+
if (res.status === 304) {
|
|
93349
|
+
res.body?.resume();
|
|
93350
|
+
return;
|
|
93351
|
+
}
|
|
93352
|
+
const header = (name) => res.headers.get(name) || void 0;
|
|
93353
|
+
return {
|
|
93354
|
+
data: await res.buffer(),
|
|
93355
|
+
encoding: header("content-encoding"),
|
|
93356
|
+
etag: header("etag"),
|
|
93357
|
+
lastModified: header("last-modified"),
|
|
93358
|
+
corgi: /vnd\.npm\.install-v1/.test(header("content-type") || ""),
|
|
93359
|
+
file: job.file
|
|
93360
|
+
};
|
|
93361
|
+
};
|
|
93362
|
+
const first = await request(packumentHeaders(job, job.full));
|
|
93363
|
+
if (!first) return { status: 304 };
|
|
93364
|
+
let saved = await save(first);
|
|
93365
|
+
if ("needFull" in saved) saved = await save(await request(packumentHeaders(void 0, true)));
|
|
93366
|
+
if ("needFull" in saved) throw new Error(`no full packument from ${job.url}`);
|
|
93367
|
+
return {
|
|
93368
|
+
status: 200,
|
|
93369
|
+
json: saved.json
|
|
93370
|
+
};
|
|
93371
|
+
}
|
|
92821
93372
|
|
|
92822
93373
|
//#endregion
|
|
92823
93374
|
//#region lib/util/inflight.ts
|
|
93375
|
+
var import_lib = /* @__PURE__ */ __toESM(require_lib$23(), 1);
|
|
92824
93376
|
var inflight_default = InflightStore;
|
|
92825
93377
|
|
|
92826
93378
|
//#endregion
|
|
@@ -92855,7 +93407,10 @@ var PkgPreper = class {
|
|
|
92855
93407
|
};
|
|
92856
93408
|
return Promise.resolve((0, import_lib$2.default)(treeStub)).then((files) => {
|
|
92857
93409
|
return Qn(tarOpt, files.map((f) => `./${f}`));
|
|
92858
|
-
}).then(() => FsPromises.rename(tmpTarget, target)
|
|
93410
|
+
}).then(() => FsPromises.rename(tmpTarget, target).catch((err) => {
|
|
93411
|
+
if (err.code !== "EXDEV") throw err;
|
|
93412
|
+
return FsPromises.copyFile(tmpTarget, target);
|
|
93413
|
+
})).then(() => void 0);
|
|
92859
93414
|
});
|
|
92860
93415
|
});
|
|
92861
93416
|
}
|
|
@@ -92872,7 +93427,7 @@ var PkgPreper = class {
|
|
|
92872
93427
|
});
|
|
92873
93428
|
});
|
|
92874
93429
|
}).catch((err) => {
|
|
92875
|
-
stream.
|
|
93430
|
+
stream.destroy(err);
|
|
92876
93431
|
});
|
|
92877
93432
|
return stream;
|
|
92878
93433
|
}
|
|
@@ -92883,7 +93438,6 @@ var PkgPreper = class {
|
|
|
92883
93438
|
|
|
92884
93439
|
//#endregion
|
|
92885
93440
|
//#region node_modules/xsh/dist/util.js
|
|
92886
|
-
var import_lib = /* @__PURE__ */ __toESM(require_lib$23(), 1);
|
|
92887
93441
|
/**
|
|
92888
93442
|
* Mutable holder for the Promise implementation xsh uses.
|
|
92889
93443
|
*
|
|
@@ -93112,12 +93666,11 @@ const envPath = {
|
|
|
93112
93666
|
//#endregion
|
|
93113
93667
|
//#region node_modules/xsh/dist/mkcmd.js
|
|
93114
93668
|
/**
|
|
93115
|
-
* Make a command string:
|
|
93116
|
-
*
|
|
93669
|
+
* Make a command string: every argument, string or array of strings,
|
|
93670
|
+
* contributes its words in order, joined with `" "`.
|
|
93117
93671
|
*/
|
|
93118
93672
|
function mkCmd(...args) {
|
|
93119
|
-
|
|
93120
|
-
return Array.isArray(a) ? a.join(" ") : args.join(" ");
|
|
93673
|
+
return args.flat().join(" ");
|
|
93121
93674
|
}
|
|
93122
93675
|
|
|
93123
93676
|
//#endregion
|
|
@@ -93268,19 +93821,14 @@ const TEN_MB = 10485760;
|
|
|
93268
93821
|
const DEFAULT_TIMEOUT_GRACE = 5e3;
|
|
93269
93822
|
const DEFAULT_LAST_LINES = 10;
|
|
93270
93823
|
const MAX_OUTPUT_IN_ERROR = 5e4;
|
|
93271
|
-
function createTimeoutError(
|
|
93272
|
-
const err = /* @__PURE__ */ new Error(`Command timed out after ${elapsed}ms: ${
|
|
93824
|
+
function createTimeoutError(command, elapsed) {
|
|
93825
|
+
const err = /* @__PURE__ */ new Error(`Command timed out after ${elapsed}ms: ${command}`);
|
|
93273
93826
|
err.name = "TimeoutError";
|
|
93274
|
-
err.context = {
|
|
93275
|
-
...context,
|
|
93276
|
-
duration: elapsed
|
|
93277
|
-
};
|
|
93278
93827
|
return err;
|
|
93279
93828
|
}
|
|
93280
|
-
function createAbortError(
|
|
93281
|
-
const err = /* @__PURE__ */ new Error(`Command aborted: ${
|
|
93829
|
+
function createAbortError(command) {
|
|
93830
|
+
const err = /* @__PURE__ */ new Error(`Command aborted: ${command}`);
|
|
93282
93831
|
err.name = "AbortError";
|
|
93283
|
-
err.context = context;
|
|
93284
93832
|
return err;
|
|
93285
93833
|
}
|
|
93286
93834
|
function lastLines(text, n) {
|
|
@@ -93388,7 +93936,7 @@ var VisualExec = class {
|
|
|
93388
93936
|
}
|
|
93389
93937
|
_extractProgress(line) {
|
|
93390
93938
|
const cfg = this._progress;
|
|
93391
|
-
if (!cfg || !this._onProgress) return;
|
|
93939
|
+
if (!cfg || !(this._onProgress || cfg.format)) return;
|
|
93392
93940
|
let progress = null;
|
|
93393
93941
|
if (cfg.extract) progress = cfg.extract(line);
|
|
93394
93942
|
else if (cfg.pattern) {
|
|
@@ -93399,7 +93947,24 @@ var VisualExec = class {
|
|
|
93399
93947
|
percent: m.groups.percent ? parseInt(m.groups.percent, 10) : void 0
|
|
93400
93948
|
};
|
|
93401
93949
|
}
|
|
93402
|
-
if (progress)
|
|
93950
|
+
if (!progress) return;
|
|
93951
|
+
if (cfg.format) {
|
|
93952
|
+
const text = cfg.format(progress);
|
|
93953
|
+
if (text !== this._progressText) {
|
|
93954
|
+
this._progressText = text;
|
|
93955
|
+
this._renderDigest(this._stdoutDigest);
|
|
93956
|
+
}
|
|
93957
|
+
}
|
|
93958
|
+
if (this._onProgress) this._onProgress(progress);
|
|
93959
|
+
}
|
|
93960
|
+
_renderDigest(item) {
|
|
93961
|
+
const display = item === this._stdoutDigest && this._progressText ? `=== ${this._title}\nstdout ${this._progressText}` : void 0;
|
|
93962
|
+
this._logger.updateItem(item.name, {
|
|
93963
|
+
msg: item.msg,
|
|
93964
|
+
display,
|
|
93965
|
+
_save: false,
|
|
93966
|
+
_render: false
|
|
93967
|
+
});
|
|
93403
93968
|
}
|
|
93404
93969
|
_updateDigest(item, buf) {
|
|
93405
93970
|
const lines = (item.buf + sanitizeForDisplay(buf)).split("\n").map((x) => x && x.trim()).filter((x) => x);
|
|
@@ -93420,11 +93985,8 @@ var VisualExec = class {
|
|
|
93420
93985
|
msgs = [item.buf];
|
|
93421
93986
|
} else item.buf = msgs.join("\n");
|
|
93422
93987
|
if (buf.endsWith("\n")) item.buf += "\n";
|
|
93423
|
-
|
|
93424
|
-
|
|
93425
|
-
_save: false,
|
|
93426
|
-
_render: false
|
|
93427
|
-
});
|
|
93988
|
+
item.msg = msgs.join(chalk.blue.inverse("\\n"));
|
|
93989
|
+
this._renderDigest(item);
|
|
93428
93990
|
}
|
|
93429
93991
|
_createDataHandler(stream) {
|
|
93430
93992
|
return (buf) => {
|
|
@@ -93459,6 +94021,9 @@ var VisualExec = class {
|
|
|
93459
94021
|
* it defaults to `ExecOutput`, which is what a run without an `onComplete` produces.
|
|
93460
94022
|
*/
|
|
93461
94023
|
show(child) {
|
|
94024
|
+
return this._show(child, this._command);
|
|
94025
|
+
}
|
|
94026
|
+
_show(child, command) {
|
|
93462
94027
|
this._stdoutKey = Symbol("visual-exec-stdout");
|
|
93463
94028
|
this._stderrKey = Symbol("visual-exec-stderr");
|
|
93464
94029
|
this._rawChild = child.child;
|
|
@@ -93477,19 +94042,30 @@ var VisualExec = class {
|
|
|
93477
94042
|
name: this._stdoutKey,
|
|
93478
94043
|
buf: ""
|
|
93479
94044
|
};
|
|
94045
|
+
this._stdoutDigest = stdoutDigest;
|
|
93480
94046
|
const stderrDigest = {
|
|
93481
94047
|
name: this._stderrKey,
|
|
93482
94048
|
buf: ""
|
|
93483
94049
|
};
|
|
93484
94050
|
this._updateStdout = (buf) => this._updateDigest(stdoutDigest, buf);
|
|
93485
94051
|
this._updateStderr = (buf) => this._updateDigest(stderrDigest, buf);
|
|
94052
|
+
const seen = {
|
|
94053
|
+
stdout: "",
|
|
94054
|
+
stderr: ""
|
|
94055
|
+
};
|
|
94056
|
+
const capture = (stream, data) => {
|
|
94057
|
+
const text = seen[stream] + data;
|
|
94058
|
+
seen[stream] = text.length > MAX_OUTPUT_IN_ERROR ? text.slice(-5e4) : text;
|
|
94059
|
+
};
|
|
93486
94060
|
this._onStdoutData = (buf) => {
|
|
93487
94061
|
const data = typeof buf === "string" ? buf : buf.toString();
|
|
94062
|
+
capture("stdout", data);
|
|
93488
94063
|
this._updateStdout(data);
|
|
93489
94064
|
this._createDataHandler("stdout")(buf);
|
|
93490
94065
|
};
|
|
93491
94066
|
this._onStderrData = (buf) => {
|
|
93492
94067
|
const data = typeof buf === "string" ? buf : buf.toString();
|
|
94068
|
+
capture("stderr", data);
|
|
93493
94069
|
this._updateStderr(data);
|
|
93494
94070
|
this._createDataHandler("stderr")(buf);
|
|
93495
94071
|
};
|
|
@@ -93508,7 +94084,9 @@ var VisualExec = class {
|
|
|
93508
94084
|
stderr: ""
|
|
93509
94085
|
};
|
|
93510
94086
|
const exitCode = (_d = (_c = err.exitCode) !== null && _c !== void 0 ? _c : err.code) !== null && _d !== void 0 ? _d : 1;
|
|
93511
|
-
|
|
94087
|
+
try {
|
|
94088
|
+
(_a = this._onComplete) === null || _a === void 0 || _a.call(this, output, exitCode);
|
|
94089
|
+
} catch (_e) {}
|
|
93512
94090
|
this.logResult(err);
|
|
93513
94091
|
throw err;
|
|
93514
94092
|
}).then((output) => {
|
|
@@ -93517,6 +94095,20 @@ var VisualExec = class {
|
|
|
93517
94095
|
const result = (_a = this._onComplete) === null || _a === void 0 ? void 0 : _a.call(this, output, 0);
|
|
93518
94096
|
return result !== void 0 ? result : output;
|
|
93519
94097
|
});
|
|
94098
|
+
const cancelError = (err, duration) => {
|
|
94099
|
+
const output = { ...seen };
|
|
94100
|
+
err.output = output;
|
|
94101
|
+
return enhanceError(err, {
|
|
94102
|
+
exitCode: -1,
|
|
94103
|
+
signal: "SIGTERM",
|
|
94104
|
+
cwd: this._cwd,
|
|
94105
|
+
command,
|
|
94106
|
+
duration,
|
|
94107
|
+
lastLines: lastLines(`${output.stdout}\n${output.stderr}`, DEFAULT_LAST_LINES),
|
|
94108
|
+
stdout: output.stdout,
|
|
94109
|
+
stderr: output.stderr
|
|
94110
|
+
});
|
|
94111
|
+
};
|
|
93520
94112
|
if (this._timeout) {
|
|
93521
94113
|
const timeoutPromise = new Promise((_, reject) => {
|
|
93522
94114
|
timeoutId = setTimeout(() => {
|
|
@@ -93530,18 +94122,15 @@ var VisualExec = class {
|
|
|
93530
94122
|
if ((_a = this._rawChild) === null || _a === void 0 ? void 0 : _a.pid) this._rawChild.kill("SIGKILL");
|
|
93531
94123
|
}, this._timeoutGrace)).unref) === null || _d === void 0 || _d.call(_c);
|
|
93532
94124
|
}
|
|
93533
|
-
reject(createTimeoutError(
|
|
93534
|
-
command: this._command,
|
|
93535
|
-
cwd: this._cwd,
|
|
93536
|
-
exitCode: -1,
|
|
93537
|
-
signal: "SIGTERM"
|
|
93538
|
-
}, this._timeout));
|
|
94125
|
+
reject(cancelError(createTimeoutError(command, this._timeout), this._timeout));
|
|
93539
94126
|
}, this._timeout);
|
|
93540
94127
|
});
|
|
93541
94128
|
execPromise = Promise.race([execPromise, timeoutPromise]);
|
|
93542
94129
|
}
|
|
94130
|
+
let handleAbort;
|
|
93543
94131
|
const cleanup = () => {
|
|
93544
94132
|
if (timeoutId) clearTimeout(timeoutId);
|
|
94133
|
+
if (handleAbort) this._signal.removeEventListener("abort", handleAbort);
|
|
93545
94134
|
const stream = this._outputStream;
|
|
93546
94135
|
this._outputStream = void 0;
|
|
93547
94136
|
if (!(stream === null || stream === void 0 ? void 0 : stream.end)) return;
|
|
@@ -93554,15 +94143,9 @@ var VisualExec = class {
|
|
|
93554
94143
|
};
|
|
93555
94144
|
if (this._signal) {
|
|
93556
94145
|
const abortPromise = new Promise((_, reject) => {
|
|
93557
|
-
|
|
94146
|
+
handleAbort = () => {
|
|
93558
94147
|
this.abort();
|
|
93559
|
-
reject(createAbortError(
|
|
93560
|
-
command: this._command,
|
|
93561
|
-
cwd: this._cwd,
|
|
93562
|
-
exitCode: -1,
|
|
93563
|
-
signal: "SIGTERM",
|
|
93564
|
-
duration: Date.now() - startTime
|
|
93565
|
-
}));
|
|
94148
|
+
reject(cancelError(createAbortError(command), Date.now() - startTime));
|
|
93566
94149
|
};
|
|
93567
94150
|
if (this._signal.aborted) handleAbort();
|
|
93568
94151
|
else this._signal.addEventListener("abort", handleAbort);
|
|
@@ -93667,7 +94250,7 @@ var VisualExec = class {
|
|
|
93667
94250
|
};
|
|
93668
94251
|
return Promise.reject(enhanceError(err, context));
|
|
93669
94252
|
});
|
|
93670
|
-
return this.
|
|
94253
|
+
return this._show(child, cmd);
|
|
93671
94254
|
}
|
|
93672
94255
|
};
|
|
93673
94256
|
|
|
@@ -93711,7 +94294,8 @@ function renameFromObj(obj, rename) {
|
|
|
93711
94294
|
function removeFromObj(obj, fields) {
|
|
93712
94295
|
for (const f of fields) if (typeof f === "string") deleteFields(f, obj);
|
|
93713
94296
|
else Object.keys(f).forEach((f2) => {
|
|
93714
|
-
|
|
94297
|
+
const sub = obj[f2];
|
|
94298
|
+
if (sub) removeFromObj(sub, f[f2]);
|
|
93715
94299
|
});
|
|
93716
94300
|
}
|
|
93717
94301
|
function extractFromObj(obj, fields, output = {}) {
|
|
@@ -93783,6 +94367,7 @@ const keepStandardFields = [
|
|
|
93783
94367
|
|
|
93784
94368
|
//#endregion
|
|
93785
94369
|
//#region node_modules/publish-util/dist/prepack.js
|
|
94370
|
+
const runsPrePack = (script) => typeof script === "string" && script.includes("publish-util-prepack");
|
|
93786
94371
|
function prePackObj(pkg, config = {}) {
|
|
93787
94372
|
renameFromObj(pkg, config.rename);
|
|
93788
94373
|
const keepObj = config.keep && extractFromObj(pkg, config.keep);
|
|
@@ -93800,7 +94385,8 @@ function prePackObj(pkg, config = {}) {
|
|
|
93800
94385
|
if (!config.silent) console.log("scripts.postpack missing, adding it.\n To skip this, set publishUtil.autoPostPack to false");
|
|
93801
94386
|
set(pkg, "scripts.postpack", "publish-util-postpack");
|
|
93802
94387
|
}
|
|
93803
|
-
if (
|
|
94388
|
+
if (scripts && runsPrePack(scripts.prepack)) delete scripts.prepack;
|
|
94389
|
+
if ((scripts === null || scripts === void 0 ? void 0 : scripts.prepublishOnly) === "publish-util-prepublishonly") delete scripts.prepublishOnly;
|
|
93804
94390
|
if (keepObj) merge(pkg, keepObj);
|
|
93805
94391
|
}
|
|
93806
94392
|
|
|
@@ -94464,6 +95050,7 @@ var PkgSrcManager = class {
|
|
|
94464
95050
|
/** trimmed packument copies, see util/trimmed-packument */
|
|
94465
95051
|
_packumentDir;
|
|
94466
95052
|
_lastMetaStatus;
|
|
95053
|
+
_registryOpts;
|
|
94467
95054
|
_fetching;
|
|
94468
95055
|
_fetchingMsg;
|
|
94469
95056
|
constructor(options) {
|
|
@@ -94665,33 +95252,38 @@ var PkgSrcManager = class {
|
|
|
94665
95252
|
this.updateFetchMetaStatus();
|
|
94666
95253
|
}
|
|
94667
95254
|
};
|
|
94668
|
-
const
|
|
94669
|
-
logger$1.debug(`
|
|
94670
|
-
|
|
94671
|
-
|
|
94672
|
-
|
|
94673
|
-
|
|
94674
|
-
|
|
94675
|
-
|
|
94676
|
-
|
|
94677
|
-
|
|
94678
|
-
|
|
94679
|
-
|
|
94680
|
-
|
|
94681
|
-
|
|
94682
|
-
if (
|
|
94683
|
-
|
|
94684
|
-
|
|
94685
|
-
|
|
94686
|
-
|
|
95255
|
+
const registryRequest = async () => {
|
|
95256
|
+
logger$1.debug(`fetch packument ${qItem.packumentUrl}`);
|
|
95257
|
+
const { cached } = qItem;
|
|
95258
|
+
const file = trimmedPackumentFile(this._packumentDir, qItem.packumentUrl);
|
|
95259
|
+
try {
|
|
95260
|
+
const job = {
|
|
95261
|
+
url: qItem.packumentUrl,
|
|
95262
|
+
file,
|
|
95263
|
+
etag: cached?.etag,
|
|
95264
|
+
lastModified: cached?.lastModified,
|
|
95265
|
+
full: Boolean(this._fyn.lockTime) || Boolean(cached && !cached.corgi)
|
|
95266
|
+
};
|
|
95267
|
+
const pool = getFsWorkerPool();
|
|
95268
|
+
const res = await fetchPackument(job, (url, headers) => this.registryGet(url, headers), pool ? (saveJob) => pool.run("savePackument", saveJob) : void 0);
|
|
95269
|
+
if (res.status === 304) {
|
|
95270
|
+
if (cached.trimmed) touchTrimmedPackument(file);
|
|
95271
|
+
else writeTrimmedPackument(file, cached.packument, void 0, cached);
|
|
95272
|
+
updateItem("304");
|
|
95273
|
+
return cached.packument;
|
|
95274
|
+
}
|
|
95275
|
+
updateItem("200");
|
|
95276
|
+
return parseTrimmed(res.json).packument;
|
|
95277
|
+
} catch (err) {
|
|
95278
|
+
const msg = `failed fetching packument of ${pkgName}`;
|
|
94687
95279
|
logger$1.error(chalk.yellow(msg), chalk.red(err.message));
|
|
94688
95280
|
throw Object.assign(new AggregateError$1([err], msg), { expected: true });
|
|
94689
|
-
}
|
|
95281
|
+
}
|
|
94690
95282
|
};
|
|
94691
95283
|
this._metaStat.wait--;
|
|
94692
95284
|
this._metaStat.inTx++;
|
|
94693
95285
|
this.updateFetchMetaStatus(false);
|
|
94694
|
-
return (qItem.item.urlType ? this.fetchUrlSemverMeta(qItem.item) :
|
|
95286
|
+
return (qItem.item.urlType ? this.fetchUrlSemverMeta(qItem.item) : dist_default.resolve(registryRequest())).then((x) => {
|
|
94695
95287
|
this._metaStat.inTx--;
|
|
94696
95288
|
const time = Date.now() - startTime;
|
|
94697
95289
|
if (time > 2e4) logger$1.info(chalk.red("Fetch meta of package"), log_format_default.pkgId(qItem.item), `took ${log_format_default.time(time)}!!!`);
|
|
@@ -94701,14 +95293,20 @@ var PkgSrcManager = class {
|
|
|
94701
95293
|
qItem.defer.reject(Object.assign(new AggregateError$1([new Error(msg)], msg), { expected: true }));
|
|
94702
95294
|
return;
|
|
94703
95295
|
}
|
|
94704
|
-
refreshCacheEntry(this._cacheDir, qItem.cacheKey).catch(() => {});
|
|
94705
|
-
if (!qItem.item.urlType) writeTrimmedPackument(trimmedPackumentFile(this._packumentDir, qItem.packumentUrl), x);
|
|
94706
95296
|
qItem.defer.resolve(x);
|
|
94707
95297
|
}).catch((err) => {
|
|
94708
95298
|
this._metaStat.inTx--;
|
|
94709
95299
|
qItem.defer.reject(err);
|
|
94710
95300
|
});
|
|
94711
95301
|
}
|
|
95302
|
+
/** the plain values of the pacote options, for util/registry-get */
|
|
95303
|
+
get registryOpts() {
|
|
95304
|
+
return this._registryOpts ??= pickRegistryOpts(this._pacoteOpts);
|
|
95305
|
+
}
|
|
95306
|
+
/** GET from the registry, see util/registry-get */
|
|
95307
|
+
registryGet(url, extraHeaders) {
|
|
95308
|
+
return registryGet(url, extraHeaders, this.registryOpts);
|
|
95309
|
+
}
|
|
94712
95310
|
hasMeta(item) {
|
|
94713
95311
|
return Boolean(this._meta[item.resolutionName || item.name]);
|
|
94714
95312
|
}
|
|
@@ -94882,16 +95480,35 @@ var PkgSrcManager = class {
|
|
|
94882
95480
|
};
|
|
94883
95481
|
};
|
|
94884
95482
|
const readMemoizedPackument = async () => {
|
|
94885
|
-
const memoized = await loadBestCachedPackument(false);
|
|
94886
|
-
if (!(memoized && memoized.data)) return;
|
|
95483
|
+
const memoized = await readTrimmedPackument(trimmedFile) || await loadBestCachedPackument(false);
|
|
95484
|
+
if (!(memoized && (memoized.packument || memoized.data))) return;
|
|
94887
95485
|
logger$1.debug(`using memoized packument cache for '${pkgName}'`);
|
|
94888
95486
|
cacheMemoized = true;
|
|
94889
95487
|
this._metaStat.wait--;
|
|
94890
|
-
return JSON.parse(memoized.data.toString());
|
|
95488
|
+
return memoized.packument || JSON.parse(memoized.data.toString());
|
|
94891
95489
|
};
|
|
94892
95490
|
let fetchAttempted = false;
|
|
94893
95491
|
let foundCache;
|
|
94894
95492
|
let foundPackument;
|
|
95493
|
+
const revalidate = (packument) => {
|
|
95494
|
+
if (foundCache.packument) {
|
|
95495
|
+
const { etag, lastModified, corgi } = foundCache;
|
|
95496
|
+
return {
|
|
95497
|
+
packument,
|
|
95498
|
+
trimmed: true,
|
|
95499
|
+
etag,
|
|
95500
|
+
lastModified,
|
|
95501
|
+
corgi
|
|
95502
|
+
};
|
|
95503
|
+
}
|
|
95504
|
+
const resHeaders = foundCache.metadata?.resHeaders || {};
|
|
95505
|
+
return {
|
|
95506
|
+
packument,
|
|
95507
|
+
trimmed: false,
|
|
95508
|
+
etag: resHeaders.etag,
|
|
95509
|
+
lastModified: resHeaders["last-modified"]
|
|
95510
|
+
};
|
|
95511
|
+
};
|
|
94895
95512
|
const queueMetaFetchRequest = (cached) => {
|
|
94896
95513
|
fetchAttempted = true;
|
|
94897
95514
|
const offline = this._fyn.remoteMetaDisabled;
|
|
@@ -94912,7 +95529,8 @@ var PkgSrcManager = class {
|
|
|
94912
95529
|
cacheKey,
|
|
94913
95530
|
item,
|
|
94914
95531
|
packumentUrl,
|
|
94915
|
-
defer: dist_default.defer()
|
|
95532
|
+
defer: dist_default.defer(),
|
|
95533
|
+
cached: cached && revalidate(cached)
|
|
94916
95534
|
};
|
|
94917
95535
|
this._netQ.addItem(netQItem);
|
|
94918
95536
|
return netQItem.defer.promise;
|
|
@@ -94922,7 +95540,7 @@ var PkgSrcManager = class {
|
|
|
94922
95540
|
let cacheLookup;
|
|
94923
95541
|
if (item.urlType) cacheLookup = this._fyn.remoteMetaDisabled ? loadPreparedUrlMeta().then((preparedUrlMeta) => ({ preparedUrlMeta })) : dist_default.resolve();
|
|
94924
95542
|
else if (forceRefresh) cacheLookup = dist_default.resolve();
|
|
94925
|
-
else cacheLookup = readTrimmedPackument(trimmedFile).then((trimmed) => trimmed
|
|
95543
|
+
else cacheLookup = readTrimmedPackument(trimmedFile).then((trimmed) => trimmed && !(trimmed.corgi && this._fyn.lockTime) ? trimmed : loadBestCachedPackument(true));
|
|
94926
95544
|
const promise = cacheLookup.then((cached) => {
|
|
94927
95545
|
if (cached && cached.preparedUrlMeta) {
|
|
94928
95546
|
cacheMemoized = true;
|
|
@@ -95053,10 +95671,21 @@ var PkgSrcManager = class {
|
|
|
95053
95671
|
if (di && di.urlType) return `${di.name}@${di.semver}`;
|
|
95054
95672
|
return `${pkgInfo.name}@${pkgInfo.version}`;
|
|
95055
95673
|
}
|
|
95056
|
-
|
|
95674
|
+
/**
|
|
95675
|
+
* A package not in the central store yet comes back as a store job, so the extractor writes
|
|
95676
|
+
* the store, not the download slot this runs in.
|
|
95677
|
+
*
|
|
95678
|
+
* @param data - the tarball's bytes, when it was downloaded for the central store and not
|
|
95679
|
+
* into cacache
|
|
95680
|
+
*/
|
|
95681
|
+
async getCentralPackage(integrity, pkgInfo, data) {
|
|
95057
95682
|
const { central, copy } = this._fyn;
|
|
95058
95683
|
const tarId = this.tarballFetchId(pkgInfo);
|
|
95059
95684
|
const tarStream = async () => {
|
|
95685
|
+
if (data) {
|
|
95686
|
+
if (!import_lib.default.checkData(data, integrity)) throw Object.assign(/* @__PURE__ */ new Error(`integrity check failed for ${tarId}`), { code: "EINTEGRITY" });
|
|
95687
|
+
return Readable.from([data]);
|
|
95688
|
+
}
|
|
95060
95689
|
return integrity && await (await loadCacache()).get.hasContent(this._cacheDir, integrity) ? this.cacacheTarballStream(integrity) : this.pacoteTarballStream(tarId, pkgInfo, integrity);
|
|
95061
95690
|
};
|
|
95062
95691
|
if (integrity && central) {
|
|
@@ -95075,7 +95704,17 @@ var PkgSrcManager = class {
|
|
|
95075
95704
|
hasCentral = false;
|
|
95076
95705
|
}
|
|
95077
95706
|
}
|
|
95078
|
-
if (!hasCentral)
|
|
95707
|
+
if (!hasCentral) {
|
|
95708
|
+
const tarSource = async () => {
|
|
95709
|
+
if (data) return { data };
|
|
95710
|
+
const content = await (await loadCacache()).get.hasContent(this._cacheDir, integrity);
|
|
95711
|
+
return content ? { file: getContentPath(this._cacheDir, content.sri) } : void 0;
|
|
95712
|
+
};
|
|
95713
|
+
return {
|
|
95714
|
+
integrity,
|
|
95715
|
+
store: (deferIfBusy) => central.storeTarStream(tarId, integrity, tarStream, deferIfBusy, tarSource)
|
|
95716
|
+
};
|
|
95717
|
+
}
|
|
95079
95718
|
return integrity;
|
|
95080
95719
|
}
|
|
95081
95720
|
}
|
|
@@ -95085,7 +95724,14 @@ var PkgSrcManager = class {
|
|
|
95085
95724
|
const startTime = Date.now();
|
|
95086
95725
|
const pkgId = this.tarballFetchId(pkgInfo);
|
|
95087
95726
|
const integrity = this.getIntegrity(pkgInfo);
|
|
95088
|
-
const
|
|
95727
|
+
const tarballUrl = get$1(pkgInfo, "dist.tarball");
|
|
95728
|
+
const central = this._fyn.central;
|
|
95729
|
+
const centralEligible = Boolean(integrity && tarballUrl && central && !tarballUrl.startsWith("~url-spec~"));
|
|
95730
|
+
const copied = () => {
|
|
95731
|
+
const { copy } = this._fyn;
|
|
95732
|
+
return copy.indexOf(pkgInfo.name) >= 0 || copy.indexOf(`${pkgInfo.name}@${pkgInfo.version}`) >= 0;
|
|
95733
|
+
};
|
|
95734
|
+
const doFetch = (fetchForCentral) => {
|
|
95089
95735
|
const fetchStartTime = Date.now();
|
|
95090
95736
|
if (!this._fetching) {
|
|
95091
95737
|
this._fetching = [];
|
|
@@ -95093,21 +95739,28 @@ var PkgSrcManager = class {
|
|
|
95093
95739
|
}
|
|
95094
95740
|
this._fetching.push(pkgId);
|
|
95095
95741
|
logger$1.updateItem(FETCH_PACKAGE, `${this._fetching.length} ${this._fetchingMsg}`);
|
|
95096
|
-
return this.pacotePrefetch(pkgId, pkgInfo, integrity).then(() => {
|
|
95742
|
+
return (fetchForCentral ? dist_default.resolve(this.registryGet(tarballUrl, {})).then((res) => res.buffer()) : this.pacotePrefetch(pkgId, pkgInfo, integrity)).then((data) => {
|
|
95097
95743
|
const status = chalk.cyan(`200`);
|
|
95098
95744
|
const time = log_format_default.time(Date.now() - fetchStartTime);
|
|
95099
95745
|
const ix = this._fetching.indexOf(pkgId);
|
|
95100
95746
|
this._fetching.splice(ix, 1);
|
|
95101
95747
|
this._fetchingMsg = `${status} ${time} ${chalk.red.bgGreen(pkgInfo.name)}`;
|
|
95102
95748
|
logger$1.updateItem(FETCH_PACKAGE, `${this._fetching.length} ${this._fetchingMsg}`);
|
|
95103
|
-
return this.getCentralPackage(integrity, pkgInfo);
|
|
95749
|
+
return this.getCentralPackage(integrity, pkgInfo, data || void 0);
|
|
95104
95750
|
});
|
|
95105
95751
|
};
|
|
95106
|
-
const
|
|
95107
|
-
if (content) return this.getCentralPackage(integrity, pkgInfo);
|
|
95752
|
+
const fetchRemote = (fetchForCentral) => {
|
|
95108
95753
|
const rd = this._fyn.remoteTgzDisabled;
|
|
95109
95754
|
if (rd) throw new Error(`option ${rd} has disabled retrieving tarball from remote`);
|
|
95110
|
-
return doFetch();
|
|
95755
|
+
return doFetch(fetchForCentral);
|
|
95756
|
+
};
|
|
95757
|
+
const promise = dist_default.resolve().then(async () => {
|
|
95758
|
+
if (centralEligible) {
|
|
95759
|
+
if (await central.has(integrity)) return this.getCentralPackage(integrity, pkgInfo);
|
|
95760
|
+
if (!this._fyn.remoteTgzDisabled && !copied() && await central.allow(integrity)) return fetchRemote(true);
|
|
95761
|
+
}
|
|
95762
|
+
if (await dist_default.resolve(loadCacache()).then((cacache) => cacache.get.hasContent(this._cacheDir, integrity)).catch(() => false)) return this.getCentralPackage(integrity, pkgInfo);
|
|
95763
|
+
return fetchRemote(false);
|
|
95111
95764
|
});
|
|
95112
95765
|
return {
|
|
95113
95766
|
then: (r, e) => promise.then(r, e),
|
|
@@ -96928,6 +97581,7 @@ var PkgDepLocker = class {
|
|
|
96928
97581
|
*/
|
|
96929
97582
|
saveInstalled(filename) {
|
|
96930
97583
|
if (!this._enable) return;
|
|
97584
|
+
file_ops_default.$.mkdirp(Path.dirname(filename));
|
|
96931
97585
|
file_ops_default.writeFileSync(filename, this._stringify(Path.dirname(filename)));
|
|
96932
97586
|
}
|
|
96933
97587
|
/**
|
|
@@ -97113,8 +97767,7 @@ const xenvConfig = (spec, userConfig, options) => {
|
|
|
97113
97767
|
};
|
|
97114
97768
|
}
|
|
97115
97769
|
};
|
|
97116
|
-
const sources = options && options.sources || ["env", "option"];
|
|
97117
|
-
sources.push("default");
|
|
97770
|
+
const sources = [...options && options.sources || ["env", "option"], "default"];
|
|
97118
97771
|
const config = Object.keys(spec).reduce((cfg, k) => {
|
|
97119
97772
|
const opt = spec[k];
|
|
97120
97773
|
const type = getType(opt);
|
|
@@ -97143,18 +97796,12 @@ const xenvConfig = (spec, userConfig, options) => {
|
|
|
97143
97796
|
//#endregion
|
|
97144
97797
|
//#region lib/fyn-config.ts
|
|
97145
97798
|
const spec = {
|
|
97146
|
-
registry: {
|
|
97147
|
-
env: "FYN_REGISTRY",
|
|
97148
|
-
default: "http://localhost:4873"
|
|
97149
|
-
},
|
|
97799
|
+
registry: { default: "http://localhost:4873" },
|
|
97150
97800
|
pkgFile: {
|
|
97151
97801
|
env: "FYN_PACKAGE_FILE",
|
|
97152
97802
|
default: "package.json"
|
|
97153
97803
|
},
|
|
97154
|
-
targetDir: {
|
|
97155
|
-
env: "FYN_TARGET_DIR",
|
|
97156
|
-
default: "xout"
|
|
97157
|
-
},
|
|
97804
|
+
targetDir: { default: "xout" },
|
|
97158
97805
|
fynDir: {
|
|
97159
97806
|
env: [
|
|
97160
97807
|
"FYN_DIR",
|
|
@@ -97183,12 +97830,135 @@ function fynConfig(override) {
|
|
|
97183
97830
|
}
|
|
97184
97831
|
|
|
97185
97832
|
//#endregion
|
|
97186
|
-
//#region lib/
|
|
97187
|
-
|
|
97188
|
-
/**
|
|
97189
|
-
|
|
97190
|
-
|
|
97833
|
+
//#region lib/util/reflink.ts
|
|
97834
|
+
let nativeReflink;
|
|
97835
|
+
/**
|
|
97836
|
+
* @fynjs/reflink is a native addon, so it cannot be bundled into dist/. Load it at runtime from
|
|
97837
|
+
* an optional dependency, and resolve to undefined when it is absent or has no binary for
|
|
97838
|
+
* this platform.
|
|
97839
|
+
*/
|
|
97840
|
+
function loadReflink() {
|
|
97841
|
+
nativeReflink ??= (async () => {
|
|
97842
|
+
try {
|
|
97843
|
+
const file = createRequire(import.meta.url).resolve("@fynjs/reflink");
|
|
97844
|
+
return await import(
|
|
97845
|
+
/* @vite-ignore */
|
|
97846
|
+
pathToFileURL(file).href
|
|
97847
|
+
);
|
|
97848
|
+
} catch (err) {
|
|
97849
|
+
logger$1.debug(`@fynjs/reflink not loaded, using JS clone: ${err.message}`);
|
|
97850
|
+
return;
|
|
97851
|
+
}
|
|
97852
|
+
})();
|
|
97853
|
+
return nativeReflink;
|
|
97191
97854
|
}
|
|
97855
|
+
async function loadReflinkCloneFiles() {
|
|
97856
|
+
return (await loadReflink())?.cloneFiles;
|
|
97857
|
+
}
|
|
97858
|
+
/** undefined with no reflink, or an reflink older than cloneDir */
|
|
97859
|
+
async function loadReflinkCloneDir() {
|
|
97860
|
+
return (await loadReflink())?.cloneDir;
|
|
97861
|
+
}
|
|
97862
|
+
|
|
97863
|
+
//#endregion
|
|
97864
|
+
//#region lib/util/untar-tree.ts
|
|
97865
|
+
/** An `onentry` for Tar.x that builds the tree, and the result once extraction finishes */
|
|
97866
|
+
function treeCollector(strip) {
|
|
97867
|
+
const newDirObj = () => {
|
|
97868
|
+
const n = Object.create(null);
|
|
97869
|
+
n["/"] = Object.create(null);
|
|
97870
|
+
return n;
|
|
97871
|
+
};
|
|
97872
|
+
const result = {
|
|
97873
|
+
tree: newDirObj(),
|
|
97874
|
+
fromHeaders: true
|
|
97875
|
+
};
|
|
97876
|
+
const onentry = (entry) => {
|
|
97877
|
+
const parts = entry.path.split(/\/|\\/);
|
|
97878
|
+
const isDir = entry.type === "Directory";
|
|
97879
|
+
const wtree = parts.slice(strip, isDir ? parts.length : parts.length - 1).reduce((wt, dir) => {
|
|
97880
|
+
return wt[dir] || (wt[dir] = newDirObj());
|
|
97881
|
+
}, result.tree);
|
|
97882
|
+
if (isDir) return;
|
|
97883
|
+
if (!entry.mtime || ![
|
|
97884
|
+
"File",
|
|
97885
|
+
"OldFile",
|
|
97886
|
+
"ContiguousFile"
|
|
97887
|
+
].includes(entry.type)) result.fromHeaders = false;
|
|
97888
|
+
const fname = parts[parts.length - 1];
|
|
97889
|
+
if (fname) {
|
|
97890
|
+
const m = Math.round((entry.mtime ? entry.mtime.getTime() : Date.now()) / 1e3);
|
|
97891
|
+
wtree["/"][fname] = {
|
|
97892
|
+
z: entry.size,
|
|
97893
|
+
m,
|
|
97894
|
+
$: entry.header.cksumValid && entry.header.cksum
|
|
97895
|
+
};
|
|
97896
|
+
}
|
|
97897
|
+
};
|
|
97898
|
+
return {
|
|
97899
|
+
onentry,
|
|
97900
|
+
result
|
|
97901
|
+
};
|
|
97902
|
+
}
|
|
97903
|
+
const hashList = (list) => Crypto$1.createHash("sha512").update(JSON.stringify(list.sort())).digest("base64");
|
|
97904
|
+
/** The shaSum of a tree from tar headers, in SUM_VERSION's format */
|
|
97905
|
+
function treeShasum(tree) {
|
|
97906
|
+
const files = [];
|
|
97907
|
+
const walk = (node, dir) => {
|
|
97908
|
+
for (const [name, child] of Object.entries(node)) if (name === "/") for (const [file, info] of Object.entries(child)) files.push(`${dir}${file}-${info.m}-${info.z}`);
|
|
97909
|
+
else walk(child, `${dir}${name}/`);
|
|
97910
|
+
};
|
|
97911
|
+
walk(tree, "");
|
|
97912
|
+
return hashList(files);
|
|
97913
|
+
}
|
|
97914
|
+
/** tree.json's content. An old entry keeps its sumVersion until validate() converts it. */
|
|
97915
|
+
function treeFileJson(info) {
|
|
97916
|
+
return JSON.stringify({
|
|
97917
|
+
$: info.tree,
|
|
97918
|
+
shaSum: info.shaSum,
|
|
97919
|
+
mutates: info.mutates,
|
|
97920
|
+
_: info.sumVersion ?? 1
|
|
97921
|
+
});
|
|
97922
|
+
}
|
|
97923
|
+
|
|
97924
|
+
//#endregion
|
|
97925
|
+
//#region lib/util/store-entry.ts
|
|
97926
|
+
/** an extraction marker or temp dir older than this was left by an install that died */
|
|
97927
|
+
const STALE_MS = 3e5;
|
|
97928
|
+
/** a name suffix no other install, or other call in this one, will pick */
|
|
97929
|
+
const uniqueSuffix = () => `${process.pid}-${Crypto$1.randomBytes(4).toString("hex")}`;
|
|
97930
|
+
/**
|
|
97931
|
+
* filterScanDir options that hash a package dir in one stat walk, in both formats: v1 for
|
|
97932
|
+
* checking an old entry, v2 for everything else (see SUM_VERSION). Call `sums` with the scan's
|
|
97933
|
+
* result.
|
|
97934
|
+
*/
|
|
97935
|
+
function shasumScan(packageDir) {
|
|
97936
|
+
const v2 = [];
|
|
97937
|
+
const filter = (_file, _path, extras) => {
|
|
97938
|
+
const { stat, dirFile } = extras;
|
|
97939
|
+
const fullStat = stat;
|
|
97940
|
+
if (!fullStat.isDirectory()) v2.push(`${dirFile.replace(/\\/g, "/")}-${Math.floor(fullStat.mtimeMs / 1e3)}-${fullStat.size}`);
|
|
97941
|
+
return { formatName: `${dirFile}-${fullStat.mtimeMs}-${fullStat.size}` };
|
|
97942
|
+
};
|
|
97943
|
+
return {
|
|
97944
|
+
options: {
|
|
97945
|
+
cwd: packageDir,
|
|
97946
|
+
filter,
|
|
97947
|
+
filterDir: filter,
|
|
97948
|
+
fullStat: true,
|
|
97949
|
+
concurrency: 500,
|
|
97950
|
+
sortFiles: false,
|
|
97951
|
+
includeDir: true
|
|
97952
|
+
},
|
|
97953
|
+
sums: (files) => ({
|
|
97954
|
+
v1: hashList(files),
|
|
97955
|
+
v2: hashList(v2)
|
|
97956
|
+
})
|
|
97957
|
+
};
|
|
97958
|
+
}
|
|
97959
|
+
|
|
97960
|
+
//#endregion
|
|
97961
|
+
//#region lib/util/place-files.ts
|
|
97192
97962
|
/** link errors that mean the filesystem can't hardlink from the store at all */
|
|
97193
97963
|
const NO_LINK_CODES = [
|
|
97194
97964
|
"EXDEV",
|
|
@@ -97197,6 +97967,14 @@ const NO_LINK_CODES = [
|
|
|
97197
97967
|
"EOPNOTSUPP",
|
|
97198
97968
|
"ENOSYS"
|
|
97199
97969
|
];
|
|
97970
|
+
|
|
97971
|
+
//#endregion
|
|
97972
|
+
//#region lib/fyn-central.ts
|
|
97973
|
+
const { missPipe } = fyntil;
|
|
97974
|
+
/** Type guard to check if parsed tree is new format with version */
|
|
97975
|
+
function isTreeFileContent(obj) {
|
|
97976
|
+
return typeof obj === "object" && obj !== null && "_" in obj && typeof obj._ === "number";
|
|
97977
|
+
}
|
|
97200
97978
|
/**
|
|
97201
97979
|
* Convert a directory tree structure to a flatten one like:
|
|
97202
97980
|
* ```
|
|
@@ -97234,11 +98012,26 @@ function flattenTree(tree, output, baseDir) {
|
|
|
97234
98012
|
var FynCentral = class {
|
|
97235
98013
|
_centralDir;
|
|
97236
98014
|
_map;
|
|
98015
|
+
/** entries found missing, so has() and allow() don't stat them again; storing re-checks */
|
|
98016
|
+
_missing = /* @__PURE__ */ new Map();
|
|
98017
|
+
/** store dirs this install has made, so each is made once */
|
|
98018
|
+
_madeDirs = /* @__PURE__ */ new Set();
|
|
97237
98019
|
_hardlink;
|
|
97238
|
-
|
|
98020
|
+
_reflink;
|
|
98021
|
+
_copyFallback;
|
|
98022
|
+
/** cleared on the first dir clone the filesystem can't do, so later packages skip it */
|
|
98023
|
+
_cloneDirs = true;
|
|
98024
|
+
/**
|
|
98025
|
+
* cleared when a package's files hardlink but none clone, so later packages hardlink in the
|
|
98026
|
+
* fs workers. That's faster than @fynjs/reflink on a filesystem that can't clone (ext4).
|
|
98027
|
+
*/
|
|
98028
|
+
_cloneFiles = true;
|
|
98029
|
+
constructor({ centralDir = ".fyn/_central-storage", hardlink = true, reflink = true, copyFallback = true } = {}) {
|
|
97239
98030
|
this._centralDir = Path.resolve(centralDir);
|
|
97240
98031
|
this._map = /* @__PURE__ */ new Map();
|
|
97241
98032
|
this._hardlink = hardlink;
|
|
98033
|
+
this._reflink = reflink;
|
|
98034
|
+
this._copyFallback = copyFallback;
|
|
97242
98035
|
}
|
|
97243
98036
|
_analyze(integrity) {
|
|
97244
98037
|
const sri = import_lib.default.parse(integrity, { single: true });
|
|
@@ -97272,14 +98065,16 @@ var FynCentral = class {
|
|
|
97272
98065
|
}
|
|
97273
98066
|
}
|
|
97274
98067
|
try {
|
|
97275
|
-
|
|
97276
|
-
info.exist = true;
|
|
97277
|
-
if (stat.isDirectory()) {
|
|
98068
|
+
if ((await file_ops_default.stat(info.contentPath)).isDirectory()) {
|
|
97278
98069
|
await this.readInfoTree(info);
|
|
97279
98070
|
if (!noSet) this._map.set(integrity, info);
|
|
97280
98071
|
}
|
|
98072
|
+
info.exist = true;
|
|
98073
|
+
this._missing.delete(integrity);
|
|
97281
98074
|
return info;
|
|
97282
98075
|
} catch (_err) {
|
|
98076
|
+
info.exist = false;
|
|
98077
|
+
if (!noSet) this._missing.set(integrity, info);
|
|
97283
98078
|
return info;
|
|
97284
98079
|
}
|
|
97285
98080
|
}
|
|
@@ -97290,7 +98085,7 @@ var FynCentral = class {
|
|
|
97290
98085
|
* @returns boolean
|
|
97291
98086
|
*/
|
|
97292
98087
|
async has(integrity) {
|
|
97293
|
-
const info = this._map.
|
|
98088
|
+
const info = this._map.get(integrity) ?? this._missing.get(integrity) ?? await this._loadTree(integrity);
|
|
97294
98089
|
return Boolean(info.tree);
|
|
97295
98090
|
}
|
|
97296
98091
|
/**
|
|
@@ -97300,7 +98095,7 @@ var FynCentral = class {
|
|
|
97300
98095
|
* @returns boolean
|
|
97301
98096
|
*/
|
|
97302
98097
|
async allow(integrity) {
|
|
97303
|
-
return (this._map.
|
|
98098
|
+
return (this._map.get(integrity) ?? this._missing.get(integrity) ?? await this._loadTree(integrity)).mutates ? false : true;
|
|
97304
98099
|
}
|
|
97305
98100
|
async getContentPath(integrity) {
|
|
97306
98101
|
return (await this.getInfo(integrity)).contentPath;
|
|
@@ -97311,28 +98106,25 @@ var FynCentral = class {
|
|
|
97311
98106
|
if (!info.tree) throw new Error(`fyn-central can't get package for integrity ${integrity}`);
|
|
97312
98107
|
return info;
|
|
97313
98108
|
}
|
|
97314
|
-
|
|
98109
|
+
/**
|
|
98110
|
+
* Hash a package dir in one stat walk, in both formats: v1 for checking an old entry, v2 for
|
|
98111
|
+
* everything else (see SUM_VERSION).
|
|
98112
|
+
*/
|
|
98113
|
+
async _scanShasums(packageDir) {
|
|
97315
98114
|
try {
|
|
97316
|
-
const
|
|
97317
|
-
|
|
97318
|
-
const { stat, dirFile } = extras;
|
|
97319
|
-
const fullStat = stat;
|
|
97320
|
-
return { formatName: `${dirFile}-${fullStat.mtimeMs}-${fullStat.size}` };
|
|
97321
|
-
};
|
|
97322
|
-
const files = await filterScanDir({
|
|
97323
|
-
cwd: packageDir,
|
|
97324
|
-
filter,
|
|
97325
|
-
filterDir: filter,
|
|
97326
|
-
fullStat: true,
|
|
97327
|
-
concurrency: 500,
|
|
97328
|
-
sortFiles: false,
|
|
97329
|
-
includeDir: true
|
|
97330
|
-
});
|
|
97331
|
-
return Crypto.createHash("sha512").update(JSON.stringify(files.sort())).digest("base64");
|
|
98115
|
+
const { options, sums } = shasumScan(packageDir);
|
|
98116
|
+
return sums(await filterScanDir(options));
|
|
97332
98117
|
} catch (_err) {
|
|
97333
98118
|
return;
|
|
97334
98119
|
}
|
|
97335
98120
|
}
|
|
98121
|
+
/** The v2 hash of a fresh extraction, from the tar header sizes and mtimes in its tree */
|
|
98122
|
+
_treeShasum(tree) {
|
|
98123
|
+
return treeShasum(tree);
|
|
98124
|
+
}
|
|
98125
|
+
async _calcContentShasum(info, pkgDir) {
|
|
98126
|
+
return (await this._scanShasums(pkgDir || Path.join(info.contentPath, "package")))?.v1;
|
|
98127
|
+
}
|
|
97336
98128
|
/**
|
|
97337
98129
|
* Get the hash of a npm package's extracted content.
|
|
97338
98130
|
* - only consider the file names and their mtime and size because npm tar files
|
|
@@ -97351,16 +98143,41 @@ var FynCentral = class {
|
|
|
97351
98143
|
}
|
|
97352
98144
|
}
|
|
97353
98145
|
async getMutation(integrity) {
|
|
97354
|
-
return (this._map.
|
|
98146
|
+
return (this._map.get(integrity) ?? this._missing.get(integrity) ?? await this._loadTree(integrity)).mutates;
|
|
97355
98147
|
}
|
|
98148
|
+
/**
|
|
98149
|
+
* Rename the entry away before removing it, so a concurrent install never finds it half
|
|
98150
|
+
* deleted, with tree.json present and package/ partly gone.
|
|
98151
|
+
*/
|
|
97356
98152
|
async delete(integrity) {
|
|
97357
98153
|
const info = this._map.get(integrity);
|
|
97358
98154
|
if (info && info.exist && info.contentPath) {
|
|
97359
|
-
|
|
98155
|
+
const trash = `${info.contentPath}.del-${uniqueSuffix()}`;
|
|
98156
|
+
try {
|
|
98157
|
+
await file_ops_default.rename(info.contentPath, trash);
|
|
98158
|
+
} catch (err) {
|
|
98159
|
+
if (err.code !== "ENOENT") throw err;
|
|
98160
|
+
}
|
|
97360
98161
|
this._map.delete(integrity);
|
|
98162
|
+
await file_ops_default.$.rimraf(trash);
|
|
97361
98163
|
}
|
|
97362
98164
|
}
|
|
97363
98165
|
/**
|
|
98166
|
+
* An entry with no readable tree.json is left from a broken write. Rename it away, then
|
|
98167
|
+
* remove it, the same way delete() does.
|
|
98168
|
+
*/
|
|
98169
|
+
async _removeBrokenEntry(contentPath) {
|
|
98170
|
+
const trash = `${contentPath}.del-${uniqueSuffix()}`;
|
|
98171
|
+
try {
|
|
98172
|
+
await file_ops_default.rename(contentPath, trash);
|
|
98173
|
+
} catch (err) {
|
|
98174
|
+
if (err.code !== "ENOENT") throw err;
|
|
98175
|
+
return;
|
|
98176
|
+
}
|
|
98177
|
+
logger$1.warn(`fyn-central: replacing a broken store entry with no tree.json at ${contentPath}`);
|
|
98178
|
+
await file_ops_default.$.rimraf(trash);
|
|
98179
|
+
}
|
|
98180
|
+
/**
|
|
97364
98181
|
* Read the content dir tree from file into info
|
|
97365
98182
|
*
|
|
97366
98183
|
* @param info - package info
|
|
@@ -97374,24 +98191,30 @@ var FynCentral = class {
|
|
|
97374
98191
|
if (parsed.mutates !== void 0) info.mutates = parsed.mutates;
|
|
97375
98192
|
info.tree = parsed.$;
|
|
97376
98193
|
info.shaSum = parsed.shaSum;
|
|
98194
|
+
info.sumVersion = parsed._;
|
|
97377
98195
|
} else info.tree = parsed;
|
|
97378
98196
|
} catch (err) {
|
|
97379
98197
|
throw new AggregateError$1([err], `fyn-central: reading tree file ${treeFile}`);
|
|
97380
98198
|
}
|
|
97381
98199
|
}
|
|
97382
98200
|
/**
|
|
97383
|
-
* Save the content dir tree from info to file
|
|
98201
|
+
* Save the content dir tree from info to file. In a live entry it's written to a temp file
|
|
98202
|
+
* and renamed over, so a concurrent install never reads half of it. A `path` is a temp dir
|
|
98203
|
+
* only this install uses, so it's written directly.
|
|
97384
98204
|
*
|
|
97385
98205
|
* @param info - package info
|
|
97386
98206
|
* @param path - path to save the file
|
|
97387
98207
|
*/
|
|
97388
98208
|
async saveInfoTree(info, path) {
|
|
97389
|
-
|
|
97390
|
-
|
|
97391
|
-
|
|
97392
|
-
|
|
97393
|
-
|
|
97394
|
-
|
|
98209
|
+
const data = treeFileJson(info);
|
|
98210
|
+
if (path) {
|
|
98211
|
+
await file_ops_default.writeFile(Path.join(path, "tree.json"), data);
|
|
98212
|
+
return;
|
|
98213
|
+
}
|
|
98214
|
+
const treeFile = Path.join(info.contentPath, "tree.json");
|
|
98215
|
+
const tmpFile = `${treeFile}.${uniqueSuffix()}`;
|
|
98216
|
+
await file_ops_default.writeFile(tmpFile, data);
|
|
98217
|
+
await file_ops_default.rename(tmpFile, treeFile);
|
|
97395
98218
|
}
|
|
97396
98219
|
async setMutation(integrity, mutates = true) {
|
|
97397
98220
|
const info = await this._loadTree(integrity);
|
|
@@ -97399,19 +98222,72 @@ var FynCentral = class {
|
|
|
97399
98222
|
info.mutates = mutates;
|
|
97400
98223
|
await this.saveInfoTree(info);
|
|
97401
98224
|
}
|
|
97402
|
-
|
|
98225
|
+
/**
|
|
98226
|
+
* @param prepare - makes destDir, when the caller hasn't. An fs worker does it instead when
|
|
98227
|
+
* it places the files.
|
|
98228
|
+
* @returns package.json as placed, when an fs worker placed the files
|
|
98229
|
+
*/
|
|
98230
|
+
async replicate(integrity, destDir, prepare) {
|
|
98231
|
+
let prepared = !prepare;
|
|
98232
|
+
const ensurePrepared = async () => {
|
|
98233
|
+
if (!prepared) {
|
|
98234
|
+
prepared = true;
|
|
98235
|
+
await prepare();
|
|
98236
|
+
}
|
|
98237
|
+
};
|
|
97403
98238
|
try {
|
|
97404
98239
|
const info = await this.getInfo(integrity);
|
|
97405
98240
|
const list = flattenTree(info.tree, {
|
|
97406
98241
|
dirs: [],
|
|
97407
98242
|
files: []
|
|
97408
98243
|
}, "");
|
|
97409
|
-
|
|
98244
|
+
const srcDir = Path.join(info.contentPath, "package");
|
|
98245
|
+
const cloneDir = this._reflink && this._cloneDirs && await loadReflinkCloneDir();
|
|
98246
|
+
if (cloneDir) {
|
|
98247
|
+
await ensurePrepared();
|
|
98248
|
+
if (await this._cloneWholeDir(cloneDir, srcDir, destDir)) return;
|
|
98249
|
+
}
|
|
98250
|
+
const reflinkCloneFiles = this._reflink && this._cloneFiles && await loadReflinkCloneFiles();
|
|
98251
|
+
const copy = this._copyFallback;
|
|
98252
|
+
const mkdirs = async () => {
|
|
98253
|
+
for (const dir of list.dirs) await file_ops_default.$.mkdirp(Path.join(destDir, dir));
|
|
98254
|
+
};
|
|
98255
|
+
if (reflinkCloneFiles) {
|
|
98256
|
+
await ensurePrepared();
|
|
98257
|
+
await mkdirs();
|
|
98258
|
+
const others = list.files.filter((f) => f !== "package.json");
|
|
98259
|
+
const [stats] = await Promise.all([reflinkCloneFiles(srcDir, destDir, others, this._hardlink, copy), others.length < list.files.length && reflinkCloneFiles(srcDir, destDir, ["package.json"], false, copy)]);
|
|
98260
|
+
if (this._cloneFiles && stats.cloned === 0 && stats.linked > 0) {
|
|
98261
|
+
this._cloneFiles = false;
|
|
98262
|
+
logger$1.debug(`fyn-central: can't clone files from ${this._centralDir}, hardlinking instead`);
|
|
98263
|
+
}
|
|
98264
|
+
return;
|
|
98265
|
+
}
|
|
98266
|
+
const pool = getFsWorkerPool();
|
|
98267
|
+
if (pool) {
|
|
98268
|
+
const { noLink, pkgJson } = await pool.run("place", {
|
|
98269
|
+
srcDir,
|
|
98270
|
+
destDir,
|
|
98271
|
+
dirs: list.dirs,
|
|
98272
|
+
files: list.files,
|
|
98273
|
+
hardlink: this._hardlink,
|
|
98274
|
+
reflink: this._reflink,
|
|
98275
|
+
copyFallback: copy,
|
|
98276
|
+
prepare: !prepared
|
|
98277
|
+
});
|
|
98278
|
+
if (noLink && this._hardlink) {
|
|
98279
|
+
this._hardlink = false;
|
|
98280
|
+
logger$1.info(`fyn-central: can't hardlink from ${this._centralDir} (${noLink}), copying instead`);
|
|
98281
|
+
}
|
|
98282
|
+
return pkgJson;
|
|
98283
|
+
}
|
|
98284
|
+
await ensurePrepared();
|
|
98285
|
+
await mkdirs();
|
|
97410
98286
|
await map$1(list.files, (file) => {
|
|
97411
98287
|
const src = Path.join(info.contentPath, "package", file);
|
|
97412
98288
|
const dest = Path.join(destDir, file);
|
|
97413
|
-
if (file === "package.json") return copyFile(src, dest);
|
|
97414
|
-
return this._hardlink ? this._linkFile(src, dest) :
|
|
98289
|
+
if (file === "package.json") return this._reflink && !copy ? cloneFile(src, dest, true) : copyFile(src, dest);
|
|
98290
|
+
return this._hardlink ? this._linkFile(src, dest) : this._cloneOrCopy(src, dest);
|
|
97415
98291
|
}, { concurrency: 5 });
|
|
97416
98292
|
} catch (err) {
|
|
97417
98293
|
const msg = `fyn-central can't replicate package at ${destDir} for integrity ${integrity}`;
|
|
@@ -97435,68 +98311,118 @@ var FynCentral = class {
|
|
|
97435
98311
|
}
|
|
97436
98312
|
} else if (code !== "EMLINK") throw err;
|
|
97437
98313
|
}
|
|
97438
|
-
await
|
|
98314
|
+
await this._cloneOrCopy(src, dest);
|
|
98315
|
+
}
|
|
98316
|
+
/** Clone, else copy, as reflink and copyFallback allow. */
|
|
98317
|
+
async _cloneOrCopy(src, dest) {
|
|
98318
|
+
if (this._reflink) await cloneFile(src, dest, !this._copyFallback);
|
|
98319
|
+
else if (this._copyFallback) await copyFile(src, dest);
|
|
98320
|
+
else throw new Error(`fyn-central: can't place ${dest}: it can't be hardlinked, and reflink and copy-fallback are off`);
|
|
98321
|
+
}
|
|
98322
|
+
/**
|
|
98323
|
+
* Clone the store's package dir to `destDir` in one call. A dir clone needs a path that
|
|
98324
|
+
* doesn't exist, so it goes to a unique sibling that's then renamed over `destDir`. The
|
|
98325
|
+
* rename replaces `destDir` only while it's still the empty dir createPkgOutDir made. If
|
|
98326
|
+
* anything put files there meanwhile, the clone is dropped for the per-file path, which never
|
|
98327
|
+
* writes through an existing file. Resolves false, with `destDir` untouched, when not cloned.
|
|
98328
|
+
*/
|
|
98329
|
+
async _cloneWholeDir(cloneDir, srcDir, destDir) {
|
|
98330
|
+
const tmp = `${destDir}.clone-${uniqueSuffix()}`;
|
|
98331
|
+
if (!await cloneDir(srcDir, tmp)) {
|
|
98332
|
+
this._cloneDirs = false;
|
|
98333
|
+
logger$1.debug(`fyn-central: can't clone dirs from ${this._centralDir}, cloning files instead`);
|
|
98334
|
+
return false;
|
|
98335
|
+
}
|
|
98336
|
+
try {
|
|
98337
|
+
await file_ops_default.rename(tmp, destDir);
|
|
98338
|
+
return true;
|
|
98339
|
+
} catch (err) {
|
|
98340
|
+
await file_ops_default.$.rimraf(tmp);
|
|
98341
|
+
const code = err.code;
|
|
98342
|
+
if (code === "ENOTEMPTY" || code === "EEXIST") return false;
|
|
98343
|
+
throw err;
|
|
98344
|
+
}
|
|
97439
98345
|
}
|
|
98346
|
+
/** Extract a tarball and build its tree from the tar headers. */
|
|
97440
98347
|
_untarStream(tarStream, targetDir) {
|
|
97441
|
-
const newDirObj = () => {
|
|
97442
|
-
const n = Object.create(null);
|
|
97443
|
-
n["/"] = Object.create(null);
|
|
97444
|
-
return n;
|
|
97445
|
-
};
|
|
97446
|
-
const dirTree = newDirObj();
|
|
97447
98348
|
const strip = 1;
|
|
98349
|
+
const { onentry, result } = treeCollector(strip);
|
|
97448
98350
|
const untarStream = So({
|
|
97449
98351
|
strip,
|
|
97450
98352
|
strict: true,
|
|
97451
98353
|
C: targetDir,
|
|
97452
|
-
onentry
|
|
97453
|
-
const parts = entry.path.split(/\/|\\/);
|
|
97454
|
-
const isDir = entry.type === "Directory";
|
|
97455
|
-
const wtree = parts.slice(strip, isDir ? parts.length : parts.length - 1).reduce((wt, dir) => {
|
|
97456
|
-
return wt[dir] || (wt[dir] = newDirObj());
|
|
97457
|
-
}, dirTree);
|
|
97458
|
-
if (isDir) return;
|
|
97459
|
-
const fname = parts[parts.length - 1];
|
|
97460
|
-
if (fname) {
|
|
97461
|
-
const m = Math.round((entry.mtime ? entry.mtime.getTime() : Date.now()) / 1e3);
|
|
97462
|
-
wtree["/"][fname] = {
|
|
97463
|
-
z: entry.size,
|
|
97464
|
-
m,
|
|
97465
|
-
$: entry.header.cksumValid && entry.header.cksum
|
|
97466
|
-
};
|
|
97467
|
-
}
|
|
97468
|
-
}
|
|
98354
|
+
onentry
|
|
97469
98355
|
});
|
|
97470
|
-
return missPipe(tarStream, untarStream).then(() =>
|
|
98356
|
+
return missPipe(tarStream, untarStream).then(() => result);
|
|
97471
98357
|
}
|
|
97472
|
-
|
|
97473
|
-
|
|
98358
|
+
/**
|
|
98359
|
+
* Claim the `.extracting` marker that tells other installs this one is writing the entry.
|
|
98360
|
+
* mkdir is atomic, so only one install gets it. A marker older than STALE_MS was left by an
|
|
98361
|
+
* install that died, so it is taken over.
|
|
98362
|
+
*
|
|
98363
|
+
* @returns true when this install owns the marker
|
|
98364
|
+
*/
|
|
98365
|
+
async _claimMarker(marker, retry = true) {
|
|
97474
98366
|
try {
|
|
97475
|
-
await file_ops_default
|
|
97476
|
-
|
|
97477
|
-
wait: 3e5,
|
|
97478
|
-
pollPeriod: 500,
|
|
97479
|
-
stale: 3e5
|
|
97480
|
-
});
|
|
98367
|
+
await file_ops_default.mkdir(marker);
|
|
98368
|
+
return true;
|
|
97481
98369
|
} catch (err) {
|
|
97482
|
-
|
|
97483
|
-
const msg = err.message && err.message.replace(tmpLock, "<lockfile>");
|
|
97484
|
-
throw new Error(`Unable to acquire fyn-central tmp lock ${tmpLock} - ${msg}`);
|
|
98370
|
+
if (err.code !== "EEXIST") throw err;
|
|
97485
98371
|
}
|
|
97486
|
-
|
|
98372
|
+
const stat = await file_ops_default.stat(marker).catch(() => void 0);
|
|
98373
|
+
if (retry && (!stat || Date.now() - stat.mtimeMs > 3e5)) {
|
|
98374
|
+
await file_ops_default.$.rimraf(marker);
|
|
98375
|
+
return this._claimMarker(marker, false);
|
|
98376
|
+
}
|
|
98377
|
+
return false;
|
|
97487
98378
|
}
|
|
97488
|
-
|
|
98379
|
+
/** Remove temp and trash dirs that installs which died left next to the entry. */
|
|
98380
|
+
async _removeStaleTemps(contentPath) {
|
|
98381
|
+
const dir = Path.dirname(contentPath);
|
|
98382
|
+
const base = Path.basename(contentPath);
|
|
98383
|
+
for (const name of await file_ops_default.readdir(dir)) {
|
|
98384
|
+
if (!name.startsWith(`${base}.tmp`) && !name.startsWith(`${base}.del-`)) continue;
|
|
98385
|
+
const stat = await file_ops_default.stat(Path.join(dir, name)).catch(() => void 0);
|
|
98386
|
+
if (stat && Date.now() - stat.mtimeMs > 3e5) await file_ops_default.$.rimraf(Path.join(dir, name));
|
|
98387
|
+
}
|
|
98388
|
+
}
|
|
98389
|
+
/**
|
|
98390
|
+
* Extract into a temp dir only this call uses, then rename it into place. The rename is
|
|
98391
|
+
* atomic, so other installs see the entry complete or not at all. If another install renamed
|
|
98392
|
+
* its copy in first, that copy has the same integrity, so this one is dropped for it.
|
|
98393
|
+
*
|
|
98394
|
+
* With an fs worker, storeTarStream hands the whole job to _storeInWorker instead.
|
|
98395
|
+
*/
|
|
98396
|
+
async _storeTarStream(info, _stream) {
|
|
97489
98397
|
let stream = _stream;
|
|
97490
|
-
const tmp = `${info.contentPath}.tmp`;
|
|
97491
|
-
|
|
97492
|
-
|
|
97493
|
-
|
|
97494
|
-
|
|
97495
|
-
|
|
97496
|
-
|
|
97497
|
-
|
|
97498
|
-
|
|
97499
|
-
|
|
98398
|
+
const tmp = `${info.contentPath}.tmp-${uniqueSuffix()}`;
|
|
98399
|
+
try {
|
|
98400
|
+
const targetDir = Path.join(tmp, "package");
|
|
98401
|
+
await file_ops_default.$.mkdirp(targetDir);
|
|
98402
|
+
if (typeof stream === "function") stream = stream();
|
|
98403
|
+
if (stream.then) stream = await stream;
|
|
98404
|
+
const { tree, fromHeaders } = await this._untarStream(stream, targetDir);
|
|
98405
|
+
info.tree = tree;
|
|
98406
|
+
info.shaSum = fromHeaders ? this._treeShasum(tree) : (await this._scanShasums(targetDir))?.v2;
|
|
98407
|
+
info.sumVersion = 2;
|
|
98408
|
+
await this.saveInfoTree(info, tmp);
|
|
98409
|
+
try {
|
|
98410
|
+
await file_ops_default.rename(tmp, info.contentPath);
|
|
98411
|
+
} catch (err) {
|
|
98412
|
+
const code = err.code;
|
|
98413
|
+
if (![
|
|
98414
|
+
"ENOTEMPTY",
|
|
98415
|
+
"EEXIST",
|
|
98416
|
+
"EPERM"
|
|
98417
|
+
].includes(code) || !await file_ops_default.exists(info.contentPath)) throw err;
|
|
98418
|
+
logger$1.debug("fyn-central: another install stored it first", info.contentPath);
|
|
98419
|
+
await file_ops_default.$.rimraf(tmp);
|
|
98420
|
+
await this.readInfoTree(info);
|
|
98421
|
+
}
|
|
98422
|
+
} catch (err) {
|
|
98423
|
+
await file_ops_default.$.rimraf(tmp);
|
|
98424
|
+
throw err;
|
|
98425
|
+
}
|
|
97500
98426
|
info.exist = true;
|
|
97501
98427
|
}
|
|
97502
98428
|
/**
|
|
@@ -97509,46 +98435,100 @@ var FynCentral = class {
|
|
|
97509
98435
|
const info = this._map.get(integrity);
|
|
97510
98436
|
if (info === void 0 || !info.exist) return false;
|
|
97511
98437
|
if (info.validated === void 0) {
|
|
97512
|
-
const
|
|
97513
|
-
|
|
97514
|
-
|
|
97515
|
-
|
|
98438
|
+
const pkgDir = Path.join(info.contentPath, "package");
|
|
98439
|
+
const pool = getFsWorkerPool();
|
|
98440
|
+
const sums = pool ? await pool.run("scan", { dir: pkgDir }) : await this._scanShasums(pkgDir);
|
|
98441
|
+
if (info.sumVersion === 2) info.validated = Boolean(sums) && info.shaSum === sums.v2;
|
|
98442
|
+
else {
|
|
98443
|
+
info.validated = Boolean(sums) && (!info.shaSum || info.shaSum === sums.v1);
|
|
98444
|
+
if (info.validated) {
|
|
98445
|
+
info.shaSum = sums.v2;
|
|
98446
|
+
info.sumVersion = 2;
|
|
98447
|
+
await this.saveInfoTree(info);
|
|
98448
|
+
}
|
|
97516
98449
|
}
|
|
97517
|
-
info.validated = info.shaSum === sum;
|
|
97518
98450
|
}
|
|
97519
98451
|
return info.validated;
|
|
97520
98452
|
}
|
|
97521
|
-
|
|
97522
|
-
|
|
98453
|
+
/**
|
|
98454
|
+
* Store a package's tarball in the central store. Installs never wait on each other: each
|
|
98455
|
+
* extracts into its own temp dir and renames it into place.
|
|
98456
|
+
*
|
|
98457
|
+
* While extracting, an install holds the entry's `.extracting` marker. With `deferIfBusy`, a
|
|
98458
|
+
* live marker from another install returns false without reading the stream, so the caller
|
|
98459
|
+
* can do its other packages first and come back to this one.
|
|
98460
|
+
*
|
|
98461
|
+
* @param tarSource - resolves the tarball's file on disk or its bytes, when it has either, so
|
|
98462
|
+
* an fs worker can untar it instead of the stream
|
|
98463
|
+
* @returns false when deferred, true when the package is in the store
|
|
98464
|
+
*/
|
|
98465
|
+
async storeTarStream(pkgId, integrity, stream, deferIfBusy = false, tarSource) {
|
|
97523
98466
|
let currentStream = stream;
|
|
98467
|
+
let marker;
|
|
97524
98468
|
try {
|
|
97525
|
-
|
|
98469
|
+
const pool = tarSource && getFsWorkerPool();
|
|
98470
|
+
const source = pool && await tarSource();
|
|
98471
|
+
if (source) return await this._storeInWorker(pool, source, pkgId, integrity, deferIfBusy);
|
|
98472
|
+
const info = await this._loadTree(integrity);
|
|
97526
98473
|
if (info.exist) {
|
|
97527
98474
|
logger$1.debug("fyn-central storeTarStream: already exist", info.contentPath);
|
|
97528
98475
|
if (!info.tree) logger$1.error(`fyn-central exist package missing tree.json`);
|
|
97529
|
-
|
|
97530
|
-
|
|
97531
|
-
|
|
97532
|
-
|
|
97533
|
-
|
|
97534
|
-
|
|
97535
|
-
|
|
97536
|
-
|
|
97537
|
-
|
|
97538
|
-
|
|
97539
|
-
|
|
97540
|
-
|
|
97541
|
-
|
|
97542
|
-
|
|
97543
|
-
|
|
97544
|
-
logger$1.debug("fyn-central storeTarStream: stored", pkgId, info.contentPath);
|
|
97545
|
-
}
|
|
98476
|
+
return true;
|
|
98477
|
+
}
|
|
98478
|
+
const entryDir = Path.dirname(info.contentPath);
|
|
98479
|
+
if (!this._madeDirs.has(entryDir)) {
|
|
98480
|
+
await file_ops_default.$.mkdirp(entryDir);
|
|
98481
|
+
this._madeDirs.add(entryDir);
|
|
98482
|
+
}
|
|
98483
|
+
const markerPath = `${info.contentPath}.extracting`;
|
|
98484
|
+
if (await this._claimMarker(markerPath)) {
|
|
98485
|
+
marker = markerPath;
|
|
98486
|
+
if ((await this._loadTree(integrity, info)).exist) return true;
|
|
98487
|
+
await this._removeStaleTemps(info.contentPath);
|
|
98488
|
+
} else if (deferIfBusy) {
|
|
98489
|
+
logger$1.debug("fyn-central: another install is storing it, deferring", pkgId);
|
|
98490
|
+
return false;
|
|
97546
98491
|
}
|
|
98492
|
+
if (await file_ops_default.exists(info.contentPath)) await this._removeBrokenEntry(info.contentPath);
|
|
98493
|
+
logger$1.debug("storing tar to central store", pkgId, integrity);
|
|
98494
|
+
await this._storeTarStream(info, currentStream);
|
|
98495
|
+
currentStream = void 0;
|
|
98496
|
+
this._map.set(integrity, info);
|
|
98497
|
+
this._missing.delete(integrity);
|
|
98498
|
+
logger$1.debug("fyn-central storeTarStream: stored", pkgId, info.contentPath);
|
|
98499
|
+
return true;
|
|
97547
98500
|
} finally {
|
|
97548
98501
|
if (currentStream && currentStream.destroy !== void 0) currentStream.destroy();
|
|
97549
|
-
if (
|
|
98502
|
+
if (marker) await file_ops_default.rmdir(marker).catch(() => void 0);
|
|
97550
98503
|
}
|
|
97551
98504
|
}
|
|
98505
|
+
/** storeTarStream's steps, run by an fs worker with sync calls, marker and all */
|
|
98506
|
+
async _storeInWorker(pool, source, pkgId, integrity, deferIfBusy) {
|
|
98507
|
+
const info = this._map.get(integrity) ?? this._missing.get(integrity) ?? this._analyze(integrity);
|
|
98508
|
+
const result = await pool.run("store", {
|
|
98509
|
+
...source,
|
|
98510
|
+
integrity,
|
|
98511
|
+
contentPath: info.contentPath,
|
|
98512
|
+
deferIfBusy
|
|
98513
|
+
});
|
|
98514
|
+
if (result.busy) {
|
|
98515
|
+
logger$1.debug("fyn-central: another install is storing it, deferring", pkgId);
|
|
98516
|
+
return false;
|
|
98517
|
+
}
|
|
98518
|
+
if (result.stored) {
|
|
98519
|
+
info.tree = result.tree;
|
|
98520
|
+
info.shaSum = result.stored.shaSum;
|
|
98521
|
+
info.sumVersion = result.stored.sumVersion;
|
|
98522
|
+
info.exist = true;
|
|
98523
|
+
this._map.set(integrity, info);
|
|
98524
|
+
this._missing.delete(integrity);
|
|
98525
|
+
logger$1.debug("fyn-central storeTarStream: stored", pkgId, info.contentPath);
|
|
98526
|
+
} else {
|
|
98527
|
+
logger$1.debug("fyn-central: the entry is in place already", info.contentPath);
|
|
98528
|
+
if (!(await this._loadTree(integrity, info)).tree) logger$1.error(`fyn-central exist package missing tree.json`);
|
|
98529
|
+
}
|
|
98530
|
+
return true;
|
|
98531
|
+
}
|
|
97552
98532
|
};
|
|
97553
98533
|
|
|
97554
98534
|
//#endregion
|
|
@@ -99499,19 +100479,10 @@ function applyChalkMethod(chalkInstance, name, values) {
|
|
|
99499
100479
|
throw new TypeError(`${name} is not a chalk function`);
|
|
99500
100480
|
}
|
|
99501
100481
|
function decodeHtml(str) {
|
|
99502
|
-
return str.replace(/&[
|
|
99503
|
-
if (Object.prototype.hasOwnProperty.call(htmlEntities, m)
|
|
99504
|
-
|
|
99505
|
-
|
|
99506
|
-
const p = parseInt(s, 16);
|
|
99507
|
-
return String.fromCodePoint(p);
|
|
99508
|
-
}
|
|
99509
|
-
if (m.startsWith("&#")) {
|
|
99510
|
-
const s = m.substring(2, m.length - 1);
|
|
99511
|
-
const p = parseInt(s, 10);
|
|
99512
|
-
return String.fromCodePoint(p);
|
|
99513
|
-
}
|
|
99514
|
-
return m;
|
|
100482
|
+
return str.replace(/&(?:#[xX]([0-9a-fA-F]+)|#([0-9]+)|\w+);/g, (m, hex, dec) => {
|
|
100483
|
+
if (hex === void 0 && dec === void 0) return Object.prototype.hasOwnProperty.call(htmlEntities, m) ? htmlEntities[m] : m;
|
|
100484
|
+
const p = hex !== void 0 ? parseInt(hex, 16) : parseInt(dec, 10);
|
|
100485
|
+
return p <= 1114111 ? String.fromCodePoint(p) : m;
|
|
99515
100486
|
});
|
|
99516
100487
|
}
|
|
99517
100488
|
function applyChalkMarkers(markers, text, userChalk) {
|
|
@@ -99553,18 +100524,19 @@ function applyChalkMarkers(markers, text, userChalk) {
|
|
|
99553
100524
|
co(typeof chalkify === "function", `final chalk value is not a function after applying ${markers}`);
|
|
99554
100525
|
return chalkify(text);
|
|
99555
100526
|
}
|
|
100527
|
+
const MARKERS_RE = /<[^>]*>/g;
|
|
99556
100528
|
function remove(s, keepHtml) {
|
|
99557
|
-
const r = s.replace(
|
|
100529
|
+
const r = s.replace(MARKERS_RE, "");
|
|
99558
100530
|
return keepHtml ? r : decodeHtml(r);
|
|
99559
100531
|
}
|
|
99560
100532
|
function format$1(s, instance, userChalk) {
|
|
99561
100533
|
userChalk = normalizeColors(userChalk || instance.CHALK);
|
|
99562
|
-
|
|
99563
|
-
const tks = s && s.match(
|
|
100534
|
+
const off = userChalk.supportsColor === false;
|
|
100535
|
+
const tks = s && s.match(/<[^<>]+>|[^<>]+|[<>]/g);
|
|
99564
100536
|
if (!tks) return s || "";
|
|
99565
|
-
|
|
100537
|
+
const colorized = tks.reduceRight((a, e, ix) => {
|
|
99566
100538
|
const lvl = a[a.length - 1];
|
|
99567
|
-
if (e[0] !== "<") {
|
|
100539
|
+
if (e[0] !== "<" || e.length === 1) {
|
|
99568
100540
|
lvl.s = e + lvl.s;
|
|
99569
100541
|
return a;
|
|
99570
100542
|
}
|
|
@@ -99577,20 +100549,27 @@ function format$1(s, instance, userChalk) {
|
|
|
99577
100549
|
return a;
|
|
99578
100550
|
}
|
|
99579
100551
|
if (a.length === 1) {
|
|
100552
|
+
if (off) return a;
|
|
99580
100553
|
const partial = tks.slice(0, ix).join("") + `[${tks[ix]}]` + (tks.length > ix + 1 ? "..." : "");
|
|
99581
100554
|
throw new Error(`unbalanced open/close markers: ${partial}`);
|
|
99582
100555
|
}
|
|
99583
100556
|
const mk = e.substring(1, e.length - 1);
|
|
99584
|
-
if (lvl.mk && mk !== lvl.mk) {
|
|
100557
|
+
if (lvl.mk && mk !== lvl.mk && !off) {
|
|
99585
100558
|
const partial = tks.slice(0, ix).join("") + `[** ${tks[ix]} **]` + tks.slice(ix + 1, lvl.ix).join("") + `[** ${tks[lvl.ix]} **]`;
|
|
99586
100559
|
throw new Error(`mismatch markers: ${partial}`);
|
|
99587
100560
|
}
|
|
99588
|
-
const t = applyChalkMarkers(mk, lvl.s, userChalk);
|
|
100561
|
+
const t = off ? lvl.s : applyChalkMarkers(mk, lvl.s, userChalk);
|
|
99589
100562
|
a.pop();
|
|
99590
100563
|
const nl = a.length - 1;
|
|
99591
100564
|
a[nl].s = t + a[nl].s;
|
|
99592
100565
|
return a;
|
|
99593
|
-
}, [{ s: "" }])
|
|
100566
|
+
}, [{ s: "" }]);
|
|
100567
|
+
while (colorized.length > 1) {
|
|
100568
|
+
const lvl = colorized.pop();
|
|
100569
|
+
const nl = colorized.length - 1;
|
|
100570
|
+
colorized[nl].s = lvl.s + tks[lvl.ix] + colorized[nl].s;
|
|
100571
|
+
}
|
|
100572
|
+
return decodeHtml(colorized[0].s);
|
|
99594
100573
|
}
|
|
99595
100574
|
/**
|
|
99596
100575
|
* Build a chalker bound to a specific colors module.
|
|
@@ -101659,6 +102638,25 @@ async function syncLocalExports(options) {
|
|
|
101659
102638
|
const createLock$1 = Util.promisify(import_lockfile.lock);
|
|
101660
102639
|
const unlock$1 = Util.promisify(import_lockfile.unlock);
|
|
101661
102640
|
const { posixify } = fyntil;
|
|
102641
|
+
/** FYN_SHORT_PKG_DIR is on only for "1" or "true" (any case); any other value is off. */
|
|
102642
|
+
function shortPkgDirFromEnv() {
|
|
102643
|
+
const v = (process.env.FYN_SHORT_PKG_DIR || "").toLowerCase();
|
|
102644
|
+
return v === "1" || v === "true";
|
|
102645
|
+
}
|
|
102646
|
+
/**
|
|
102647
|
+
* Whether an install lock was left by a process on this host that no longer runs. A lock
|
|
102648
|
+
* without an owner, from an older fyn, is left to lockfile's stale time.
|
|
102649
|
+
*/
|
|
102650
|
+
async function installLockOwnerGone(fname) {
|
|
102651
|
+
try {
|
|
102652
|
+
const { pid, host } = JSON.parse(await file_ops_default.readFile(fname, "utf8"));
|
|
102653
|
+
if (host !== os$1.hostname() || !Number.isInteger(pid)) return false;
|
|
102654
|
+
process.kill(pid, 0);
|
|
102655
|
+
return false;
|
|
102656
|
+
} catch (err) {
|
|
102657
|
+
return err.code === "ESRCH";
|
|
102658
|
+
}
|
|
102659
|
+
}
|
|
101662
102660
|
var Fyn = class Fyn {
|
|
101663
102661
|
_cliSource;
|
|
101664
102662
|
_shownMissingFiles;
|
|
@@ -101726,7 +102724,7 @@ var Fyn = class Fyn {
|
|
|
101726
102724
|
logger$1.info("dep lock time set to", this._lockTime.toString());
|
|
101727
102725
|
}
|
|
101728
102726
|
this._installConfig = { time: 0 };
|
|
101729
|
-
this._shortPkgDir =
|
|
102727
|
+
this._shortPkgDir = shortPkgDirFromEnv();
|
|
101730
102728
|
if (!_fynpo) this._fynpo = {};
|
|
101731
102729
|
else if (typeof _fynpo === "object") this._fynpo = _fynpo;
|
|
101732
102730
|
}
|
|
@@ -101809,8 +102807,11 @@ var Fyn = class Fyn {
|
|
|
101809
102807
|
} else if (options.centralStore) {
|
|
101810
102808
|
centralDir = Path.join(this.fynDir, "_central-storage");
|
|
101811
102809
|
logger$1.debug(`Enabling central store by CLI flag using dir ${centralDir}`);
|
|
101812
|
-
} else if (!this._fynpo?.config)
|
|
101813
|
-
|
|
102810
|
+
} else if (!this._fynpo?.config) {
|
|
102811
|
+
if (!await this._defaultCentralStore()) return this._central = false;
|
|
102812
|
+
centralDir = Path.join(this.fynDir, "_central-storage");
|
|
102813
|
+
logger$1.debug(`Enabling central store by default using dir ${centralDir}`);
|
|
102814
|
+
} else {
|
|
101814
102815
|
centralDir = this._fynpo.config.centralDir;
|
|
101815
102816
|
if (!centralDir) {
|
|
101816
102817
|
const storeBaseDir = await fyntil.resolveGitMainWorktreeDir(this._fynpo.dir);
|
|
@@ -101827,15 +102828,31 @@ var Fyn = class Fyn {
|
|
|
101827
102828
|
}
|
|
101828
102829
|
return this._central = new FynCentral({
|
|
101829
102830
|
centralDir,
|
|
101830
|
-
hardlink: this.hardlink
|
|
102831
|
+
hardlink: this.hardlink,
|
|
102832
|
+
reflink: this.reflink,
|
|
102833
|
+
copyFallback: this.copyFallback
|
|
101831
102834
|
});
|
|
101832
102835
|
}
|
|
101833
102836
|
/**
|
|
101834
|
-
*
|
|
101835
|
-
*
|
|
102837
|
+
* A new install uses the central store on macOS when @fynjs/reflink can clone dirs, and on
|
|
102838
|
+
* Linux when it can hardlink or clone, since warm installs then run 2-3x faster than copying.
|
|
102839
|
+
* Files are cloned where possible, else hardlinked, else copied. A .fyn.json that saved
|
|
102840
|
+
* centralDir false keeps copying, and --no-central-store opts out.
|
|
102841
|
+
*/
|
|
102842
|
+
async _defaultCentralStore() {
|
|
102843
|
+
if (this._options.centralStore !== void 0 || this._installConfig.centralDir !== void 0) return false;
|
|
102844
|
+
if (process.platform === "darwin") return this.reflink && Boolean(await loadReflinkCloneDir());
|
|
102845
|
+
if (process.platform === "linux") return this.hardlink || this.reflink && Boolean(await loadReflinkCloneFiles());
|
|
102846
|
+
return false;
|
|
102847
|
+
}
|
|
102848
|
+
/**
|
|
102849
|
+
* The central store only pays off when node_modules links or clones from it. Copying out of
|
|
102850
|
+
* it writes every file twice, so it's skipped when neither is known to be possible.
|
|
101836
102851
|
*/
|
|
101837
102852
|
async _centralCopyOnlyReason(centralDir) {
|
|
101838
|
-
if (!this.
|
|
102853
|
+
if (!this.copyFallback) return;
|
|
102854
|
+
if (!this.hardlink && !this.reflink) return "hardlink and reflink are off";
|
|
102855
|
+
if (!this.hardlink && ["darwin", "win32"].includes(process.platform) && !await loadReflinkCloneFiles()) return "hardlink is off and @fynjs/reflink isn't loaded";
|
|
101839
102856
|
const deviceOf = async (dir) => {
|
|
101840
102857
|
for (;;) try {
|
|
101841
102858
|
return (await file_ops_default.stat(dir)).dev;
|
|
@@ -102425,9 +103442,6 @@ var Fyn = class Fyn {
|
|
|
102425
103442
|
get refreshOptionals() {
|
|
102426
103443
|
return this._options.refreshOptionals;
|
|
102427
103444
|
}
|
|
102428
|
-
get ignoreDist() {
|
|
102429
|
-
return this._options.ignoreDist;
|
|
102430
|
-
}
|
|
102431
103445
|
get production() {
|
|
102432
103446
|
return this._options.production;
|
|
102433
103447
|
}
|
|
@@ -102441,9 +103455,20 @@ var Fyn = class Fyn {
|
|
|
102441
103455
|
if (process.env.FYN_HARDLINK !== void 0) return fyntil.strToBool(process.env.FYN_HARDLINK);
|
|
102442
103456
|
return this._installConfig.hardlink !== false;
|
|
102443
103457
|
}
|
|
103458
|
+
/** --no-reflink never clones store files into node_modules, so @fynjs/reflink isn't used */
|
|
103459
|
+
get reflink() {
|
|
103460
|
+
return this._options.reflink !== false;
|
|
103461
|
+
}
|
|
103462
|
+
/** --no-copy-fallback fails the install on a store file that can't be cloned or hardlinked */
|
|
103463
|
+
get copyFallback() {
|
|
103464
|
+
return this._options.copyFallback !== false;
|
|
103465
|
+
}
|
|
102444
103466
|
get concurrency() {
|
|
102445
103467
|
return this._options.concurrency;
|
|
102446
103468
|
}
|
|
103469
|
+
get extractConcurrency() {
|
|
103470
|
+
return this._options.extractConcurrency;
|
|
103471
|
+
}
|
|
102447
103472
|
get deepResolve() {
|
|
102448
103473
|
return this._options.deepResolve;
|
|
102449
103474
|
}
|
|
@@ -102574,10 +103599,18 @@ var Fyn = class Fyn {
|
|
|
102574
103599
|
async createInstallLock() {
|
|
102575
103600
|
await this.createDir(this.getFvDir());
|
|
102576
103601
|
const fname = this.getFvDir(".installing.lock");
|
|
103602
|
+
if (await installLockOwnerGone(fname)) {
|
|
103603
|
+
logger$1.debug(`taking over ${fname}, its install process is gone`);
|
|
103604
|
+
await file_ops_default.unlink(fname).catch(() => void 0);
|
|
103605
|
+
}
|
|
102577
103606
|
await createLock$1(fname, {
|
|
102578
103607
|
wait: 3e3,
|
|
102579
103608
|
stale: 18e5
|
|
102580
103609
|
});
|
|
103610
|
+
await file_ops_default.writeFile(fname, JSON.stringify({
|
|
103611
|
+
pid: process.pid,
|
|
103612
|
+
host: os$1.hostname()
|
|
103613
|
+
}));
|
|
102581
103614
|
return true;
|
|
102582
103615
|
}
|
|
102583
103616
|
/**
|
|
@@ -102706,9 +103739,10 @@ var Fyn = class Fyn {
|
|
|
102706
103739
|
}
|
|
102707
103740
|
return null;
|
|
102708
103741
|
}
|
|
102709
|
-
|
|
103742
|
+
/** @param placed - package.json as an fs worker placed it, so it isn't read back */
|
|
103743
|
+
async loadJsonForPkg(pkg, dir, placed) {
|
|
102710
103744
|
const fullOutDir = dir || this.getInstalledPkgDir(pkg.name, pkg.version, pkg);
|
|
102711
|
-
const json = await fyntil.readPkgJson(fullOutDir, true);
|
|
103745
|
+
const json = await fyntil.readPkgJson(fullOutDir, true, false, placed?.str);
|
|
102712
103746
|
const pkgId = `${pkg.name}@${pkg.version}`;
|
|
102713
103747
|
const id = `${json.name}@${json.version}`;
|
|
102714
103748
|
if (json.version !== pkg.version) {
|
|
@@ -102732,13 +103766,11 @@ var Fyn = class Fyn {
|
|
|
102732
103766
|
}
|
|
102733
103767
|
pkg.dir = json[PACKAGE_RAW_INFO].dir;
|
|
102734
103768
|
pkg.str = json[PACKAGE_RAW_INFO].str;
|
|
102735
|
-
|
|
102736
|
-
const gypFile = Path.join(fullOutDir, "binding.gyp");
|
|
102737
|
-
await file_ops_default.lstat(gypFile);
|
|
103769
|
+
if (placed?.gyp ?? await file_ops_default.lstat(Path.join(fullOutDir, "binding.gyp")).then(() => true, () => false)) {
|
|
102738
103770
|
json.gypfile = true;
|
|
102739
103771
|
const scr = json.scripts;
|
|
102740
103772
|
if (isEmpty(scr) || !scr.install && !scr.postinstall && !scr.postInstall) set(json, "scripts.install", "node-gyp rebuild");
|
|
102741
|
-
}
|
|
103773
|
+
}
|
|
102742
103774
|
pkg.json = json;
|
|
102743
103775
|
return json;
|
|
102744
103776
|
}
|
|
@@ -105006,13 +106038,15 @@ const showOutdated = async (fyn, options = {}) => {
|
|
|
105006
106038
|
/**
|
|
105007
106039
|
* Audit cache utilities for storing/retrieving npm security advisory data.
|
|
105008
106040
|
*
|
|
105009
|
-
*
|
|
105010
|
-
*
|
|
106041
|
+
* New advisories get published against versions that already exist, and a pinned lockfile
|
|
106042
|
+
* keeps the same cache key for a long time. So entries expire after AUDIT_CACHE_TTL.
|
|
105011
106043
|
*
|
|
105012
106044
|
* Cache key is generated from SHA256 hash of the sorted bulk request payload,
|
|
105013
106045
|
* ensuring different dependency sets get different cache entries.
|
|
105014
106046
|
*/
|
|
105015
106047
|
const AUDIT_CACHE_PREFIX = "fyn-audit-";
|
|
106048
|
+
/** How long a cached audit result stays fresh, in ms. */
|
|
106049
|
+
const AUDIT_CACHE_TTL = 18e5;
|
|
105016
106050
|
/**
|
|
105017
106051
|
* Generate a deterministic cache key from the bulk request payload.
|
|
105018
106052
|
* Sorts package names and versions to ensure same dependencies = same key.
|
|
@@ -105036,12 +106070,17 @@ async function cacheAuditResult(cacheDir, key, result) {
|
|
|
105036
106070
|
}
|
|
105037
106071
|
/**
|
|
105038
106072
|
* Retrieve cached audit result.
|
|
105039
|
-
* Returns null if not found (
|
|
106073
|
+
* Returns null if not found, or if `maxAge` (ms) is given and the entry is older than that.
|
|
105040
106074
|
*/
|
|
105041
|
-
async function getCachedAuditResult(cacheDir, key) {
|
|
106075
|
+
async function getCachedAuditResult(cacheDir, key, maxAge) {
|
|
105042
106076
|
const auditCacheDir = Path.join(cacheDir, "audit");
|
|
106077
|
+
const cacache = await loadCacache();
|
|
105043
106078
|
try {
|
|
105044
|
-
|
|
106079
|
+
if (maxAge !== void 0) {
|
|
106080
|
+
const info = await cacache.get.info(auditCacheDir, key);
|
|
106081
|
+
if (!info || Date.now() - info.time > maxAge) return null;
|
|
106082
|
+
}
|
|
106083
|
+
const { data } = await cacache.get(auditCacheDir, key);
|
|
105045
106084
|
return JSON.parse(data.toString());
|
|
105046
106085
|
} catch (err) {
|
|
105047
106086
|
const code = err.code;
|
|
@@ -105057,7 +106096,7 @@ async function getCachedAuditResult(cacheDir, key) {
|
|
|
105057
106096
|
*
|
|
105058
106097
|
* Workflow:
|
|
105059
106098
|
* 1. Build bulk payload from resolved DepData.pkgs
|
|
105060
|
-
* 2. Check cache for
|
|
106099
|
+
* 2. Check cache for advisories fetched within AUDIT_CACHE_TTL
|
|
105061
106100
|
* 3. If miss, POST to /-/npm/v1/security/advisories/bulk
|
|
105062
106101
|
* 4. Cache response and return
|
|
105063
106102
|
*/
|
|
@@ -105166,7 +106205,7 @@ var AuditReport = class {
|
|
|
105166
106205
|
}
|
|
105167
106206
|
const cacheKey = generateCacheKey(payload);
|
|
105168
106207
|
if (!this._noCache) {
|
|
105169
|
-
const cached = await getCachedAuditResult(this._cacheDir, cacheKey);
|
|
106208
|
+
const cached = await getCachedAuditResult(this._cacheDir, cacheKey, AUDIT_CACHE_TTL);
|
|
105170
106209
|
if (cached) {
|
|
105171
106210
|
logger$1.debug("Using cached audit result");
|
|
105172
106211
|
return cached;
|
|
@@ -105306,6 +106345,12 @@ var AuditFormatter = class {
|
|
|
105306
106345
|
return this.getSeverityLevel(severity) >= this.getSeverityLevel(this._auditLevel);
|
|
105307
106346
|
}
|
|
105308
106347
|
/**
|
|
106348
|
+
* Exit code like npm audit: 1 when any vulnerability meets the audit level.
|
|
106349
|
+
*/
|
|
106350
|
+
exitCodeFor(filtered) {
|
|
106351
|
+
return filtered.length > 0 ? 1 : 0;
|
|
106352
|
+
}
|
|
106353
|
+
/**
|
|
105309
106354
|
* Colorize text based on severity.
|
|
105310
106355
|
*/
|
|
105311
106356
|
colorize(text, severity) {
|
|
@@ -105343,7 +106388,7 @@ var AuditFormatter = class {
|
|
|
105343
106388
|
const total = filtered.length;
|
|
105344
106389
|
return {
|
|
105345
106390
|
output: `audited ${pkgCount} packages\n\n${total} ${total === 1 ? "vulnerability" : "vulnerabilities"} (${parts.join(", ")})\n\nRun \`fyn audit\` for details.`,
|
|
105346
|
-
exitCode:
|
|
106391
|
+
exitCode: 1
|
|
105347
106392
|
};
|
|
105348
106393
|
}
|
|
105349
106394
|
/**
|
|
@@ -105357,7 +106402,7 @@ var AuditFormatter = class {
|
|
|
105357
106402
|
metadata: auditResult.metadata,
|
|
105358
106403
|
advisories: auditResult.advisories
|
|
105359
106404
|
}, null, 2),
|
|
105360
|
-
exitCode:
|
|
106405
|
+
exitCode: this.exitCodeFor(filtered)
|
|
105361
106406
|
};
|
|
105362
106407
|
}
|
|
105363
106408
|
/**
|
|
@@ -105404,7 +106449,7 @@ var AuditFormatter = class {
|
|
|
105404
106449
|
lines.push("");
|
|
105405
106450
|
return {
|
|
105406
106451
|
output: lines.join("\n"),
|
|
105407
|
-
exitCode:
|
|
106452
|
+
exitCode: this.exitCodeFor(filtered)
|
|
105408
106453
|
};
|
|
105409
106454
|
}
|
|
105410
106455
|
/**
|
|
@@ -105481,6 +106526,9 @@ var ShowAudit = class {
|
|
|
105481
106526
|
}
|
|
105482
106527
|
/**
|
|
105483
106528
|
* Run the audit workflow.
|
|
106529
|
+
*
|
|
106530
|
+
* @returns exit code like npm audit: 1 if a vulnerability meets the audit level
|
|
106531
|
+
* or the audit fails, else 0. Errors are logged, not thrown.
|
|
105484
106532
|
*/
|
|
105485
106533
|
async runAudit() {
|
|
105486
106534
|
const spinner = cli_logger_default.spinners[1];
|
|
@@ -105499,7 +106547,7 @@ var ShowAudit = class {
|
|
|
105499
106547
|
}
|
|
105500
106548
|
if (Object.keys(depData.pkgs).length === 0) {
|
|
105501
106549
|
logger$1.info("No dependencies to audit");
|
|
105502
|
-
return;
|
|
106550
|
+
return 0;
|
|
105503
106551
|
}
|
|
105504
106552
|
logger$1.addItem({
|
|
105505
106553
|
name: FETCH_META,
|
|
@@ -105529,7 +106577,7 @@ var ShowAudit = class {
|
|
|
105529
106577
|
statProvider
|
|
105530
106578
|
});
|
|
105531
106579
|
if (statProvider) await formatter.precomputeStats(vulnerabilities);
|
|
105532
|
-
const { output } = formatter.format(auditResult, vulnerabilities);
|
|
106580
|
+
const { output, exitCode } = formatter.format(auditResult, vulnerabilities);
|
|
105533
106581
|
if (output) console.log(output);
|
|
105534
106582
|
if (this._opts.auditFile) {
|
|
105535
106583
|
const { output: jsonOutput } = new AuditFormatter({
|
|
@@ -105541,10 +106589,12 @@ var ShowAudit = class {
|
|
|
105541
106589
|
const targetPath = Path.isAbsolute(this._opts.auditFile) ? this._opts.auditFile : Path.join(baseDir, this._opts.auditFile);
|
|
105542
106590
|
await fs.promises.writeFile(targetPath, jsonOutput, "utf8");
|
|
105543
106591
|
}
|
|
106592
|
+
return exitCode;
|
|
105544
106593
|
} catch (err) {
|
|
105545
106594
|
logger$1.removeItem(FETCH_META);
|
|
105546
106595
|
logger$1.error("Audit failed:", err.message);
|
|
105547
106596
|
if (process.env.FYN_DEBUG) logger$1.error(err.stack);
|
|
106597
|
+
return 1;
|
|
105548
106598
|
}
|
|
105549
106599
|
}
|
|
105550
106600
|
};
|
|
@@ -105845,7 +106895,7 @@ async function fetchDistTags2(baseUrl, _authToken, options) {
|
|
|
105845
106895
|
try {
|
|
105846
106896
|
return (await options.fetchJSON(pkUrl.toString(), { headers }))["dist-tags"];
|
|
105847
106897
|
} catch (_a) {
|
|
105848
|
-
return
|
|
106898
|
+
return;
|
|
105849
106899
|
}
|
|
105850
106900
|
}
|
|
105851
106901
|
/**
|
|
@@ -105859,7 +106909,7 @@ async function fetchDistTags2(baseUrl, _authToken, options) {
|
|
|
105859
106909
|
function getNpmRegistryInfo(npmConfig, pkg) {
|
|
105860
106910
|
const pkgNames = pkg.name.split("/");
|
|
105861
106911
|
const scope = pkgNames.length > 1 ? pkgNames[0] : "";
|
|
105862
|
-
const regKey = Object.keys(npmConfig).find((k) => k.endsWith("registry") &&
|
|
106912
|
+
const regKey = scope && Object.keys(npmConfig).find((k) => k.endsWith("registry") && k.startsWith(scope));
|
|
105863
106913
|
const registry = regKey && npmConfig[regKey] || npmConfig.registry || "https://registry.npmjs.org/";
|
|
105864
106914
|
const regHost = `//${new URL(registry).host}/`;
|
|
105865
106915
|
const authKey = Object.keys(npmConfig).find((k) => k.endsWith("_authToken") && k.startsWith(regHost));
|
|
@@ -105920,6 +106970,7 @@ async function _internalCheck(options) {
|
|
|
105920
106970
|
}));
|
|
105921
106971
|
};
|
|
105922
106972
|
if (shouldFetch) {
|
|
106973
|
+
if (!distTags || typeof distTags !== "object") return false;
|
|
105923
106974
|
let notifiedVersion = typeof existMeta.notifiedVersion === "string" ? existMeta.notifiedVersion : "";
|
|
105924
106975
|
let notifiedTime = existMeta.notifiedTime || 0;
|
|
105925
106976
|
const checked = options.checkIsNewer(pkg, distTags, tag);
|
|
@@ -107097,6 +108148,18 @@ var FynCli = class {
|
|
|
107097
108148
|
const start = Date.now();
|
|
107098
108149
|
const runAudit = argv.opts?.audit !== false;
|
|
107099
108150
|
const auditFile = argv.opts?.auditFile;
|
|
108151
|
+
const auditAfterInstall = async () => {
|
|
108152
|
+
if (!runAudit) return;
|
|
108153
|
+
try {
|
|
108154
|
+
await showAudit(this.fyn, {
|
|
108155
|
+
colors: this.fyn._options.colors !== false,
|
|
108156
|
+
summary: true,
|
|
108157
|
+
auditFile
|
|
108158
|
+
});
|
|
108159
|
+
} catch (err) {
|
|
108160
|
+
logger$1.warn("Security audit failed:", err.message);
|
|
108161
|
+
}
|
|
108162
|
+
};
|
|
107100
108163
|
return dist_default.try(() => this.fyn._initializePkg()).then(async () => {
|
|
107101
108164
|
checkNewVersion(this.fyn._options);
|
|
107102
108165
|
if (!this.fyn._changeProdMode && !this.fyn._options.forceInstall && this.fyn._installConfig.fynlocal === Boolean(this.fyn.fynlocal) && this.fyn._installConfig.time) {
|
|
@@ -107211,19 +108274,13 @@ var FynCli = class {
|
|
|
107211
108274
|
const end = Date.now();
|
|
107212
108275
|
await this.fyn.saveFynpoIndirects();
|
|
107213
108276
|
logger$1.info(chalk.green("complete in total"), chalk.magenta(`${(end - start) / 1e3}`) + "secs");
|
|
107214
|
-
|
|
107215
|
-
|
|
107216
|
-
|
|
107217
|
-
|
|
107218
|
-
auditFile
|
|
107219
|
-
});
|
|
107220
|
-
} catch (err) {
|
|
107221
|
-
logger$1.warn("Security audit failed:", err.message);
|
|
107222
|
-
}
|
|
107223
|
-
}).catch((err) => {
|
|
107224
|
-
if (err.message === "No Change") logger$1.info(`No changes detected since last fyn install - nothing to be done.
|
|
108277
|
+
await auditAfterInstall();
|
|
108278
|
+
}).catch(async (err) => {
|
|
108279
|
+
if (err.message === "No Change") {
|
|
108280
|
+
logger$1.info(`No changes detected since last fyn install - nothing to be done.
|
|
107225
108281
|
To force install, run 'fyn install --force-install' or 'fyn install --fi'`);
|
|
107226
|
-
|
|
108282
|
+
await auditAfterInstall();
|
|
108283
|
+
} else failure = err;
|
|
107227
108284
|
}).finally(async () => {
|
|
107228
108285
|
const localPkgBuild = this.fyn._localPkgBuilder?.waitForDone();
|
|
107229
108286
|
if (localPkgBuild) try {
|
|
@@ -107288,16 +108345,16 @@ var FynCli = class {
|
|
|
107288
108345
|
if (this._opts.saveLogs) await this.saveLogs(this._opts.saveLogs);
|
|
107289
108346
|
}
|
|
107290
108347
|
}
|
|
107291
|
-
audit(argv) {
|
|
108348
|
+
async audit(argv) {
|
|
107292
108349
|
const opts = {
|
|
107293
108350
|
json: argv.opts?.json || false,
|
|
107294
108351
|
omit: argv.opts?.omit || [],
|
|
107295
108352
|
auditLevel: argv.opts?.auditLevel || "info",
|
|
107296
|
-
noCache: argv.opts?.
|
|
108353
|
+
noCache: argv.opts?.cache === false
|
|
107297
108354
|
};
|
|
107298
|
-
|
|
107299
|
-
|
|
107300
|
-
|
|
108355
|
+
const exitCode = await showAudit(this.fyn, opts);
|
|
108356
|
+
if (this._opts.saveLogs) await this.saveLogs(this._opts.saveLogs);
|
|
108357
|
+
if (exitCode) fyntil.exit(exitCode);
|
|
107301
108358
|
}
|
|
107302
108359
|
/**
|
|
107303
108360
|
* Remove non-runtime files from a production node_modules. Only runs on demand,
|
|
@@ -107818,7 +108875,7 @@ var CliBase = class {
|
|
|
107818
108875
|
if (!args) return;
|
|
107819
108876
|
let seenOptional;
|
|
107820
108877
|
args.replace(/([<[])([^>\]]*)([>\]])/g, (a, mark, xname) => {
|
|
107821
|
-
assert(!this.variadic, `For args specifier of '${this.name}', only the last one can be variadic
|
|
108878
|
+
assert(!this.variadic, new InvalidArgSpecifierError(`For args specifier of '${this.name}', only the last one can be variadic`, args));
|
|
107822
108879
|
const xm = xname.match(/([^\. ]+)?( +)?([^\.]+)?(\.\.+)?([^\.,]*)?( *, *)?([^\.]+)?$/);
|
|
107823
108880
|
assert(xm, new InvalidArgSpecifierError(`Invalid args specifier '${xname}' for '${this.name}'.`));
|
|
107824
108881
|
let variadic;
|
|
@@ -108026,6 +109083,7 @@ var Options = class {
|
|
|
108026
109083
|
makeHelp() {
|
|
108027
109084
|
const width = this.findLongestOptionHelpText();
|
|
108028
109085
|
let help = [];
|
|
109086
|
+
setHelpZebra(this.command.ncConfig?.helpZebra !== false);
|
|
108029
109087
|
resetZebraIndex();
|
|
108030
109088
|
for (const opt of Object.values(this._options)) {
|
|
108031
109089
|
const tail = [];
|
|
@@ -108249,6 +109307,7 @@ var CommandBase = class CommandBase extends CliBase {
|
|
|
108249
109307
|
data.push(strs);
|
|
108250
109308
|
}
|
|
108251
109309
|
const cmdWidth = data.reduce((max, n) => n[0].length > max ? n[0].length : max, 0);
|
|
109310
|
+
setHelpZebra(this.ncConfig?.helpZebra !== false);
|
|
108252
109311
|
resetZebraIndex();
|
|
108253
109312
|
return data.reduce((help, strs) => {
|
|
108254
109313
|
const lines = fitLines(strs, " ", " ", cmdWidth, getTerminalWidth());
|
|
@@ -108489,6 +109548,9 @@ var CommandNode = class extends ClapNode {
|
|
|
108489
109548
|
* Allow you to apply extra config to the parsed object, overriding any `opts` with `source` not start with `cli`.
|
|
108490
109549
|
*
|
|
108491
109550
|
* For example, you can allow user to specify options in their `package.json` file, and apply those after the command line is parsed.
|
|
109551
|
+
*
|
|
109552
|
+
* Each key goes to this command and any parsed sub command that declares the option.
|
|
109553
|
+
* Keys that match no declared option are ignored.
|
|
108492
109554
|
* @param config - Config object containing user options config
|
|
108493
109555
|
* @param src - Name of the source that provided the config. Default to `user`
|
|
108494
109556
|
* @returns
|
|
@@ -108515,8 +109577,9 @@ var CommandNode = class extends ClapNode {
|
|
|
108515
109577
|
this.optCount[camelCaseKey] = this.optCount[matchOpt.name];
|
|
108516
109578
|
}
|
|
108517
109579
|
}
|
|
108518
|
-
}
|
|
109580
|
+
}
|
|
108519
109581
|
}
|
|
109582
|
+
for (const name in this.subCmdNodes) this.subCmdNodes[name].applyConfig(config, src);
|
|
108520
109583
|
for (let command = this; command; command = command.getParent()) command._jsonMeta = void 0;
|
|
108521
109584
|
}
|
|
108522
109585
|
/**
|
|
@@ -108849,6 +109912,7 @@ var ClapNodeGenerator = class ClapNodeGenerator {
|
|
|
108849
109912
|
}
|
|
108850
109913
|
return [null];
|
|
108851
109914
|
}
|
|
109915
|
+
if (this.optNode && this.takesNegativeNumber(opt)) return this.consumeNonOptAsOption(opt);
|
|
108852
109916
|
if (this.optNode) {
|
|
108853
109917
|
this.complete();
|
|
108854
109918
|
return [null].concat(this.parent.consumeOpt(opt));
|
|
@@ -108891,6 +109955,17 @@ var ClapNodeGenerator = class ClapNodeGenerator {
|
|
|
108891
109955
|
});
|
|
108892
109956
|
}
|
|
108893
109957
|
/**
|
|
109958
|
+
* Whether this open option takes a negative number like `-5` as its next value.
|
|
109959
|
+
* Boolean args don't, so `--flag -5` still reads `-5` as an option.
|
|
109960
|
+
*
|
|
109961
|
+
* @param arg - an argv entry that starts with '-'
|
|
109962
|
+
*/
|
|
109963
|
+
takesNegativeNumber(arg) {
|
|
109964
|
+
if (!isNumber(arg)) return false;
|
|
109965
|
+
const args = this.optNode.option.args;
|
|
109966
|
+
return args[Math.min(this.node.argsList.length, args.length - 1)].type !== "boolean";
|
|
109967
|
+
}
|
|
109968
|
+
/**
|
|
108894
109969
|
*
|
|
108895
109970
|
* @param data
|
|
108896
109971
|
* @returns
|
|
@@ -108918,7 +109993,11 @@ var ClapNodeGenerator = class ClapNodeGenerator {
|
|
|
108918
109993
|
node.argsMap[argIx] = setValue;
|
|
108919
109994
|
};
|
|
108920
109995
|
if (opt.hasArgs) for (let i = 0; i < args.length && i < node.argsList.length; i++) setArg(i, args[i], node.argsList[i]);
|
|
108921
|
-
else
|
|
109996
|
+
else {
|
|
109997
|
+
const value = node.argsList[0];
|
|
109998
|
+
const isBool = isBoolean(value) || !opt.isUnknown && (value === "0" || value === "1");
|
|
109999
|
+
node.argsMap[0] = node.argsList.length > 0 ? this.convertValue(isBool ? "boolean" : isNumber(value) ? "number" : "string", value, opt) : true;
|
|
110000
|
+
}
|
|
108922
110001
|
if (args.length > 0 && args[args.length - 1].array) {
|
|
108923
110002
|
const lastIx = args.length - 1;
|
|
108924
110003
|
if (node.argsList.length > lastIx) setArg(lastIx, args[lastIx], node.argsList.slice(lastIx));
|
|
@@ -109248,7 +110327,6 @@ var NixClap = class extends EventEmitter$1 {
|
|
|
109248
110327
|
this._config = config;
|
|
109249
110328
|
this._name = config.name;
|
|
109250
110329
|
this._version = config.version || false;
|
|
109251
|
-
setHelpZebra(config.helpZebra !== false);
|
|
109252
110330
|
this._versionAlias = config.versionAlias;
|
|
109253
110331
|
this._helpOpt = config.hasOwnProperty("help") ? config.help : {
|
|
109254
110332
|
[HELP]: true,
|
|
@@ -109284,10 +110362,13 @@ var NixClap = class extends EventEmitter$1 {
|
|
|
109284
110362
|
"parse-fail": (parsed) => this.showError(parsed.command.getErrorNodes()[0].error),
|
|
109285
110363
|
"no-action": () => this.showHelp(/* @__PURE__ */ new Error("No command given"))
|
|
109286
110364
|
};
|
|
109287
|
-
if (!config.noDefaultHandlers) this.on("exit", defaultExit);
|
|
109288
110365
|
const handlers = config.handlers || {};
|
|
109289
|
-
|
|
109290
|
-
|
|
110366
|
+
const exitHandler = Object.hasOwn(handlers, "exit") ? handlers.exit : !config.noDefaultHandlers && defaultExit;
|
|
110367
|
+
if (typeof exitHandler === "function") this.on("exit", exitHandler);
|
|
110368
|
+
const names = /* @__PURE__ */ new Set([...Object.keys(this._evtHandlers), ...Object.keys(handlers)]);
|
|
110369
|
+
names.delete("exit");
|
|
110370
|
+
for (const name of names) {
|
|
110371
|
+
const h = Object.hasOwn(handlers, name) ? handlers[name] : this._evtHandlers[name];
|
|
109291
110372
|
if (typeof h === "function") this.on(name, h);
|
|
109292
110373
|
}
|
|
109293
110374
|
this._skipExec = config.skipExec;
|
|
@@ -109356,6 +110437,23 @@ var NixClap = class extends EventEmitter$1 {
|
|
|
109356
110437
|
return this;
|
|
109357
110438
|
}
|
|
109358
110439
|
/**
|
|
110440
|
+
* Make a copy of the help option without aliases that other options already use.
|
|
110441
|
+
*/
|
|
110442
|
+
_withFreeHelpAliases(existingOptions) {
|
|
110443
|
+
const helpOpt = this._helpOpt;
|
|
110444
|
+
const usedAliases = /* @__PURE__ */ new Set();
|
|
110445
|
+
for (const optName in existingOptions) {
|
|
110446
|
+
const opt = existingOptions[optName];
|
|
110447
|
+
if (optName !== "help" && opt.alias) (Array.isArray(opt.alias) ? opt.alias : [opt.alias]).forEach((a) => usedAliases.add(a));
|
|
110448
|
+
}
|
|
110449
|
+
/* c8 ignore next 3 */
|
|
110450
|
+
const helpAliases = helpOpt.alias ? Array.isArray(helpOpt.alias) ? helpOpt.alias : [helpOpt.alias] : [];
|
|
110451
|
+
return {
|
|
110452
|
+
...helpOpt,
|
|
110453
|
+
alias: helpAliases.filter((a) => !usedAliases.has(a))
|
|
110454
|
+
};
|
|
110455
|
+
}
|
|
110456
|
+
/**
|
|
109359
110457
|
* Recursively adds help option to all subcommands.
|
|
109360
110458
|
* Filters out help aliases that conflict with existing options in the subcommand.
|
|
109361
110459
|
*/
|
|
@@ -109364,18 +110462,9 @@ var NixClap = class extends EventEmitter$1 {
|
|
|
109364
110462
|
for (const name in commands) {
|
|
109365
110463
|
const cmd = commands[name];
|
|
109366
110464
|
const existingOptions = cmd.options || {};
|
|
109367
|
-
const usedAliases = /* @__PURE__ */ new Set();
|
|
109368
|
-
for (const optName in existingOptions) {
|
|
109369
|
-
const opt = existingOptions[optName];
|
|
109370
|
-
if (opt.alias) (Array.isArray(opt.alias) ? opt.alias : [opt.alias]).forEach((a) => usedAliases.add(a));
|
|
109371
|
-
}
|
|
109372
|
-
const filteredAliases = (this._helpOpt.alias ? Array.isArray(this._helpOpt.alias) ? this._helpOpt.alias : [this._helpOpt.alias] : []).filter((a) => !usedAliases.has(a));
|
|
109373
110465
|
if (!existingOptions.hasOwnProperty("help")) cmd.options = {
|
|
109374
110466
|
...existingOptions,
|
|
109375
|
-
help:
|
|
109376
|
-
...this._helpOpt,
|
|
109377
|
-
alias: filteredAliases
|
|
109378
|
-
}
|
|
110467
|
+
help: this._withFreeHelpAliases(existingOptions)
|
|
109379
110468
|
};
|
|
109380
110469
|
if (cmd.subCommands) this._addHelpToSubCommands(cmd.subCommands);
|
|
109381
110470
|
}
|
|
@@ -109396,13 +110485,13 @@ var NixClap = class extends EventEmitter$1 {
|
|
|
109396
110485
|
let verAlias = ["V", "v"];
|
|
109397
110486
|
Object.keys(options).forEach((k) => {
|
|
109398
110487
|
const opt = options[k];
|
|
109399
|
-
if (opt.alias) verAlias = verAlias.filter((x) => opt.alias.
|
|
110488
|
+
if (opt.alias) verAlias = verAlias.filter((x) => ![].concat(opt.alias).includes(x));
|
|
109400
110489
|
});
|
|
109401
110490
|
options.version = this._getVersionOpt(verAlias);
|
|
109402
110491
|
}
|
|
109403
110492
|
if (this._helpOpt) {
|
|
109404
110493
|
options = { ...options };
|
|
109405
|
-
options["help"] = this.
|
|
110494
|
+
options["help"] = this._withFreeHelpAliases(options);
|
|
109406
110495
|
this._addHelpToSubCommands(commands);
|
|
109407
110496
|
}
|
|
109408
110497
|
this._options = options;
|
|
@@ -109581,6 +110670,7 @@ var NixClap = class extends EventEmitter$1 {
|
|
|
109581
110670
|
skipExec(skip = true) {
|
|
109582
110671
|
this._skipExec = skip;
|
|
109583
110672
|
this._skipExecDefault = skip;
|
|
110673
|
+
return this;
|
|
109584
110674
|
}
|
|
109585
110675
|
/**
|
|
109586
110676
|
* Parses the given arguments and returns the result.
|
|
@@ -109671,9 +110761,10 @@ var NixClap = class extends EventEmitter$1 {
|
|
|
109671
110761
|
this._rootCommand.name = this._name;
|
|
109672
110762
|
}
|
|
109673
110763
|
const { command, index } = new Parser(this).parse(argv, start);
|
|
110764
|
+
if (this._config.config) command.applyConfig(this._config.config(command) || {}, "user");
|
|
110765
|
+
command.applyDefaults();
|
|
109674
110766
|
const missing = command.checkRequiredOptions();
|
|
109675
110767
|
if (missing.length > 0) command.addError(/* @__PURE__ */ new Error("missing these required options " + missing.join(", ")));
|
|
109676
|
-
command.applyDefaults();
|
|
109677
110768
|
command.makeCamelCaseOptions();
|
|
109678
110769
|
const errorNodes = command.getErrorNodes();
|
|
109679
110770
|
return {
|
|
@@ -116550,8 +117641,7 @@ function setLogLevel(ll) {
|
|
|
116550
117641
|
if (ll) {
|
|
116551
117642
|
const levels = Object.keys(cli_logger_default.Levels);
|
|
116552
117643
|
const real = find(levels, (l) => l.startsWith(ll));
|
|
116553
|
-
|
|
116554
|
-
if (x !== void 0) logger$1._logLevel = x;
|
|
117644
|
+
if ((real ? cli_logger_default.Levels[real] : void 0) !== void 0) logger$1.logLevel = real;
|
|
116555
117645
|
else {
|
|
116556
117646
|
logger$1.error(`Invalid log level "${ll}". Supported levels are: ${levels.join(", ")}`);
|
|
116557
117647
|
fyntil.exit(1);
|
|
@@ -116691,12 +117781,21 @@ const options = {
|
|
|
116691
117781
|
"central-store": {
|
|
116692
117782
|
args: "<flag boolean>",
|
|
116693
117783
|
alias: ["central", "cs"],
|
|
116694
|
-
desc: "keep single copy of packages in central store"
|
|
116695
|
-
argDefault: "false"
|
|
117784
|
+
desc: "keep single copy of packages in central store. On by default on macOS when @fynjs/reflink can clone, and on Linux when it can hardlink or clone, unless node_modules was installed without it. --no-central-store turns the default off"
|
|
116696
117785
|
},
|
|
116697
117786
|
hardlink: {
|
|
116698
117787
|
args: "<flag boolean>",
|
|
116699
|
-
desc: "hardlink central store files into node_modules (default). --no-hardlink is remembered, and skips the central store on macOS and Windows, where it would only copy"
|
|
117788
|
+
desc: "hardlink central store files into node_modules (default). --no-hardlink is remembered, and skips the central store on macOS and Windows, where it would only copy unless @fynjs/reflink can clone"
|
|
117789
|
+
},
|
|
117790
|
+
reflink: {
|
|
117791
|
+
args: "<flag boolean>",
|
|
117792
|
+
desc: "reflink (copy-on-write clone) central store files into node_modules where the filesystem can (default). --no-reflink never clones, so @fynjs/reflink isn't used",
|
|
117793
|
+
argDefault: "true"
|
|
117794
|
+
},
|
|
117795
|
+
"copy-fallback": {
|
|
117796
|
+
args: "<flag boolean>",
|
|
117797
|
+
desc: "copy central store files that can't be cloned or hardlinked (default). --no-copy-fallback fails the install instead",
|
|
117798
|
+
argDefault: "true"
|
|
116700
117799
|
},
|
|
116701
117800
|
copy: {
|
|
116702
117801
|
args: "[packages string..]",
|
|
@@ -116776,11 +117875,6 @@ const options = {
|
|
|
116776
117875
|
argDefault: "false",
|
|
116777
117876
|
desc: "force refresh package meta from registry"
|
|
116778
117877
|
},
|
|
116779
|
-
"ignore-dist": {
|
|
116780
|
-
alias: "i",
|
|
116781
|
-
args: "<flag boolean>",
|
|
116782
|
-
desc: "Ignore host in tarball URL from meta dist."
|
|
116783
|
-
},
|
|
116784
117878
|
"ignore-lock-url": {
|
|
116785
117879
|
args: "<flag boolean>",
|
|
116786
117880
|
argDefault: "false",
|
|
@@ -116828,6 +117922,11 @@ const options = {
|
|
|
116828
117922
|
desc: "Max network concurrency (registry sockets)",
|
|
116829
117923
|
argDefault: "32"
|
|
116830
117924
|
},
|
|
117925
|
+
"extract-concurrency": {
|
|
117926
|
+
args: "<num number>",
|
|
117927
|
+
alias: "excc",
|
|
117928
|
+
desc: "Max packages extracted at once (default: CPU cores, at most 4)"
|
|
117929
|
+
},
|
|
116831
117930
|
"auto-run": {
|
|
116832
117931
|
args: "<flag boolean>",
|
|
116833
117932
|
argDefault: "true",
|
|
@@ -116986,14 +118085,14 @@ const commands = {
|
|
|
116986
118085
|
args: "[packages string..]",
|
|
116987
118086
|
exec: async (cmd) => {
|
|
116988
118087
|
const json = Boolean(cmd.jsonMeta.opts.json);
|
|
116989
|
-
const previousLogLevel = logger$1.
|
|
118088
|
+
const previousLogLevel = logger$1.logLevel;
|
|
116990
118089
|
if (json) cmd.jsonMeta.opts.logLevel = "none";
|
|
116991
118090
|
try {
|
|
116992
118091
|
const config = await pickOptions(cmd);
|
|
116993
118092
|
config.noStartupInfo = json;
|
|
116994
118093
|
return await new FynCli(config).outdated(cmd.jsonMeta);
|
|
116995
118094
|
} finally {
|
|
116996
|
-
if (json) logger$1.
|
|
118095
|
+
if (json) logger$1.logLevel = previousLogLevel;
|
|
116997
118096
|
}
|
|
116998
118097
|
},
|
|
116999
118098
|
options: { json: {
|
|
@@ -117022,9 +118121,10 @@ const commands = {
|
|
|
117022
118121
|
desc: "Minimum severity level to report (info, low, moderate, high, critical)",
|
|
117023
118122
|
argDefault: "info"
|
|
117024
118123
|
},
|
|
117025
|
-
|
|
118124
|
+
cache: {
|
|
117026
118125
|
args: "<flag boolean>",
|
|
117027
|
-
desc: "
|
|
118126
|
+
desc: "use the audit cache (use --no-cache to fetch fresh data)",
|
|
118127
|
+
argDefault: "true"
|
|
117028
118128
|
}
|
|
117029
118129
|
}
|
|
117030
118130
|
},
|
|
@@ -117051,7 +118151,7 @@ const commands = {
|
|
|
117051
118151
|
} else {
|
|
117052
118152
|
logger$1.error(chalk.red("Script execution failed:"));
|
|
117053
118153
|
logger$1.error(err.message || err.toString());
|
|
117054
|
-
if (err.stack && logger$1.
|
|
118154
|
+
if (err.stack && cli_logger_default.Levels[logger$1.logLevel] <= cli_logger_default.Levels.debug) logger$1.debug(err.stack);
|
|
117055
118155
|
}
|
|
117056
118156
|
fyntil.exit(typeof exitCode === "number" ? exitCode : 1);
|
|
117057
118157
|
}
|