fyn 3.2.3 → 3.3.1
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 +70 -31
- package/dist/fs-worker.mjs +5477 -0
- package/dist/fyn.mjs +1745 -502
- package/docs/reference.md +680 -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;
|
|
@@ -1221,15 +1238,20 @@ const defaultPathFilter = [new RegExp(`/node_modules.*/(pirates/|isomorphic-load
|
|
|
1221
1238
|
function cleanErrorStack(error, { replacePath = `${process.cwd()}/`, ignorePathFilter = [] } = {}) {
|
|
1222
1239
|
const stack = error && (error.stack || error.message);
|
|
1223
1240
|
if (!stack) return String(stack);
|
|
1224
|
-
return stack.split(
|
|
1241
|
+
return stack.split(/\r?\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) {
|
|
1250
|
+
const prefix = path.startsWith(`file://${replacePath}`) ? `file://${replacePath}` : replacePath;
|
|
1251
|
+
if (path.startsWith(prefix)) path2 = path.slice(prefix.length);
|
|
1252
|
+
}
|
|
1253
|
+
return `${at}${name}${path2}${tail}`;
|
|
1254
|
+
}).filter((x) => x !== false).join("\n");
|
|
1233
1255
|
}
|
|
1234
1256
|
/**
|
|
1235
1257
|
* Build stack of aggregate errors
|
|
@@ -1239,9 +1261,10 @@ function cleanErrorStack(error, { replacePath = `${process.cwd()}/`, ignorePathF
|
|
|
1239
1261
|
* @returns aggregate stack
|
|
1240
1262
|
*/
|
|
1241
1263
|
function aggregateStack(stack, errors) {
|
|
1242
|
-
|
|
1264
|
+
const stacks = errors && errors.map ? errors.map((e) => {
|
|
1243
1265
|
return (e && (e.stack || e.message) || String(e)).replace(/^/gm, " ");
|
|
1244
|
-
})
|
|
1266
|
+
}) : [];
|
|
1267
|
+
return [stack].concat(stacks).join("\n");
|
|
1245
1268
|
}
|
|
1246
1269
|
/**
|
|
1247
1270
|
* build the aggregate stack of an AggregateError
|
|
@@ -1250,16 +1273,17 @@ function aggregateStack(stack, errors) {
|
|
|
1250
1273
|
* @returns aggregate stack
|
|
1251
1274
|
*/
|
|
1252
1275
|
function aggregateErrorStack(error) {
|
|
1253
|
-
return aggregateStack(error.__stack || error.message || String(error), error.errors);
|
|
1276
|
+
return aggregateStack(error.__stack || (error instanceof AggregateError$1 ? "" : error.stack) || error.message || String(error), error.errors);
|
|
1254
1277
|
}
|
|
1255
1278
|
/**
|
|
1256
1279
|
* AggregateError
|
|
1257
1280
|
* - https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-aggregate-error-objects
|
|
1258
1281
|
*/
|
|
1259
1282
|
var AggregateError$1 = class extends globalThis.AggregateError {
|
|
1260
|
-
constructor(errors, msg) {
|
|
1283
|
+
constructor(errors, msg, options) {
|
|
1261
1284
|
if (!errors || !(errors[Symbol.iterator] instanceof Function)) throw new TypeError(`input errors must be iterable but it's ${typeof errors}`);
|
|
1262
|
-
|
|
1285
|
+
const list = Array.from(errors);
|
|
1286
|
+
super(list, msg, options);
|
|
1263
1287
|
Object.defineProperty(this, "name", { value: "AggregateError" });
|
|
1264
1288
|
let aggStack;
|
|
1265
1289
|
Object.defineProperties(this, {
|
|
@@ -1267,15 +1291,22 @@ var AggregateError$1 = class extends globalThis.AggregateError {
|
|
|
1267
1291
|
configurable: true,
|
|
1268
1292
|
enumerable: false,
|
|
1269
1293
|
writable: true,
|
|
1270
|
-
value:
|
|
1294
|
+
value: list
|
|
1271
1295
|
},
|
|
1272
1296
|
__stack: {
|
|
1273
1297
|
enumerable: false,
|
|
1298
|
+
writable: true,
|
|
1274
1299
|
value: this.stack
|
|
1275
1300
|
},
|
|
1276
|
-
stack: {
|
|
1277
|
-
|
|
1278
|
-
|
|
1301
|
+
stack: {
|
|
1302
|
+
get() {
|
|
1303
|
+
return aggStack || (aggStack = aggregateErrorStack(this));
|
|
1304
|
+
},
|
|
1305
|
+
set(value) {
|
|
1306
|
+
this.__stack = value;
|
|
1307
|
+
aggStack = "";
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1279
1310
|
});
|
|
1280
1311
|
}
|
|
1281
1312
|
};
|
|
@@ -1540,6 +1571,22 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1540
1571
|
constructor(executor) {
|
|
1541
1572
|
super(executor);
|
|
1542
1573
|
}
|
|
1574
|
+
catch(...args) {
|
|
1575
|
+
if (args.length <= 1) return super.catch(args[0]);
|
|
1576
|
+
const handler = args.pop();
|
|
1577
|
+
if (typeof handler !== "function") throw new TypeError("The last argument to .catch() must be a function, got " + String(handler));
|
|
1578
|
+
const filters = args;
|
|
1579
|
+
return super.catch((err) => {
|
|
1580
|
+
for (const f of filters) if (f === Error || f != null && f.prototype instanceof Error) {
|
|
1581
|
+
if (err instanceof f) return handler(err);
|
|
1582
|
+
} else if (typeof f === "function") {
|
|
1583
|
+
if (f(err)) return handler(err);
|
|
1584
|
+
} else if (err !== null && (typeof err === "object" || typeof err === "function")) {
|
|
1585
|
+
if (Object.keys(f).every((k) => f[k] == err[k])) return handler(err);
|
|
1586
|
+
}
|
|
1587
|
+
throw err;
|
|
1588
|
+
});
|
|
1589
|
+
}
|
|
1543
1590
|
/**
|
|
1544
1591
|
* Bluebird-style tap() method that lets you perform side effects in a chain
|
|
1545
1592
|
* Similar to Bluebird's Promise.prototype.tap()
|
|
@@ -1559,7 +1606,16 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1559
1606
|
* @returns Promise that resolves with the filtered array
|
|
1560
1607
|
*/
|
|
1561
1608
|
filter(fn) {
|
|
1562
|
-
return this.then((value) =>
|
|
1609
|
+
return this.then(async (value) => {
|
|
1610
|
+
const arr = toArray$1(value);
|
|
1611
|
+
const len = arr.length;
|
|
1612
|
+
const result = [];
|
|
1613
|
+
for (let i = 0; i < len; i++) {
|
|
1614
|
+
const x = isPromise(arr[i]) ? await arr[i] : arr[i];
|
|
1615
|
+
if (await fn(x, i, len)) result.push(x);
|
|
1616
|
+
}
|
|
1617
|
+
return result;
|
|
1618
|
+
});
|
|
1563
1619
|
}
|
|
1564
1620
|
/**
|
|
1565
1621
|
* Bluebird-style map() method for array operations
|
|
@@ -1568,7 +1624,11 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1568
1624
|
* @returns Promise that resolves with the mapped array
|
|
1569
1625
|
*/
|
|
1570
1626
|
map(fn, options = { concurrency: 50 }) {
|
|
1571
|
-
return this.then((value) =>
|
|
1627
|
+
return this.then((value) => {
|
|
1628
|
+
const arr = toArray$1(value);
|
|
1629
|
+
const len = arr.length;
|
|
1630
|
+
return map$1(arr, (item, index) => fn(item, index, len), options);
|
|
1631
|
+
});
|
|
1572
1632
|
}
|
|
1573
1633
|
/**
|
|
1574
1634
|
* Bluebird-style mapSeries() method for array operations
|
|
@@ -1605,7 +1665,7 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1605
1665
|
*/
|
|
1606
1666
|
each(fn) {
|
|
1607
1667
|
return this.then(async (value) => {
|
|
1608
|
-
const arr = value;
|
|
1668
|
+
const arr = toArray$1(value);
|
|
1609
1669
|
const result = [];
|
|
1610
1670
|
for (let i = 0; i < arr.length; i++) {
|
|
1611
1671
|
let x = arr[i];
|
|
@@ -1675,7 +1735,7 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1675
1735
|
reduce(fn, initialValue) {
|
|
1676
1736
|
const hasInitial = arguments.length > 1;
|
|
1677
1737
|
return this.then(async (array) => {
|
|
1678
|
-
const arr = array;
|
|
1738
|
+
const arr = toArray$1(array);
|
|
1679
1739
|
const len = arr.length;
|
|
1680
1740
|
let value;
|
|
1681
1741
|
let idx;
|
|
@@ -1750,8 +1810,9 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1750
1810
|
if (typeof fn !== "function") return AveAzul.reject(/* @__PURE__ */ new TypeError("expecting a function but got " + fn));
|
|
1751
1811
|
return this.then(async (args) => {
|
|
1752
1812
|
if (Array.isArray(args)) {
|
|
1753
|
-
|
|
1754
|
-
|
|
1813
|
+
const values = args.slice();
|
|
1814
|
+
for (let i = 0; i < values.length; i++) if (isPromise(values[i])) values[i] = await values[i];
|
|
1815
|
+
return fn(...values);
|
|
1755
1816
|
} else return fn(args);
|
|
1756
1817
|
});
|
|
1757
1818
|
}
|
|
@@ -1931,6 +1992,15 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1931
1992
|
return AveAzul.resolve(items).each(fn);
|
|
1932
1993
|
}
|
|
1933
1994
|
/**
|
|
1995
|
+
* Bluebird-style filter() for array filtering
|
|
1996
|
+
* @param items - Array or iterable to filter
|
|
1997
|
+
* @param fn - Filter function (item, index, length)
|
|
1998
|
+
* @returns Promise that resolves with the items that passed the filter
|
|
1999
|
+
*/
|
|
2000
|
+
static filter(items, fn) {
|
|
2001
|
+
return AveAzul.resolve(items).filter(fn);
|
|
2002
|
+
}
|
|
2003
|
+
/**
|
|
1934
2004
|
* Bluebird-style reduce() for array reduction
|
|
1935
2005
|
* @param array - Array to reduce
|
|
1936
2006
|
* @param fn - Reducer function (value, item, index, length)
|
|
@@ -1990,7 +2060,7 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1990
2060
|
* @returns Promise that resolves with handler result
|
|
1991
2061
|
*/
|
|
1992
2062
|
static using(resources, ...args) {
|
|
1993
|
-
if (args.length === 0) throw new TypeError("
|
|
2063
|
+
if (args.length === 0) throw new TypeError("resources and handler function required");
|
|
1994
2064
|
if (Array.isArray(resources)) {
|
|
1995
2065
|
if (args.length > 1) throw new TypeError("only two arguments are allowed when passing an array of resources");
|
|
1996
2066
|
return using(resources, args[0], AveAzul, true);
|
|
@@ -2118,7 +2188,7 @@ var require_signal_exit = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
2118
2188
|
/* istanbul ignore if */
|
|
2119
2189
|
if (!processOk(global.process)) return function() {};
|
|
2120
2190
|
assert$3.equal(typeof cb, "function", "a callback must be provided for exit handler");
|
|
2121
|
-
if (loaded === false) load$
|
|
2191
|
+
if (loaded === false) load$2();
|
|
2122
2192
|
var ev = "exit";
|
|
2123
2193
|
if (opts && opts.alwaysLast) ev = "afterexit";
|
|
2124
2194
|
var remove = function() {
|
|
@@ -2168,7 +2238,7 @@ var require_signal_exit = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
2168
2238
|
return signals$1;
|
|
2169
2239
|
};
|
|
2170
2240
|
var loaded = false;
|
|
2171
|
-
var load$
|
|
2241
|
+
var load$2 = function load() {
|
|
2172
2242
|
if (loaded || !processOk(global.process)) return;
|
|
2173
2243
|
loaded = true;
|
|
2174
2244
|
emitter.count += 1;
|
|
@@ -2183,7 +2253,7 @@ var require_signal_exit = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
2183
2253
|
process.emit = processEmit;
|
|
2184
2254
|
process.reallyExit = processReallyExit;
|
|
2185
2255
|
};
|
|
2186
|
-
module.exports.load = load$
|
|
2256
|
+
module.exports.load = load$2;
|
|
2187
2257
|
var originalProcessReallyExit = process.reallyExit;
|
|
2188
2258
|
var processReallyExit = function processReallyExit(code) {
|
|
2189
2259
|
/* istanbul ignore if */
|
|
@@ -21628,7 +21698,7 @@ var SignalExit = class extends SignalExitBase {
|
|
|
21628
21698
|
}
|
|
21629
21699
|
};
|
|
21630
21700
|
const process$3 = globalThis.process;
|
|
21631
|
-
const { onExit, load, unload } = signalExitWrap(processOk(process$3) ? new SignalExit(process$3) : new SignalExitFallback());
|
|
21701
|
+
const { onExit, load: load$1, unload } = signalExitWrap(processOk(process$3) ? new SignalExit(process$3) : new SignalExitFallback());
|
|
21632
21702
|
|
|
21633
21703
|
//#endregion
|
|
21634
21704
|
//#region node_modules/restore-cursor/index.js
|
|
@@ -24034,11 +24104,16 @@ const LogItemTypes = {
|
|
|
24034
24104
|
none: 0
|
|
24035
24105
|
};
|
|
24036
24106
|
const DEFAULT_SPINNER_INTERVAL = 100;
|
|
24107
|
+
function levelValue(level) {
|
|
24108
|
+
if (!Object.prototype.hasOwnProperty.call(Levels, level)) throw new TypeError(`VisualLogger unknown log level: ${String(level)}`);
|
|
24109
|
+
return Levels[level];
|
|
24110
|
+
}
|
|
24037
24111
|
const SPIN_OFF = 0;
|
|
24038
24112
|
const SPIN_STARTED = 1;
|
|
24039
24113
|
const SPIN_RUNNING = 2;
|
|
24040
24114
|
var VisualLogger = class VisualLogger {
|
|
24041
24115
|
constructor(options = {}) {
|
|
24116
|
+
var _a;
|
|
24042
24117
|
options = {
|
|
24043
24118
|
renderFps: 30,
|
|
24044
24119
|
...options
|
|
@@ -24047,7 +24122,7 @@ var VisualLogger = class VisualLogger {
|
|
|
24047
24122
|
this._items = [];
|
|
24048
24123
|
this._itemOptions = {};
|
|
24049
24124
|
this._lines = [];
|
|
24050
|
-
this._logLevel =
|
|
24125
|
+
this._logLevel = levelValue((_a = options.logLevel) !== null && _a !== void 0 ? _a : "info");
|
|
24051
24126
|
this._itemType = LogItemTypes.normal;
|
|
24052
24127
|
this._logData = [];
|
|
24053
24128
|
this._output = options.output || defaultOutput$1;
|
|
@@ -24076,6 +24151,12 @@ var VisualLogger = class VisualLogger {
|
|
|
24076
24151
|
this._color = enable;
|
|
24077
24152
|
this.setPrefix();
|
|
24078
24153
|
}
|
|
24154
|
+
get logLevel() {
|
|
24155
|
+
return Object.keys(Levels).find((k) => Levels[k] === this._logLevel);
|
|
24156
|
+
}
|
|
24157
|
+
set logLevel(level) {
|
|
24158
|
+
this._logLevel = levelValue(level);
|
|
24159
|
+
}
|
|
24079
24160
|
static get spinners() {
|
|
24080
24161
|
return [
|
|
24081
24162
|
"|/-\\",
|
|
@@ -24210,7 +24291,10 @@ var VisualLogger = class VisualLogger {
|
|
|
24210
24291
|
this._renderLineMsg(options, data);
|
|
24211
24292
|
const updateData = typeof data === "string" ? {} : data;
|
|
24212
24293
|
if (options.save !== false && updateData._save !== false) this._save(options._msg);
|
|
24213
|
-
if (updateData._render === false)
|
|
24294
|
+
if (updateData._render === false) {
|
|
24295
|
+
this._lines[itemIdx] = this._shouldLogItem() ? this._renderLine(options) : options._msg;
|
|
24296
|
+
return this;
|
|
24297
|
+
}
|
|
24214
24298
|
}
|
|
24215
24299
|
if (this._shouldLogItem()) {
|
|
24216
24300
|
if (data === void 0 && !this._nextSpin(options)) return this;
|
|
@@ -26695,6 +26779,7 @@ var InflightStore = class {
|
|
|
26695
26779
|
//#endregion
|
|
26696
26780
|
//#region node_modules/item-queue/dist/item-queue.js
|
|
26697
26781
|
const PAUSE_ITEM = Symbol("pause");
|
|
26782
|
+
const PAUSE_CALL = Symbol("pauseCall");
|
|
26698
26783
|
const RESUME_ITEM = Symbol("resume");
|
|
26699
26784
|
const NOOP_ITEM = Symbol("NOOP");
|
|
26700
26785
|
const WATCH_PERIOD = 500;
|
|
@@ -26705,6 +26790,8 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
26705
26790
|
constructor(options) {
|
|
26706
26791
|
assert(options && typeof options.processItem === "function", "ItemQueue: must provide options.processItem callback");
|
|
26707
26792
|
super();
|
|
26793
|
+
/** bumped by an immediate pause(), so a resume() tick scheduled earlier skips itself */
|
|
26794
|
+
this._pauseSeq = 0;
|
|
26708
26795
|
this.Promise = options.Promise || ItemQueue.Promise;
|
|
26709
26796
|
assert(this.Promise, "ItemQueue: No Promise implementation available");
|
|
26710
26797
|
this._pending = new InflightStore();
|
|
@@ -26714,7 +26801,7 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
26714
26801
|
this._processItem = options.processItem;
|
|
26715
26802
|
this._stopOnError = options.stopOnError;
|
|
26716
26803
|
this._failed = false;
|
|
26717
|
-
this._timeout = options.timeout;
|
|
26804
|
+
this._timeout = options.timeout > 0 ? options.timeout : 0;
|
|
26718
26805
|
this._watchPeriod = options.watchPeriod || WATCH_PERIOD;
|
|
26719
26806
|
this._watchTime = options.watchTime;
|
|
26720
26807
|
this._id = 1;
|
|
@@ -26731,19 +26818,18 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
26731
26818
|
* @returns promise that wait for queue to finish
|
|
26732
26819
|
*/
|
|
26733
26820
|
wait() {
|
|
26734
|
-
if (this._failed) return this.Promise.reject(this.
|
|
26821
|
+
if (this._failed) return this.Promise.reject(this._failError);
|
|
26735
26822
|
if (this.isPending) return new this.Promise((resolve, reject) => {
|
|
26736
|
-
const
|
|
26737
|
-
|
|
26738
|
-
|
|
26739
|
-
reject(data.error);
|
|
26740
|
-
} else {
|
|
26741
|
-
this.removeListener("fail", h);
|
|
26742
|
-
resolve(data);
|
|
26743
|
-
}
|
|
26823
|
+
const onDone = (data) => {
|
|
26824
|
+
this.removeListener("fail", onFail);
|
|
26825
|
+
resolve(data);
|
|
26744
26826
|
};
|
|
26745
|
-
|
|
26746
|
-
|
|
26827
|
+
const onFail = (data) => {
|
|
26828
|
+
this.removeListener("done", onDone);
|
|
26829
|
+
reject(data.error);
|
|
26830
|
+
};
|
|
26831
|
+
this.once("done", onDone);
|
|
26832
|
+
this.once("fail", onFail);
|
|
26747
26833
|
});
|
|
26748
26834
|
return this.Promise.resolve();
|
|
26749
26835
|
}
|
|
@@ -26831,7 +26917,15 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
26831
26917
|
* @returns instance self
|
|
26832
26918
|
*/
|
|
26833
26919
|
pause() {
|
|
26834
|
-
this._itemQ.unshift(
|
|
26920
|
+
if (this._processing || !this._pending.isEmpty) this._itemQ.unshift({
|
|
26921
|
+
item: void 0,
|
|
26922
|
+
_control: PAUSE_CALL
|
|
26923
|
+
});
|
|
26924
|
+
else {
|
|
26925
|
+
this._pause = true;
|
|
26926
|
+
this._pauseSeq++;
|
|
26927
|
+
process.nextTick(() => this.emit("pause"));
|
|
26928
|
+
}
|
|
26835
26929
|
return this;
|
|
26836
26930
|
}
|
|
26837
26931
|
/**
|
|
@@ -26854,7 +26948,10 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
26854
26948
|
* @returns instance self
|
|
26855
26949
|
*/
|
|
26856
26950
|
resume() {
|
|
26951
|
+
this._itemQ = this._itemQ.filter((x) => x._control !== PAUSE_CALL);
|
|
26952
|
+
const pauseSeq = this._pauseSeq;
|
|
26857
26953
|
process.nextTick(() => {
|
|
26954
|
+
if (pauseSeq !== this._pauseSeq) return;
|
|
26858
26955
|
this.unpause();
|
|
26859
26956
|
if (this._itemQ.length === 0) this._itemQ.push(this._wrap(RESUME_ITEM));
|
|
26860
26957
|
this._process();
|
|
@@ -26872,7 +26969,7 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
26872
26969
|
return this.resume();
|
|
26873
26970
|
}
|
|
26874
26971
|
_wrap(item, stopOnError) {
|
|
26875
|
-
if (
|
|
26972
|
+
if (item === PAUSE_ITEM || item === RESUME_ITEM) return {
|
|
26876
26973
|
item: void 0,
|
|
26877
26974
|
_control: item
|
|
26878
26975
|
};
|
|
@@ -26884,14 +26981,15 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
26884
26981
|
_emit(evt, data) {
|
|
26885
26982
|
this.emit(evt, data);
|
|
26886
26983
|
}
|
|
26887
|
-
_handleQueueItemDone(data) {
|
|
26984
|
+
_handleQueueItemDone(data, failed) {
|
|
26888
26985
|
if (data.id > 0) this._pending.remove(data.id);
|
|
26889
26986
|
if (this._failed) return;
|
|
26890
26987
|
if (!data._control && data.id > 0) {
|
|
26891
|
-
if (
|
|
26988
|
+
if (failed) {
|
|
26892
26989
|
this._emit("failItem", data);
|
|
26893
26990
|
if (data.stopOnError !== false && this._stopOnError) {
|
|
26894
|
-
this._failed =
|
|
26991
|
+
this._failed = true;
|
|
26992
|
+
this._failError = data.error;
|
|
26895
26993
|
this._emit("fail", data);
|
|
26896
26994
|
return;
|
|
26897
26995
|
}
|
|
@@ -26963,25 +27061,60 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
26963
27061
|
}
|
|
26964
27062
|
this._watchTimer = setTimeout(() => this._pendingWatcher(), this._watchPeriod).unref();
|
|
26965
27063
|
}
|
|
27064
|
+
/**
|
|
27065
|
+
* Fail the item if it doesn't settle within `options.timeout`. The first outcome wins,
|
|
27066
|
+
* so a result that arrives after the timeout is ignored.
|
|
27067
|
+
*/
|
|
27068
|
+
_withTimeout(promise, abort) {
|
|
27069
|
+
return new this.Promise((resolve, reject) => {
|
|
27070
|
+
const timer = setTimeout(() => {
|
|
27071
|
+
const error = Object.assign(/* @__PURE__ */ new Error(`item-queue: item timed out after ${this._timeout}ms`), { code: "ETIMEDOUT" });
|
|
27072
|
+
abort.abort(error);
|
|
27073
|
+
reject(error);
|
|
27074
|
+
}, this._timeout);
|
|
27075
|
+
promise.then((res) => {
|
|
27076
|
+
clearTimeout(timer);
|
|
27077
|
+
resolve(res);
|
|
27078
|
+
}, (err) => {
|
|
27079
|
+
clearTimeout(timer);
|
|
27080
|
+
reject(err);
|
|
27081
|
+
});
|
|
27082
|
+
});
|
|
27083
|
+
}
|
|
26966
27084
|
_setupWatch() {
|
|
26967
27085
|
if (!this._watchTimer && this._watchTime) process.nextTick(() => this._pendingWatcher());
|
|
26968
27086
|
}
|
|
27087
|
+
/**
|
|
27088
|
+
* A failed queue never runs queued items. Report each one as a failed item
|
|
27089
|
+
* with the queue's error, so callers waiting on a `failItem` don't hang.
|
|
27090
|
+
*/
|
|
27091
|
+
_failQueued() {
|
|
27092
|
+
const queued = this._itemQ;
|
|
27093
|
+
this._itemQ = [];
|
|
27094
|
+
for (const wrapped of queued) if (!wrapped._control) this._emit("failItem", {
|
|
27095
|
+
id: this._id++,
|
|
27096
|
+
error: this._failError,
|
|
27097
|
+
...wrapped
|
|
27098
|
+
});
|
|
27099
|
+
return 0;
|
|
27100
|
+
}
|
|
26969
27101
|
_process() {
|
|
26970
27102
|
if (this._startTime === void 0) this._startTime = Date.now();
|
|
27103
|
+
if (this._failed) return this._failQueued();
|
|
26971
27104
|
if (this._processing || this._pause || this._itemQ.length === 0) return 0;
|
|
26972
27105
|
this._processing = true;
|
|
26973
27106
|
let count = 0;
|
|
26974
27107
|
let i = this._pending.count;
|
|
26975
27108
|
for (; this._itemQ.length > 0 && i < this._concurrency; i++) {
|
|
26976
27109
|
const wrapped = this._itemQ.shift();
|
|
26977
|
-
if (wrapped._control === PAUSE_ITEM) {
|
|
27110
|
+
if (wrapped._control === PAUSE_ITEM || wrapped._control === PAUSE_CALL) {
|
|
26978
27111
|
this._pause = true;
|
|
26979
27112
|
if (this._pending.isEmpty) process.nextTick(() => {
|
|
26980
27113
|
this._handleQueueItemDone({
|
|
26981
27114
|
id: 0,
|
|
26982
27115
|
item: void 0,
|
|
26983
27116
|
_control: NOOP_ITEM
|
|
26984
|
-
});
|
|
27117
|
+
}, false);
|
|
26985
27118
|
});
|
|
26986
27119
|
break;
|
|
26987
27120
|
}
|
|
@@ -26989,12 +27122,16 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
26989
27122
|
const id = this._id++;
|
|
26990
27123
|
let promise;
|
|
26991
27124
|
if (wrapped._control === RESUME_ITEM) promise = this.Promise.resolve({});
|
|
26992
|
-
else
|
|
26993
|
-
const
|
|
26994
|
-
|
|
26995
|
-
|
|
26996
|
-
|
|
26997
|
-
|
|
27125
|
+
else {
|
|
27126
|
+
const abort = this._timeout ? new AbortController() : void 0;
|
|
27127
|
+
try {
|
|
27128
|
+
const res = this._processItem(wrapped.item, id, abort === null || abort === void 0 ? void 0 : abort.signal);
|
|
27129
|
+
if (res && res.then) promise = res;
|
|
27130
|
+
else promise = this.Promise.resolve(res);
|
|
27131
|
+
} catch (err) {
|
|
27132
|
+
promise = this.Promise.reject(err);
|
|
27133
|
+
}
|
|
27134
|
+
if (abort) promise = this._withTimeout(promise, abort);
|
|
26998
27135
|
}
|
|
26999
27136
|
this._pending.add(id, {
|
|
27000
27137
|
item: wrapped.item,
|
|
@@ -27002,12 +27139,12 @@ var ItemQueue = class ItemQueue extends EventEmitter$1 {
|
|
|
27002
27139
|
id,
|
|
27003
27140
|
res,
|
|
27004
27141
|
...wrapped
|
|
27005
|
-
}), (error) => {
|
|
27142
|
+
}, false), (error) => {
|
|
27006
27143
|
this._handleQueueItemDone({
|
|
27007
27144
|
id,
|
|
27008
27145
|
error,
|
|
27009
27146
|
...wrapped
|
|
27010
|
-
});
|
|
27147
|
+
}, true);
|
|
27011
27148
|
})
|
|
27012
27149
|
});
|
|
27013
27150
|
}
|
|
@@ -27192,7 +27329,7 @@ function makeExtrasData(file, fullFile, path, stat, files, options) {
|
|
|
27192
27329
|
* @param extras
|
|
27193
27330
|
*/
|
|
27194
27331
|
function addResult(result, options, extras) {
|
|
27195
|
-
const group =
|
|
27332
|
+
const group = options.grouping && (typeof result === "string" ? result : result.group) || "files";
|
|
27196
27333
|
if (!options.result[group]) options.result[group] = [];
|
|
27197
27334
|
if (result.formatName !== void 0) options.result[group].push(result.formatName);
|
|
27198
27335
|
else options.result[group].push(options.prependCwd ? extras.fullFile : extras.dirFile);
|
|
@@ -27234,10 +27371,10 @@ function processFile(options, extras) {
|
|
|
27234
27371
|
}
|
|
27235
27372
|
return false;
|
|
27236
27373
|
}
|
|
27237
|
-
function acceptEntry(options, entry, path, gitignore) {
|
|
27374
|
+
function acceptEntry(options, entry, path, gitignore, fsPath) {
|
|
27238
27375
|
const isDirectory = entry.isDirectory();
|
|
27239
27376
|
if (isDirectory && options._ignoreDirs.has(entry.name)) return false;
|
|
27240
|
-
if (gitignore === null || gitignore === void 0 ? void 0 : gitignore.ignores(Path.resolve(options.dir,
|
|
27377
|
+
if (gitignore === null || gitignore === void 0 ? void 0 : gitignore.ignores(Path.resolve(options.dir, fsPath, entry.name), isDirectory)) return false;
|
|
27241
27378
|
if (options.prefilter && !options.prefilter(entry.name, path, entry)) return false;
|
|
27242
27379
|
if (isDirectory) return true;
|
|
27243
27380
|
if (options.ignoreExt.length || options.filterExt.length) {
|
|
@@ -27280,7 +27417,7 @@ function releaseDirectory(options) {
|
|
|
27280
27417
|
* @param level
|
|
27281
27418
|
* @returns
|
|
27282
27419
|
*/
|
|
27283
|
-
async function walk(path, options, level = 0, parentRules) {
|
|
27420
|
+
async function walk(path, options, level = 0, parentRules, fsPath = path) {
|
|
27284
27421
|
let promises = [];
|
|
27285
27422
|
let hasSlot = false;
|
|
27286
27423
|
try {
|
|
@@ -27290,7 +27427,9 @@ async function walk(path, options, level = 0, parentRules) {
|
|
|
27290
27427
|
hasSlot = true;
|
|
27291
27428
|
}
|
|
27292
27429
|
if (options._stopped) return void 0;
|
|
27293
|
-
const dir = Path.join(options.dir,
|
|
27430
|
+
const dir = Path.join(options.dir, fsPath);
|
|
27431
|
+
const posixSep = options._sep === "/";
|
|
27432
|
+
const outDir = posixSep ? dir : join2(options._sep, options._outCwd, path);
|
|
27294
27433
|
const gitignore = options.gitignore ? await GitignoreRules.load(Path.resolve(dir), options.gitignore, parentRules) : void 0;
|
|
27295
27434
|
let files = await asyncReaddir(dir, options.readdirOpts);
|
|
27296
27435
|
if (options.sortFiles) {
|
|
@@ -27301,16 +27440,16 @@ async function walk(path, options, level = 0, parentRules) {
|
|
|
27301
27440
|
const extrasFiles = options.fullStat && options._earlyFilter && (options.filter || options.filterDir) ? files.map((entry) => entry.name) : files;
|
|
27302
27441
|
for (let ix = 0; !options._stopped && ix < files.length; ix++) {
|
|
27303
27442
|
const file = files[ix];
|
|
27304
|
-
if (options._earlyFilter && !acceptEntry(options, file, path, gitignore)) continue;
|
|
27443
|
+
if (options._earlyFilter && !acceptEntry(options, file, path, gitignore, fsPath)) continue;
|
|
27305
27444
|
let extras;
|
|
27306
27445
|
if (options.fullStat) {
|
|
27307
27446
|
const name = options._earlyFilter ? file.name : file;
|
|
27308
|
-
const fullFile = join2(options._sep,
|
|
27309
|
-
const stat = await asyncLStat(fullFile);
|
|
27447
|
+
const fullFile = join2(options._sep, outDir, name);
|
|
27448
|
+
const stat = await asyncLStat(posixSep ? fullFile : join2("/", dir, name));
|
|
27310
27449
|
if (options._stopped) break;
|
|
27311
27450
|
extras = makeExtrasData(name, fullFile, path, stat, extrasFiles, options);
|
|
27312
27451
|
} else {
|
|
27313
|
-
const fullFile = join2(options._sep,
|
|
27452
|
+
const fullFile = join2(options._sep, outDir, file.name);
|
|
27314
27453
|
extras = makeExtrasData(file.name, fullFile, path, file, files, options);
|
|
27315
27454
|
}
|
|
27316
27455
|
if (extras.stat.isDirectory()) dirs.push(extras);
|
|
@@ -27328,7 +27467,8 @@ async function walk(path, options, level = 0, parentRules) {
|
|
|
27328
27467
|
break;
|
|
27329
27468
|
}
|
|
27330
27469
|
if (!flags.skip && level < options.maxLevel) {
|
|
27331
|
-
const
|
|
27470
|
+
const childFsPath = posixSep ? extras.dirFile : join2("/", fsPath, extras.file);
|
|
27471
|
+
const walkP = walk(extras.dirFile, options, level + 1, gitignore, childFsPath);
|
|
27332
27472
|
if (options.concurrency > 1) {
|
|
27333
27473
|
promises.push(walkP);
|
|
27334
27474
|
if (promises.length >= options.concurrency) {
|
|
@@ -27357,8 +27497,15 @@ async function walk(path, options, level = 0, parentRules) {
|
|
|
27357
27497
|
* @returns
|
|
27358
27498
|
*/
|
|
27359
27499
|
function makeOptions(opts) {
|
|
27360
|
-
const
|
|
27500
|
+
const input = typeof opts === "string" ? { cwd: opts } : opts;
|
|
27501
|
+
const options = {};
|
|
27502
|
+
for (const key of Object.keys(input)) if (input[key] !== void 0) options[key] = input[key];
|
|
27361
27503
|
if (options.prefilter && options.fullStat === false) throw new TypeError("prefilter requires fullStat: true");
|
|
27504
|
+
for (const name of [
|
|
27505
|
+
"filter",
|
|
27506
|
+
"filterDir",
|
|
27507
|
+
"prefilter"
|
|
27508
|
+
]) if (Object.prototype.toString.call(options[name]) === "[object AsyncFunction]") throw new TypeError(`${name} must return a result synchronously, not a promise`);
|
|
27362
27509
|
const sep = options.pathSep || Path.posix.sep;
|
|
27363
27510
|
let cwd = options.cwd || options.dir || process.cwd();
|
|
27364
27511
|
if (!options.hasOwnProperty("pathSep") && cwd.includes("\\")) cwd = cwd.replace(/\\/g, "/");
|
|
@@ -27380,6 +27527,7 @@ function makeOptions(opts) {
|
|
|
27380
27527
|
grouping: void 0
|
|
27381
27528
|
}, options, {
|
|
27382
27529
|
dir: cwd,
|
|
27530
|
+
_outCwd: Path.join(cwd),
|
|
27383
27531
|
fullStat: options.fullStat === void 0 ? true : options.fullStat,
|
|
27384
27532
|
result: Object.create(null),
|
|
27385
27533
|
ignoreExt: [].concat(options.ignoreExt).map(cleanExt).filter((x) => x),
|
|
@@ -27469,6 +27617,8 @@ const commaPattern = /\\,/g;
|
|
|
27469
27617
|
const periodPattern = /\\\./g;
|
|
27470
27618
|
const EXPANSION_MAX = 1e5;
|
|
27471
27619
|
const EXPANSION_MAX_LENGTH = 4e6;
|
|
27620
|
+
const EXPANSION_MAX_DEPTH = 1e3;
|
|
27621
|
+
const EXPANSION_MAX_REWRITES = 1e3;
|
|
27472
27622
|
function numeric(str) {
|
|
27473
27623
|
return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
|
|
27474
27624
|
}
|
|
@@ -27478,32 +27628,43 @@ function escapeBraces(str) {
|
|
|
27478
27628
|
function unescapeBraces(str) {
|
|
27479
27629
|
return str.replace(escSlashPattern, "\\").replace(escOpenPattern, "{").replace(escClosePattern, "}").replace(escCommaPattern, ",").replace(escPeriodPattern, ".");
|
|
27480
27630
|
}
|
|
27631
|
+
function pushAll(target, items) {
|
|
27632
|
+
for (let i = 0; i < items.length; i++) target.push(items[i]);
|
|
27633
|
+
}
|
|
27481
27634
|
/**
|
|
27482
27635
|
* Basically just str.split(","), but handling cases
|
|
27483
27636
|
* where we have nested braced sections, which should be
|
|
27484
27637
|
* treated as individual members, like {a,{b,c},d}
|
|
27485
27638
|
*/
|
|
27486
27639
|
function parseCommaParts(str) {
|
|
27487
|
-
if (!str) return [""];
|
|
27488
27640
|
const parts = [];
|
|
27489
|
-
|
|
27490
|
-
|
|
27491
|
-
|
|
27492
|
-
|
|
27493
|
-
|
|
27494
|
-
|
|
27495
|
-
|
|
27496
|
-
|
|
27497
|
-
|
|
27498
|
-
|
|
27499
|
-
|
|
27500
|
-
|
|
27641
|
+
let carry = "";
|
|
27642
|
+
for (;;) {
|
|
27643
|
+
const m = balanced("{", "}", str);
|
|
27644
|
+
if (!m) {
|
|
27645
|
+
const tail = str.split(",");
|
|
27646
|
+
tail[0] = carry + tail[0];
|
|
27647
|
+
pushAll(parts, tail);
|
|
27648
|
+
return parts;
|
|
27649
|
+
}
|
|
27650
|
+
const { pre, body, post } = m;
|
|
27651
|
+
const p = pre.split(",");
|
|
27652
|
+
p[0] = carry + p[0];
|
|
27653
|
+
p[p.length - 1] += "{" + body + "}";
|
|
27654
|
+
if (!post.length) {
|
|
27655
|
+
pushAll(parts, p);
|
|
27656
|
+
return parts;
|
|
27657
|
+
}
|
|
27658
|
+
carry = p.pop();
|
|
27659
|
+
pushAll(parts, p);
|
|
27660
|
+
str = post;
|
|
27661
|
+
}
|
|
27501
27662
|
}
|
|
27502
27663
|
function expand(str, options = {}) {
|
|
27503
27664
|
if (!str) return [];
|
|
27504
|
-
const { max = EXPANSION_MAX, maxLength = EXPANSION_MAX_LENGTH } = options;
|
|
27665
|
+
const { max = EXPANSION_MAX, maxLength = EXPANSION_MAX_LENGTH, maxDepth = EXPANSION_MAX_DEPTH, maxRewrites = EXPANSION_MAX_REWRITES } = options;
|
|
27505
27666
|
if (str.slice(0, 2) === "{}") str = "\\{\\}" + str.slice(2);
|
|
27506
|
-
return expand_(escapeBraces(str), max, maxLength, true).map(unescapeBraces);
|
|
27667
|
+
return expand_(escapeBraces(str), max, maxLength, maxDepth, 0, maxRewrites, true).map(unescapeBraces);
|
|
27507
27668
|
}
|
|
27508
27669
|
function embrace(str) {
|
|
27509
27670
|
return "{" + str + "}";
|
|
@@ -27569,8 +27730,10 @@ function expandSequence(body, isAlphaSequence, max, maxLength) {
|
|
|
27569
27730
|
}
|
|
27570
27731
|
return N;
|
|
27571
27732
|
}
|
|
27572
|
-
function expand_(str, max, maxLength, isTop) {
|
|
27733
|
+
function expand_(str, max, maxLength, maxDepth, depth, maxRewrites, isTop) {
|
|
27734
|
+
if (depth > maxDepth) return [str];
|
|
27573
27735
|
let acc = [""];
|
|
27736
|
+
let rewrites = 0;
|
|
27574
27737
|
let dropEmpties = false;
|
|
27575
27738
|
let firstGroup = true;
|
|
27576
27739
|
for (;;) {
|
|
@@ -27589,7 +27752,8 @@ function expand_(str, max, maxLength, isTop) {
|
|
|
27589
27752
|
const isSequence = isNumericSequence || isAlphaSequence;
|
|
27590
27753
|
const isOptions = m.body.indexOf(",") >= 0;
|
|
27591
27754
|
if (!isSequence && !isOptions) {
|
|
27592
|
-
if (m.post.match(/,(?!,).*\}/)) {
|
|
27755
|
+
if (rewrites < maxRewrites && m.post.match(/,(?!,).*\}/)) {
|
|
27756
|
+
rewrites++;
|
|
27593
27757
|
str = m.pre + "{" + m.body + escClose + m.post;
|
|
27594
27758
|
isTop = true;
|
|
27595
27759
|
continue;
|
|
@@ -27605,7 +27769,7 @@ function expand_(str, max, maxLength, isTop) {
|
|
|
27605
27769
|
else {
|
|
27606
27770
|
let n = parseCommaParts(m.body);
|
|
27607
27771
|
if (n.length === 1 && n[0] !== void 0) {
|
|
27608
|
-
n = expand_(n[0], max, maxLength, false).map(embrace);
|
|
27772
|
+
n = expand_(n[0], max, maxLength, maxDepth, depth + 1, maxRewrites, false).map(embrace);
|
|
27609
27773
|
/* c8 ignore start */
|
|
27610
27774
|
if (n.length === 1) {
|
|
27611
27775
|
acc = combine(acc, pre + n[0], [""], max, maxLength, dropEmpties && !m.post.length);
|
|
@@ -27619,7 +27783,7 @@ function expand_(str, max, maxLength, isTop) {
|
|
|
27619
27783
|
values = [];
|
|
27620
27784
|
let valuesLength = 0;
|
|
27621
27785
|
outer: for (let j = 0; j < n.length; j++) {
|
|
27622
|
-
const expanded = expand_(n[j], max, maxLength, false);
|
|
27786
|
+
const expanded = expand_(n[j], max, maxLength, maxDepth, depth + 1, maxRewrites, false);
|
|
27623
27787
|
for (let k = 0; k < expanded.length; k++) {
|
|
27624
27788
|
const v = expanded[k];
|
|
27625
27789
|
if (dropsEmpties && !v) continue;
|
|
@@ -29724,14 +29888,14 @@ var PackageRef = class {
|
|
|
29724
29888
|
* @param ref package string reference
|
|
29725
29889
|
*/
|
|
29726
29890
|
parseRef(ref) {
|
|
29727
|
-
const
|
|
29728
|
-
if (
|
|
29729
|
-
const tmp =
|
|
29891
|
+
const colonIx = ref.indexOf(":");
|
|
29892
|
+
if (colonIx >= 0) {
|
|
29893
|
+
const tmp = ref.substring(0, colonIx).trim();
|
|
29730
29894
|
if (tmp === "id" || tmp === "path" || tmp === "name") this.type = tmp;
|
|
29731
29895
|
else throw new Error(`package ref '${ref}' has unknown type '${tmp}' - must be 'id', 'path', or 'name'`);
|
|
29732
|
-
this.value =
|
|
29896
|
+
this.value = ref.substring(colonIx + 1).trim();
|
|
29733
29897
|
} else {
|
|
29734
|
-
this.value =
|
|
29898
|
+
this.value = ref.trim();
|
|
29735
29899
|
if (this.value.lastIndexOf("@") > 0) this.type = "id";
|
|
29736
29900
|
else this.type = "name";
|
|
29737
29901
|
}
|
|
@@ -29745,6 +29909,7 @@ var PackageRef = class {
|
|
|
29745
29909
|
} else if (this.type === "path") this.mm = new Minimatch(this.value);
|
|
29746
29910
|
}
|
|
29747
29911
|
match(pkgInfo) {
|
|
29912
|
+
if (this.regex) this.regex.lastIndex = 0;
|
|
29748
29913
|
if (this.type === "path") return this.regex ? this.regex.exec(pkgInfo.path) !== null : this.mm.match(pkgInfo.path);
|
|
29749
29914
|
else if (this.type === "id") return this.regex ? this.regex.exec(pkgInfoId(pkgInfo)) !== null : this.value === pkgInfoId(pkgInfo);
|
|
29750
29915
|
else return this.regex ? this.regex.exec(pkgInfo.name) !== null : this.value === pkgInfo.name;
|
|
@@ -29776,6 +29941,24 @@ function resolvePackage(semver, packages, fallbackToFirst = true) {
|
|
|
29776
29941
|
if (fallbackToFirst) return packages[0];
|
|
29777
29942
|
}
|
|
29778
29943
|
/**
|
|
29944
|
+
* Widen a local dep's semver per `localDepAutoSemver`, same as fyn's getAutoSemver.
|
|
29945
|
+
*
|
|
29946
|
+
* @param semver semver string
|
|
29947
|
+
* @param autoSemver the `localDepAutoSemver` setting
|
|
29948
|
+
* @returns the semver to match local versions with
|
|
29949
|
+
*/
|
|
29950
|
+
function localAutoSemver(semver, autoSemver) {
|
|
29951
|
+
if (autoSemver) {
|
|
29952
|
+
const parsedSv = import_semver.default.coerce(semver);
|
|
29953
|
+
if (parsedSv && parsedSv.raw) switch (autoSemver) {
|
|
29954
|
+
case "patch": return `~${parsedSv.raw}`;
|
|
29955
|
+
case "minor": return `^${parsedSv.raw}`;
|
|
29956
|
+
case "major": return "*";
|
|
29957
|
+
}
|
|
29958
|
+
}
|
|
29959
|
+
return semver;
|
|
29960
|
+
}
|
|
29961
|
+
/**
|
|
29779
29962
|
* Make a package ID from basic info by joining name and version into a single string.
|
|
29780
29963
|
*
|
|
29781
29964
|
* @param info package basic info
|
|
@@ -29949,6 +30132,7 @@ var FynpoDepGraph = class {
|
|
|
29949
30132
|
});
|
|
29950
30133
|
files.push(scanned);
|
|
29951
30134
|
}
|
|
30135
|
+
this.packages.byName = Object.create(null);
|
|
29952
30136
|
const filesByDepth = [...[].concat(...files)].sort((a, b) => {
|
|
29953
30137
|
const depth = (file) => posixify$2(Path.dirname(file)).split("/").length;
|
|
29954
30138
|
return depth(a) - depth(b) || a.localeCompare(b);
|
|
@@ -30115,16 +30299,17 @@ var FynpoDepGraph = class {
|
|
|
30115
30299
|
if (this.checkNoFynLocal(pkgInfo, name)) continue;
|
|
30116
30300
|
const semId = pkgId$1(name, semver);
|
|
30117
30301
|
const resolveId = this.resolvedCache[semId];
|
|
30118
|
-
|
|
30119
|
-
|
|
30120
|
-
|
|
30302
|
+
if (resolveId === "") continue;
|
|
30303
|
+
let depPkg = resolveId ? byId[resolveId] : void 0;
|
|
30304
|
+
if (!depPkg) {
|
|
30305
|
+
const localSemver = localAutoSemver(semver, this._options.localDepAutoSemver);
|
|
30306
|
+
depPkg = resolvePackage(localSemver, byName[name], !import_semver.default.validRange(localSemver));
|
|
30307
|
+
this.resolvedCache[semId] = depPkg ? pkgInfoId(depPkg) : "";
|
|
30308
|
+
}
|
|
30309
|
+
if (depPkg) this.addDep(pkgInfo, depPkg, section);
|
|
30121
30310
|
}
|
|
30122
30311
|
};
|
|
30123
|
-
for (const path in byPath)
|
|
30124
|
-
pkgInfo: byPath[path],
|
|
30125
|
-
localDepsByPath: Object.create(null),
|
|
30126
|
-
dependentsByPath: Object.create(null)
|
|
30127
|
-
};
|
|
30312
|
+
for (const path in byPath) this.getDepData(byPath[path]);
|
|
30128
30313
|
for (const path in byPath) {
|
|
30129
30314
|
const pkgInfo = byPath[path];
|
|
30130
30315
|
const depData = depMapByPath[pkgInfo.path];
|
|
@@ -30134,6 +30319,21 @@ var FynpoDepGraph = class {
|
|
|
30134
30319
|
}
|
|
30135
30320
|
}
|
|
30136
30321
|
/**
|
|
30322
|
+
* Get the dep data of a package, creating an empty one if it doesn't exist yet
|
|
30323
|
+
*
|
|
30324
|
+
* @param pkgInfo package info
|
|
30325
|
+
* @returns dep data
|
|
30326
|
+
*/
|
|
30327
|
+
getDepData(pkgInfo) {
|
|
30328
|
+
let depData = this.depMapByPath[pkgInfo.path];
|
|
30329
|
+
if (!depData) depData = this.depMapByPath[pkgInfo.path] = {
|
|
30330
|
+
pkgInfo,
|
|
30331
|
+
localDepsByPath: Object.create(null),
|
|
30332
|
+
dependentsByPath: Object.create(null)
|
|
30333
|
+
};
|
|
30334
|
+
return depData;
|
|
30335
|
+
}
|
|
30336
|
+
/**
|
|
30137
30337
|
* Add a dependency relation by package paths
|
|
30138
30338
|
*
|
|
30139
30339
|
* @param from - path of package depend from
|
|
@@ -30198,8 +30398,8 @@ var FynpoDepGraph = class {
|
|
|
30198
30398
|
*/
|
|
30199
30399
|
addDep(pkgInfo, depPkg, depSection, indirectSteps) {
|
|
30200
30400
|
if (pkgInfo.path === depPkg.path) return false;
|
|
30201
|
-
const dataPkg = this.
|
|
30202
|
-
const dataDep = this.
|
|
30401
|
+
const dataPkg = this.getDepData(pkgInfo);
|
|
30402
|
+
const dataDep = this.getDepData(depPkg);
|
|
30203
30403
|
if (dataPkg.localDepsByPath[depPkg.path]) return false;
|
|
30204
30404
|
dataPkg.localDepsByPath[depPkg.path] = {
|
|
30205
30405
|
name: depPkg.name,
|
|
@@ -30367,7 +30567,7 @@ let defaultLog$1 = consoleLog;
|
|
|
30367
30567
|
const ERR_MODULE_NOT_FOUND = "ERR_MODULE_NOT_FOUND";
|
|
30368
30568
|
const ERR_PACKAGE_PATH_NOT_EXPORTED = "ERR_PACKAGE_PATH_NOT_EXPORTED";
|
|
30369
30569
|
function normalizeOpts(optsOrMsg) {
|
|
30370
|
-
if (optsOrMsg
|
|
30570
|
+
if (optsOrMsg == null) return {};
|
|
30371
30571
|
if (optsOrMsg === true || typeof optsOrMsg === "string") return { message: optsOrMsg };
|
|
30372
30572
|
return optsOrMsg;
|
|
30373
30573
|
}
|
|
@@ -30852,7 +31052,8 @@ const fyntil = {
|
|
|
30852
31052
|
const graph = new FynpoDepGraph({
|
|
30853
31053
|
cwd: fcm.topDir,
|
|
30854
31054
|
packages: config.packages,
|
|
30855
|
-
noFynLocal: config.noFynLocal
|
|
31055
|
+
noFynLocal: config.noFynLocal,
|
|
31056
|
+
localDepAutoSemver: config.localDepAutoSemver
|
|
30856
31057
|
});
|
|
30857
31058
|
await graph.resolve();
|
|
30858
31059
|
return fyntil.fynpoConfig = {
|
|
@@ -30942,14 +31143,15 @@ const fyntil = {
|
|
|
30942
31143
|
if (!Path.isAbsolute(rel) && !rel.startsWith(".")) return `.${Path.sep}${rel}`;
|
|
30943
31144
|
return shouldPosixify ? posixify$2(rel) : rel;
|
|
30944
31145
|
},
|
|
30945
|
-
|
|
31146
|
+
/** @param pkgJsonStr - package.json's content, when the caller has it already */
|
|
31147
|
+
async readPkgJson(dirOrFile, keepRaw = false, packageFyn = false, pkgJsonStr) {
|
|
30946
31148
|
const dir = !dirOrFile.endsWith(".json") ? dirOrFile : Path.dirname(dirOrFile);
|
|
30947
31149
|
const files = ["package.json", packageFyn && "package-fyn.json"].filter(Boolean);
|
|
30948
31150
|
const finalJson = {};
|
|
30949
31151
|
for (const fname of files) {
|
|
30950
31152
|
const file = Path.join(dir, fname);
|
|
30951
31153
|
try {
|
|
30952
|
-
const str = await file_ops_default.readFile(file, "utf8");
|
|
31154
|
+
const str = fname === "package.json" && pkgJsonStr !== void 0 ? pkgJsonStr : await file_ops_default.readFile(file, "utf8");
|
|
30953
31155
|
const json = JSON.parse(str.trim());
|
|
30954
31156
|
merge(finalJson, json);
|
|
30955
31157
|
if (keepRaw && fname !== "package-fyn.json") finalJson[PACKAGE_RAW_INFO] = {
|
|
@@ -35966,15 +36168,114 @@ var To = (s) => {
|
|
|
35966
36168
|
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
36169
|
};
|
|
35968
36170
|
|
|
36171
|
+
//#endregion
|
|
36172
|
+
//#region lib/util/fs-worker-pool.ts
|
|
36173
|
+
/** One worker less than the CPUs, for the main thread, and at most 8 */
|
|
36174
|
+
const POOL_SIZE = Math.max(1, Math.min(8, os.availableParallelism() - 1));
|
|
36175
|
+
/**
|
|
36176
|
+
* A downloaded Buffer is often a view into a much bigger ArrayBuffer, and postMessage copies the
|
|
36177
|
+
* whole ArrayBuffer. So the message gets a copy of just the view, transferred. The caller's
|
|
36178
|
+
* Buffer stays usable.
|
|
36179
|
+
*/
|
|
36180
|
+
function postJob(worker, id, { op, job }) {
|
|
36181
|
+
const { data } = job;
|
|
36182
|
+
if (!data) {
|
|
36183
|
+
worker.postMessage({
|
|
36184
|
+
id,
|
|
36185
|
+
op,
|
|
36186
|
+
job
|
|
36187
|
+
});
|
|
36188
|
+
return;
|
|
36189
|
+
}
|
|
36190
|
+
const copy = new Uint8Array(data.byteLength);
|
|
36191
|
+
copy.set(data);
|
|
36192
|
+
worker.postMessage({
|
|
36193
|
+
id,
|
|
36194
|
+
op,
|
|
36195
|
+
job: {
|
|
36196
|
+
...job,
|
|
36197
|
+
data: copy
|
|
36198
|
+
}
|
|
36199
|
+
}, [copy.buffer]);
|
|
36200
|
+
}
|
|
36201
|
+
var FsWorkerPool = class {
|
|
36202
|
+
_file;
|
|
36203
|
+
_workers = [];
|
|
36204
|
+
_queue = [];
|
|
36205
|
+
_nextId = 0;
|
|
36206
|
+
constructor(file) {
|
|
36207
|
+
this._file = file;
|
|
36208
|
+
}
|
|
36209
|
+
run(op, job) {
|
|
36210
|
+
return new Promise((resolve, reject) => {
|
|
36211
|
+
this._queue.push({
|
|
36212
|
+
job: {
|
|
36213
|
+
op,
|
|
36214
|
+
job
|
|
36215
|
+
},
|
|
36216
|
+
resolve,
|
|
36217
|
+
reject
|
|
36218
|
+
});
|
|
36219
|
+
this._dispatch();
|
|
36220
|
+
});
|
|
36221
|
+
}
|
|
36222
|
+
_dispatch() {
|
|
36223
|
+
while (this._queue.length > 0) {
|
|
36224
|
+
let pw = this._workers.find((w) => !w.busy);
|
|
36225
|
+
if (!pw) {
|
|
36226
|
+
if (this._workers.length >= POOL_SIZE) return;
|
|
36227
|
+
pw = this._start();
|
|
36228
|
+
}
|
|
36229
|
+
const pending = this._queue.shift();
|
|
36230
|
+
pw.busy = pending;
|
|
36231
|
+
pw.worker.ref();
|
|
36232
|
+
postJob(pw.worker, this._nextId++, pending.job);
|
|
36233
|
+
}
|
|
36234
|
+
}
|
|
36235
|
+
_start() {
|
|
36236
|
+
const pw = { worker: new Worker(this._file) };
|
|
36237
|
+
pw.worker.on("message", (msg) => {
|
|
36238
|
+
const pending = pw.busy;
|
|
36239
|
+
pw.busy = void 0;
|
|
36240
|
+
pw.worker.unref();
|
|
36241
|
+
if (msg.error) pending.reject(Object.assign(new Error(msg.error.message), msg.error));
|
|
36242
|
+
else pending.resolve(msg.result);
|
|
36243
|
+
this._dispatch();
|
|
36244
|
+
});
|
|
36245
|
+
pw.worker.on("error", (err) => {
|
|
36246
|
+
this._workers = this._workers.filter((w) => w !== pw);
|
|
36247
|
+
pw.busy?.reject(err);
|
|
36248
|
+
pw.busy = void 0;
|
|
36249
|
+
this._dispatch();
|
|
36250
|
+
});
|
|
36251
|
+
this._workers.push(pw);
|
|
36252
|
+
return pw;
|
|
36253
|
+
}
|
|
36254
|
+
};
|
|
36255
|
+
let pool;
|
|
36256
|
+
/**
|
|
36257
|
+
* The pool, or undefined when there's no built worker next to this module, which is the case
|
|
36258
|
+
* when running from source. Callers then do the work in-thread.
|
|
36259
|
+
*/
|
|
36260
|
+
function getFsWorkerPool() {
|
|
36261
|
+
if (pool === void 0) {
|
|
36262
|
+
const file = fileURLToPath(new URL("./fs-worker.mjs", import.meta.url));
|
|
36263
|
+
pool = Br.existsSync(file) && new FsWorkerPool(file);
|
|
36264
|
+
logger$1.debug(pool ? `fs workers: up to ${POOL_SIZE} from ${file}` : "fs workers: none built, working in-thread");
|
|
36265
|
+
}
|
|
36266
|
+
return pool || void 0;
|
|
36267
|
+
}
|
|
36268
|
+
|
|
35969
36269
|
//#endregion
|
|
35970
36270
|
//#region lib/pkg-dist-extractor.ts
|
|
35971
36271
|
const { retry, missPipe: missPipe$2 } = fyntil;
|
|
36272
|
+
const isStoreJob = (result) => typeof result?.store === "function";
|
|
35972
36273
|
var PkgDistExtractor = class {
|
|
35973
36274
|
_promiseQ;
|
|
35974
36275
|
_fyn;
|
|
35975
36276
|
constructor(options) {
|
|
35976
36277
|
this._promiseQ = new promise_queue_default({
|
|
35977
|
-
concurrency: 4,
|
|
36278
|
+
concurrency: options.fyn.extractConcurrency || Math.min(4, POOL_SIZE + 1),
|
|
35978
36279
|
stopOnError: true,
|
|
35979
36280
|
processItem: (x, id) => this.processItem(x, id)
|
|
35980
36281
|
});
|
|
@@ -36024,6 +36325,7 @@ var PkgDistExtractor = class {
|
|
|
36024
36325
|
const { pkg } = data;
|
|
36025
36326
|
const promotedOpt = defaults$1({ promoted }, pick(pkg, "promoted"));
|
|
36026
36327
|
const fullOutDir = this._fyn.getInstalledPkgDir(pkg.name, pkg.version, promotedOpt);
|
|
36328
|
+
let placed;
|
|
36027
36329
|
if (pkg.extracted && pkg.extracted === fullOutDir) {
|
|
36028
36330
|
logger$1.debug(`package ${pkg.name} ${pkg.version} has already been extracted to ${pkg.extracted}`);
|
|
36029
36331
|
if (this._fyn.isNormalLayout && pkg.promoted && !promotedOpt.promoted) await this.movePromotedPkgFromFV(pkg, fullOutDir);
|
|
@@ -36036,18 +36338,24 @@ var PkgDistExtractor = class {
|
|
|
36036
36338
|
}
|
|
36037
36339
|
return json;
|
|
36038
36340
|
}
|
|
36039
|
-
|
|
36040
|
-
|
|
36341
|
+
const job = data.result;
|
|
36342
|
+
if (isStoreJob(job) && !await job.store(!data.listener && !data.deferred)) {
|
|
36343
|
+
data.deferred = true;
|
|
36344
|
+
this._promiseQ.addItem(data);
|
|
36345
|
+
return;
|
|
36346
|
+
}
|
|
36347
|
+
const result = isStoreJob(job) ? job.integrity : job;
|
|
36041
36348
|
let act;
|
|
36042
36349
|
let retrieve;
|
|
36043
36350
|
if (typeof result === "string") {
|
|
36044
36351
|
act = "hardlink";
|
|
36045
|
-
retrieve = () => {
|
|
36046
|
-
|
|
36352
|
+
retrieve = async () => {
|
|
36353
|
+
placed = await this._fyn.central.replicate(result, fullOutDir, () => this._fyn.createPkgOutDir(fullOutDir));
|
|
36047
36354
|
};
|
|
36048
36355
|
} else {
|
|
36049
36356
|
act = "extract";
|
|
36050
|
-
retrieve = () => {
|
|
36357
|
+
retrieve = async () => {
|
|
36358
|
+
await this._fyn.createPkgOutDir(fullOutDir);
|
|
36051
36359
|
const untarStream = So({
|
|
36052
36360
|
strip: 1,
|
|
36053
36361
|
strict: true,
|
|
@@ -36063,7 +36371,7 @@ var PkgDistExtractor = class {
|
|
|
36063
36371
|
logger$1.updateItem(LOAD_PACKAGE, `${act}ed ${msg}`);
|
|
36064
36372
|
}
|
|
36065
36373
|
let retries = 0;
|
|
36066
|
-
return retry(() => this._fyn.loadJsonForPkg(pkg, fullOutDir), () => {
|
|
36374
|
+
return retry(() => this._fyn.loadJsonForPkg(pkg, fullOutDir, placed), () => {
|
|
36067
36375
|
retries++;
|
|
36068
36376
|
logger$1.warn(`retrying ${retries} reading package.json`, fullOutDir);
|
|
36069
36377
|
return true;
|
|
@@ -38464,7 +38772,7 @@ var require_commonjs$8 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
38464
38772
|
//#region node_modules/brace-expansion/dist/commonjs/index.js
|
|
38465
38773
|
var require_commonjs$7 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
38466
38774
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38467
|
-
exports.EXPANSION_MAX_LENGTH = exports.EXPANSION_MAX = void 0;
|
|
38775
|
+
exports.EXPANSION_MAX_REWRITES = exports.EXPANSION_MAX_DEPTH = exports.EXPANSION_MAX_LENGTH = exports.EXPANSION_MAX = void 0;
|
|
38468
38776
|
exports.expand = expand;
|
|
38469
38777
|
const balanced_match_1 = require_commonjs$8();
|
|
38470
38778
|
const escSlash = "\0SLASH" + Math.random() + "\0";
|
|
@@ -38484,6 +38792,8 @@ var require_commonjs$7 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
38484
38792
|
const periodPattern = /\\\./g;
|
|
38485
38793
|
exports.EXPANSION_MAX = 1e5;
|
|
38486
38794
|
exports.EXPANSION_MAX_LENGTH = 4e6;
|
|
38795
|
+
exports.EXPANSION_MAX_DEPTH = 1e3;
|
|
38796
|
+
exports.EXPANSION_MAX_REWRITES = 1e3;
|
|
38487
38797
|
function numeric(str) {
|
|
38488
38798
|
return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
|
|
38489
38799
|
}
|
|
@@ -38493,32 +38803,43 @@ var require_commonjs$7 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
38493
38803
|
function unescapeBraces(str) {
|
|
38494
38804
|
return str.replace(escSlashPattern, "\\").replace(escOpenPattern, "{").replace(escClosePattern, "}").replace(escCommaPattern, ",").replace(escPeriodPattern, ".");
|
|
38495
38805
|
}
|
|
38806
|
+
function pushAll(target, items) {
|
|
38807
|
+
for (let i = 0; i < items.length; i++) target.push(items[i]);
|
|
38808
|
+
}
|
|
38496
38809
|
/**
|
|
38497
38810
|
* Basically just str.split(","), but handling cases
|
|
38498
38811
|
* where we have nested braced sections, which should be
|
|
38499
38812
|
* treated as individual members, like {a,{b,c},d}
|
|
38500
38813
|
*/
|
|
38501
38814
|
function parseCommaParts(str) {
|
|
38502
|
-
if (!str) return [""];
|
|
38503
38815
|
const parts = [];
|
|
38504
|
-
|
|
38505
|
-
|
|
38506
|
-
|
|
38507
|
-
|
|
38508
|
-
|
|
38509
|
-
|
|
38510
|
-
|
|
38511
|
-
|
|
38512
|
-
|
|
38816
|
+
let carry = "";
|
|
38817
|
+
for (;;) {
|
|
38818
|
+
const m = (0, balanced_match_1.balanced)("{", "}", str);
|
|
38819
|
+
if (!m) {
|
|
38820
|
+
const tail = str.split(",");
|
|
38821
|
+
tail[0] = carry + tail[0];
|
|
38822
|
+
pushAll(parts, tail);
|
|
38823
|
+
return parts;
|
|
38824
|
+
}
|
|
38825
|
+
const { pre, body, post } = m;
|
|
38826
|
+
const p = pre.split(",");
|
|
38827
|
+
p[0] = carry + p[0];
|
|
38828
|
+
p[p.length - 1] += "{" + body + "}";
|
|
38829
|
+
if (!post.length) {
|
|
38830
|
+
pushAll(parts, p);
|
|
38831
|
+
return parts;
|
|
38832
|
+
}
|
|
38833
|
+
carry = p.pop();
|
|
38834
|
+
pushAll(parts, p);
|
|
38835
|
+
str = post;
|
|
38513
38836
|
}
|
|
38514
|
-
parts.push.apply(parts, p);
|
|
38515
|
-
return parts;
|
|
38516
38837
|
}
|
|
38517
38838
|
function expand(str, options = {}) {
|
|
38518
38839
|
if (!str) return [];
|
|
38519
|
-
const { max = exports.EXPANSION_MAX, maxLength = exports.EXPANSION_MAX_LENGTH } = options;
|
|
38840
|
+
const { max = exports.EXPANSION_MAX, maxLength = exports.EXPANSION_MAX_LENGTH, maxDepth = exports.EXPANSION_MAX_DEPTH, maxRewrites = exports.EXPANSION_MAX_REWRITES } = options;
|
|
38520
38841
|
if (str.slice(0, 2) === "{}") str = "\\{\\}" + str.slice(2);
|
|
38521
|
-
return expand_(escapeBraces(str), max, maxLength, true).map(unescapeBraces);
|
|
38842
|
+
return expand_(escapeBraces(str), max, maxLength, maxDepth, 0, maxRewrites, true).map(unescapeBraces);
|
|
38522
38843
|
}
|
|
38523
38844
|
function embrace(str) {
|
|
38524
38845
|
return "{" + str + "}";
|
|
@@ -38584,8 +38905,10 @@ var require_commonjs$7 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
38584
38905
|
}
|
|
38585
38906
|
return N;
|
|
38586
38907
|
}
|
|
38587
|
-
function expand_(str, max, maxLength, isTop) {
|
|
38908
|
+
function expand_(str, max, maxLength, maxDepth, depth, maxRewrites, isTop) {
|
|
38909
|
+
if (depth > maxDepth) return [str];
|
|
38588
38910
|
let acc = [""];
|
|
38911
|
+
let rewrites = 0;
|
|
38589
38912
|
let dropEmpties = false;
|
|
38590
38913
|
let firstGroup = true;
|
|
38591
38914
|
for (;;) {
|
|
@@ -38604,7 +38927,8 @@ var require_commonjs$7 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
38604
38927
|
const isSequence = isNumericSequence || isAlphaSequence;
|
|
38605
38928
|
const isOptions = m.body.indexOf(",") >= 0;
|
|
38606
38929
|
if (!isSequence && !isOptions) {
|
|
38607
|
-
if (m.post.match(/,(?!,).*\}/)) {
|
|
38930
|
+
if (rewrites < maxRewrites && m.post.match(/,(?!,).*\}/)) {
|
|
38931
|
+
rewrites++;
|
|
38608
38932
|
str = m.pre + "{" + m.body + escClose + m.post;
|
|
38609
38933
|
isTop = true;
|
|
38610
38934
|
continue;
|
|
@@ -38620,7 +38944,7 @@ var require_commonjs$7 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
38620
38944
|
else {
|
|
38621
38945
|
let n = parseCommaParts(m.body);
|
|
38622
38946
|
if (n.length === 1 && n[0] !== void 0) {
|
|
38623
|
-
n = expand_(n[0], max, maxLength, false).map(embrace);
|
|
38947
|
+
n = expand_(n[0], max, maxLength, maxDepth, depth + 1, maxRewrites, false).map(embrace);
|
|
38624
38948
|
/* c8 ignore start */
|
|
38625
38949
|
if (n.length === 1) {
|
|
38626
38950
|
acc = combine(acc, pre + n[0], [""], max, maxLength, dropEmpties && !m.post.length);
|
|
@@ -38634,7 +38958,7 @@ var require_commonjs$7 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
38634
38958
|
values = [];
|
|
38635
38959
|
let valuesLength = 0;
|
|
38636
38960
|
outer: for (let j = 0; j < n.length; j++) {
|
|
38637
|
-
const expanded = expand_(n[j], max, maxLength, false);
|
|
38961
|
+
const expanded = expand_(n[j], max, maxLength, maxDepth, depth + 1, maxRewrites, false);
|
|
38638
38962
|
for (let k = 0; k < expanded.length; k++) {
|
|
38639
38963
|
const v = expanded[k];
|
|
38640
38964
|
if (dropsEmpties && !v) continue;
|
|
@@ -45425,7 +45749,7 @@ var require_normalize_data = /* @__PURE__ */ __commonJSMin(((exports, module) =>
|
|
|
45425
45749
|
}));
|
|
45426
45750
|
|
|
45427
45751
|
//#endregion
|
|
45428
|
-
//#region node_modules
|
|
45752
|
+
//#region node_modules/isexe/dist/commonjs/index.min.js
|
|
45429
45753
|
var require_index_min$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
45430
45754
|
var a = (t, e) => () => (e || t((e = { exports: {} }).exports, e), e.exports);
|
|
45431
45755
|
var _ = a((i) => {
|
|
@@ -50375,12 +50699,18 @@ var require_cache_dir$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
50375
50699
|
# This file is a cache directory tag created by cacache.
|
|
50376
50700
|
# For information about cache directory tags, see https://bford.info/cachedir/
|
|
50377
50701
|
`;
|
|
50378
|
-
|
|
50379
|
-
|
|
50380
|
-
|
|
50381
|
-
|
|
50382
|
-
|
|
50383
|
-
|
|
50702
|
+
const made = /* @__PURE__ */ new Map();
|
|
50703
|
+
function mkdir(cache) {
|
|
50704
|
+
let p = made.get(cache);
|
|
50705
|
+
if (!p) {
|
|
50706
|
+
p = fs$15.mkdir(cache, {
|
|
50707
|
+
recursive: true,
|
|
50708
|
+
owner: "inherit"
|
|
50709
|
+
}).then(() => writeTag(cache));
|
|
50710
|
+
made.set(cache, p);
|
|
50711
|
+
p.catch(() => made.delete(cache));
|
|
50712
|
+
}
|
|
50713
|
+
return p;
|
|
50384
50714
|
}
|
|
50385
50715
|
async function writeTag(cache) {
|
|
50386
50716
|
try {
|
|
@@ -58967,11 +59297,14 @@ var require_http_cache_semantics = /* @__PURE__ */ __commonJSMin(((exports, modu
|
|
|
58967
59297
|
}
|
|
58968
59298
|
/**
|
|
58969
59299
|
* @param {{headers: Record<string, string>, synchronous: boolean}|undefined} revalidation - Revalidation information, if any.
|
|
58970
|
-
* @returns {{response:
|
|
59300
|
+
* @returns {{response: HttpResponse, revalidation: {headers: Record<string, string>, synchronous: boolean}|undefined}} An object with a cached response headers and revalidation info.
|
|
58971
59301
|
*/
|
|
58972
59302
|
_evaluateRequestHitResult(revalidation) {
|
|
58973
59303
|
return {
|
|
58974
|
-
response: {
|
|
59304
|
+
response: {
|
|
59305
|
+
headers: this.responseHeaders(),
|
|
59306
|
+
status: this._status
|
|
59307
|
+
},
|
|
58975
59308
|
revalidation
|
|
58976
59309
|
};
|
|
58977
59310
|
}
|
|
@@ -59015,9 +59348,9 @@ var require_http_cache_semantics = /* @__PURE__ */ __commonJSMin(((exports, modu
|
|
|
59015
59348
|
* }
|
|
59016
59349
|
* ```
|
|
59017
59350
|
* @param {HttpRequest} req - new incoming HTTP request
|
|
59018
|
-
* @returns {{response:
|
|
59351
|
+
* @returns {{response: HttpResponse|undefined, revalidation: {headers: Record<string, string>, synchronous: boolean}|undefined}} An object containing keys:
|
|
59019
59352
|
* - revalidation: { headers: Record<string, string>, synchronous: boolean } Set if you should send this to the origin server
|
|
59020
|
-
* - response:
|
|
59353
|
+
* - response: HttpResponse Set if you can respond to the client with these cached headers
|
|
59021
59354
|
*/
|
|
59022
59355
|
evaluateRequest(req) {
|
|
59023
59356
|
this._assertRequestHasHeaders(req);
|
|
@@ -59056,9 +59389,11 @@ var require_http_cache_semantics = /* @__PURE__ */ __commonJSMin(((exports, modu
|
|
|
59056
59389
|
*/
|
|
59057
59390
|
_varyMatches(req) {
|
|
59058
59391
|
if (!this._resHeaders.vary) return true;
|
|
59059
|
-
if (this._resHeaders.vary === "*") return false;
|
|
59060
59392
|
const fields = this._resHeaders.vary.trim().toLowerCase().split(/\s*,\s*/);
|
|
59061
|
-
for (const name of fields)
|
|
59393
|
+
for (const name of fields) {
|
|
59394
|
+
if (name === "*") return false;
|
|
59395
|
+
if ((Object.prototype.hasOwnProperty.call(req.headers, name) && req.headers[name]) !== (Object.prototype.hasOwnProperty.call(this._reqHeaders, name) && this._reqHeaders[name])) return false;
|
|
59396
|
+
}
|
|
59062
59397
|
return true;
|
|
59063
59398
|
}
|
|
59064
59399
|
/**
|
|
@@ -59100,6 +59435,13 @@ var require_http_cache_semantics = /* @__PURE__ */ __commonJSMin(((exports, modu
|
|
|
59100
59435
|
return headers;
|
|
59101
59436
|
}
|
|
59102
59437
|
/**
|
|
59438
|
+
* Returns the status code of the cached response.
|
|
59439
|
+
* @returns {number} The response status code.
|
|
59440
|
+
*/
|
|
59441
|
+
status() {
|
|
59442
|
+
return this._status;
|
|
59443
|
+
}
|
|
59444
|
+
/**
|
|
59103
59445
|
* Returns the Date header value from the response or the current time if invalid.
|
|
59104
59446
|
* @returns {number} Timestamp (in milliseconds) representing the Date header or response time.
|
|
59105
59447
|
*/
|
|
@@ -62205,8 +62547,14 @@ var require_common = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
62205
62547
|
* {@link isInSubnet} when classifying a single address — notably when the
|
|
62206
62548
|
* address came from untrusted input and the result backs a trust-boundary
|
|
62207
62549
|
* decision such as an SSRF allow/deny filter.
|
|
62550
|
+
*
|
|
62551
|
+
* An address of one family is never inside a network of the other, so an
|
|
62552
|
+
* `Address4` against an `Address6` (or the reverse) is `false`. To compare
|
|
62553
|
+
* across families, convert first: `Address6.fromAddress4()`, `to4()`, or
|
|
62554
|
+
* `toAddress4Nat64()`.
|
|
62208
62555
|
*/
|
|
62209
62556
|
function isHostInSubnet(address) {
|
|
62557
|
+
if (this.binaryZeroPad().length !== address.binaryZeroPad().length) return false;
|
|
62210
62558
|
return this.mask(address.subnetMask) === address.mask();
|
|
62211
62559
|
}
|
|
62212
62560
|
/**
|
|
@@ -62493,7 +62841,9 @@ var require_ipv4 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
62493
62841
|
*/
|
|
62494
62842
|
this.isCorrect = isCorrect4;
|
|
62495
62843
|
/**
|
|
62496
|
-
* Returns true if the given address is in the subnet of the current address
|
|
62844
|
+
* Returns true if the given address is in the subnet of the current address.
|
|
62845
|
+
* An `Address6` is never in the subnet of an `Address4`; convert with
|
|
62846
|
+
* `to4()` or `Address6.fromAddress4()` to compare across families.
|
|
62497
62847
|
* @returns {boolean}
|
|
62498
62848
|
*/
|
|
62499
62849
|
this.isInSubnet = common.isInSubnet;
|
|
@@ -62503,6 +62853,8 @@ var require_ipv4 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
62503
62853
|
* when classifying a single address, so the answer doesn't change with the
|
|
62504
62854
|
* CIDR suffix the caller happened to write — notably when the address came
|
|
62505
62855
|
* from untrusted input and the result backs a trust-boundary decision.
|
|
62856
|
+
* An `Address6` is never in the subnet of an `Address4`; convert with
|
|
62857
|
+
* `to4()` or `Address6.fromAddress4()` to compare across families.
|
|
62506
62858
|
* @returns {boolean}
|
|
62507
62859
|
*/
|
|
62508
62860
|
this.isHostInSubnet = common.isHostInSubnet;
|
|
@@ -62515,6 +62867,8 @@ var require_ipv4 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
62515
62867
|
if (this.subnetMask < 0 || this.subnetMask > constants.BITS) throw new address_error_1.AddressError("Invalid subnet mask.");
|
|
62516
62868
|
address = address.replace(constants.RE_SUBNET_STRING, "");
|
|
62517
62869
|
}
|
|
62870
|
+
const longest = constants.GROUPS * 4 - 1;
|
|
62871
|
+
if (address.length > longest) throw new address_error_1.AddressError(`IPv4 addresses are at most ${longest} characters.`);
|
|
62518
62872
|
this.addressMinusSuffix = address;
|
|
62519
62873
|
this.parsedAddress = this.parse(address);
|
|
62520
62874
|
}
|
|
@@ -62631,15 +62985,20 @@ var require_ipv4 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
62631
62985
|
return Address4.fromHex(integer.toString(16).padStart(8, "0"));
|
|
62632
62986
|
}
|
|
62633
62987
|
/**
|
|
62634
|
-
* Return an address from in-addr.arpa form
|
|
62988
|
+
* Return an address from in-addr.arpa form: the four octets reversed, with
|
|
62989
|
+
* or without the `.in-addr.arpa` suffix and root dot, in any case. Throws
|
|
62990
|
+
* `AddressError` unless the reversed labels form a valid IPv4 address, so
|
|
62991
|
+
* `fromArpa(x.reverseForm())` round-trips {@link reverseForm}.
|
|
62635
62992
|
* @param {string} arpaFormAddress - an 'in-addr.arpa' form ipv4 address
|
|
62636
62993
|
* @returns {Adress4}
|
|
62637
62994
|
* @example
|
|
62638
|
-
* var address = Address4.fromArpa(42.2.0.192.in-addr.arpa.)
|
|
62995
|
+
* var address = Address4.fromArpa('42.2.0.192.in-addr.arpa.')
|
|
62639
62996
|
* address.correctForm(); // '192.0.2.42'
|
|
62640
62997
|
*/
|
|
62641
62998
|
static fromArpa(arpaFormAddress) {
|
|
62642
|
-
const
|
|
62999
|
+
const longest = constants.GROUPS * 4 - 1 + 3 + 14;
|
|
63000
|
+
if (arpaFormAddress.length > longest) throw new address_error_1.AddressError(`in-addr.arpa names are at most ${longest} characters.`);
|
|
63001
|
+
const address = arpaFormAddress.replace(/(\.in-addr\.arpa)?\.?$/i, "").split(".").reverse().join(".");
|
|
62643
63002
|
return new Address4(address);
|
|
62644
63003
|
}
|
|
62645
63004
|
/**
|
|
@@ -63420,7 +63779,9 @@ var require_ipv6 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
63420
63779
|
this.v4 = false;
|
|
63421
63780
|
this.zone = "";
|
|
63422
63781
|
/**
|
|
63423
|
-
* Returns true if the given address is in the subnet of the current address
|
|
63782
|
+
* Returns true if the given address is in the subnet of the current address.
|
|
63783
|
+
* An `Address4` is never in the subnet of an `Address6`; convert with
|
|
63784
|
+
* `Address6.fromAddress4()` or `to4()` to compare across families.
|
|
63424
63785
|
* @returns {boolean}
|
|
63425
63786
|
*/
|
|
63426
63787
|
this.isInSubnet = common.isInSubnet;
|
|
@@ -63430,6 +63791,8 @@ var require_ipv6 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
63430
63791
|
* when classifying a single address, so the answer doesn't change with the
|
|
63431
63792
|
* CIDR suffix the caller happened to write — notably when the address came
|
|
63432
63793
|
* from untrusted input and the result backs a trust-boundary decision.
|
|
63794
|
+
* An `Address4` is never in the subnet of an `Address6`; convert with
|
|
63795
|
+
* `Address6.fromAddress4()` or `to4()` to compare across families.
|
|
63433
63796
|
* @returns {boolean}
|
|
63434
63797
|
*/
|
|
63435
63798
|
this.isHostInSubnet = common.isHostInSubnet;
|
|
@@ -63455,6 +63818,8 @@ var require_ipv6 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
63455
63818
|
this.zone = zone[0];
|
|
63456
63819
|
address = address.replace(constants6.RE_ZONE_STRING, "");
|
|
63457
63820
|
}
|
|
63821
|
+
const longest = this.groups * 5 + 5;
|
|
63822
|
+
if (address.length > longest) throw new address_error_1.AddressError(`IPv6 addresses are at most ${longest} characters.`);
|
|
63458
63823
|
this.addressMinusSuffix = address;
|
|
63459
63824
|
this.parsedAddress = this.parse(this.addressMinusSuffix);
|
|
63460
63825
|
}
|
|
@@ -63640,7 +64005,7 @@ var require_ipv6 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
63640
64005
|
* Address6.fromArpa('8.b.d.0.1.0.0.2.ip6.arpa.').networkForm(); // '2001:db8::/32'
|
|
63641
64006
|
*/
|
|
63642
64007
|
static fromArpa(arpaFormAddress) {
|
|
63643
|
-
const nibbles = arpaFormAddress.replace(/(\.ip6\.arpa)
|
|
64008
|
+
const nibbles = arpaFormAddress.replace(/(\.ip6\.arpa)?\.?$/i, "");
|
|
63644
64009
|
if (!/^[0-9a-f](\.[0-9a-f]){0,31}$/i.test(nibbles)) throw new address_error_1.AddressError("Invalid 'ip6.arpa' form.");
|
|
63645
64010
|
const reversed = nibbles.split(".").reverse();
|
|
63646
64011
|
const subnetMask = reversed.length * 4;
|
|
@@ -65801,6 +66166,7 @@ var require_lib$14 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
65801
66166
|
});
|
|
65802
66167
|
if (agentCache.has(cacheKey)) return agentCache.get(cacheKey);
|
|
65803
66168
|
const newAgent = new Agent(normalizedOptions);
|
|
66169
|
+
newAgent.protocol = url.protocol;
|
|
65804
66170
|
agentCache.set(cacheKey, newAgent);
|
|
65805
66171
|
return newAgent;
|
|
65806
66172
|
};
|
|
@@ -65892,7 +66258,7 @@ var require_package$5 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
65892
66258
|
"publish": "true"
|
|
65893
66259
|
},
|
|
65894
66260
|
"_fyn": {},
|
|
65895
|
-
"_from": "make-fetch-happen@^16.0.
|
|
66261
|
+
"_from": "make-fetch-happen@^16.0.1",
|
|
65896
66262
|
"_id": "make-fetch-happen@16.0.1"
|
|
65897
66263
|
};
|
|
65898
66264
|
}));
|
|
@@ -86762,7 +87128,7 @@ var require_package_extensions = /* @__PURE__ */ __commonJSMin(((exports, module
|
|
|
86762
87128
|
var require_npm_extension = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
86763
87129
|
const { resolve: resolve$9, sep: sep$3 } = __require("node:path");
|
|
86764
87130
|
const { readFileSync, existsSync: existsSync$3 } = __require("node:fs");
|
|
86765
|
-
const { pathToFileURL } = __require("node:url");
|
|
87131
|
+
const { pathToFileURL: pathToFileURL$1 } = __require("node:url");
|
|
86766
87132
|
const { isDeepStrictEqual } = __require("node:util");
|
|
86767
87133
|
const { log } = require_lib$38();
|
|
86768
87134
|
const ssri = require_lib$23();
|
|
@@ -86831,7 +87197,7 @@ var require_npm_extension = /* @__PURE__ */ __commonJSMin(((exports, module) =>
|
|
|
86831
87197
|
async load() {
|
|
86832
87198
|
if (!this.present) return;
|
|
86833
87199
|
let mod;
|
|
86834
|
-
if (this.format === "mjs") mod = await import(`${pathToFileURL(this.path).href}?h=${this.hash}`);
|
|
87200
|
+
if (this.format === "mjs") mod = await import(`${pathToFileURL$1(this.path).href}?h=${this.hash}`);
|
|
86835
87201
|
else {
|
|
86836
87202
|
delete __require.cache[__require.resolve(this.path)];
|
|
86837
87203
|
mod = __require(this.path);
|
|
@@ -92175,10 +92541,11 @@ async function copyFile(srcFp, destFp) {
|
|
|
92175
92541
|
*
|
|
92176
92542
|
* @param {*} srcFp - source file path
|
|
92177
92543
|
* @param {*} destFp - destination file path
|
|
92544
|
+
* @param {*} noCopy - fail instead of falling back to a copy (always fails on macOS)
|
|
92178
92545
|
* @returns
|
|
92179
92546
|
*/
|
|
92180
|
-
async function cloneFile(srcFp, destFp) {
|
|
92181
|
-
return copyNew(srcFp, destFp, fs.constants.COPYFILE_FICLONE);
|
|
92547
|
+
async function cloneFile(srcFp, destFp, noCopy = false) {
|
|
92548
|
+
return copyNew(srcFp, destFp, noCopy ? fs.constants.COPYFILE_FICLONE_FORCE : fs.constants.COPYFILE_FICLONE);
|
|
92182
92549
|
}
|
|
92183
92550
|
async function prepDestDir(dest) {
|
|
92184
92551
|
const statDest = await tryCatch(() => file_ops_default.lstat(dest));
|
|
@@ -92679,6 +93046,15 @@ function getBucketPath(cache, key) {
|
|
|
92679
93046
|
return Path.join(cache, `index-v${indexV}`, hashed.slice(0, 2), hashed.slice(2, 4), hashed.slice(4));
|
|
92680
93047
|
}
|
|
92681
93048
|
/**
|
|
93049
|
+
* Get the content file path for an integrity that cacache matched, such as the `sri` from
|
|
93050
|
+
* `get.hasContent`. Same layout as cacache: the algorithm, then the hex digest in segments.
|
|
93051
|
+
*/
|
|
93052
|
+
function getContentPath(cache, sri) {
|
|
93053
|
+
const hex = sri.hexDigest();
|
|
93054
|
+
const contentV = import_package.default["cache-version"].content;
|
|
93055
|
+
return Path.join(cache, `content-v${contentV}`, sri.algorithm, hex.slice(0, 2), hex.slice(2, 4), hex.slice(4));
|
|
93056
|
+
}
|
|
93057
|
+
/**
|
|
92682
93058
|
* Update cache entry refresh timestamp by modifying bucket file mtime.
|
|
92683
93059
|
* Does not modify file contents, only filesystem metadata.
|
|
92684
93060
|
* Errors are silently ignored (cache refresh is non-critical).
|
|
@@ -92714,7 +93090,7 @@ async function getCacheInfoWithRefreshTime(cache, key) {
|
|
|
92714
93090
|
//#endregion
|
|
92715
93091
|
//#region lib/util/trimmed-packument.ts
|
|
92716
93092
|
/** Bump when the kept fields change, so files from older versions are rebuilt. */
|
|
92717
|
-
const TRIMMED_FORMAT =
|
|
93093
|
+
const TRIMMED_FORMAT = 2;
|
|
92718
93094
|
/**
|
|
92719
93095
|
* The version fields fyn reads from a registry packument. Code that starts reading another
|
|
92720
93096
|
* field from `meta.versions[v]` must add it here and bump TRIMMED_FORMAT.
|
|
@@ -92731,6 +93107,7 @@ const KEEP_VERSION_FIELDS = [
|
|
|
92731
93107
|
"cpu",
|
|
92732
93108
|
"deprecated",
|
|
92733
93109
|
"_hasShrinkwrap",
|
|
93110
|
+
"_shrinkwrap",
|
|
92734
93111
|
"fyn"
|
|
92735
93112
|
];
|
|
92736
93113
|
/** Only the install hooks are read from `scripts`. */
|
|
@@ -92762,7 +93139,7 @@ function trimPackument(packument) {
|
|
|
92762
93139
|
versions[version] = trimmed;
|
|
92763
93140
|
}
|
|
92764
93141
|
return {
|
|
92765
|
-
$format:
|
|
93142
|
+
$format: 2,
|
|
92766
93143
|
name: packument.name,
|
|
92767
93144
|
"dist-tags": packument["dist-tags"],
|
|
92768
93145
|
time: packument.time,
|
|
@@ -92775,33 +93152,68 @@ function trimmedPackumentFile(dir, packumentUrl) {
|
|
|
92775
93152
|
return Path.join(dir, `${hash}.json`);
|
|
92776
93153
|
}
|
|
92777
93154
|
/**
|
|
92778
|
-
* Read a trimmed packument
|
|
92779
|
-
* unreadable, or from another format, so the caller falls back to the full copy.
|
|
93155
|
+
* Read a trimmed packument, its refresh time, and its validators. Resolves undefined when the
|
|
93156
|
+
* file is missing, unreadable, or from another format, so the caller falls back to the full copy.
|
|
92780
93157
|
*/
|
|
92781
93158
|
async function readTrimmedPackument(file) {
|
|
92782
93159
|
try {
|
|
92783
93160
|
const [data, stat] = await Promise.all([fs.promises.readFile(file), fs.promises.stat(file)]);
|
|
92784
|
-
const
|
|
92785
|
-
|
|
92786
|
-
|
|
92787
|
-
return {
|
|
92788
|
-
packument,
|
|
93161
|
+
const parsed = parseTrimmed(data.toString());
|
|
93162
|
+
return parsed && {
|
|
93163
|
+
...parsed,
|
|
92789
93164
|
refreshTime: stat.mtimeMs
|
|
92790
93165
|
};
|
|
92791
93166
|
} catch {
|
|
92792
93167
|
return;
|
|
92793
93168
|
}
|
|
92794
93169
|
}
|
|
93170
|
+
/** Parse a trimmed copy's JSON into the packument and its validators. Undefined for another format. */
|
|
93171
|
+
function parseTrimmed(json) {
|
|
93172
|
+
const packument = JSON.parse(json);
|
|
93173
|
+
if (packument.$format !== 2) return void 0;
|
|
93174
|
+
const { $etag: etag, $lastModified: lastModified, $corgi: corgi } = packument;
|
|
93175
|
+
delete packument.$format;
|
|
93176
|
+
delete packument.$etag;
|
|
93177
|
+
delete packument.$lastModified;
|
|
93178
|
+
delete packument.$corgi;
|
|
93179
|
+
return {
|
|
93180
|
+
packument,
|
|
93181
|
+
etag,
|
|
93182
|
+
lastModified,
|
|
93183
|
+
corgi
|
|
93184
|
+
};
|
|
93185
|
+
}
|
|
93186
|
+
/** Mark a trimmed packument as refreshed now, after the registry said it hasn't changed */
|
|
93187
|
+
async function touchTrimmedPackument(file) {
|
|
93188
|
+
const now = /* @__PURE__ */ new Date();
|
|
93189
|
+
await fs.promises.utimes(file, now, now).catch(() => void 0);
|
|
93190
|
+
}
|
|
92795
93191
|
/**
|
|
92796
93192
|
* Write a trimmed copy of a packument. The write goes to a temp file renamed over the target,
|
|
92797
93193
|
* 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
|
-
*
|
|
93194
|
+
* made from an existing cache entry rather than a fresh fetch. Failures are ignored: the next
|
|
93195
|
+
* install fetches the packument again.
|
|
92800
93196
|
*/
|
|
92801
|
-
async function writeTrimmedPackument(file, packument, refreshTime) {
|
|
93197
|
+
async function writeTrimmedPackument(file, packument, refreshTime, validators) {
|
|
93198
|
+
let json;
|
|
93199
|
+
try {
|
|
93200
|
+
json = trimmedJson(trimPackument(packument), validators);
|
|
93201
|
+
} catch {
|
|
93202
|
+
return;
|
|
93203
|
+
}
|
|
93204
|
+
await writeTrimmed(file, json, refreshTime);
|
|
93205
|
+
}
|
|
93206
|
+
function trimmedJson(trimmed, validators) {
|
|
93207
|
+
return JSON.stringify({
|
|
93208
|
+
...trimmed,
|
|
93209
|
+
$etag: validators?.etag,
|
|
93210
|
+
$lastModified: validators?.lastModified,
|
|
93211
|
+
$corgi: validators?.corgi || void 0
|
|
93212
|
+
});
|
|
93213
|
+
}
|
|
93214
|
+
async function writeTrimmed(file, data, refreshTime) {
|
|
92802
93215
|
const tmp = `${file}.${process.pid}.${Crypto.randomBytes(4).toString("hex")}.tmp`;
|
|
92803
93216
|
try {
|
|
92804
|
-
const data = JSON.stringify(trimPackument(packument));
|
|
92805
93217
|
try {
|
|
92806
93218
|
await fs.promises.writeFile(tmp, data);
|
|
92807
93219
|
} catch (err) {
|
|
@@ -92818,9 +93230,160 @@ async function writeTrimmedPackument(file, packument, refreshTime) {
|
|
|
92818
93230
|
await fs.promises.rm(tmp, { force: true }).catch(() => void 0);
|
|
92819
93231
|
}
|
|
92820
93232
|
}
|
|
93233
|
+
/** Parse a registry response body, as sent with `encoding` */
|
|
93234
|
+
function decodePackument(data, encoding) {
|
|
93235
|
+
const json = encoding === "gzip" || encoding === "x-gzip" || encoding === "deflate" ? en.unzipSync(data) : encoding === "br" ? en.brotliDecompressSync(data) : data;
|
|
93236
|
+
return JSON.parse(Buffer.from(json.buffer, json.byteOffset, json.byteLength).toString());
|
|
93237
|
+
}
|
|
93238
|
+
/**
|
|
93239
|
+
* Decode a packument response and write its trimmed copy. The abbreviated form only flags that
|
|
93240
|
+
* a version has install scripts, and fyn records which ones, so one with any isn't saved. This
|
|
93241
|
+
* is the CPU-heavy part of a packument fetch, so an fs worker runs it when fyn has them built.
|
|
93242
|
+
*/
|
|
93243
|
+
async function savePackument(job) {
|
|
93244
|
+
const packument = decodePackument(job.data, job.encoding);
|
|
93245
|
+
if (job.corgi && Object.values(packument.versions || {}).some((v) => v.hasInstallScript)) return { needFull: true };
|
|
93246
|
+
return { json: await saveTrimmed(job.file, packument, job) };
|
|
93247
|
+
}
|
|
93248
|
+
/** Trim a packument and write it with its validators. @returns the JSON written */
|
|
93249
|
+
async function saveTrimmed(file, packument, validators) {
|
|
93250
|
+
const text = trimmedJson(trimPackument(packument), validators);
|
|
93251
|
+
await writeTrimmed(file, text);
|
|
93252
|
+
return text;
|
|
93253
|
+
}
|
|
93254
|
+
|
|
93255
|
+
//#endregion
|
|
93256
|
+
//#region lib/util/registry-get.ts
|
|
93257
|
+
let load;
|
|
93258
|
+
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]) => ({
|
|
93259
|
+
fetch: mfh.default,
|
|
93260
|
+
getAuth: nrf.default.getAuth
|
|
93261
|
+
}));
|
|
93262
|
+
/** The plain values of `opts`, which is all auth needs and all that can go to a worker */
|
|
93263
|
+
function pickRegistryOpts(opts) {
|
|
93264
|
+
const out = {};
|
|
93265
|
+
for (const [k, v] of Object.entries(opts)) if (v === void 0 || [
|
|
93266
|
+
"string",
|
|
93267
|
+
"number",
|
|
93268
|
+
"boolean"
|
|
93269
|
+
].includes(typeof v)) out[k] = v;
|
|
93270
|
+
return out;
|
|
93271
|
+
}
|
|
93272
|
+
/** getAuth results, per opts, by authCacheKey */
|
|
93273
|
+
const authCaches = /* @__PURE__ */ new WeakMap();
|
|
93274
|
+
/**
|
|
93275
|
+
* What getAuth's result for `url` depends on. It walks up the URL's path for the longest
|
|
93276
|
+
* `//host/path` that has auth configured, and without one, falls back to the registry's auth.
|
|
93277
|
+
* So it's the longest configured prefix that matches, else the host.
|
|
93278
|
+
*/
|
|
93279
|
+
function authCacheKey(url, prefixes) {
|
|
93280
|
+
const m = /^[a-z]+:(\/\/[^/?#]+)([^?#]*)/i.exec(url);
|
|
93281
|
+
if (!m) return void 0;
|
|
93282
|
+
const full = m[1] + m[2];
|
|
93283
|
+
let best = "";
|
|
93284
|
+
for (const p of prefixes) if (p.length > best.length && full.startsWith(p) && (p.endsWith("/") || full.length === p.length || full[p.length] === "/")) best = p;
|
|
93285
|
+
return best || `host ${m[1]}`;
|
|
93286
|
+
}
|
|
93287
|
+
function cachedAuth(getAuth, url, opts) {
|
|
93288
|
+
if (opts.forceAuth) return getAuth(url, opts);
|
|
93289
|
+
let cache = authCaches.get(opts);
|
|
93290
|
+
if (!cache) {
|
|
93291
|
+
cache = {
|
|
93292
|
+
prefixes: Object.keys(opts).map((k) => /^(\/\/.+):(_authToken|_auth|username|_password|certfile|keyfile)$/.exec(k)?.[1]).filter((p) => Boolean(p)),
|
|
93293
|
+
auths: /* @__PURE__ */ new Map()
|
|
93294
|
+
};
|
|
93295
|
+
authCaches.set(opts, cache);
|
|
93296
|
+
}
|
|
93297
|
+
const key = authCacheKey(url, cache.prefixes);
|
|
93298
|
+
if (key === void 0) return getAuth(url, opts);
|
|
93299
|
+
let auth = cache.auths.get(key);
|
|
93300
|
+
if (!auth) cache.auths.set(key, auth = getAuth(url, opts));
|
|
93301
|
+
return auth;
|
|
93302
|
+
}
|
|
93303
|
+
/** Statuses from 400 up throw */
|
|
93304
|
+
async function registryGet(url, extraHeaders, opts) {
|
|
93305
|
+
const { fetch, getAuth } = await loadRegistryFetch();
|
|
93306
|
+
const auth = cachedAuth(getAuth, url, opts);
|
|
93307
|
+
const headers = {
|
|
93308
|
+
"user-agent": `fyn node/${process.version}`,
|
|
93309
|
+
...extraHeaders
|
|
93310
|
+
};
|
|
93311
|
+
if (auth.token) headers.authorization = `Bearer ${auth.token}`;
|
|
93312
|
+
else if (auth.auth) headers.authorization = `Basic ${auth.auth}`;
|
|
93313
|
+
const res = await fetch(url, {
|
|
93314
|
+
headers,
|
|
93315
|
+
compress: false,
|
|
93316
|
+
cert: auth.cert,
|
|
93317
|
+
key: auth.key,
|
|
93318
|
+
maxSockets: opts.maxSockets,
|
|
93319
|
+
noProxy: process.env.NOPROXY,
|
|
93320
|
+
retry: { retries: 3 },
|
|
93321
|
+
timeout: 3e5
|
|
93322
|
+
});
|
|
93323
|
+
if (res.status >= 400) {
|
|
93324
|
+
res.body.resume();
|
|
93325
|
+
throw Object.assign(/* @__PURE__ */ new Error(`${res.status} ${res.statusText} - GET ${url}`), {
|
|
93326
|
+
code: `E${res.status}`,
|
|
93327
|
+
statusCode: res.status
|
|
93328
|
+
});
|
|
93329
|
+
}
|
|
93330
|
+
return res;
|
|
93331
|
+
}
|
|
93332
|
+
/** npm's abbreviated install metadata, about a third the size of a full packument */
|
|
93333
|
+
const CORGI_DOC = "application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*";
|
|
93334
|
+
/**
|
|
93335
|
+
* The request headers for a packument, with validators so the registry can answer 304.
|
|
93336
|
+
*
|
|
93337
|
+
* @param full - ask for the full packument, not the abbreviated one
|
|
93338
|
+
*/
|
|
93339
|
+
function packumentHeaders(validators, full) {
|
|
93340
|
+
const headers = {
|
|
93341
|
+
accept: full ? "application/json" : CORGI_DOC,
|
|
93342
|
+
"accept-encoding": "gzip"
|
|
93343
|
+
};
|
|
93344
|
+
if (validators?.etag) headers["if-none-match"] = validators.etag;
|
|
93345
|
+
if (validators?.lastModified) headers["if-modified-since"] = validators.lastModified;
|
|
93346
|
+
return headers;
|
|
93347
|
+
}
|
|
93348
|
+
/**
|
|
93349
|
+
* Fetch a packument and write fyn's trimmed copy of it. It starts with the abbreviated form, and
|
|
93350
|
+
* gets the full one when `save` finds that abbreviated isn't enough.
|
|
93351
|
+
*
|
|
93352
|
+
* @param get - does the GET, registryGet with the job's opts by default
|
|
93353
|
+
* @param save - decodes and writes the response; an fs worker can run it
|
|
93354
|
+
*/
|
|
93355
|
+
async function fetchPackument(job, get, save = savePackument) {
|
|
93356
|
+
const doGet = get || ((url, headers) => registryGet(url, headers, job.opts || {}));
|
|
93357
|
+
const request = async (headers) => {
|
|
93358
|
+
const res = await doGet(job.url, headers);
|
|
93359
|
+
if (res.status === 304) {
|
|
93360
|
+
res.body?.resume();
|
|
93361
|
+
return;
|
|
93362
|
+
}
|
|
93363
|
+
const header = (name) => res.headers.get(name) || void 0;
|
|
93364
|
+
return {
|
|
93365
|
+
data: await res.buffer(),
|
|
93366
|
+
encoding: header("content-encoding"),
|
|
93367
|
+
etag: header("etag"),
|
|
93368
|
+
lastModified: header("last-modified"),
|
|
93369
|
+
corgi: /vnd\.npm\.install-v1/.test(header("content-type") || ""),
|
|
93370
|
+
file: job.file
|
|
93371
|
+
};
|
|
93372
|
+
};
|
|
93373
|
+
const first = await request(packumentHeaders(job, job.full));
|
|
93374
|
+
if (!first) return { status: 304 };
|
|
93375
|
+
let saved = await save(first);
|
|
93376
|
+
if ("needFull" in saved) saved = await save(await request(packumentHeaders(void 0, true)));
|
|
93377
|
+
if ("needFull" in saved) throw new Error(`no full packument from ${job.url}`);
|
|
93378
|
+
return {
|
|
93379
|
+
status: 200,
|
|
93380
|
+
json: saved.json
|
|
93381
|
+
};
|
|
93382
|
+
}
|
|
92821
93383
|
|
|
92822
93384
|
//#endregion
|
|
92823
93385
|
//#region lib/util/inflight.ts
|
|
93386
|
+
var import_lib = /* @__PURE__ */ __toESM(require_lib$23(), 1);
|
|
92824
93387
|
var inflight_default = InflightStore;
|
|
92825
93388
|
|
|
92826
93389
|
//#endregion
|
|
@@ -92855,7 +93418,10 @@ var PkgPreper = class {
|
|
|
92855
93418
|
};
|
|
92856
93419
|
return Promise.resolve((0, import_lib$2.default)(treeStub)).then((files) => {
|
|
92857
93420
|
return Qn(tarOpt, files.map((f) => `./${f}`));
|
|
92858
|
-
}).then(() => FsPromises.rename(tmpTarget, target)
|
|
93421
|
+
}).then(() => FsPromises.rename(tmpTarget, target).catch((err) => {
|
|
93422
|
+
if (err.code !== "EXDEV") throw err;
|
|
93423
|
+
return FsPromises.copyFile(tmpTarget, target);
|
|
93424
|
+
})).then(() => void 0);
|
|
92859
93425
|
});
|
|
92860
93426
|
});
|
|
92861
93427
|
}
|
|
@@ -92872,7 +93438,7 @@ var PkgPreper = class {
|
|
|
92872
93438
|
});
|
|
92873
93439
|
});
|
|
92874
93440
|
}).catch((err) => {
|
|
92875
|
-
stream.
|
|
93441
|
+
stream.destroy(err);
|
|
92876
93442
|
});
|
|
92877
93443
|
return stream;
|
|
92878
93444
|
}
|
|
@@ -92883,7 +93449,6 @@ var PkgPreper = class {
|
|
|
92883
93449
|
|
|
92884
93450
|
//#endregion
|
|
92885
93451
|
//#region node_modules/xsh/dist/util.js
|
|
92886
|
-
var import_lib = /* @__PURE__ */ __toESM(require_lib$23(), 1);
|
|
92887
93452
|
/**
|
|
92888
93453
|
* Mutable holder for the Promise implementation xsh uses.
|
|
92889
93454
|
*
|
|
@@ -93112,12 +93677,11 @@ const envPath = {
|
|
|
93112
93677
|
//#endregion
|
|
93113
93678
|
//#region node_modules/xsh/dist/mkcmd.js
|
|
93114
93679
|
/**
|
|
93115
|
-
* Make a command string:
|
|
93116
|
-
*
|
|
93680
|
+
* Make a command string: every argument, string or array of strings,
|
|
93681
|
+
* contributes its words in order, joined with `" "`.
|
|
93117
93682
|
*/
|
|
93118
93683
|
function mkCmd(...args) {
|
|
93119
|
-
|
|
93120
|
-
return Array.isArray(a) ? a.join(" ") : args.join(" ");
|
|
93684
|
+
return args.flat().join(" ");
|
|
93121
93685
|
}
|
|
93122
93686
|
|
|
93123
93687
|
//#endregion
|
|
@@ -93268,19 +93832,14 @@ const TEN_MB = 10485760;
|
|
|
93268
93832
|
const DEFAULT_TIMEOUT_GRACE = 5e3;
|
|
93269
93833
|
const DEFAULT_LAST_LINES = 10;
|
|
93270
93834
|
const MAX_OUTPUT_IN_ERROR = 5e4;
|
|
93271
|
-
function createTimeoutError(
|
|
93272
|
-
const err = /* @__PURE__ */ new Error(`Command timed out after ${elapsed}ms: ${
|
|
93835
|
+
function createTimeoutError(command, elapsed) {
|
|
93836
|
+
const err = /* @__PURE__ */ new Error(`Command timed out after ${elapsed}ms: ${command}`);
|
|
93273
93837
|
err.name = "TimeoutError";
|
|
93274
|
-
err.context = {
|
|
93275
|
-
...context,
|
|
93276
|
-
duration: elapsed
|
|
93277
|
-
};
|
|
93278
93838
|
return err;
|
|
93279
93839
|
}
|
|
93280
|
-
function createAbortError(
|
|
93281
|
-
const err = /* @__PURE__ */ new Error(`Command aborted: ${
|
|
93840
|
+
function createAbortError(command) {
|
|
93841
|
+
const err = /* @__PURE__ */ new Error(`Command aborted: ${command}`);
|
|
93282
93842
|
err.name = "AbortError";
|
|
93283
|
-
err.context = context;
|
|
93284
93843
|
return err;
|
|
93285
93844
|
}
|
|
93286
93845
|
function lastLines(text, n) {
|
|
@@ -93388,7 +93947,7 @@ var VisualExec = class {
|
|
|
93388
93947
|
}
|
|
93389
93948
|
_extractProgress(line) {
|
|
93390
93949
|
const cfg = this._progress;
|
|
93391
|
-
if (!cfg || !this._onProgress) return;
|
|
93950
|
+
if (!cfg || !(this._onProgress || cfg.format)) return;
|
|
93392
93951
|
let progress = null;
|
|
93393
93952
|
if (cfg.extract) progress = cfg.extract(line);
|
|
93394
93953
|
else if (cfg.pattern) {
|
|
@@ -93399,7 +93958,24 @@ var VisualExec = class {
|
|
|
93399
93958
|
percent: m.groups.percent ? parseInt(m.groups.percent, 10) : void 0
|
|
93400
93959
|
};
|
|
93401
93960
|
}
|
|
93402
|
-
if (progress)
|
|
93961
|
+
if (!progress) return;
|
|
93962
|
+
if (cfg.format) {
|
|
93963
|
+
const text = cfg.format(progress);
|
|
93964
|
+
if (text !== this._progressText) {
|
|
93965
|
+
this._progressText = text;
|
|
93966
|
+
this._renderDigest(this._stdoutDigest);
|
|
93967
|
+
}
|
|
93968
|
+
}
|
|
93969
|
+
if (this._onProgress) this._onProgress(progress);
|
|
93970
|
+
}
|
|
93971
|
+
_renderDigest(item) {
|
|
93972
|
+
const display = item === this._stdoutDigest && this._progressText ? `=== ${this._title}\nstdout ${this._progressText}` : void 0;
|
|
93973
|
+
this._logger.updateItem(item.name, {
|
|
93974
|
+
msg: item.msg,
|
|
93975
|
+
display,
|
|
93976
|
+
_save: false,
|
|
93977
|
+
_render: false
|
|
93978
|
+
});
|
|
93403
93979
|
}
|
|
93404
93980
|
_updateDigest(item, buf) {
|
|
93405
93981
|
const lines = (item.buf + sanitizeForDisplay(buf)).split("\n").map((x) => x && x.trim()).filter((x) => x);
|
|
@@ -93420,11 +93996,8 @@ var VisualExec = class {
|
|
|
93420
93996
|
msgs = [item.buf];
|
|
93421
93997
|
} else item.buf = msgs.join("\n");
|
|
93422
93998
|
if (buf.endsWith("\n")) item.buf += "\n";
|
|
93423
|
-
|
|
93424
|
-
|
|
93425
|
-
_save: false,
|
|
93426
|
-
_render: false
|
|
93427
|
-
});
|
|
93999
|
+
item.msg = msgs.join(chalk.blue.inverse("\\n"));
|
|
94000
|
+
this._renderDigest(item);
|
|
93428
94001
|
}
|
|
93429
94002
|
_createDataHandler(stream) {
|
|
93430
94003
|
return (buf) => {
|
|
@@ -93459,6 +94032,9 @@ var VisualExec = class {
|
|
|
93459
94032
|
* it defaults to `ExecOutput`, which is what a run without an `onComplete` produces.
|
|
93460
94033
|
*/
|
|
93461
94034
|
show(child) {
|
|
94035
|
+
return this._show(child, this._command);
|
|
94036
|
+
}
|
|
94037
|
+
_show(child, command) {
|
|
93462
94038
|
this._stdoutKey = Symbol("visual-exec-stdout");
|
|
93463
94039
|
this._stderrKey = Symbol("visual-exec-stderr");
|
|
93464
94040
|
this._rawChild = child.child;
|
|
@@ -93477,19 +94053,30 @@ var VisualExec = class {
|
|
|
93477
94053
|
name: this._stdoutKey,
|
|
93478
94054
|
buf: ""
|
|
93479
94055
|
};
|
|
94056
|
+
this._stdoutDigest = stdoutDigest;
|
|
93480
94057
|
const stderrDigest = {
|
|
93481
94058
|
name: this._stderrKey,
|
|
93482
94059
|
buf: ""
|
|
93483
94060
|
};
|
|
93484
94061
|
this._updateStdout = (buf) => this._updateDigest(stdoutDigest, buf);
|
|
93485
94062
|
this._updateStderr = (buf) => this._updateDigest(stderrDigest, buf);
|
|
94063
|
+
const seen = {
|
|
94064
|
+
stdout: "",
|
|
94065
|
+
stderr: ""
|
|
94066
|
+
};
|
|
94067
|
+
const capture = (stream, data) => {
|
|
94068
|
+
const text = seen[stream] + data;
|
|
94069
|
+
seen[stream] = text.length > MAX_OUTPUT_IN_ERROR ? text.slice(-5e4) : text;
|
|
94070
|
+
};
|
|
93486
94071
|
this._onStdoutData = (buf) => {
|
|
93487
94072
|
const data = typeof buf === "string" ? buf : buf.toString();
|
|
94073
|
+
capture("stdout", data);
|
|
93488
94074
|
this._updateStdout(data);
|
|
93489
94075
|
this._createDataHandler("stdout")(buf);
|
|
93490
94076
|
};
|
|
93491
94077
|
this._onStderrData = (buf) => {
|
|
93492
94078
|
const data = typeof buf === "string" ? buf : buf.toString();
|
|
94079
|
+
capture("stderr", data);
|
|
93493
94080
|
this._updateStderr(data);
|
|
93494
94081
|
this._createDataHandler("stderr")(buf);
|
|
93495
94082
|
};
|
|
@@ -93508,7 +94095,9 @@ var VisualExec = class {
|
|
|
93508
94095
|
stderr: ""
|
|
93509
94096
|
};
|
|
93510
94097
|
const exitCode = (_d = (_c = err.exitCode) !== null && _c !== void 0 ? _c : err.code) !== null && _d !== void 0 ? _d : 1;
|
|
93511
|
-
|
|
94098
|
+
try {
|
|
94099
|
+
(_a = this._onComplete) === null || _a === void 0 || _a.call(this, output, exitCode);
|
|
94100
|
+
} catch (_e) {}
|
|
93512
94101
|
this.logResult(err);
|
|
93513
94102
|
throw err;
|
|
93514
94103
|
}).then((output) => {
|
|
@@ -93517,6 +94106,20 @@ var VisualExec = class {
|
|
|
93517
94106
|
const result = (_a = this._onComplete) === null || _a === void 0 ? void 0 : _a.call(this, output, 0);
|
|
93518
94107
|
return result !== void 0 ? result : output;
|
|
93519
94108
|
});
|
|
94109
|
+
const cancelError = (err, duration) => {
|
|
94110
|
+
const output = { ...seen };
|
|
94111
|
+
err.output = output;
|
|
94112
|
+
return enhanceError(err, {
|
|
94113
|
+
exitCode: -1,
|
|
94114
|
+
signal: "SIGTERM",
|
|
94115
|
+
cwd: this._cwd,
|
|
94116
|
+
command,
|
|
94117
|
+
duration,
|
|
94118
|
+
lastLines: lastLines(`${output.stdout}\n${output.stderr}`, DEFAULT_LAST_LINES),
|
|
94119
|
+
stdout: output.stdout,
|
|
94120
|
+
stderr: output.stderr
|
|
94121
|
+
});
|
|
94122
|
+
};
|
|
93520
94123
|
if (this._timeout) {
|
|
93521
94124
|
const timeoutPromise = new Promise((_, reject) => {
|
|
93522
94125
|
timeoutId = setTimeout(() => {
|
|
@@ -93530,18 +94133,15 @@ var VisualExec = class {
|
|
|
93530
94133
|
if ((_a = this._rawChild) === null || _a === void 0 ? void 0 : _a.pid) this._rawChild.kill("SIGKILL");
|
|
93531
94134
|
}, this._timeoutGrace)).unref) === null || _d === void 0 || _d.call(_c);
|
|
93532
94135
|
}
|
|
93533
|
-
reject(createTimeoutError(
|
|
93534
|
-
command: this._command,
|
|
93535
|
-
cwd: this._cwd,
|
|
93536
|
-
exitCode: -1,
|
|
93537
|
-
signal: "SIGTERM"
|
|
93538
|
-
}, this._timeout));
|
|
94136
|
+
reject(cancelError(createTimeoutError(command, this._timeout), this._timeout));
|
|
93539
94137
|
}, this._timeout);
|
|
93540
94138
|
});
|
|
93541
94139
|
execPromise = Promise.race([execPromise, timeoutPromise]);
|
|
93542
94140
|
}
|
|
94141
|
+
let handleAbort;
|
|
93543
94142
|
const cleanup = () => {
|
|
93544
94143
|
if (timeoutId) clearTimeout(timeoutId);
|
|
94144
|
+
if (handleAbort) this._signal.removeEventListener("abort", handleAbort);
|
|
93545
94145
|
const stream = this._outputStream;
|
|
93546
94146
|
this._outputStream = void 0;
|
|
93547
94147
|
if (!(stream === null || stream === void 0 ? void 0 : stream.end)) return;
|
|
@@ -93554,15 +94154,9 @@ var VisualExec = class {
|
|
|
93554
94154
|
};
|
|
93555
94155
|
if (this._signal) {
|
|
93556
94156
|
const abortPromise = new Promise((_, reject) => {
|
|
93557
|
-
|
|
94157
|
+
handleAbort = () => {
|
|
93558
94158
|
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
|
-
}));
|
|
94159
|
+
reject(cancelError(createAbortError(command), Date.now() - startTime));
|
|
93566
94160
|
};
|
|
93567
94161
|
if (this._signal.aborted) handleAbort();
|
|
93568
94162
|
else this._signal.addEventListener("abort", handleAbort);
|
|
@@ -93667,7 +94261,7 @@ var VisualExec = class {
|
|
|
93667
94261
|
};
|
|
93668
94262
|
return Promise.reject(enhanceError(err, context));
|
|
93669
94263
|
});
|
|
93670
|
-
return this.
|
|
94264
|
+
return this._show(child, cmd);
|
|
93671
94265
|
}
|
|
93672
94266
|
};
|
|
93673
94267
|
|
|
@@ -93711,7 +94305,8 @@ function renameFromObj(obj, rename) {
|
|
|
93711
94305
|
function removeFromObj(obj, fields) {
|
|
93712
94306
|
for (const f of fields) if (typeof f === "string") deleteFields(f, obj);
|
|
93713
94307
|
else Object.keys(f).forEach((f2) => {
|
|
93714
|
-
|
|
94308
|
+
const sub = obj[f2];
|
|
94309
|
+
if (sub) removeFromObj(sub, f[f2]);
|
|
93715
94310
|
});
|
|
93716
94311
|
}
|
|
93717
94312
|
function extractFromObj(obj, fields, output = {}) {
|
|
@@ -93783,6 +94378,7 @@ const keepStandardFields = [
|
|
|
93783
94378
|
|
|
93784
94379
|
//#endregion
|
|
93785
94380
|
//#region node_modules/publish-util/dist/prepack.js
|
|
94381
|
+
const runsPrePack = (script) => typeof script === "string" && script.includes("publish-util-prepack");
|
|
93786
94382
|
function prePackObj(pkg, config = {}) {
|
|
93787
94383
|
renameFromObj(pkg, config.rename);
|
|
93788
94384
|
const keepObj = config.keep && extractFromObj(pkg, config.keep);
|
|
@@ -93800,7 +94396,8 @@ function prePackObj(pkg, config = {}) {
|
|
|
93800
94396
|
if (!config.silent) console.log("scripts.postpack missing, adding it.\n To skip this, set publishUtil.autoPostPack to false");
|
|
93801
94397
|
set(pkg, "scripts.postpack", "publish-util-postpack");
|
|
93802
94398
|
}
|
|
93803
|
-
if (
|
|
94399
|
+
if (scripts && runsPrePack(scripts.prepack)) delete scripts.prepack;
|
|
94400
|
+
if ((scripts === null || scripts === void 0 ? void 0 : scripts.prepublishOnly) === "publish-util-prepublishonly") delete scripts.prepublishOnly;
|
|
93804
94401
|
if (keepObj) merge(pkg, keepObj);
|
|
93805
94402
|
}
|
|
93806
94403
|
|
|
@@ -94464,6 +95061,7 @@ var PkgSrcManager = class {
|
|
|
94464
95061
|
/** trimmed packument copies, see util/trimmed-packument */
|
|
94465
95062
|
_packumentDir;
|
|
94466
95063
|
_lastMetaStatus;
|
|
95064
|
+
_registryOpts;
|
|
94467
95065
|
_fetching;
|
|
94468
95066
|
_fetchingMsg;
|
|
94469
95067
|
constructor(options) {
|
|
@@ -94665,33 +95263,38 @@ var PkgSrcManager = class {
|
|
|
94665
95263
|
this.updateFetchMetaStatus();
|
|
94666
95264
|
}
|
|
94667
95265
|
};
|
|
94668
|
-
const
|
|
94669
|
-
logger$1.debug(`
|
|
94670
|
-
|
|
94671
|
-
|
|
94672
|
-
|
|
94673
|
-
|
|
94674
|
-
|
|
94675
|
-
|
|
94676
|
-
|
|
94677
|
-
|
|
94678
|
-
|
|
94679
|
-
|
|
94680
|
-
|
|
94681
|
-
|
|
94682
|
-
if (
|
|
94683
|
-
|
|
94684
|
-
|
|
94685
|
-
|
|
94686
|
-
|
|
95266
|
+
const registryRequest = async () => {
|
|
95267
|
+
logger$1.debug(`fetch packument ${qItem.packumentUrl}`);
|
|
95268
|
+
const { cached } = qItem;
|
|
95269
|
+
const file = trimmedPackumentFile(this._packumentDir, qItem.packumentUrl);
|
|
95270
|
+
try {
|
|
95271
|
+
const job = {
|
|
95272
|
+
url: qItem.packumentUrl,
|
|
95273
|
+
file,
|
|
95274
|
+
etag: cached?.etag,
|
|
95275
|
+
lastModified: cached?.lastModified,
|
|
95276
|
+
full: Boolean(this._fyn.lockTime) || Boolean(cached && !cached.corgi)
|
|
95277
|
+
};
|
|
95278
|
+
const pool = getFsWorkerPool();
|
|
95279
|
+
const res = await fetchPackument(job, (url, headers) => this.registryGet(url, headers), pool ? (saveJob) => pool.run("savePackument", saveJob) : void 0);
|
|
95280
|
+
if (res.status === 304) {
|
|
95281
|
+
if (cached.trimmed) touchTrimmedPackument(file);
|
|
95282
|
+
else writeTrimmedPackument(file, cached.packument, void 0, cached);
|
|
95283
|
+
updateItem("304");
|
|
95284
|
+
return cached.packument;
|
|
95285
|
+
}
|
|
95286
|
+
updateItem("200");
|
|
95287
|
+
return parseTrimmed(res.json).packument;
|
|
95288
|
+
} catch (err) {
|
|
95289
|
+
const msg = `failed fetching packument of ${pkgName}`;
|
|
94687
95290
|
logger$1.error(chalk.yellow(msg), chalk.red(err.message));
|
|
94688
95291
|
throw Object.assign(new AggregateError$1([err], msg), { expected: true });
|
|
94689
|
-
}
|
|
95292
|
+
}
|
|
94690
95293
|
};
|
|
94691
95294
|
this._metaStat.wait--;
|
|
94692
95295
|
this._metaStat.inTx++;
|
|
94693
95296
|
this.updateFetchMetaStatus(false);
|
|
94694
|
-
return (qItem.item.urlType ? this.fetchUrlSemverMeta(qItem.item) :
|
|
95297
|
+
return (qItem.item.urlType ? this.fetchUrlSemverMeta(qItem.item) : dist_default.resolve(registryRequest())).then((x) => {
|
|
94695
95298
|
this._metaStat.inTx--;
|
|
94696
95299
|
const time = Date.now() - startTime;
|
|
94697
95300
|
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 +95304,20 @@ var PkgSrcManager = class {
|
|
|
94701
95304
|
qItem.defer.reject(Object.assign(new AggregateError$1([new Error(msg)], msg), { expected: true }));
|
|
94702
95305
|
return;
|
|
94703
95306
|
}
|
|
94704
|
-
refreshCacheEntry(this._cacheDir, qItem.cacheKey).catch(() => {});
|
|
94705
|
-
if (!qItem.item.urlType) writeTrimmedPackument(trimmedPackumentFile(this._packumentDir, qItem.packumentUrl), x);
|
|
94706
95307
|
qItem.defer.resolve(x);
|
|
94707
95308
|
}).catch((err) => {
|
|
94708
95309
|
this._metaStat.inTx--;
|
|
94709
95310
|
qItem.defer.reject(err);
|
|
94710
95311
|
});
|
|
94711
95312
|
}
|
|
95313
|
+
/** the plain values of the pacote options, for util/registry-get */
|
|
95314
|
+
get registryOpts() {
|
|
95315
|
+
return this._registryOpts ??= pickRegistryOpts(this._pacoteOpts);
|
|
95316
|
+
}
|
|
95317
|
+
/** GET from the registry, see util/registry-get */
|
|
95318
|
+
registryGet(url, extraHeaders) {
|
|
95319
|
+
return registryGet(url, extraHeaders, this.registryOpts);
|
|
95320
|
+
}
|
|
94712
95321
|
hasMeta(item) {
|
|
94713
95322
|
return Boolean(this._meta[item.resolutionName || item.name]);
|
|
94714
95323
|
}
|
|
@@ -94882,16 +95491,35 @@ var PkgSrcManager = class {
|
|
|
94882
95491
|
};
|
|
94883
95492
|
};
|
|
94884
95493
|
const readMemoizedPackument = async () => {
|
|
94885
|
-
const memoized = await loadBestCachedPackument(false);
|
|
94886
|
-
if (!(memoized && memoized.data)) return;
|
|
95494
|
+
const memoized = await readTrimmedPackument(trimmedFile) || await loadBestCachedPackument(false);
|
|
95495
|
+
if (!(memoized && (memoized.packument || memoized.data))) return;
|
|
94887
95496
|
logger$1.debug(`using memoized packument cache for '${pkgName}'`);
|
|
94888
95497
|
cacheMemoized = true;
|
|
94889
95498
|
this._metaStat.wait--;
|
|
94890
|
-
return JSON.parse(memoized.data.toString());
|
|
95499
|
+
return memoized.packument || JSON.parse(memoized.data.toString());
|
|
94891
95500
|
};
|
|
94892
95501
|
let fetchAttempted = false;
|
|
94893
95502
|
let foundCache;
|
|
94894
95503
|
let foundPackument;
|
|
95504
|
+
const revalidate = (packument) => {
|
|
95505
|
+
if (foundCache.packument) {
|
|
95506
|
+
const { etag, lastModified, corgi } = foundCache;
|
|
95507
|
+
return {
|
|
95508
|
+
packument,
|
|
95509
|
+
trimmed: true,
|
|
95510
|
+
etag,
|
|
95511
|
+
lastModified,
|
|
95512
|
+
corgi
|
|
95513
|
+
};
|
|
95514
|
+
}
|
|
95515
|
+
const resHeaders = foundCache.metadata?.resHeaders || {};
|
|
95516
|
+
return {
|
|
95517
|
+
packument,
|
|
95518
|
+
trimmed: false,
|
|
95519
|
+
etag: resHeaders.etag,
|
|
95520
|
+
lastModified: resHeaders["last-modified"]
|
|
95521
|
+
};
|
|
95522
|
+
};
|
|
94895
95523
|
const queueMetaFetchRequest = (cached) => {
|
|
94896
95524
|
fetchAttempted = true;
|
|
94897
95525
|
const offline = this._fyn.remoteMetaDisabled;
|
|
@@ -94912,7 +95540,8 @@ var PkgSrcManager = class {
|
|
|
94912
95540
|
cacheKey,
|
|
94913
95541
|
item,
|
|
94914
95542
|
packumentUrl,
|
|
94915
|
-
defer: dist_default.defer()
|
|
95543
|
+
defer: dist_default.defer(),
|
|
95544
|
+
cached: cached && revalidate(cached)
|
|
94916
95545
|
};
|
|
94917
95546
|
this._netQ.addItem(netQItem);
|
|
94918
95547
|
return netQItem.defer.promise;
|
|
@@ -94922,7 +95551,7 @@ var PkgSrcManager = class {
|
|
|
94922
95551
|
let cacheLookup;
|
|
94923
95552
|
if (item.urlType) cacheLookup = this._fyn.remoteMetaDisabled ? loadPreparedUrlMeta().then((preparedUrlMeta) => ({ preparedUrlMeta })) : dist_default.resolve();
|
|
94924
95553
|
else if (forceRefresh) cacheLookup = dist_default.resolve();
|
|
94925
|
-
else cacheLookup = readTrimmedPackument(trimmedFile).then((trimmed) => trimmed
|
|
95554
|
+
else cacheLookup = readTrimmedPackument(trimmedFile).then((trimmed) => trimmed && !(trimmed.corgi && this._fyn.lockTime) ? trimmed : loadBestCachedPackument(true));
|
|
94926
95555
|
const promise = cacheLookup.then((cached) => {
|
|
94927
95556
|
if (cached && cached.preparedUrlMeta) {
|
|
94928
95557
|
cacheMemoized = true;
|
|
@@ -95053,10 +95682,21 @@ var PkgSrcManager = class {
|
|
|
95053
95682
|
if (di && di.urlType) return `${di.name}@${di.semver}`;
|
|
95054
95683
|
return `${pkgInfo.name}@${pkgInfo.version}`;
|
|
95055
95684
|
}
|
|
95056
|
-
|
|
95685
|
+
/**
|
|
95686
|
+
* A package not in the central store yet comes back as a store job, so the extractor writes
|
|
95687
|
+
* the store, not the download slot this runs in.
|
|
95688
|
+
*
|
|
95689
|
+
* @param data - the tarball's bytes, when it was downloaded for the central store and not
|
|
95690
|
+
* into cacache
|
|
95691
|
+
*/
|
|
95692
|
+
async getCentralPackage(integrity, pkgInfo, data) {
|
|
95057
95693
|
const { central, copy } = this._fyn;
|
|
95058
95694
|
const tarId = this.tarballFetchId(pkgInfo);
|
|
95059
95695
|
const tarStream = async () => {
|
|
95696
|
+
if (data) {
|
|
95697
|
+
if (!import_lib.default.checkData(data, integrity)) throw Object.assign(/* @__PURE__ */ new Error(`integrity check failed for ${tarId}`), { code: "EINTEGRITY" });
|
|
95698
|
+
return Readable.from([data]);
|
|
95699
|
+
}
|
|
95060
95700
|
return integrity && await (await loadCacache()).get.hasContent(this._cacheDir, integrity) ? this.cacacheTarballStream(integrity) : this.pacoteTarballStream(tarId, pkgInfo, integrity);
|
|
95061
95701
|
};
|
|
95062
95702
|
if (integrity && central) {
|
|
@@ -95075,7 +95715,17 @@ var PkgSrcManager = class {
|
|
|
95075
95715
|
hasCentral = false;
|
|
95076
95716
|
}
|
|
95077
95717
|
}
|
|
95078
|
-
if (!hasCentral)
|
|
95718
|
+
if (!hasCentral) {
|
|
95719
|
+
const tarSource = async () => {
|
|
95720
|
+
if (data) return { data };
|
|
95721
|
+
const content = await (await loadCacache()).get.hasContent(this._cacheDir, integrity);
|
|
95722
|
+
return content ? { file: getContentPath(this._cacheDir, content.sri) } : void 0;
|
|
95723
|
+
};
|
|
95724
|
+
return {
|
|
95725
|
+
integrity,
|
|
95726
|
+
store: (deferIfBusy) => central.storeTarStream(tarId, integrity, tarStream, deferIfBusy, tarSource)
|
|
95727
|
+
};
|
|
95728
|
+
}
|
|
95079
95729
|
return integrity;
|
|
95080
95730
|
}
|
|
95081
95731
|
}
|
|
@@ -95085,7 +95735,14 @@ var PkgSrcManager = class {
|
|
|
95085
95735
|
const startTime = Date.now();
|
|
95086
95736
|
const pkgId = this.tarballFetchId(pkgInfo);
|
|
95087
95737
|
const integrity = this.getIntegrity(pkgInfo);
|
|
95088
|
-
const
|
|
95738
|
+
const tarballUrl = get$1(pkgInfo, "dist.tarball");
|
|
95739
|
+
const central = this._fyn.central;
|
|
95740
|
+
const centralEligible = Boolean(integrity && tarballUrl && central && !tarballUrl.startsWith("~url-spec~"));
|
|
95741
|
+
const copied = () => {
|
|
95742
|
+
const { copy } = this._fyn;
|
|
95743
|
+
return copy.indexOf(pkgInfo.name) >= 0 || copy.indexOf(`${pkgInfo.name}@${pkgInfo.version}`) >= 0;
|
|
95744
|
+
};
|
|
95745
|
+
const doFetch = (fetchForCentral) => {
|
|
95089
95746
|
const fetchStartTime = Date.now();
|
|
95090
95747
|
if (!this._fetching) {
|
|
95091
95748
|
this._fetching = [];
|
|
@@ -95093,21 +95750,28 @@ var PkgSrcManager = class {
|
|
|
95093
95750
|
}
|
|
95094
95751
|
this._fetching.push(pkgId);
|
|
95095
95752
|
logger$1.updateItem(FETCH_PACKAGE, `${this._fetching.length} ${this._fetchingMsg}`);
|
|
95096
|
-
return this.pacotePrefetch(pkgId, pkgInfo, integrity).then(() => {
|
|
95753
|
+
return (fetchForCentral ? dist_default.resolve(this.registryGet(tarballUrl, {})).then((res) => res.buffer()) : this.pacotePrefetch(pkgId, pkgInfo, integrity)).then((data) => {
|
|
95097
95754
|
const status = chalk.cyan(`200`);
|
|
95098
95755
|
const time = log_format_default.time(Date.now() - fetchStartTime);
|
|
95099
95756
|
const ix = this._fetching.indexOf(pkgId);
|
|
95100
95757
|
this._fetching.splice(ix, 1);
|
|
95101
95758
|
this._fetchingMsg = `${status} ${time} ${chalk.red.bgGreen(pkgInfo.name)}`;
|
|
95102
95759
|
logger$1.updateItem(FETCH_PACKAGE, `${this._fetching.length} ${this._fetchingMsg}`);
|
|
95103
|
-
return this.getCentralPackage(integrity, pkgInfo);
|
|
95760
|
+
return this.getCentralPackage(integrity, pkgInfo, data || void 0);
|
|
95104
95761
|
});
|
|
95105
95762
|
};
|
|
95106
|
-
const
|
|
95107
|
-
if (content) return this.getCentralPackage(integrity, pkgInfo);
|
|
95763
|
+
const fetchRemote = (fetchForCentral) => {
|
|
95108
95764
|
const rd = this._fyn.remoteTgzDisabled;
|
|
95109
95765
|
if (rd) throw new Error(`option ${rd} has disabled retrieving tarball from remote`);
|
|
95110
|
-
return doFetch();
|
|
95766
|
+
return doFetch(fetchForCentral);
|
|
95767
|
+
};
|
|
95768
|
+
const promise = dist_default.resolve().then(async () => {
|
|
95769
|
+
if (centralEligible) {
|
|
95770
|
+
if (await central.has(integrity)) return this.getCentralPackage(integrity, pkgInfo);
|
|
95771
|
+
if (!this._fyn.remoteTgzDisabled && !copied() && await central.allow(integrity)) return fetchRemote(true);
|
|
95772
|
+
}
|
|
95773
|
+
if (await dist_default.resolve(loadCacache()).then((cacache) => cacache.get.hasContent(this._cacheDir, integrity)).catch(() => false)) return this.getCentralPackage(integrity, pkgInfo);
|
|
95774
|
+
return fetchRemote(false);
|
|
95111
95775
|
});
|
|
95112
95776
|
return {
|
|
95113
95777
|
then: (r, e) => promise.then(r, e),
|
|
@@ -96872,6 +97536,51 @@ var PkgDepLocker = class {
|
|
|
96872
97536
|
if (sorted) remove$3(sorted, (x) => x === item.resolved);
|
|
96873
97537
|
}
|
|
96874
97538
|
}
|
|
97539
|
+
/**
|
|
97540
|
+
* Locked versions by package name, newest first, from the serialized lock data
|
|
97541
|
+
*/
|
|
97542
|
+
lockedVersions() {
|
|
97543
|
+
assert(this._isFynFormat, "lock data is no longer in fyn format");
|
|
97544
|
+
const result = {};
|
|
97545
|
+
for (const name in this._lockData) {
|
|
97546
|
+
if (name.startsWith("$")) continue;
|
|
97547
|
+
const versions = Object.keys(this._lockData[name]).filter((v) => !v.startsWith("_"));
|
|
97548
|
+
if (versions.length > 0) result[name] = versions.sort(simpleCompare);
|
|
97549
|
+
}
|
|
97550
|
+
return result;
|
|
97551
|
+
}
|
|
97552
|
+
/**
|
|
97553
|
+
* Drop lock data so the resolver picks the newest versions the ranges allow.
|
|
97554
|
+
* With no names, drop every package. With names, drop those packages and
|
|
97555
|
+
* everything they depend on, directly or not.
|
|
97556
|
+
*
|
|
97557
|
+
* @param names - packages to unlock, or none for all
|
|
97558
|
+
* @returns the unlocked package names
|
|
97559
|
+
*/
|
|
97560
|
+
unlock(names = []) {
|
|
97561
|
+
assert(this._isFynFormat, "lock data is no longer in fyn format");
|
|
97562
|
+
const data = this._lockData;
|
|
97563
|
+
const pending = names.length > 0 ? [...names] : Object.keys(data).filter((n) => !n.startsWith("$"));
|
|
97564
|
+
const unlocked = /* @__PURE__ */ new Set();
|
|
97565
|
+
while (pending.length > 0) {
|
|
97566
|
+
const name = pending.pop();
|
|
97567
|
+
const pkgLocked = data[name];
|
|
97568
|
+
if (unlocked.has(name) || !pkgLocked) continue;
|
|
97569
|
+
unlocked.add(name);
|
|
97570
|
+
if (names.length === 0) continue;
|
|
97571
|
+
for (const version in pkgLocked) {
|
|
97572
|
+
if (version.startsWith("_")) continue;
|
|
97573
|
+
const vpkg = pkgLocked[version];
|
|
97574
|
+
const deps = {
|
|
97575
|
+
...vpkg.dependencies,
|
|
97576
|
+
...vpkg.optionalDependencies
|
|
97577
|
+
};
|
|
97578
|
+
for (const dep in deps) pending.push(parseNpmAlias(deps[dep], dep)?.name || dep);
|
|
97579
|
+
}
|
|
97580
|
+
}
|
|
97581
|
+
for (const name of unlocked) delete data[name];
|
|
97582
|
+
return [...unlocked].sort();
|
|
97583
|
+
}
|
|
96875
97584
|
shasum(data) {
|
|
96876
97585
|
return Crypto.createHash("sha1").update(data).digest("hex");
|
|
96877
97586
|
}
|
|
@@ -96928,6 +97637,7 @@ var PkgDepLocker = class {
|
|
|
96928
97637
|
*/
|
|
96929
97638
|
saveInstalled(filename) {
|
|
96930
97639
|
if (!this._enable) return;
|
|
97640
|
+
file_ops_default.$.mkdirp(Path.dirname(filename));
|
|
96931
97641
|
file_ops_default.writeFileSync(filename, this._stringify(Path.dirname(filename)));
|
|
96932
97642
|
}
|
|
96933
97643
|
/**
|
|
@@ -97055,7 +97765,8 @@ const typeGetters = {
|
|
|
97055
97765
|
return lower === "true" || lower === "yes" || lower === "1" || lower === "on";
|
|
97056
97766
|
},
|
|
97057
97767
|
truthy: (x) => !!x,
|
|
97058
|
-
json: (x) => JSON.parse(x)
|
|
97768
|
+
json: (x) => JSON.parse(x),
|
|
97769
|
+
array: (x) => JSON.parse(x)
|
|
97059
97770
|
};
|
|
97060
97771
|
const getEnvName = (optKey, opt, env) => {
|
|
97061
97772
|
if (!Object.prototype.hasOwnProperty.call(opt, "env")) return void 0;
|
|
@@ -97078,9 +97789,12 @@ const xenvConfig = (spec, userConfig, options) => {
|
|
|
97078
97789
|
userConfig = userConfig || {};
|
|
97079
97790
|
const trace = {};
|
|
97080
97791
|
const getType = (opt) => {
|
|
97081
|
-
|
|
97082
|
-
|
|
97083
|
-
|
|
97792
|
+
if (opt.type) return opt.type === "object" ? "json" : opt.type;
|
|
97793
|
+
if (!Object.prototype.hasOwnProperty.call(opt, "default")) return "string";
|
|
97794
|
+
if (opt.default === null) return "string";
|
|
97795
|
+
if (Array.isArray(opt.default)) return "array";
|
|
97796
|
+
const tod = typeof opt.default;
|
|
97797
|
+
return tod === "object" ? "json" : tod === "function" ? "string" : tod;
|
|
97084
97798
|
};
|
|
97085
97799
|
const getGetter = (opt) => {
|
|
97086
97800
|
const type = getType(opt);
|
|
@@ -97113,19 +97827,27 @@ const xenvConfig = (spec, userConfig, options) => {
|
|
|
97113
97827
|
};
|
|
97114
97828
|
}
|
|
97115
97829
|
};
|
|
97116
|
-
const sources = options && options.sources || ["env", "option"];
|
|
97117
|
-
sources.
|
|
97830
|
+
const sources = [...options && options.sources || ["env", "option"], "default"];
|
|
97831
|
+
const badSource = sources.find((s) => !Object.prototype.hasOwnProperty.call(getters, s));
|
|
97832
|
+
if (badSource !== void 0) throw new Error(`xenv-config: unknown source "${badSource}"; valid sources are ${Object.keys(getters).join(", ")}`);
|
|
97118
97833
|
const config = Object.keys(spec).reduce((cfg, k) => {
|
|
97834
|
+
var _a;
|
|
97119
97835
|
const opt = spec[k];
|
|
97120
97836
|
const type = getType(opt);
|
|
97121
97837
|
let found;
|
|
97122
97838
|
if (type !== "json") sources.find((s) => found = getters[s](opt, k));
|
|
97123
97839
|
else {
|
|
97124
97840
|
const mapped = sources.map((s) => getters[s](opt, k)).filter((x) => Boolean(x));
|
|
97125
|
-
if (mapped.length > 0)
|
|
97126
|
-
|
|
97127
|
-
|
|
97128
|
-
|
|
97841
|
+
if (mapped.length > 0) {
|
|
97842
|
+
const name = (_a = mapped.find((x) => x.trace.name)) === null || _a === void 0 ? void 0 : _a.trace.name;
|
|
97843
|
+
found = {
|
|
97844
|
+
trace: {
|
|
97845
|
+
src: mapped.map((x) => x.trace.src).join(","),
|
|
97846
|
+
...name && { name }
|
|
97847
|
+
},
|
|
97848
|
+
value: merge.apply(null, [{}].concat(mapped.map((x) => x.value).reverse()))
|
|
97849
|
+
};
|
|
97850
|
+
}
|
|
97129
97851
|
}
|
|
97130
97852
|
if (!found) return cfg;
|
|
97131
97853
|
trace[k] = found.trace;
|
|
@@ -97143,18 +97865,12 @@ const xenvConfig = (spec, userConfig, options) => {
|
|
|
97143
97865
|
//#endregion
|
|
97144
97866
|
//#region lib/fyn-config.ts
|
|
97145
97867
|
const spec = {
|
|
97146
|
-
registry: {
|
|
97147
|
-
env: "FYN_REGISTRY",
|
|
97148
|
-
default: "http://localhost:4873"
|
|
97149
|
-
},
|
|
97868
|
+
registry: { default: "http://localhost:4873" },
|
|
97150
97869
|
pkgFile: {
|
|
97151
97870
|
env: "FYN_PACKAGE_FILE",
|
|
97152
97871
|
default: "package.json"
|
|
97153
97872
|
},
|
|
97154
|
-
targetDir: {
|
|
97155
|
-
env: "FYN_TARGET_DIR",
|
|
97156
|
-
default: "xout"
|
|
97157
|
-
},
|
|
97873
|
+
targetDir: { default: "xout" },
|
|
97158
97874
|
fynDir: {
|
|
97159
97875
|
env: [
|
|
97160
97876
|
"FYN_DIR",
|
|
@@ -97183,12 +97899,135 @@ function fynConfig(override) {
|
|
|
97183
97899
|
}
|
|
97184
97900
|
|
|
97185
97901
|
//#endregion
|
|
97186
|
-
//#region lib/
|
|
97187
|
-
|
|
97188
|
-
/**
|
|
97189
|
-
|
|
97190
|
-
|
|
97902
|
+
//#region lib/util/reflink.ts
|
|
97903
|
+
let nativeReflink;
|
|
97904
|
+
/**
|
|
97905
|
+
* @fynjs/reflink is a native addon, so it cannot be bundled into dist/. Load it at runtime from
|
|
97906
|
+
* an optional dependency, and resolve to undefined when it is absent or has no binary for
|
|
97907
|
+
* this platform.
|
|
97908
|
+
*/
|
|
97909
|
+
function loadReflink() {
|
|
97910
|
+
nativeReflink ??= (async () => {
|
|
97911
|
+
try {
|
|
97912
|
+
const file = createRequire(import.meta.url).resolve("@fynjs/reflink");
|
|
97913
|
+
return await import(
|
|
97914
|
+
/* @vite-ignore */
|
|
97915
|
+
pathToFileURL(file).href
|
|
97916
|
+
);
|
|
97917
|
+
} catch (err) {
|
|
97918
|
+
logger$1.debug(`@fynjs/reflink not loaded, using JS clone: ${err.message}`);
|
|
97919
|
+
return;
|
|
97920
|
+
}
|
|
97921
|
+
})();
|
|
97922
|
+
return nativeReflink;
|
|
97923
|
+
}
|
|
97924
|
+
async function loadReflinkCloneFiles() {
|
|
97925
|
+
return (await loadReflink())?.cloneFiles;
|
|
97191
97926
|
}
|
|
97927
|
+
/** undefined with no reflink, or an reflink older than cloneDir */
|
|
97928
|
+
async function loadReflinkCloneDir() {
|
|
97929
|
+
return (await loadReflink())?.cloneDir;
|
|
97930
|
+
}
|
|
97931
|
+
|
|
97932
|
+
//#endregion
|
|
97933
|
+
//#region lib/util/untar-tree.ts
|
|
97934
|
+
/** An `onentry` for Tar.x that builds the tree, and the result once extraction finishes */
|
|
97935
|
+
function treeCollector(strip) {
|
|
97936
|
+
const newDirObj = () => {
|
|
97937
|
+
const n = Object.create(null);
|
|
97938
|
+
n["/"] = Object.create(null);
|
|
97939
|
+
return n;
|
|
97940
|
+
};
|
|
97941
|
+
const result = {
|
|
97942
|
+
tree: newDirObj(),
|
|
97943
|
+
fromHeaders: true
|
|
97944
|
+
};
|
|
97945
|
+
const onentry = (entry) => {
|
|
97946
|
+
const isDir = entry.type === "Directory";
|
|
97947
|
+
const parts = entry.path.split(/\/|\\/).slice(strip).filter((p) => p && p !== ".");
|
|
97948
|
+
const wtree = (isDir ? parts : parts.slice(0, -1)).reduce((wt, dir) => {
|
|
97949
|
+
return wt[dir] || (wt[dir] = newDirObj());
|
|
97950
|
+
}, result.tree);
|
|
97951
|
+
if (isDir) return;
|
|
97952
|
+
if (!entry.mtime || ![
|
|
97953
|
+
"File",
|
|
97954
|
+
"OldFile",
|
|
97955
|
+
"ContiguousFile"
|
|
97956
|
+
].includes(entry.type)) result.fromHeaders = false;
|
|
97957
|
+
const fname = parts[parts.length - 1];
|
|
97958
|
+
if (fname) {
|
|
97959
|
+
const m = Math.round((entry.mtime ? entry.mtime.getTime() : Date.now()) / 1e3);
|
|
97960
|
+
wtree["/"][fname] = {
|
|
97961
|
+
z: entry.size,
|
|
97962
|
+
m,
|
|
97963
|
+
$: entry.header.cksumValid && entry.header.cksum
|
|
97964
|
+
};
|
|
97965
|
+
}
|
|
97966
|
+
};
|
|
97967
|
+
return {
|
|
97968
|
+
onentry,
|
|
97969
|
+
result
|
|
97970
|
+
};
|
|
97971
|
+
}
|
|
97972
|
+
const hashList = (list) => Crypto$1.createHash("sha512").update(JSON.stringify(list.sort())).digest("base64");
|
|
97973
|
+
/** The shaSum of a tree from tar headers, in SUM_VERSION's format */
|
|
97974
|
+
function treeShasum(tree) {
|
|
97975
|
+
const files = [];
|
|
97976
|
+
const walk = (node, dir) => {
|
|
97977
|
+
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}`);
|
|
97978
|
+
else walk(child, `${dir}${name}/`);
|
|
97979
|
+
};
|
|
97980
|
+
walk(tree, "");
|
|
97981
|
+
return hashList(files);
|
|
97982
|
+
}
|
|
97983
|
+
/** tree.json's content. An old entry keeps its sumVersion until validate() converts it. */
|
|
97984
|
+
function treeFileJson(info) {
|
|
97985
|
+
return JSON.stringify({
|
|
97986
|
+
$: info.tree,
|
|
97987
|
+
shaSum: info.shaSum,
|
|
97988
|
+
mutates: info.mutates,
|
|
97989
|
+
_: info.sumVersion ?? 1
|
|
97990
|
+
});
|
|
97991
|
+
}
|
|
97992
|
+
|
|
97993
|
+
//#endregion
|
|
97994
|
+
//#region lib/util/store-entry.ts
|
|
97995
|
+
/** an extraction marker or temp dir older than this was left by an install that died */
|
|
97996
|
+
const STALE_MS = 3e5;
|
|
97997
|
+
/** a name suffix no other install, or other call in this one, will pick */
|
|
97998
|
+
const uniqueSuffix = () => `${process.pid}-${Crypto$1.randomBytes(4).toString("hex")}`;
|
|
97999
|
+
/**
|
|
98000
|
+
* filterScanDir options that hash a package dir in one stat walk, in both formats: v1 for
|
|
98001
|
+
* checking an old entry, v2 for everything else (see SUM_VERSION). Call `sums` with the scan's
|
|
98002
|
+
* result.
|
|
98003
|
+
*/
|
|
98004
|
+
function shasumScan(packageDir) {
|
|
98005
|
+
const v2 = [];
|
|
98006
|
+
const filter = (_file, _path, extras) => {
|
|
98007
|
+
const { stat, dirFile } = extras;
|
|
98008
|
+
const fullStat = stat;
|
|
98009
|
+
if (!fullStat.isDirectory()) v2.push(`${dirFile.replace(/\\/g, "/")}-${Math.floor(fullStat.mtimeMs / 1e3)}-${fullStat.size}`);
|
|
98010
|
+
return { formatName: `${dirFile}-${fullStat.mtimeMs}-${fullStat.size}` };
|
|
98011
|
+
};
|
|
98012
|
+
return {
|
|
98013
|
+
options: {
|
|
98014
|
+
cwd: packageDir,
|
|
98015
|
+
filter,
|
|
98016
|
+
filterDir: filter,
|
|
98017
|
+
fullStat: true,
|
|
98018
|
+
concurrency: 500,
|
|
98019
|
+
sortFiles: false,
|
|
98020
|
+
includeDir: true
|
|
98021
|
+
},
|
|
98022
|
+
sums: (files) => ({
|
|
98023
|
+
v1: hashList(files),
|
|
98024
|
+
v2: hashList(v2)
|
|
98025
|
+
})
|
|
98026
|
+
};
|
|
98027
|
+
}
|
|
98028
|
+
|
|
98029
|
+
//#endregion
|
|
98030
|
+
//#region lib/util/place-files.ts
|
|
97192
98031
|
/** link errors that mean the filesystem can't hardlink from the store at all */
|
|
97193
98032
|
const NO_LINK_CODES = [
|
|
97194
98033
|
"EXDEV",
|
|
@@ -97197,6 +98036,14 @@ const NO_LINK_CODES = [
|
|
|
97197
98036
|
"EOPNOTSUPP",
|
|
97198
98037
|
"ENOSYS"
|
|
97199
98038
|
];
|
|
98039
|
+
|
|
98040
|
+
//#endregion
|
|
98041
|
+
//#region lib/fyn-central.ts
|
|
98042
|
+
const { missPipe } = fyntil;
|
|
98043
|
+
/** Type guard to check if parsed tree is new format with version */
|
|
98044
|
+
function isTreeFileContent(obj) {
|
|
98045
|
+
return typeof obj === "object" && obj !== null && "_" in obj && typeof obj._ === "number";
|
|
98046
|
+
}
|
|
97200
98047
|
/**
|
|
97201
98048
|
* Convert a directory tree structure to a flatten one like:
|
|
97202
98049
|
* ```
|
|
@@ -97234,11 +98081,26 @@ function flattenTree(tree, output, baseDir) {
|
|
|
97234
98081
|
var FynCentral = class {
|
|
97235
98082
|
_centralDir;
|
|
97236
98083
|
_map;
|
|
98084
|
+
/** entries found missing, so has() and allow() don't stat them again; storing re-checks */
|
|
98085
|
+
_missing = /* @__PURE__ */ new Map();
|
|
98086
|
+
/** store dirs this install has made, so each is made once */
|
|
98087
|
+
_madeDirs = /* @__PURE__ */ new Set();
|
|
97237
98088
|
_hardlink;
|
|
97238
|
-
|
|
98089
|
+
_reflink;
|
|
98090
|
+
_copyFallback;
|
|
98091
|
+
/** cleared on the first dir clone the filesystem can't do, so later packages skip it */
|
|
98092
|
+
_cloneDirs = true;
|
|
98093
|
+
/**
|
|
98094
|
+
* cleared when a package's files hardlink but none clone, so later packages hardlink in the
|
|
98095
|
+
* fs workers. That's faster than @fynjs/reflink on a filesystem that can't clone (ext4).
|
|
98096
|
+
*/
|
|
98097
|
+
_cloneFiles = true;
|
|
98098
|
+
constructor({ centralDir = ".fyn/_central-storage", hardlink = true, reflink = true, copyFallback = true } = {}) {
|
|
97239
98099
|
this._centralDir = Path.resolve(centralDir);
|
|
97240
98100
|
this._map = /* @__PURE__ */ new Map();
|
|
97241
98101
|
this._hardlink = hardlink;
|
|
98102
|
+
this._reflink = reflink;
|
|
98103
|
+
this._copyFallback = copyFallback;
|
|
97242
98104
|
}
|
|
97243
98105
|
_analyze(integrity) {
|
|
97244
98106
|
const sri = import_lib.default.parse(integrity, { single: true });
|
|
@@ -97272,14 +98134,16 @@ var FynCentral = class {
|
|
|
97272
98134
|
}
|
|
97273
98135
|
}
|
|
97274
98136
|
try {
|
|
97275
|
-
|
|
97276
|
-
info.exist = true;
|
|
97277
|
-
if (stat.isDirectory()) {
|
|
98137
|
+
if ((await file_ops_default.stat(info.contentPath)).isDirectory()) {
|
|
97278
98138
|
await this.readInfoTree(info);
|
|
97279
98139
|
if (!noSet) this._map.set(integrity, info);
|
|
97280
98140
|
}
|
|
98141
|
+
info.exist = true;
|
|
98142
|
+
this._missing.delete(integrity);
|
|
97281
98143
|
return info;
|
|
97282
98144
|
} catch (_err) {
|
|
98145
|
+
info.exist = false;
|
|
98146
|
+
if (!noSet) this._missing.set(integrity, info);
|
|
97283
98147
|
return info;
|
|
97284
98148
|
}
|
|
97285
98149
|
}
|
|
@@ -97290,7 +98154,7 @@ var FynCentral = class {
|
|
|
97290
98154
|
* @returns boolean
|
|
97291
98155
|
*/
|
|
97292
98156
|
async has(integrity) {
|
|
97293
|
-
const info = this._map.
|
|
98157
|
+
const info = this._map.get(integrity) ?? this._missing.get(integrity) ?? await this._loadTree(integrity);
|
|
97294
98158
|
return Boolean(info.tree);
|
|
97295
98159
|
}
|
|
97296
98160
|
/**
|
|
@@ -97300,7 +98164,7 @@ var FynCentral = class {
|
|
|
97300
98164
|
* @returns boolean
|
|
97301
98165
|
*/
|
|
97302
98166
|
async allow(integrity) {
|
|
97303
|
-
return (this._map.
|
|
98167
|
+
return (this._map.get(integrity) ?? this._missing.get(integrity) ?? await this._loadTree(integrity)).mutates ? false : true;
|
|
97304
98168
|
}
|
|
97305
98169
|
async getContentPath(integrity) {
|
|
97306
98170
|
return (await this.getInfo(integrity)).contentPath;
|
|
@@ -97311,28 +98175,25 @@ var FynCentral = class {
|
|
|
97311
98175
|
if (!info.tree) throw new Error(`fyn-central can't get package for integrity ${integrity}`);
|
|
97312
98176
|
return info;
|
|
97313
98177
|
}
|
|
97314
|
-
|
|
98178
|
+
/**
|
|
98179
|
+
* Hash a package dir in one stat walk, in both formats: v1 for checking an old entry, v2 for
|
|
98180
|
+
* everything else (see SUM_VERSION).
|
|
98181
|
+
*/
|
|
98182
|
+
async _scanShasums(packageDir) {
|
|
97315
98183
|
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");
|
|
98184
|
+
const { options, sums } = shasumScan(packageDir);
|
|
98185
|
+
return sums(await filterScanDir(options));
|
|
97332
98186
|
} catch (_err) {
|
|
97333
98187
|
return;
|
|
97334
98188
|
}
|
|
97335
98189
|
}
|
|
98190
|
+
/** The v2 hash of a fresh extraction, from the tar header sizes and mtimes in its tree */
|
|
98191
|
+
_treeShasum(tree) {
|
|
98192
|
+
return treeShasum(tree);
|
|
98193
|
+
}
|
|
98194
|
+
async _calcContentShasum(info, pkgDir) {
|
|
98195
|
+
return (await this._scanShasums(pkgDir || Path.join(info.contentPath, "package")))?.v1;
|
|
98196
|
+
}
|
|
97336
98197
|
/**
|
|
97337
98198
|
* Get the hash of a npm package's extracted content.
|
|
97338
98199
|
* - only consider the file names and their mtime and size because npm tar files
|
|
@@ -97351,16 +98212,41 @@ var FynCentral = class {
|
|
|
97351
98212
|
}
|
|
97352
98213
|
}
|
|
97353
98214
|
async getMutation(integrity) {
|
|
97354
|
-
return (this._map.
|
|
98215
|
+
return (this._map.get(integrity) ?? this._missing.get(integrity) ?? await this._loadTree(integrity)).mutates;
|
|
97355
98216
|
}
|
|
98217
|
+
/**
|
|
98218
|
+
* Rename the entry away before removing it, so a concurrent install never finds it half
|
|
98219
|
+
* deleted, with tree.json present and package/ partly gone.
|
|
98220
|
+
*/
|
|
97356
98221
|
async delete(integrity) {
|
|
97357
98222
|
const info = this._map.get(integrity);
|
|
97358
98223
|
if (info && info.exist && info.contentPath) {
|
|
97359
|
-
|
|
98224
|
+
const trash = `${info.contentPath}.del-${uniqueSuffix()}`;
|
|
98225
|
+
try {
|
|
98226
|
+
await file_ops_default.rename(info.contentPath, trash);
|
|
98227
|
+
} catch (err) {
|
|
98228
|
+
if (err.code !== "ENOENT") throw err;
|
|
98229
|
+
}
|
|
97360
98230
|
this._map.delete(integrity);
|
|
98231
|
+
await file_ops_default.$.rimraf(trash);
|
|
97361
98232
|
}
|
|
97362
98233
|
}
|
|
97363
98234
|
/**
|
|
98235
|
+
* An entry with no readable tree.json is left from a broken write. Rename it away, then
|
|
98236
|
+
* remove it, the same way delete() does.
|
|
98237
|
+
*/
|
|
98238
|
+
async _removeBrokenEntry(contentPath) {
|
|
98239
|
+
const trash = `${contentPath}.del-${uniqueSuffix()}`;
|
|
98240
|
+
try {
|
|
98241
|
+
await file_ops_default.rename(contentPath, trash);
|
|
98242
|
+
} catch (err) {
|
|
98243
|
+
if (err.code !== "ENOENT") throw err;
|
|
98244
|
+
return;
|
|
98245
|
+
}
|
|
98246
|
+
logger$1.warn(`fyn-central: replacing a broken store entry with no tree.json at ${contentPath}`);
|
|
98247
|
+
await file_ops_default.$.rimraf(trash);
|
|
98248
|
+
}
|
|
98249
|
+
/**
|
|
97364
98250
|
* Read the content dir tree from file into info
|
|
97365
98251
|
*
|
|
97366
98252
|
* @param info - package info
|
|
@@ -97374,24 +98260,30 @@ var FynCentral = class {
|
|
|
97374
98260
|
if (parsed.mutates !== void 0) info.mutates = parsed.mutates;
|
|
97375
98261
|
info.tree = parsed.$;
|
|
97376
98262
|
info.shaSum = parsed.shaSum;
|
|
98263
|
+
info.sumVersion = parsed._;
|
|
97377
98264
|
} else info.tree = parsed;
|
|
97378
98265
|
} catch (err) {
|
|
97379
98266
|
throw new AggregateError$1([err], `fyn-central: reading tree file ${treeFile}`);
|
|
97380
98267
|
}
|
|
97381
98268
|
}
|
|
97382
98269
|
/**
|
|
97383
|
-
* Save the content dir tree from info to file
|
|
98270
|
+
* Save the content dir tree from info to file. In a live entry it's written to a temp file
|
|
98271
|
+
* and renamed over, so a concurrent install never reads half of it. A `path` is a temp dir
|
|
98272
|
+
* only this install uses, so it's written directly.
|
|
97384
98273
|
*
|
|
97385
98274
|
* @param info - package info
|
|
97386
98275
|
* @param path - path to save the file
|
|
97387
98276
|
*/
|
|
97388
98277
|
async saveInfoTree(info, path) {
|
|
97389
|
-
|
|
97390
|
-
|
|
97391
|
-
|
|
97392
|
-
|
|
97393
|
-
|
|
97394
|
-
|
|
98278
|
+
const data = treeFileJson(info);
|
|
98279
|
+
if (path) {
|
|
98280
|
+
await file_ops_default.writeFile(Path.join(path, "tree.json"), data);
|
|
98281
|
+
return;
|
|
98282
|
+
}
|
|
98283
|
+
const treeFile = Path.join(info.contentPath, "tree.json");
|
|
98284
|
+
const tmpFile = `${treeFile}.${uniqueSuffix()}`;
|
|
98285
|
+
await file_ops_default.writeFile(tmpFile, data);
|
|
98286
|
+
await file_ops_default.rename(tmpFile, treeFile);
|
|
97395
98287
|
}
|
|
97396
98288
|
async setMutation(integrity, mutates = true) {
|
|
97397
98289
|
const info = await this._loadTree(integrity);
|
|
@@ -97399,21 +98291,81 @@ var FynCentral = class {
|
|
|
97399
98291
|
info.mutates = mutates;
|
|
97400
98292
|
await this.saveInfoTree(info);
|
|
97401
98293
|
}
|
|
97402
|
-
|
|
98294
|
+
/**
|
|
98295
|
+
* @param prepare - makes destDir, when the caller hasn't. An fs worker does it instead when
|
|
98296
|
+
* it places the files.
|
|
98297
|
+
* @returns package.json as placed, when an fs worker placed the files
|
|
98298
|
+
*/
|
|
98299
|
+
async replicate(integrity, destDir, prepare) {
|
|
98300
|
+
let prepared = !prepare;
|
|
98301
|
+
const ensurePrepared = async () => {
|
|
98302
|
+
if (!prepared) {
|
|
98303
|
+
prepared = true;
|
|
98304
|
+
await prepare();
|
|
98305
|
+
}
|
|
98306
|
+
};
|
|
98307
|
+
const placing = [];
|
|
97403
98308
|
try {
|
|
97404
98309
|
const info = await this.getInfo(integrity);
|
|
97405
98310
|
const list = flattenTree(info.tree, {
|
|
97406
98311
|
dirs: [],
|
|
97407
98312
|
files: []
|
|
97408
98313
|
}, "");
|
|
97409
|
-
|
|
98314
|
+
list.dirs = [...new Set(list.dirs)];
|
|
98315
|
+
list.files = [...new Set(list.files)];
|
|
98316
|
+
const srcDir = Path.join(info.contentPath, "package");
|
|
98317
|
+
const cloneDir = this._reflink && this._cloneDirs && await loadReflinkCloneDir();
|
|
98318
|
+
if (cloneDir) {
|
|
98319
|
+
await ensurePrepared();
|
|
98320
|
+
if (await this._cloneWholeDir(cloneDir, srcDir, destDir)) return;
|
|
98321
|
+
}
|
|
98322
|
+
const reflinkCloneFiles = this._reflink && this._cloneFiles && await loadReflinkCloneFiles();
|
|
98323
|
+
const copy = this._copyFallback;
|
|
98324
|
+
const mkdirs = async () => {
|
|
98325
|
+
for (const dir of list.dirs) await file_ops_default.$.mkdirp(Path.join(destDir, dir));
|
|
98326
|
+
};
|
|
98327
|
+
if (reflinkCloneFiles) {
|
|
98328
|
+
await ensurePrepared();
|
|
98329
|
+
await mkdirs();
|
|
98330
|
+
const others = list.files.filter((f) => f !== "package.json");
|
|
98331
|
+
const [stats] = await Promise.all([reflinkCloneFiles(srcDir, destDir, others, this._hardlink, copy), others.length < list.files.length && reflinkCloneFiles(srcDir, destDir, ["package.json"], false, copy)]);
|
|
98332
|
+
if (this._cloneFiles && stats.cloned === 0 && stats.linked > 0) {
|
|
98333
|
+
this._cloneFiles = false;
|
|
98334
|
+
logger$1.debug(`fyn-central: can't clone files from ${this._centralDir}, hardlinking instead`);
|
|
98335
|
+
}
|
|
98336
|
+
return;
|
|
98337
|
+
}
|
|
98338
|
+
const pool = getFsWorkerPool();
|
|
98339
|
+
if (pool) {
|
|
98340
|
+
const { noLink, pkgJson } = await pool.run("place", {
|
|
98341
|
+
srcDir,
|
|
98342
|
+
destDir,
|
|
98343
|
+
dirs: list.dirs,
|
|
98344
|
+
files: list.files,
|
|
98345
|
+
hardlink: this._hardlink,
|
|
98346
|
+
reflink: this._reflink,
|
|
98347
|
+
copyFallback: copy,
|
|
98348
|
+
prepare: !prepared
|
|
98349
|
+
});
|
|
98350
|
+
if (noLink && this._hardlink) {
|
|
98351
|
+
this._hardlink = false;
|
|
98352
|
+
logger$1.info(`fyn-central: can't hardlink from ${this._centralDir} (${noLink}), copying instead`);
|
|
98353
|
+
}
|
|
98354
|
+
return pkgJson;
|
|
98355
|
+
}
|
|
98356
|
+
await ensurePrepared();
|
|
98357
|
+
await mkdirs();
|
|
97410
98358
|
await map$1(list.files, (file) => {
|
|
97411
98359
|
const src = Path.join(info.contentPath, "package", file);
|
|
97412
98360
|
const dest = Path.join(destDir, file);
|
|
97413
|
-
|
|
97414
|
-
|
|
98361
|
+
let placed;
|
|
98362
|
+
if (file === "package.json") placed = this._reflink && !copy ? cloneFile(src, dest, true) : copyFile(src, dest);
|
|
98363
|
+
else placed = this._hardlink ? this._linkFile(src, dest) : this._cloneOrCopy(src, dest);
|
|
98364
|
+
placing.push(placed);
|
|
98365
|
+
return placed;
|
|
97415
98366
|
}, { concurrency: 5 });
|
|
97416
98367
|
} catch (err) {
|
|
98368
|
+
await Promise.allSettled(placing);
|
|
97417
98369
|
const msg = `fyn-central can't replicate package at ${destDir} for integrity ${integrity}`;
|
|
97418
98370
|
throw new AggregateError$1([err], msg);
|
|
97419
98371
|
}
|
|
@@ -97435,68 +98387,118 @@ var FynCentral = class {
|
|
|
97435
98387
|
}
|
|
97436
98388
|
} else if (code !== "EMLINK") throw err;
|
|
97437
98389
|
}
|
|
97438
|
-
await
|
|
98390
|
+
await this._cloneOrCopy(src, dest);
|
|
98391
|
+
}
|
|
98392
|
+
/** Clone, else copy, as reflink and copyFallback allow. */
|
|
98393
|
+
async _cloneOrCopy(src, dest) {
|
|
98394
|
+
if (this._reflink) await cloneFile(src, dest, !this._copyFallback);
|
|
98395
|
+
else if (this._copyFallback) await copyFile(src, dest);
|
|
98396
|
+
else throw new Error(`fyn-central: can't place ${dest}: it can't be hardlinked, and reflink and copy-fallback are off`);
|
|
98397
|
+
}
|
|
98398
|
+
/**
|
|
98399
|
+
* Clone the store's package dir to `destDir` in one call. A dir clone needs a path that
|
|
98400
|
+
* doesn't exist, so it goes to a unique sibling that's then renamed over `destDir`. The
|
|
98401
|
+
* rename replaces `destDir` only while it's still the empty dir createPkgOutDir made. If
|
|
98402
|
+
* anything put files there meanwhile, the clone is dropped for the per-file path, which never
|
|
98403
|
+
* writes through an existing file. Resolves false, with `destDir` untouched, when not cloned.
|
|
98404
|
+
*/
|
|
98405
|
+
async _cloneWholeDir(cloneDir, srcDir, destDir) {
|
|
98406
|
+
const tmp = `${destDir}.clone-${uniqueSuffix()}`;
|
|
98407
|
+
if (!await cloneDir(srcDir, tmp)) {
|
|
98408
|
+
this._cloneDirs = false;
|
|
98409
|
+
logger$1.debug(`fyn-central: can't clone dirs from ${this._centralDir}, cloning files instead`);
|
|
98410
|
+
return false;
|
|
98411
|
+
}
|
|
98412
|
+
try {
|
|
98413
|
+
await file_ops_default.rename(tmp, destDir);
|
|
98414
|
+
return true;
|
|
98415
|
+
} catch (err) {
|
|
98416
|
+
await file_ops_default.$.rimraf(tmp);
|
|
98417
|
+
const code = err.code;
|
|
98418
|
+
if (code === "ENOTEMPTY" || code === "EEXIST") return false;
|
|
98419
|
+
throw err;
|
|
98420
|
+
}
|
|
97439
98421
|
}
|
|
98422
|
+
/** Extract a tarball and build its tree from the tar headers. */
|
|
97440
98423
|
_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
98424
|
const strip = 1;
|
|
98425
|
+
const { onentry, result } = treeCollector(strip);
|
|
97448
98426
|
const untarStream = So({
|
|
97449
98427
|
strip,
|
|
97450
98428
|
strict: true,
|
|
97451
98429
|
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
|
-
}
|
|
98430
|
+
onentry
|
|
97469
98431
|
});
|
|
97470
|
-
return missPipe(tarStream, untarStream).then(() =>
|
|
98432
|
+
return missPipe(tarStream, untarStream).then(() => result);
|
|
97471
98433
|
}
|
|
97472
|
-
|
|
97473
|
-
|
|
98434
|
+
/**
|
|
98435
|
+
* Claim the `.extracting` marker that tells other installs this one is writing the entry.
|
|
98436
|
+
* mkdir is atomic, so only one install gets it. A marker older than STALE_MS was left by an
|
|
98437
|
+
* install that died, so it is taken over.
|
|
98438
|
+
*
|
|
98439
|
+
* @returns true when this install owns the marker
|
|
98440
|
+
*/
|
|
98441
|
+
async _claimMarker(marker, retry = true) {
|
|
97474
98442
|
try {
|
|
97475
|
-
await file_ops_default
|
|
97476
|
-
|
|
97477
|
-
wait: 3e5,
|
|
97478
|
-
pollPeriod: 500,
|
|
97479
|
-
stale: 3e5
|
|
97480
|
-
});
|
|
98443
|
+
await file_ops_default.mkdir(marker);
|
|
98444
|
+
return true;
|
|
97481
98445
|
} catch (err) {
|
|
97482
|
-
|
|
97483
|
-
|
|
97484
|
-
|
|
98446
|
+
if (err.code !== "EEXIST") throw err;
|
|
98447
|
+
}
|
|
98448
|
+
const stat = await file_ops_default.stat(marker).catch(() => void 0);
|
|
98449
|
+
if (retry && (!stat || Date.now() - stat.mtimeMs > 3e5)) {
|
|
98450
|
+
await file_ops_default.$.rimraf(marker);
|
|
98451
|
+
return this._claimMarker(marker, false);
|
|
97485
98452
|
}
|
|
97486
|
-
return
|
|
98453
|
+
return false;
|
|
97487
98454
|
}
|
|
97488
|
-
|
|
98455
|
+
/** Remove temp and trash dirs that installs which died left next to the entry. */
|
|
98456
|
+
async _removeStaleTemps(contentPath) {
|
|
98457
|
+
const dir = Path.dirname(contentPath);
|
|
98458
|
+
const base = Path.basename(contentPath);
|
|
98459
|
+
for (const name of await file_ops_default.readdir(dir)) {
|
|
98460
|
+
if (!name.startsWith(`${base}.tmp`) && !name.startsWith(`${base}.del-`)) continue;
|
|
98461
|
+
const stat = await file_ops_default.stat(Path.join(dir, name)).catch(() => void 0);
|
|
98462
|
+
if (stat && Date.now() - stat.mtimeMs > 3e5) await file_ops_default.$.rimraf(Path.join(dir, name));
|
|
98463
|
+
}
|
|
98464
|
+
}
|
|
98465
|
+
/**
|
|
98466
|
+
* Extract into a temp dir only this call uses, then rename it into place. The rename is
|
|
98467
|
+
* atomic, so other installs see the entry complete or not at all. If another install renamed
|
|
98468
|
+
* its copy in first, that copy has the same integrity, so this one is dropped for it.
|
|
98469
|
+
*
|
|
98470
|
+
* With an fs worker, storeTarStream hands the whole job to _storeInWorker instead.
|
|
98471
|
+
*/
|
|
98472
|
+
async _storeTarStream(info, _stream) {
|
|
97489
98473
|
let stream = _stream;
|
|
97490
|
-
const tmp = `${info.contentPath}.tmp`;
|
|
97491
|
-
|
|
97492
|
-
|
|
97493
|
-
|
|
97494
|
-
|
|
97495
|
-
|
|
97496
|
-
|
|
97497
|
-
|
|
97498
|
-
|
|
97499
|
-
|
|
98474
|
+
const tmp = `${info.contentPath}.tmp-${uniqueSuffix()}`;
|
|
98475
|
+
try {
|
|
98476
|
+
const targetDir = Path.join(tmp, "package");
|
|
98477
|
+
await file_ops_default.$.mkdirp(targetDir);
|
|
98478
|
+
if (typeof stream === "function") stream = stream();
|
|
98479
|
+
if (stream.then) stream = await stream;
|
|
98480
|
+
const { tree, fromHeaders } = await this._untarStream(stream, targetDir);
|
|
98481
|
+
info.tree = tree;
|
|
98482
|
+
info.shaSum = fromHeaders ? this._treeShasum(tree) : (await this._scanShasums(targetDir))?.v2;
|
|
98483
|
+
info.sumVersion = 2;
|
|
98484
|
+
await this.saveInfoTree(info, tmp);
|
|
98485
|
+
try {
|
|
98486
|
+
await file_ops_default.rename(tmp, info.contentPath);
|
|
98487
|
+
} catch (err) {
|
|
98488
|
+
const code = err.code;
|
|
98489
|
+
if (![
|
|
98490
|
+
"ENOTEMPTY",
|
|
98491
|
+
"EEXIST",
|
|
98492
|
+
"EPERM"
|
|
98493
|
+
].includes(code) || !await file_ops_default.exists(info.contentPath)) throw err;
|
|
98494
|
+
logger$1.debug("fyn-central: another install stored it first", info.contentPath);
|
|
98495
|
+
await file_ops_default.$.rimraf(tmp);
|
|
98496
|
+
await this.readInfoTree(info);
|
|
98497
|
+
}
|
|
98498
|
+
} catch (err) {
|
|
98499
|
+
await file_ops_default.$.rimraf(tmp);
|
|
98500
|
+
throw err;
|
|
98501
|
+
}
|
|
97500
98502
|
info.exist = true;
|
|
97501
98503
|
}
|
|
97502
98504
|
/**
|
|
@@ -97509,45 +98511,99 @@ var FynCentral = class {
|
|
|
97509
98511
|
const info = this._map.get(integrity);
|
|
97510
98512
|
if (info === void 0 || !info.exist) return false;
|
|
97511
98513
|
if (info.validated === void 0) {
|
|
97512
|
-
const
|
|
97513
|
-
|
|
97514
|
-
|
|
97515
|
-
|
|
98514
|
+
const pkgDir = Path.join(info.contentPath, "package");
|
|
98515
|
+
const pool = getFsWorkerPool();
|
|
98516
|
+
const sums = pool ? await pool.run("scan", { dir: pkgDir }) : await this._scanShasums(pkgDir);
|
|
98517
|
+
if (info.sumVersion === 2) info.validated = Boolean(sums) && info.shaSum === sums.v2;
|
|
98518
|
+
else {
|
|
98519
|
+
info.validated = Boolean(sums) && (!info.shaSum || info.shaSum === sums.v1);
|
|
98520
|
+
if (info.validated) {
|
|
98521
|
+
info.shaSum = sums.v2;
|
|
98522
|
+
info.sumVersion = 2;
|
|
98523
|
+
await this.saveInfoTree(info);
|
|
98524
|
+
}
|
|
97516
98525
|
}
|
|
97517
|
-
info.validated = info.shaSum === sum;
|
|
97518
98526
|
}
|
|
97519
98527
|
return info.validated;
|
|
97520
98528
|
}
|
|
97521
|
-
|
|
97522
|
-
|
|
98529
|
+
/**
|
|
98530
|
+
* Store a package's tarball in the central store. Installs never wait on each other: each
|
|
98531
|
+
* extracts into its own temp dir and renames it into place.
|
|
98532
|
+
*
|
|
98533
|
+
* While extracting, an install holds the entry's `.extracting` marker. With `deferIfBusy`, a
|
|
98534
|
+
* live marker from another install returns false without reading the stream, so the caller
|
|
98535
|
+
* can do its other packages first and come back to this one.
|
|
98536
|
+
*
|
|
98537
|
+
* @param tarSource - resolves the tarball's file on disk or its bytes, when it has either, so
|
|
98538
|
+
* an fs worker can untar it instead of the stream
|
|
98539
|
+
* @returns false when deferred, true when the package is in the store
|
|
98540
|
+
*/
|
|
98541
|
+
async storeTarStream(pkgId, integrity, stream, deferIfBusy = false, tarSource) {
|
|
97523
98542
|
let currentStream = stream;
|
|
98543
|
+
let marker;
|
|
97524
98544
|
try {
|
|
97525
|
-
|
|
98545
|
+
const pool = tarSource && getFsWorkerPool();
|
|
98546
|
+
const source = pool && await tarSource();
|
|
98547
|
+
if (source) return await this._storeInWorker(pool, source, pkgId, integrity, deferIfBusy);
|
|
98548
|
+
const info = await this._loadTree(integrity);
|
|
97526
98549
|
if (info.exist) {
|
|
97527
98550
|
logger$1.debug("fyn-central storeTarStream: already exist", info.contentPath);
|
|
97528
98551
|
if (!info.tree) logger$1.error(`fyn-central exist package missing tree.json`);
|
|
97529
|
-
|
|
97530
|
-
tmpLock = await this._acquireTmpLock(info);
|
|
97531
|
-
info = await this._loadTree(integrity, info, true);
|
|
97532
|
-
if (info.exist) {
|
|
97533
|
-
logger$1.debug("fyn-central storeTarStream: found after lock acquired", info.contentPath);
|
|
97534
|
-
if (!info.tree) {
|
|
97535
|
-
const msg = `fyn-central content exist but no tree.json ${info.contentPath}`;
|
|
97536
|
-
logger$1.error(msg);
|
|
97537
|
-
throw new Error(msg);
|
|
97538
|
-
}
|
|
97539
|
-
} else {
|
|
97540
|
-
logger$1.debug("storing tar to central store", pkgId, integrity);
|
|
97541
|
-
await this._storeTarStream(info, integrity, currentStream);
|
|
97542
|
-
currentStream = void 0;
|
|
97543
|
-
this._map.set(integrity, info);
|
|
97544
|
-
logger$1.debug("fyn-central storeTarStream: stored", pkgId, info.contentPath);
|
|
97545
|
-
}
|
|
98552
|
+
return true;
|
|
97546
98553
|
}
|
|
98554
|
+
const entryDir = Path.dirname(info.contentPath);
|
|
98555
|
+
if (!this._madeDirs.has(entryDir)) {
|
|
98556
|
+
await file_ops_default.$.mkdirp(entryDir);
|
|
98557
|
+
this._madeDirs.add(entryDir);
|
|
98558
|
+
}
|
|
98559
|
+
const markerPath = `${info.contentPath}.extracting`;
|
|
98560
|
+
if (await this._claimMarker(markerPath)) {
|
|
98561
|
+
marker = markerPath;
|
|
98562
|
+
if ((await this._loadTree(integrity, info)).exist) return true;
|
|
98563
|
+
await this._removeStaleTemps(info.contentPath);
|
|
98564
|
+
} else if (deferIfBusy) {
|
|
98565
|
+
logger$1.debug("fyn-central: another install is storing it, deferring", pkgId);
|
|
98566
|
+
return false;
|
|
98567
|
+
}
|
|
98568
|
+
if (await file_ops_default.exists(info.contentPath)) await this._removeBrokenEntry(info.contentPath);
|
|
98569
|
+
logger$1.debug("storing tar to central store", pkgId, integrity);
|
|
98570
|
+
await this._storeTarStream(info, currentStream);
|
|
98571
|
+
currentStream = void 0;
|
|
98572
|
+
this._map.set(integrity, info);
|
|
98573
|
+
this._missing.delete(integrity);
|
|
98574
|
+
logger$1.debug("fyn-central storeTarStream: stored", pkgId, info.contentPath);
|
|
98575
|
+
return true;
|
|
97547
98576
|
} finally {
|
|
97548
98577
|
if (currentStream && currentStream.destroy !== void 0) currentStream.destroy();
|
|
97549
|
-
if (
|
|
98578
|
+
if (marker) await file_ops_default.rmdir(marker).catch(() => void 0);
|
|
98579
|
+
}
|
|
98580
|
+
}
|
|
98581
|
+
/** storeTarStream's steps, run by an fs worker with sync calls, marker and all */
|
|
98582
|
+
async _storeInWorker(pool, source, pkgId, integrity, deferIfBusy) {
|
|
98583
|
+
const info = this._map.get(integrity) ?? this._missing.get(integrity) ?? this._analyze(integrity);
|
|
98584
|
+
const result = await pool.run("store", {
|
|
98585
|
+
...source,
|
|
98586
|
+
integrity,
|
|
98587
|
+
contentPath: info.contentPath,
|
|
98588
|
+
deferIfBusy
|
|
98589
|
+
});
|
|
98590
|
+
if (result.busy) {
|
|
98591
|
+
logger$1.debug("fyn-central: another install is storing it, deferring", pkgId);
|
|
98592
|
+
return false;
|
|
98593
|
+
}
|
|
98594
|
+
if (result.stored) {
|
|
98595
|
+
info.tree = result.tree;
|
|
98596
|
+
info.shaSum = result.stored.shaSum;
|
|
98597
|
+
info.sumVersion = result.stored.sumVersion;
|
|
98598
|
+
info.exist = true;
|
|
98599
|
+
this._map.set(integrity, info);
|
|
98600
|
+
this._missing.delete(integrity);
|
|
98601
|
+
logger$1.debug("fyn-central storeTarStream: stored", pkgId, info.contentPath);
|
|
98602
|
+
} else {
|
|
98603
|
+
logger$1.debug("fyn-central: the entry is in place already", info.contentPath);
|
|
98604
|
+
if (!(await this._loadTree(integrity, info)).tree) logger$1.error(`fyn-central exist package missing tree.json`);
|
|
97550
98605
|
}
|
|
98606
|
+
return true;
|
|
97551
98607
|
}
|
|
97552
98608
|
};
|
|
97553
98609
|
|
|
@@ -99499,19 +100555,10 @@ function applyChalkMethod(chalkInstance, name, values) {
|
|
|
99499
100555
|
throw new TypeError(`${name} is not a chalk function`);
|
|
99500
100556
|
}
|
|
99501
100557
|
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;
|
|
100558
|
+
return str.replace(/&(?:#[xX]([0-9a-fA-F]+)|#([0-9]+)|\w+);/g, (m, hex, dec) => {
|
|
100559
|
+
if (hex === void 0 && dec === void 0) return Object.prototype.hasOwnProperty.call(htmlEntities, m) ? htmlEntities[m] : m;
|
|
100560
|
+
const p = hex !== void 0 ? parseInt(hex, 16) : parseInt(dec, 10);
|
|
100561
|
+
return p <= 1114111 ? String.fromCodePoint(p) : m;
|
|
99515
100562
|
});
|
|
99516
100563
|
}
|
|
99517
100564
|
function applyChalkMarkers(markers, text, userChalk) {
|
|
@@ -99553,18 +100600,19 @@ function applyChalkMarkers(markers, text, userChalk) {
|
|
|
99553
100600
|
co(typeof chalkify === "function", `final chalk value is not a function after applying ${markers}`);
|
|
99554
100601
|
return chalkify(text);
|
|
99555
100602
|
}
|
|
100603
|
+
const MARKERS_RE = /<[^>]*>/g;
|
|
99556
100604
|
function remove(s, keepHtml) {
|
|
99557
|
-
const r = s.replace(
|
|
100605
|
+
const r = s.replace(MARKERS_RE, "");
|
|
99558
100606
|
return keepHtml ? r : decodeHtml(r);
|
|
99559
100607
|
}
|
|
99560
100608
|
function format$1(s, instance, userChalk) {
|
|
99561
100609
|
userChalk = normalizeColors(userChalk || instance.CHALK);
|
|
99562
|
-
|
|
99563
|
-
const tks = s && s.match(
|
|
100610
|
+
const off = userChalk.supportsColor === false;
|
|
100611
|
+
const tks = s && s.match(/<[^<>]+>|[^<>]+|[<>]/g);
|
|
99564
100612
|
if (!tks) return s || "";
|
|
99565
|
-
|
|
100613
|
+
const colorized = tks.reduceRight((a, e, ix) => {
|
|
99566
100614
|
const lvl = a[a.length - 1];
|
|
99567
|
-
if (e[0] !== "<") {
|
|
100615
|
+
if (e[0] !== "<" || e.length === 1) {
|
|
99568
100616
|
lvl.s = e + lvl.s;
|
|
99569
100617
|
return a;
|
|
99570
100618
|
}
|
|
@@ -99577,20 +100625,27 @@ function format$1(s, instance, userChalk) {
|
|
|
99577
100625
|
return a;
|
|
99578
100626
|
}
|
|
99579
100627
|
if (a.length === 1) {
|
|
100628
|
+
if (off) return a;
|
|
99580
100629
|
const partial = tks.slice(0, ix).join("") + `[${tks[ix]}]` + (tks.length > ix + 1 ? "..." : "");
|
|
99581
100630
|
throw new Error(`unbalanced open/close markers: ${partial}`);
|
|
99582
100631
|
}
|
|
99583
100632
|
const mk = e.substring(1, e.length - 1);
|
|
99584
|
-
if (lvl.mk && mk !== lvl.mk) {
|
|
100633
|
+
if (lvl.mk && mk !== lvl.mk && !off) {
|
|
99585
100634
|
const partial = tks.slice(0, ix).join("") + `[** ${tks[ix]} **]` + tks.slice(ix + 1, lvl.ix).join("") + `[** ${tks[lvl.ix]} **]`;
|
|
99586
100635
|
throw new Error(`mismatch markers: ${partial}`);
|
|
99587
100636
|
}
|
|
99588
|
-
const t = applyChalkMarkers(mk, lvl.s, userChalk);
|
|
100637
|
+
const t = off ? lvl.s : applyChalkMarkers(mk, lvl.s, userChalk);
|
|
99589
100638
|
a.pop();
|
|
99590
100639
|
const nl = a.length - 1;
|
|
99591
100640
|
a[nl].s = t + a[nl].s;
|
|
99592
100641
|
return a;
|
|
99593
|
-
}, [{ s: "" }])
|
|
100642
|
+
}, [{ s: "" }]);
|
|
100643
|
+
while (colorized.length > 1) {
|
|
100644
|
+
const lvl = colorized.pop();
|
|
100645
|
+
const nl = colorized.length - 1;
|
|
100646
|
+
colorized[nl].s = lvl.s + tks[lvl.ix] + colorized[nl].s;
|
|
100647
|
+
}
|
|
100648
|
+
return decodeHtml(colorized[0].s);
|
|
99594
100649
|
}
|
|
99595
100650
|
/**
|
|
99596
100651
|
* Build a chalker bound to a specific colors module.
|
|
@@ -101659,6 +102714,25 @@ async function syncLocalExports(options) {
|
|
|
101659
102714
|
const createLock$1 = Util.promisify(import_lockfile.lock);
|
|
101660
102715
|
const unlock$1 = Util.promisify(import_lockfile.unlock);
|
|
101661
102716
|
const { posixify } = fyntil;
|
|
102717
|
+
/** FYN_SHORT_PKG_DIR is on only for "1" or "true" (any case); any other value is off. */
|
|
102718
|
+
function shortPkgDirFromEnv() {
|
|
102719
|
+
const v = (process.env.FYN_SHORT_PKG_DIR || "").toLowerCase();
|
|
102720
|
+
return v === "1" || v === "true";
|
|
102721
|
+
}
|
|
102722
|
+
/**
|
|
102723
|
+
* Whether an install lock was left by a process on this host that no longer runs. A lock
|
|
102724
|
+
* without an owner, from an older fyn, is left to lockfile's stale time.
|
|
102725
|
+
*/
|
|
102726
|
+
async function installLockOwnerGone(fname) {
|
|
102727
|
+
try {
|
|
102728
|
+
const { pid, host } = JSON.parse(await file_ops_default.readFile(fname, "utf8"));
|
|
102729
|
+
if (host !== os$1.hostname() || !Number.isInteger(pid)) return false;
|
|
102730
|
+
process.kill(pid, 0);
|
|
102731
|
+
return false;
|
|
102732
|
+
} catch (err) {
|
|
102733
|
+
return err.code === "ESRCH";
|
|
102734
|
+
}
|
|
102735
|
+
}
|
|
101662
102736
|
var Fyn = class Fyn {
|
|
101663
102737
|
_cliSource;
|
|
101664
102738
|
_shownMissingFiles;
|
|
@@ -101726,7 +102800,7 @@ var Fyn = class Fyn {
|
|
|
101726
102800
|
logger$1.info("dep lock time set to", this._lockTime.toString());
|
|
101727
102801
|
}
|
|
101728
102802
|
this._installConfig = { time: 0 };
|
|
101729
|
-
this._shortPkgDir =
|
|
102803
|
+
this._shortPkgDir = shortPkgDirFromEnv();
|
|
101730
102804
|
if (!_fynpo) this._fynpo = {};
|
|
101731
102805
|
else if (typeof _fynpo === "object") this._fynpo = _fynpo;
|
|
101732
102806
|
}
|
|
@@ -101809,8 +102883,11 @@ var Fyn = class Fyn {
|
|
|
101809
102883
|
} else if (options.centralStore) {
|
|
101810
102884
|
centralDir = Path.join(this.fynDir, "_central-storage");
|
|
101811
102885
|
logger$1.debug(`Enabling central store by CLI flag using dir ${centralDir}`);
|
|
101812
|
-
} else if (!this._fynpo?.config)
|
|
101813
|
-
|
|
102886
|
+
} else if (!this._fynpo?.config) {
|
|
102887
|
+
if (!await this._defaultCentralStore()) return this._central = false;
|
|
102888
|
+
centralDir = Path.join(this.fynDir, "_central-storage");
|
|
102889
|
+
logger$1.debug(`Enabling central store by default using dir ${centralDir}`);
|
|
102890
|
+
} else {
|
|
101814
102891
|
centralDir = this._fynpo.config.centralDir;
|
|
101815
102892
|
if (!centralDir) {
|
|
101816
102893
|
const storeBaseDir = await fyntil.resolveGitMainWorktreeDir(this._fynpo.dir);
|
|
@@ -101827,15 +102904,31 @@ var Fyn = class Fyn {
|
|
|
101827
102904
|
}
|
|
101828
102905
|
return this._central = new FynCentral({
|
|
101829
102906
|
centralDir,
|
|
101830
|
-
hardlink: this.hardlink
|
|
102907
|
+
hardlink: this.hardlink,
|
|
102908
|
+
reflink: this.reflink,
|
|
102909
|
+
copyFallback: this.copyFallback
|
|
101831
102910
|
});
|
|
101832
102911
|
}
|
|
101833
102912
|
/**
|
|
101834
|
-
*
|
|
101835
|
-
*
|
|
102913
|
+
* A new install uses the central store on macOS when @fynjs/reflink can clone dirs, and on
|
|
102914
|
+
* Linux when it can hardlink or clone, since warm installs then run 2-3x faster than copying.
|
|
102915
|
+
* Files are cloned where possible, else hardlinked, else copied. A .fyn.json that saved
|
|
102916
|
+
* centralDir false keeps copying, and --no-central-store opts out.
|
|
102917
|
+
*/
|
|
102918
|
+
async _defaultCentralStore() {
|
|
102919
|
+
if (this._options.centralStore !== void 0 || this._installConfig.centralDir !== void 0) return false;
|
|
102920
|
+
if (process.platform === "darwin") return this.reflink && Boolean(await loadReflinkCloneDir());
|
|
102921
|
+
if (process.platform === "linux") return this.hardlink || this.reflink && Boolean(await loadReflinkCloneFiles());
|
|
102922
|
+
return false;
|
|
102923
|
+
}
|
|
102924
|
+
/**
|
|
102925
|
+
* The central store only pays off when node_modules links or clones from it. Copying out of
|
|
102926
|
+
* it writes every file twice, so it's skipped when neither is known to be possible.
|
|
101836
102927
|
*/
|
|
101837
102928
|
async _centralCopyOnlyReason(centralDir) {
|
|
101838
|
-
if (!this.
|
|
102929
|
+
if (!this.copyFallback) return;
|
|
102930
|
+
if (!this.hardlink && !this.reflink) return "hardlink and reflink are off";
|
|
102931
|
+
if (!this.hardlink && ["darwin", "win32"].includes(process.platform) && !await loadReflinkCloneFiles()) return "hardlink is off and @fynjs/reflink isn't loaded";
|
|
101839
102932
|
const deviceOf = async (dir) => {
|
|
101840
102933
|
for (;;) try {
|
|
101841
102934
|
return (await file_ops_default.stat(dir)).dev;
|
|
@@ -102425,9 +103518,6 @@ var Fyn = class Fyn {
|
|
|
102425
103518
|
get refreshOptionals() {
|
|
102426
103519
|
return this._options.refreshOptionals;
|
|
102427
103520
|
}
|
|
102428
|
-
get ignoreDist() {
|
|
102429
|
-
return this._options.ignoreDist;
|
|
102430
|
-
}
|
|
102431
103521
|
get production() {
|
|
102432
103522
|
return this._options.production;
|
|
102433
103523
|
}
|
|
@@ -102441,9 +103531,20 @@ var Fyn = class Fyn {
|
|
|
102441
103531
|
if (process.env.FYN_HARDLINK !== void 0) return fyntil.strToBool(process.env.FYN_HARDLINK);
|
|
102442
103532
|
return this._installConfig.hardlink !== false;
|
|
102443
103533
|
}
|
|
103534
|
+
/** --no-reflink never clones store files into node_modules, so @fynjs/reflink isn't used */
|
|
103535
|
+
get reflink() {
|
|
103536
|
+
return this._options.reflink !== false;
|
|
103537
|
+
}
|
|
103538
|
+
/** --no-copy-fallback fails the install on a store file that can't be cloned or hardlinked */
|
|
103539
|
+
get copyFallback() {
|
|
103540
|
+
return this._options.copyFallback !== false;
|
|
103541
|
+
}
|
|
102444
103542
|
get concurrency() {
|
|
102445
103543
|
return this._options.concurrency;
|
|
102446
103544
|
}
|
|
103545
|
+
get extractConcurrency() {
|
|
103546
|
+
return this._options.extractConcurrency;
|
|
103547
|
+
}
|
|
102447
103548
|
get deepResolve() {
|
|
102448
103549
|
return this._options.deepResolve;
|
|
102449
103550
|
}
|
|
@@ -102574,10 +103675,18 @@ var Fyn = class Fyn {
|
|
|
102574
103675
|
async createInstallLock() {
|
|
102575
103676
|
await this.createDir(this.getFvDir());
|
|
102576
103677
|
const fname = this.getFvDir(".installing.lock");
|
|
103678
|
+
if (await installLockOwnerGone(fname)) {
|
|
103679
|
+
logger$1.debug(`taking over ${fname}, its install process is gone`);
|
|
103680
|
+
await file_ops_default.unlink(fname).catch(() => void 0);
|
|
103681
|
+
}
|
|
102577
103682
|
await createLock$1(fname, {
|
|
102578
103683
|
wait: 3e3,
|
|
102579
103684
|
stale: 18e5
|
|
102580
103685
|
});
|
|
103686
|
+
await file_ops_default.writeFile(fname, JSON.stringify({
|
|
103687
|
+
pid: process.pid,
|
|
103688
|
+
host: os$1.hostname()
|
|
103689
|
+
}));
|
|
102581
103690
|
return true;
|
|
102582
103691
|
}
|
|
102583
103692
|
/**
|
|
@@ -102706,9 +103815,10 @@ var Fyn = class Fyn {
|
|
|
102706
103815
|
}
|
|
102707
103816
|
return null;
|
|
102708
103817
|
}
|
|
102709
|
-
|
|
103818
|
+
/** @param placed - package.json as an fs worker placed it, so it isn't read back */
|
|
103819
|
+
async loadJsonForPkg(pkg, dir, placed) {
|
|
102710
103820
|
const fullOutDir = dir || this.getInstalledPkgDir(pkg.name, pkg.version, pkg);
|
|
102711
|
-
const json = await fyntil.readPkgJson(fullOutDir, true);
|
|
103821
|
+
const json = await fyntil.readPkgJson(fullOutDir, true, false, placed?.str);
|
|
102712
103822
|
const pkgId = `${pkg.name}@${pkg.version}`;
|
|
102713
103823
|
const id = `${json.name}@${json.version}`;
|
|
102714
103824
|
if (json.version !== pkg.version) {
|
|
@@ -102732,13 +103842,11 @@ var Fyn = class Fyn {
|
|
|
102732
103842
|
}
|
|
102733
103843
|
pkg.dir = json[PACKAGE_RAW_INFO].dir;
|
|
102734
103844
|
pkg.str = json[PACKAGE_RAW_INFO].str;
|
|
102735
|
-
|
|
102736
|
-
const gypFile = Path.join(fullOutDir, "binding.gyp");
|
|
102737
|
-
await file_ops_default.lstat(gypFile);
|
|
103845
|
+
if (placed?.gyp ?? await file_ops_default.lstat(Path.join(fullOutDir, "binding.gyp")).then(() => true, () => false)) {
|
|
102738
103846
|
json.gypfile = true;
|
|
102739
103847
|
const scr = json.scripts;
|
|
102740
103848
|
if (isEmpty(scr) || !scr.install && !scr.postinstall && !scr.postInstall) set(json, "scripts.install", "node-gyp rebuild");
|
|
102741
|
-
}
|
|
103849
|
+
}
|
|
102742
103850
|
pkg.json = json;
|
|
102743
103851
|
return json;
|
|
102744
103852
|
}
|
|
@@ -104950,7 +106058,8 @@ var PkgOutdatedProvider = class {
|
|
|
104950
106058
|
if (failed) throw failed.reason;
|
|
104951
106059
|
return {
|
|
104952
106060
|
records: settled.map((result) => result.status === "fulfilled" ? result.value : void 0).filter((record) => Boolean(record)),
|
|
104953
|
-
skipped: skipped.sort()
|
|
106061
|
+
skipped: skipped.sort(),
|
|
106062
|
+
checked: selected.length - skipped.length
|
|
104954
106063
|
};
|
|
104955
106064
|
}
|
|
104956
106065
|
};
|
|
@@ -104997,6 +106106,7 @@ const showOutdated = async (fyn, options = {}) => {
|
|
|
104997
106106
|
if (output) await new Promise((resolve, reject) => {
|
|
104998
106107
|
process.stdout.write(`${output}\n`, (error) => error ? reject(error) : resolve());
|
|
104999
106108
|
});
|
|
106109
|
+
else if (!options.json) logger$1.info(result.checked === 1 ? "The only direct dependency is up to date" : result.checked > 1 ? `All ${result.checked} direct dependencies are up to date` : "No registry dependencies to check");
|
|
105000
106110
|
if (!options.json && options.packages?.length) for (const name of result.skipped) logger$1.info(`Skipping non-registry dependency ${chalk.cyan(name)}`);
|
|
105001
106111
|
return result;
|
|
105002
106112
|
};
|
|
@@ -105006,13 +106116,15 @@ const showOutdated = async (fyn, options = {}) => {
|
|
|
105006
106116
|
/**
|
|
105007
106117
|
* Audit cache utilities for storing/retrieving npm security advisory data.
|
|
105008
106118
|
*
|
|
105009
|
-
*
|
|
105010
|
-
*
|
|
106119
|
+
* New advisories get published against versions that already exist, and a pinned lockfile
|
|
106120
|
+
* keeps the same cache key for a long time. So entries expire after AUDIT_CACHE_TTL.
|
|
105011
106121
|
*
|
|
105012
106122
|
* Cache key is generated from SHA256 hash of the sorted bulk request payload,
|
|
105013
106123
|
* ensuring different dependency sets get different cache entries.
|
|
105014
106124
|
*/
|
|
105015
106125
|
const AUDIT_CACHE_PREFIX = "fyn-audit-";
|
|
106126
|
+
/** How long a cached audit result stays fresh, in ms. */
|
|
106127
|
+
const AUDIT_CACHE_TTL = 18e5;
|
|
105016
106128
|
/**
|
|
105017
106129
|
* Generate a deterministic cache key from the bulk request payload.
|
|
105018
106130
|
* Sorts package names and versions to ensure same dependencies = same key.
|
|
@@ -105036,12 +106148,17 @@ async function cacheAuditResult(cacheDir, key, result) {
|
|
|
105036
106148
|
}
|
|
105037
106149
|
/**
|
|
105038
106150
|
* Retrieve cached audit result.
|
|
105039
|
-
* Returns null if not found (
|
|
106151
|
+
* Returns null if not found, or if `maxAge` (ms) is given and the entry is older than that.
|
|
105040
106152
|
*/
|
|
105041
|
-
async function getCachedAuditResult(cacheDir, key) {
|
|
106153
|
+
async function getCachedAuditResult(cacheDir, key, maxAge) {
|
|
105042
106154
|
const auditCacheDir = Path.join(cacheDir, "audit");
|
|
106155
|
+
const cacache = await loadCacache();
|
|
105043
106156
|
try {
|
|
105044
|
-
|
|
106157
|
+
if (maxAge !== void 0) {
|
|
106158
|
+
const info = await cacache.get.info(auditCacheDir, key);
|
|
106159
|
+
if (!info || Date.now() - info.time > maxAge) return null;
|
|
106160
|
+
}
|
|
106161
|
+
const { data } = await cacache.get(auditCacheDir, key);
|
|
105045
106162
|
return JSON.parse(data.toString());
|
|
105046
106163
|
} catch (err) {
|
|
105047
106164
|
const code = err.code;
|
|
@@ -105057,7 +106174,7 @@ async function getCachedAuditResult(cacheDir, key) {
|
|
|
105057
106174
|
*
|
|
105058
106175
|
* Workflow:
|
|
105059
106176
|
* 1. Build bulk payload from resolved DepData.pkgs
|
|
105060
|
-
* 2. Check cache for
|
|
106177
|
+
* 2. Check cache for advisories fetched within AUDIT_CACHE_TTL
|
|
105061
106178
|
* 3. If miss, POST to /-/npm/v1/security/advisories/bulk
|
|
105062
106179
|
* 4. Cache response and return
|
|
105063
106180
|
*/
|
|
@@ -105166,7 +106283,7 @@ var AuditReport = class {
|
|
|
105166
106283
|
}
|
|
105167
106284
|
const cacheKey = generateCacheKey(payload);
|
|
105168
106285
|
if (!this._noCache) {
|
|
105169
|
-
const cached = await getCachedAuditResult(this._cacheDir, cacheKey);
|
|
106286
|
+
const cached = await getCachedAuditResult(this._cacheDir, cacheKey, AUDIT_CACHE_TTL);
|
|
105170
106287
|
if (cached) {
|
|
105171
106288
|
logger$1.debug("Using cached audit result");
|
|
105172
106289
|
return cached;
|
|
@@ -105306,6 +106423,12 @@ var AuditFormatter = class {
|
|
|
105306
106423
|
return this.getSeverityLevel(severity) >= this.getSeverityLevel(this._auditLevel);
|
|
105307
106424
|
}
|
|
105308
106425
|
/**
|
|
106426
|
+
* Exit code like npm audit: 1 when any vulnerability meets the audit level.
|
|
106427
|
+
*/
|
|
106428
|
+
exitCodeFor(filtered) {
|
|
106429
|
+
return filtered.length > 0 ? 1 : 0;
|
|
106430
|
+
}
|
|
106431
|
+
/**
|
|
105309
106432
|
* Colorize text based on severity.
|
|
105310
106433
|
*/
|
|
105311
106434
|
colorize(text, severity) {
|
|
@@ -105343,7 +106466,7 @@ var AuditFormatter = class {
|
|
|
105343
106466
|
const total = filtered.length;
|
|
105344
106467
|
return {
|
|
105345
106468
|
output: `audited ${pkgCount} packages\n\n${total} ${total === 1 ? "vulnerability" : "vulnerabilities"} (${parts.join(", ")})\n\nRun \`fyn audit\` for details.`,
|
|
105346
|
-
exitCode:
|
|
106469
|
+
exitCode: 1
|
|
105347
106470
|
};
|
|
105348
106471
|
}
|
|
105349
106472
|
/**
|
|
@@ -105357,7 +106480,7 @@ var AuditFormatter = class {
|
|
|
105357
106480
|
metadata: auditResult.metadata,
|
|
105358
106481
|
advisories: auditResult.advisories
|
|
105359
106482
|
}, null, 2),
|
|
105360
|
-
exitCode:
|
|
106483
|
+
exitCode: this.exitCodeFor(filtered)
|
|
105361
106484
|
};
|
|
105362
106485
|
}
|
|
105363
106486
|
/**
|
|
@@ -105404,7 +106527,7 @@ var AuditFormatter = class {
|
|
|
105404
106527
|
lines.push("");
|
|
105405
106528
|
return {
|
|
105406
106529
|
output: lines.join("\n"),
|
|
105407
|
-
exitCode:
|
|
106530
|
+
exitCode: this.exitCodeFor(filtered)
|
|
105408
106531
|
};
|
|
105409
106532
|
}
|
|
105410
106533
|
/**
|
|
@@ -105481,6 +106604,9 @@ var ShowAudit = class {
|
|
|
105481
106604
|
}
|
|
105482
106605
|
/**
|
|
105483
106606
|
* Run the audit workflow.
|
|
106607
|
+
*
|
|
106608
|
+
* @returns exit code like npm audit: 1 if a vulnerability meets the audit level
|
|
106609
|
+
* or the audit fails, else 0. Errors are logged, not thrown.
|
|
105484
106610
|
*/
|
|
105485
106611
|
async runAudit() {
|
|
105486
106612
|
const spinner = cli_logger_default.spinners[1];
|
|
@@ -105499,7 +106625,7 @@ var ShowAudit = class {
|
|
|
105499
106625
|
}
|
|
105500
106626
|
if (Object.keys(depData.pkgs).length === 0) {
|
|
105501
106627
|
logger$1.info("No dependencies to audit");
|
|
105502
|
-
return;
|
|
106628
|
+
return 0;
|
|
105503
106629
|
}
|
|
105504
106630
|
logger$1.addItem({
|
|
105505
106631
|
name: FETCH_META,
|
|
@@ -105529,7 +106655,7 @@ var ShowAudit = class {
|
|
|
105529
106655
|
statProvider
|
|
105530
106656
|
});
|
|
105531
106657
|
if (statProvider) await formatter.precomputeStats(vulnerabilities);
|
|
105532
|
-
const { output } = formatter.format(auditResult, vulnerabilities);
|
|
106658
|
+
const { output, exitCode } = formatter.format(auditResult, vulnerabilities);
|
|
105533
106659
|
if (output) console.log(output);
|
|
105534
106660
|
if (this._opts.auditFile) {
|
|
105535
106661
|
const { output: jsonOutput } = new AuditFormatter({
|
|
@@ -105541,10 +106667,12 @@ var ShowAudit = class {
|
|
|
105541
106667
|
const targetPath = Path.isAbsolute(this._opts.auditFile) ? this._opts.auditFile : Path.join(baseDir, this._opts.auditFile);
|
|
105542
106668
|
await fs.promises.writeFile(targetPath, jsonOutput, "utf8");
|
|
105543
106669
|
}
|
|
106670
|
+
return exitCode;
|
|
105544
106671
|
} catch (err) {
|
|
105545
106672
|
logger$1.removeItem(FETCH_META);
|
|
105546
106673
|
logger$1.error("Audit failed:", err.message);
|
|
105547
106674
|
if (process.env.FYN_DEBUG) logger$1.error(err.stack);
|
|
106675
|
+
return 1;
|
|
105548
106676
|
}
|
|
105549
106677
|
}
|
|
105550
106678
|
};
|
|
@@ -105558,6 +106686,28 @@ const showAudit = (fyn, opts) => {
|
|
|
105558
106686
|
}).runAudit();
|
|
105559
106687
|
};
|
|
105560
106688
|
|
|
106689
|
+
//#endregion
|
|
106690
|
+
//#region cli/show-updates.ts
|
|
106691
|
+
/**
|
|
106692
|
+
* Lines of `name old -> new` for every package whose locked versions changed
|
|
106693
|
+
*/
|
|
106694
|
+
const formatUpdates = (before, after) => {
|
|
106695
|
+
const names = [.../* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)])].sort();
|
|
106696
|
+
const lines = [];
|
|
106697
|
+
for (const name of names) {
|
|
106698
|
+
const oldVersions = (before[name] || []).join(", ");
|
|
106699
|
+
const newVersions = (after[name] || []).join(", ");
|
|
106700
|
+
if (oldVersions === newVersions) continue;
|
|
106701
|
+
lines.push(`${chalk.cyan(name)} ${chalk.red(oldVersions || "(none)")} -> ${chalk.green(newVersions || "(removed)")}`);
|
|
106702
|
+
}
|
|
106703
|
+
return lines;
|
|
106704
|
+
};
|
|
106705
|
+
const showUpdates = (before, after) => {
|
|
106706
|
+
const lines = formatUpdates(before, after);
|
|
106707
|
+
if (lines.length === 0) logger$1.info("All locked versions are already the newest their ranges allow");
|
|
106708
|
+
else logger$1.info(`Updated ${lines.length} packages:\n ${lines.join("\n ")}`);
|
|
106709
|
+
};
|
|
106710
|
+
|
|
105561
106711
|
//#endregion
|
|
105562
106712
|
//#region node_modules/.f/_/ini/4.1.1/node_modules/ini/lib/ini.js
|
|
105563
106713
|
var require_ini = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
@@ -105845,7 +106995,7 @@ async function fetchDistTags2(baseUrl, _authToken, options) {
|
|
|
105845
106995
|
try {
|
|
105846
106996
|
return (await options.fetchJSON(pkUrl.toString(), { headers }))["dist-tags"];
|
|
105847
106997
|
} catch (_a) {
|
|
105848
|
-
return
|
|
106998
|
+
return;
|
|
105849
106999
|
}
|
|
105850
107000
|
}
|
|
105851
107001
|
/**
|
|
@@ -105859,7 +107009,7 @@ async function fetchDistTags2(baseUrl, _authToken, options) {
|
|
|
105859
107009
|
function getNpmRegistryInfo(npmConfig, pkg) {
|
|
105860
107010
|
const pkgNames = pkg.name.split("/");
|
|
105861
107011
|
const scope = pkgNames.length > 1 ? pkgNames[0] : "";
|
|
105862
|
-
const regKey = Object.keys(npmConfig).find((k) => k.endsWith("registry") &&
|
|
107012
|
+
const regKey = scope && Object.keys(npmConfig).find((k) => k.endsWith("registry") && k.startsWith(scope));
|
|
105863
107013
|
const registry = regKey && npmConfig[regKey] || npmConfig.registry || "https://registry.npmjs.org/";
|
|
105864
107014
|
const regHost = `//${new URL(registry).host}/`;
|
|
105865
107015
|
const authKey = Object.keys(npmConfig).find((k) => k.endsWith("_authToken") && k.startsWith(regHost));
|
|
@@ -105920,6 +107070,7 @@ async function _internalCheck(options) {
|
|
|
105920
107070
|
}));
|
|
105921
107071
|
};
|
|
105922
107072
|
if (shouldFetch) {
|
|
107073
|
+
if (!distTags || typeof distTags !== "object") return false;
|
|
105923
107074
|
let notifiedVersion = typeof existMeta.notifiedVersion === "string" ? existMeta.notifiedVersion : "";
|
|
105924
107075
|
let notifiedTime = existMeta.notifiedTime || 0;
|
|
105925
107076
|
const checked = options.checkIsNewer(pkg, distTags, tag);
|
|
@@ -107097,6 +108248,20 @@ var FynCli = class {
|
|
|
107097
108248
|
const start = Date.now();
|
|
107098
108249
|
const runAudit = argv.opts?.audit !== false;
|
|
107099
108250
|
const auditFile = argv.opts?.auditFile;
|
|
108251
|
+
const update = argv.opts?.update;
|
|
108252
|
+
let lockedBefore;
|
|
108253
|
+
const auditAfterInstall = async () => {
|
|
108254
|
+
if (!runAudit) return;
|
|
108255
|
+
try {
|
|
108256
|
+
await showAudit(this.fyn, {
|
|
108257
|
+
colors: this.fyn._options.colors !== false,
|
|
108258
|
+
summary: true,
|
|
108259
|
+
auditFile
|
|
108260
|
+
});
|
|
108261
|
+
} catch (err) {
|
|
108262
|
+
logger$1.warn("Security audit failed:", err.message);
|
|
108263
|
+
}
|
|
108264
|
+
};
|
|
107100
108265
|
return dist_default.try(() => this.fyn._initializePkg()).then(async () => {
|
|
107101
108266
|
checkNewVersion(this.fyn._options);
|
|
107102
108267
|
if (!this.fyn._changeProdMode && !this.fyn._options.forceInstall && this.fyn._installConfig.fynlocal === Boolean(this.fyn.fynlocal) && this.fyn._installConfig.time) {
|
|
@@ -107111,6 +108276,7 @@ var FynCli = class {
|
|
|
107111
108276
|
}
|
|
107112
108277
|
installLocked = await this.fyn.createInstallLock();
|
|
107113
108278
|
await this.fyn.readLockFiles();
|
|
108279
|
+
if (update) lockedBefore = this.unlockForUpdate(update);
|
|
107114
108280
|
await this.fyn._startInstall();
|
|
107115
108281
|
const pkg = this.fyn._pkg;
|
|
107116
108282
|
if (get$1(pkg, "scripts.preinstall")) {
|
|
@@ -107211,19 +108377,14 @@ var FynCli = class {
|
|
|
107211
108377
|
const end = Date.now();
|
|
107212
108378
|
await this.fyn.saveFynpoIndirects();
|
|
107213
108379
|
logger$1.info(chalk.green("complete in total"), chalk.magenta(`${(end - start) / 1e3}`) + "secs");
|
|
107214
|
-
if (
|
|
107215
|
-
|
|
107216
|
-
|
|
107217
|
-
|
|
107218
|
-
|
|
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.
|
|
108380
|
+
if (lockedBefore) showUpdates(lockedBefore, this.fyn.depLocker.lockedVersions());
|
|
108381
|
+
await auditAfterInstall();
|
|
108382
|
+
}).catch(async (err) => {
|
|
108383
|
+
if (err.message === "No Change") {
|
|
108384
|
+
logger$1.info(`No changes detected since last fyn install - nothing to be done.
|
|
107225
108385
|
To force install, run 'fyn install --force-install' or 'fyn install --fi'`);
|
|
107226
|
-
|
|
108386
|
+
await auditAfterInstall();
|
|
108387
|
+
} else failure = err;
|
|
107227
108388
|
}).finally(async () => {
|
|
107228
108389
|
const localPkgBuild = this.fyn._localPkgBuilder?.waitForDone();
|
|
107229
108390
|
if (localPkgBuild) try {
|
|
@@ -107241,6 +108402,21 @@ var FynCli = class {
|
|
|
107241
108402
|
fyntil.exit(0);
|
|
107242
108403
|
});
|
|
107243
108404
|
}
|
|
108405
|
+
/**
|
|
108406
|
+
* Drop lock data for `fyn update` so the resolver picks the newest in-range versions
|
|
108407
|
+
*
|
|
108408
|
+
* @param names - packages to update, or empty for all
|
|
108409
|
+
* @returns the locked versions from before
|
|
108410
|
+
*/
|
|
108411
|
+
unlockForUpdate(names) {
|
|
108412
|
+
const locker = this.fyn.depLocker;
|
|
108413
|
+
const before = locker.lockedVersions();
|
|
108414
|
+
const missing = names.filter((name) => !before[name]);
|
|
108415
|
+
if (missing.length > 0) throw new Error(`not found in lock data: ${missing.join(", ")}`);
|
|
108416
|
+
const unlocked = locker.unlock(names);
|
|
108417
|
+
logger$1.info(`updating ${unlocked.length} locked packages to the newest versions their ranges allow`);
|
|
108418
|
+
return before;
|
|
108419
|
+
}
|
|
107244
108420
|
stat(argv) {
|
|
107245
108421
|
return showStat(this.fyn, argv.args.packages).finally(() => {
|
|
107246
108422
|
return this._opts.saveLogs && this.saveLogs(this._opts.saveLogs);
|
|
@@ -107288,16 +108464,16 @@ var FynCli = class {
|
|
|
107288
108464
|
if (this._opts.saveLogs) await this.saveLogs(this._opts.saveLogs);
|
|
107289
108465
|
}
|
|
107290
108466
|
}
|
|
107291
|
-
audit(argv) {
|
|
108467
|
+
async audit(argv) {
|
|
107292
108468
|
const opts = {
|
|
107293
108469
|
json: argv.opts?.json || false,
|
|
107294
108470
|
omit: argv.opts?.omit || [],
|
|
107295
108471
|
auditLevel: argv.opts?.auditLevel || "info",
|
|
107296
|
-
noCache: argv.opts?.
|
|
108472
|
+
noCache: argv.opts?.cache === false
|
|
107297
108473
|
};
|
|
107298
|
-
|
|
107299
|
-
|
|
107300
|
-
|
|
108474
|
+
const exitCode = await showAudit(this.fyn, opts);
|
|
108475
|
+
if (this._opts.saveLogs) await this.saveLogs(this._opts.saveLogs);
|
|
108476
|
+
if (exitCode) fyntil.exit(exitCode);
|
|
107301
108477
|
}
|
|
107302
108478
|
/**
|
|
107303
108479
|
* Remove non-runtime files from a production node_modules. Only runs on demand,
|
|
@@ -107818,7 +108994,7 @@ var CliBase = class {
|
|
|
107818
108994
|
if (!args) return;
|
|
107819
108995
|
let seenOptional;
|
|
107820
108996
|
args.replace(/([<[])([^>\]]*)([>\]])/g, (a, mark, xname) => {
|
|
107821
|
-
assert(!this.variadic, `For args specifier of '${this.name}', only the last one can be variadic
|
|
108997
|
+
assert(!this.variadic, new InvalidArgSpecifierError(`For args specifier of '${this.name}', only the last one can be variadic`, args));
|
|
107822
108998
|
const xm = xname.match(/([^\. ]+)?( +)?([^\.]+)?(\.\.+)?([^\.,]*)?( *, *)?([^\.]+)?$/);
|
|
107823
108999
|
assert(xm, new InvalidArgSpecifierError(`Invalid args specifier '${xname}' for '${this.name}'.`));
|
|
107824
109000
|
let variadic;
|
|
@@ -108026,6 +109202,7 @@ var Options = class {
|
|
|
108026
109202
|
makeHelp() {
|
|
108027
109203
|
const width = this.findLongestOptionHelpText();
|
|
108028
109204
|
let help = [];
|
|
109205
|
+
setHelpZebra(this.command.ncConfig?.helpZebra !== false);
|
|
108029
109206
|
resetZebraIndex();
|
|
108030
109207
|
for (const opt of Object.values(this._options)) {
|
|
108031
109208
|
const tail = [];
|
|
@@ -108249,6 +109426,7 @@ var CommandBase = class CommandBase extends CliBase {
|
|
|
108249
109426
|
data.push(strs);
|
|
108250
109427
|
}
|
|
108251
109428
|
const cmdWidth = data.reduce((max, n) => n[0].length > max ? n[0].length : max, 0);
|
|
109429
|
+
setHelpZebra(this.ncConfig?.helpZebra !== false);
|
|
108252
109430
|
resetZebraIndex();
|
|
108253
109431
|
return data.reduce((help, strs) => {
|
|
108254
109432
|
const lines = fitLines(strs, " ", " ", cmdWidth, getTerminalWidth());
|
|
@@ -108489,6 +109667,9 @@ var CommandNode = class extends ClapNode {
|
|
|
108489
109667
|
* Allow you to apply extra config to the parsed object, overriding any `opts` with `source` not start with `cli`.
|
|
108490
109668
|
*
|
|
108491
109669
|
* For example, you can allow user to specify options in their `package.json` file, and apply those after the command line is parsed.
|
|
109670
|
+
*
|
|
109671
|
+
* Each key goes to this command and any parsed sub command that declares the option.
|
|
109672
|
+
* Keys that match no declared option are ignored.
|
|
108492
109673
|
* @param config - Config object containing user options config
|
|
108493
109674
|
* @param src - Name of the source that provided the config. Default to `user`
|
|
108494
109675
|
* @returns
|
|
@@ -108515,8 +109696,9 @@ var CommandNode = class extends ClapNode {
|
|
|
108515
109696
|
this.optCount[camelCaseKey] = this.optCount[matchOpt.name];
|
|
108516
109697
|
}
|
|
108517
109698
|
}
|
|
108518
|
-
}
|
|
109699
|
+
}
|
|
108519
109700
|
}
|
|
109701
|
+
for (const name in this.subCmdNodes) this.subCmdNodes[name].applyConfig(config, src);
|
|
108520
109702
|
for (let command = this; command; command = command.getParent()) command._jsonMeta = void 0;
|
|
108521
109703
|
}
|
|
108522
109704
|
/**
|
|
@@ -108849,6 +110031,7 @@ var ClapNodeGenerator = class ClapNodeGenerator {
|
|
|
108849
110031
|
}
|
|
108850
110032
|
return [null];
|
|
108851
110033
|
}
|
|
110034
|
+
if (this.optNode && this.takesNegativeNumber(opt)) return this.consumeNonOptAsOption(opt);
|
|
108852
110035
|
if (this.optNode) {
|
|
108853
110036
|
this.complete();
|
|
108854
110037
|
return [null].concat(this.parent.consumeOpt(opt));
|
|
@@ -108891,6 +110074,17 @@ var ClapNodeGenerator = class ClapNodeGenerator {
|
|
|
108891
110074
|
});
|
|
108892
110075
|
}
|
|
108893
110076
|
/**
|
|
110077
|
+
* Whether this open option takes a negative number like `-5` as its next value.
|
|
110078
|
+
* Boolean args don't, so `--flag -5` still reads `-5` as an option.
|
|
110079
|
+
*
|
|
110080
|
+
* @param arg - an argv entry that starts with '-'
|
|
110081
|
+
*/
|
|
110082
|
+
takesNegativeNumber(arg) {
|
|
110083
|
+
if (!isNumber(arg)) return false;
|
|
110084
|
+
const args = this.optNode.option.args;
|
|
110085
|
+
return args[Math.min(this.node.argsList.length, args.length - 1)].type !== "boolean";
|
|
110086
|
+
}
|
|
110087
|
+
/**
|
|
108894
110088
|
*
|
|
108895
110089
|
* @param data
|
|
108896
110090
|
* @returns
|
|
@@ -108918,7 +110112,11 @@ var ClapNodeGenerator = class ClapNodeGenerator {
|
|
|
108918
110112
|
node.argsMap[argIx] = setValue;
|
|
108919
110113
|
};
|
|
108920
110114
|
if (opt.hasArgs) for (let i = 0; i < args.length && i < node.argsList.length; i++) setArg(i, args[i], node.argsList[i]);
|
|
108921
|
-
else
|
|
110115
|
+
else {
|
|
110116
|
+
const value = node.argsList[0];
|
|
110117
|
+
const isBool = isBoolean(value) || !opt.isUnknown && (value === "0" || value === "1");
|
|
110118
|
+
node.argsMap[0] = node.argsList.length > 0 ? this.convertValue(isBool ? "boolean" : isNumber(value) ? "number" : "string", value, opt) : true;
|
|
110119
|
+
}
|
|
108922
110120
|
if (args.length > 0 && args[args.length - 1].array) {
|
|
108923
110121
|
const lastIx = args.length - 1;
|
|
108924
110122
|
if (node.argsList.length > lastIx) setArg(lastIx, args[lastIx], node.argsList.slice(lastIx));
|
|
@@ -109248,7 +110446,6 @@ var NixClap = class extends EventEmitter$1 {
|
|
|
109248
110446
|
this._config = config;
|
|
109249
110447
|
this._name = config.name;
|
|
109250
110448
|
this._version = config.version || false;
|
|
109251
|
-
setHelpZebra(config.helpZebra !== false);
|
|
109252
110449
|
this._versionAlias = config.versionAlias;
|
|
109253
110450
|
this._helpOpt = config.hasOwnProperty("help") ? config.help : {
|
|
109254
110451
|
[HELP]: true,
|
|
@@ -109284,10 +110481,13 @@ var NixClap = class extends EventEmitter$1 {
|
|
|
109284
110481
|
"parse-fail": (parsed) => this.showError(parsed.command.getErrorNodes()[0].error),
|
|
109285
110482
|
"no-action": () => this.showHelp(/* @__PURE__ */ new Error("No command given"))
|
|
109286
110483
|
};
|
|
109287
|
-
if (!config.noDefaultHandlers) this.on("exit", defaultExit);
|
|
109288
110484
|
const handlers = config.handlers || {};
|
|
109289
|
-
|
|
109290
|
-
|
|
110485
|
+
const exitHandler = Object.hasOwn(handlers, "exit") ? handlers.exit : !config.noDefaultHandlers && defaultExit;
|
|
110486
|
+
if (typeof exitHandler === "function") this.on("exit", exitHandler);
|
|
110487
|
+
const names = /* @__PURE__ */ new Set([...Object.keys(this._evtHandlers), ...Object.keys(handlers)]);
|
|
110488
|
+
names.delete("exit");
|
|
110489
|
+
for (const name of names) {
|
|
110490
|
+
const h = Object.hasOwn(handlers, name) ? handlers[name] : this._evtHandlers[name];
|
|
109291
110491
|
if (typeof h === "function") this.on(name, h);
|
|
109292
110492
|
}
|
|
109293
110493
|
this._skipExec = config.skipExec;
|
|
@@ -109356,6 +110556,23 @@ var NixClap = class extends EventEmitter$1 {
|
|
|
109356
110556
|
return this;
|
|
109357
110557
|
}
|
|
109358
110558
|
/**
|
|
110559
|
+
* Make a copy of the help option without aliases that other options already use.
|
|
110560
|
+
*/
|
|
110561
|
+
_withFreeHelpAliases(existingOptions) {
|
|
110562
|
+
const helpOpt = this._helpOpt;
|
|
110563
|
+
const usedAliases = /* @__PURE__ */ new Set();
|
|
110564
|
+
for (const optName in existingOptions) {
|
|
110565
|
+
const opt = existingOptions[optName];
|
|
110566
|
+
if (optName !== "help" && opt.alias) (Array.isArray(opt.alias) ? opt.alias : [opt.alias]).forEach((a) => usedAliases.add(a));
|
|
110567
|
+
}
|
|
110568
|
+
/* c8 ignore next 3 */
|
|
110569
|
+
const helpAliases = helpOpt.alias ? Array.isArray(helpOpt.alias) ? helpOpt.alias : [helpOpt.alias] : [];
|
|
110570
|
+
return {
|
|
110571
|
+
...helpOpt,
|
|
110572
|
+
alias: helpAliases.filter((a) => !usedAliases.has(a))
|
|
110573
|
+
};
|
|
110574
|
+
}
|
|
110575
|
+
/**
|
|
109359
110576
|
* Recursively adds help option to all subcommands.
|
|
109360
110577
|
* Filters out help aliases that conflict with existing options in the subcommand.
|
|
109361
110578
|
*/
|
|
@@ -109364,18 +110581,9 @@ var NixClap = class extends EventEmitter$1 {
|
|
|
109364
110581
|
for (const name in commands) {
|
|
109365
110582
|
const cmd = commands[name];
|
|
109366
110583
|
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
110584
|
if (!existingOptions.hasOwnProperty("help")) cmd.options = {
|
|
109374
110585
|
...existingOptions,
|
|
109375
|
-
help:
|
|
109376
|
-
...this._helpOpt,
|
|
109377
|
-
alias: filteredAliases
|
|
109378
|
-
}
|
|
110586
|
+
help: this._withFreeHelpAliases(existingOptions)
|
|
109379
110587
|
};
|
|
109380
110588
|
if (cmd.subCommands) this._addHelpToSubCommands(cmd.subCommands);
|
|
109381
110589
|
}
|
|
@@ -109396,13 +110604,13 @@ var NixClap = class extends EventEmitter$1 {
|
|
|
109396
110604
|
let verAlias = ["V", "v"];
|
|
109397
110605
|
Object.keys(options).forEach((k) => {
|
|
109398
110606
|
const opt = options[k];
|
|
109399
|
-
if (opt.alias) verAlias = verAlias.filter((x) => opt.alias.
|
|
110607
|
+
if (opt.alias) verAlias = verAlias.filter((x) => ![].concat(opt.alias).includes(x));
|
|
109400
110608
|
});
|
|
109401
110609
|
options.version = this._getVersionOpt(verAlias);
|
|
109402
110610
|
}
|
|
109403
110611
|
if (this._helpOpt) {
|
|
109404
110612
|
options = { ...options };
|
|
109405
|
-
options["help"] = this.
|
|
110613
|
+
options["help"] = this._withFreeHelpAliases(options);
|
|
109406
110614
|
this._addHelpToSubCommands(commands);
|
|
109407
110615
|
}
|
|
109408
110616
|
this._options = options;
|
|
@@ -109581,6 +110789,7 @@ var NixClap = class extends EventEmitter$1 {
|
|
|
109581
110789
|
skipExec(skip = true) {
|
|
109582
110790
|
this._skipExec = skip;
|
|
109583
110791
|
this._skipExecDefault = skip;
|
|
110792
|
+
return this;
|
|
109584
110793
|
}
|
|
109585
110794
|
/**
|
|
109586
110795
|
* Parses the given arguments and returns the result.
|
|
@@ -109671,9 +110880,10 @@ var NixClap = class extends EventEmitter$1 {
|
|
|
109671
110880
|
this._rootCommand.name = this._name;
|
|
109672
110881
|
}
|
|
109673
110882
|
const { command, index } = new Parser(this).parse(argv, start);
|
|
110883
|
+
if (this._config.config) command.applyConfig(this._config.config(command) || {}, "user");
|
|
110884
|
+
command.applyDefaults();
|
|
109674
110885
|
const missing = command.checkRequiredOptions();
|
|
109675
110886
|
if (missing.length > 0) command.addError(/* @__PURE__ */ new Error("missing these required options " + missing.join(", ")));
|
|
109676
|
-
command.applyDefaults();
|
|
109677
110887
|
command.makeCamelCaseOptions();
|
|
109678
110888
|
const errorNodes = command.getErrorNodes();
|
|
109679
110889
|
return {
|
|
@@ -116550,8 +117760,7 @@ function setLogLevel(ll) {
|
|
|
116550
117760
|
if (ll) {
|
|
116551
117761
|
const levels = Object.keys(cli_logger_default.Levels);
|
|
116552
117762
|
const real = find(levels, (l) => l.startsWith(ll));
|
|
116553
|
-
|
|
116554
|
-
if (x !== void 0) logger$1._logLevel = x;
|
|
117763
|
+
if ((real ? cli_logger_default.Levels[real] : void 0) !== void 0) logger$1.logLevel = real;
|
|
116555
117764
|
else {
|
|
116556
117765
|
logger$1.error(`Invalid log level "${ll}". Supported levels are: ${levels.join(", ")}`);
|
|
116557
117766
|
fyntil.exit(1);
|
|
@@ -116691,12 +117900,21 @@ const options = {
|
|
|
116691
117900
|
"central-store": {
|
|
116692
117901
|
args: "<flag boolean>",
|
|
116693
117902
|
alias: ["central", "cs"],
|
|
116694
|
-
desc: "keep single copy of packages in central store"
|
|
116695
|
-
argDefault: "false"
|
|
117903
|
+
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
117904
|
},
|
|
116697
117905
|
hardlink: {
|
|
116698
117906
|
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"
|
|
117907
|
+
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"
|
|
117908
|
+
},
|
|
117909
|
+
reflink: {
|
|
117910
|
+
args: "<flag boolean>",
|
|
117911
|
+
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",
|
|
117912
|
+
argDefault: "true"
|
|
117913
|
+
},
|
|
117914
|
+
"copy-fallback": {
|
|
117915
|
+
args: "<flag boolean>",
|
|
117916
|
+
desc: "copy central store files that can't be cloned or hardlinked (default). --no-copy-fallback fails the install instead",
|
|
117917
|
+
argDefault: "true"
|
|
116700
117918
|
},
|
|
116701
117919
|
copy: {
|
|
116702
117920
|
args: "[packages string..]",
|
|
@@ -116776,11 +117994,6 @@ const options = {
|
|
|
116776
117994
|
argDefault: "false",
|
|
116777
117995
|
desc: "force refresh package meta from registry"
|
|
116778
117996
|
},
|
|
116779
|
-
"ignore-dist": {
|
|
116780
|
-
alias: "i",
|
|
116781
|
-
args: "<flag boolean>",
|
|
116782
|
-
desc: "Ignore host in tarball URL from meta dist."
|
|
116783
|
-
},
|
|
116784
117997
|
"ignore-lock-url": {
|
|
116785
117998
|
args: "<flag boolean>",
|
|
116786
117999
|
argDefault: "false",
|
|
@@ -116828,6 +118041,11 @@ const options = {
|
|
|
116828
118041
|
desc: "Max network concurrency (registry sockets)",
|
|
116829
118042
|
argDefault: "32"
|
|
116830
118043
|
},
|
|
118044
|
+
"extract-concurrency": {
|
|
118045
|
+
args: "<num number>",
|
|
118046
|
+
alias: "excc",
|
|
118047
|
+
desc: "Max packages extracted at once (default: CPU cores, at most 4)"
|
|
118048
|
+
},
|
|
116831
118049
|
"auto-run": {
|
|
116832
118050
|
args: "<flag boolean>",
|
|
116833
118051
|
argDefault: "true",
|
|
@@ -116972,6 +118190,30 @@ const commands = {
|
|
|
116972
118190
|
}
|
|
116973
118191
|
}
|
|
116974
118192
|
},
|
|
118193
|
+
update: {
|
|
118194
|
+
args: "[packages string..]",
|
|
118195
|
+
usage: "$0 $1 [packages..]",
|
|
118196
|
+
desc: "Update locked versions to the newest their package.json ranges allow",
|
|
118197
|
+
exec: async (cmd) => {
|
|
118198
|
+
const meta = cmd.jsonMeta;
|
|
118199
|
+
const config = await pickOptions(cmd);
|
|
118200
|
+
Object.assign(config.opts, {
|
|
118201
|
+
forceInstall: true,
|
|
118202
|
+
refreshMeta: true,
|
|
118203
|
+
npmLock: false
|
|
118204
|
+
});
|
|
118205
|
+
const update = meta.args.packages || [];
|
|
118206
|
+
return new FynCli(config).install({ opts: {
|
|
118207
|
+
audit: meta.opts.audit !== false,
|
|
118208
|
+
update
|
|
118209
|
+
} });
|
|
118210
|
+
},
|
|
118211
|
+
options: { audit: {
|
|
118212
|
+
desc: "run security audit after update (use --no-audit to skip)",
|
|
118213
|
+
args: "<flag boolean>",
|
|
118214
|
+
argDefault: "true"
|
|
118215
|
+
} }
|
|
118216
|
+
},
|
|
116975
118217
|
stat: {
|
|
116976
118218
|
desc: "Show stats of installed packages",
|
|
116977
118219
|
usage: "$0 $1 <package-name>[@semver] [...]",
|
|
@@ -116986,14 +118228,14 @@ const commands = {
|
|
|
116986
118228
|
args: "[packages string..]",
|
|
116987
118229
|
exec: async (cmd) => {
|
|
116988
118230
|
const json = Boolean(cmd.jsonMeta.opts.json);
|
|
116989
|
-
const previousLogLevel = logger$1.
|
|
118231
|
+
const previousLogLevel = logger$1.logLevel;
|
|
116990
118232
|
if (json) cmd.jsonMeta.opts.logLevel = "none";
|
|
116991
118233
|
try {
|
|
116992
118234
|
const config = await pickOptions(cmd);
|
|
116993
118235
|
config.noStartupInfo = json;
|
|
116994
118236
|
return await new FynCli(config).outdated(cmd.jsonMeta);
|
|
116995
118237
|
} finally {
|
|
116996
|
-
if (json) logger$1.
|
|
118238
|
+
if (json) logger$1.logLevel = previousLogLevel;
|
|
116997
118239
|
}
|
|
116998
118240
|
},
|
|
116999
118241
|
options: { json: {
|
|
@@ -117022,9 +118264,10 @@ const commands = {
|
|
|
117022
118264
|
desc: "Minimum severity level to report (info, low, moderate, high, critical)",
|
|
117023
118265
|
argDefault: "info"
|
|
117024
118266
|
},
|
|
117025
|
-
|
|
118267
|
+
cache: {
|
|
117026
118268
|
args: "<flag boolean>",
|
|
117027
|
-
desc: "
|
|
118269
|
+
desc: "use the audit cache (use --no-cache to fetch fresh data)",
|
|
118270
|
+
argDefault: "true"
|
|
117028
118271
|
}
|
|
117029
118272
|
}
|
|
117030
118273
|
},
|
|
@@ -117051,7 +118294,7 @@ const commands = {
|
|
|
117051
118294
|
} else {
|
|
117052
118295
|
logger$1.error(chalk.red("Script execution failed:"));
|
|
117053
118296
|
logger$1.error(err.message || err.toString());
|
|
117054
|
-
if (err.stack && logger$1.
|
|
118297
|
+
if (err.stack && cli_logger_default.Levels[logger$1.logLevel] <= cli_logger_default.Levels.debug) logger$1.debug(err.stack);
|
|
117055
118298
|
}
|
|
117056
118299
|
fyntil.exit(typeof exitCode === "number" ? exitCode : 1);
|
|
117057
118300
|
}
|