token-goat 2.9.29 → 2.9.30
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 +34 -40
- package/SECURITY.md +28 -10
- package/THIRD_PARTY_NOTICES.md +40 -3
- package/dist/native/linux-arm64/tg-hook +0 -0
- package/dist/native/linux-x64/tg-hook +0 -0
- package/dist/ort-wasm-simd-threaded.mjs +59 -0
- package/dist/token-goat-chunk-3CHUNJ2O.mjs +53 -0
- package/dist/token-goat-chunk-3Z5S4KGM.mjs +918 -0
- package/dist/token-goat-chunk-4FVIAHSI.mjs +211 -0
- package/dist/{token-goat-chunk-PGTH2U4C.mjs → token-goat-chunk-4JJS54TR.mjs} +4 -3
- package/dist/token-goat-chunk-4LCCNRTG.mjs +313 -0
- package/dist/{token-goat-chunk-L7H3U27L.mjs → token-goat-chunk-54K3EUV3.mjs} +1 -1
- package/dist/token-goat-chunk-56EIMS3E.mjs +159 -0
- package/dist/token-goat-chunk-5BCIJXMO.mjs +609 -0
- package/dist/token-goat-chunk-5KDMCMF2.mjs +362 -0
- package/dist/token-goat-chunk-5RG5SBL6.mjs +221 -0
- package/dist/{token-goat-chunk-RRNZMM3A.mjs → token-goat-chunk-5Y6ZYL6U.mjs} +21 -2
- package/dist/{token-goat-chunk-GLXRTTLE.mjs → token-goat-chunk-64FBPDTK.mjs} +12 -8
- package/dist/{token-goat-chunk-G23DWHV4.mjs → token-goat-chunk-664RTTUV.mjs} +28 -15
- package/dist/token-goat-chunk-67TQJ76B.mjs +57 -0
- package/dist/token-goat-chunk-6QMAS7AB.mjs +42 -0
- package/dist/token-goat-chunk-7BXSNBY5.mjs +253 -0
- package/dist/{token-goat-chunk-IVWI2OCK.mjs → token-goat-chunk-7F2UBPD3.mjs} +40 -11
- package/dist/{token-goat-chunk-TGOXNAHW.mjs → token-goat-chunk-7IN2MKDS.mjs} +682 -501
- package/dist/token-goat-chunk-7NADEDKJ.mjs +124 -0
- package/dist/{token-goat-chunk-KOPIR3KZ.mjs → token-goat-chunk-A3CK6N5Z.mjs} +618 -72
- package/dist/{token-goat-chunk-O6I2XU4P.mjs → token-goat-chunk-AFLYLHDH.mjs} +44 -31
- package/dist/{token-goat-chunk-TCQANXYC.mjs → token-goat-chunk-AM5V6GSX.mjs} +18 -2
- package/dist/{token-goat-chunk-E4ZOJIZK.mjs → token-goat-chunk-APGZXSPS.mjs} +39 -146
- package/dist/{token-goat-chunk-D4ETHJD6.mjs → token-goat-chunk-ARDNEC2U.mjs} +9 -7
- package/dist/token-goat-chunk-ATCPY7EQ.mjs +134 -0
- package/dist/token-goat-chunk-B2RZZCSS.mjs +354 -0
- package/dist/{token-goat-chunk-BGYOZ6DO.mjs → token-goat-chunk-B45VMIIH.mjs} +6 -7
- package/dist/token-goat-chunk-BPGCUMR7.mjs +30 -0
- package/dist/{token-goat-chunk-TDUT2CL6.mjs → token-goat-chunk-C63JQV5K.mjs} +45 -6
- package/dist/{token-goat-chunk-ZER6EAXZ.mjs → token-goat-chunk-COBQGL5S.mjs} +2661 -2440
- package/dist/token-goat-chunk-COTXZHTS.mjs +39 -0
- package/dist/{token-goat-chunk-RQGGMPCR.mjs → token-goat-chunk-CYCEYAEO.mjs} +76 -16
- package/dist/token-goat-chunk-CZ3LUXYZ.mjs +4115 -0
- package/dist/{token-goat-chunk-ASLWOQ3I.mjs → token-goat-chunk-DZX2YDPT.mjs} +2 -1
- package/dist/token-goat-chunk-E3OQX2XT.mjs +824 -0
- package/dist/token-goat-chunk-EFHMMIGP.mjs +68 -0
- package/dist/token-goat-chunk-ETBHVDB6.mjs +328 -0
- package/dist/token-goat-chunk-EVMZJ27Z.mjs +147 -0
- package/dist/token-goat-chunk-EXKGNHEG.mjs +2096 -0
- package/dist/{token-goat-chunk-RTMVLHWX.mjs → token-goat-chunk-FBNQNSJK.mjs} +2555 -5127
- package/dist/{token-goat-chunk-NMTKNYGF.mjs → token-goat-chunk-FNFBKLRD.mjs} +74 -9
- package/dist/{token-goat-chunk-RLP6J7WR.mjs → token-goat-chunk-FZ3NEW5O.mjs} +33 -19
- package/dist/token-goat-chunk-G5PJ7AGM.mjs +36 -0
- package/dist/{token-goat-chunk-DNRPXHYH.mjs → token-goat-chunk-GFBSN7BD.mjs} +29 -401
- package/dist/{token-goat-chunk-XYWPOSCN.mjs → token-goat-chunk-GOLEOXZP.mjs} +763 -211
- package/dist/token-goat-chunk-H2K3QP6H.mjs +24 -0
- package/dist/token-goat-chunk-H2PHHGM5.mjs +188 -0
- package/dist/token-goat-chunk-HAVAOB3S.mjs +87 -0
- package/dist/token-goat-chunk-HG45AF2B.mjs +2228 -0
- package/dist/{token-goat-chunk-HUYUHODZ.mjs → token-goat-chunk-HOJLCGDP.mjs} +12965 -11748
- package/dist/{token-goat-chunk-435UQTKD.mjs → token-goat-chunk-HYBFA5X3.mjs} +118 -19
- package/dist/token-goat-chunk-IVALLT3S.mjs +48 -0
- package/dist/{token-goat-chunk-UXSXQQIY.mjs → token-goat-chunk-IVKIZWAB.mjs} +3 -3
- package/dist/{token-goat-chunk-52NSDWYY.mjs → token-goat-chunk-JB6QN6VF.mjs} +6 -4
- package/dist/{token-goat-chunk-HNFZZHFW.mjs → token-goat-chunk-JDHE26RP.mjs} +10 -3
- package/dist/{token-goat-chunk-FTP4U4QA.mjs → token-goat-chunk-JDU3EXSU.mjs} +12 -11
- package/dist/token-goat-chunk-JDWCRD6M.mjs +253 -0
- package/dist/{token-goat-chunk-6AK46ZT7.mjs → token-goat-chunk-JN4XMLSD.mjs} +5 -1
- package/dist/token-goat-chunk-JTQQGXZH.mjs +733 -0
- package/dist/token-goat-chunk-KKUFXAPD.mjs +25 -0
- package/dist/token-goat-chunk-KQNZDCBD.mjs +47 -0
- package/dist/{token-goat-chunk-2WOUYWLM.mjs → token-goat-chunk-KWPNJBDH.mjs} +27 -3
- package/dist/{token-goat-chunk-DPNLUJWB.mjs → token-goat-chunk-LOBGHXPB.mjs} +30 -8
- package/dist/token-goat-chunk-MKPF4CL5.mjs +37 -0
- package/dist/token-goat-chunk-MNWKPRAL.mjs +13 -0
- package/dist/{token-goat-chunk-DNSPXQXQ.mjs → token-goat-chunk-N2NMER56.mjs} +25 -15
- package/dist/token-goat-chunk-NYKZLXMK.mjs +218 -0
- package/dist/token-goat-chunk-OJBNYTJP.mjs +3087 -0
- package/dist/token-goat-chunk-P4QMM4WK.mjs +295 -0
- package/dist/token-goat-chunk-PD5VKH46.mjs +184 -0
- package/dist/token-goat-chunk-PEPTHRFF.mjs +129 -0
- package/dist/{token-goat-chunk-NMBWLRHW.mjs → token-goat-chunk-PU7V3FD6.mjs} +8721 -11104
- package/dist/token-goat-chunk-PY533T7F.mjs +46 -0
- package/dist/token-goat-chunk-Q5VTGRH7.mjs +761 -0
- package/dist/{token-goat-chunk-67BNIKKO.mjs → token-goat-chunk-QCLDAQTS.mjs} +31 -20
- package/dist/{token-goat-chunk-SE6E4BKJ.mjs → token-goat-chunk-QSBRTGM2.mjs} +9 -2
- package/dist/{token-goat-chunk-VZQEWRVH.mjs → token-goat-chunk-RC35RBUL.mjs} +4 -4
- package/dist/{token-goat-chunk-VMFWNHGR.mjs → token-goat-chunk-RHXKCZX3.mjs} +873 -504
- package/dist/{token-goat-chunk-PYSUADX4.mjs → token-goat-chunk-RZRTDST7.mjs} +17 -7
- package/dist/{token-goat-chunk-ONXH6NZ5.mjs → token-goat-chunk-SJHWVNDQ.mjs} +15 -21
- package/dist/token-goat-chunk-SMVRN2HU.mjs +188 -0
- package/dist/{token-goat-chunk-QO3LXVVR.mjs → token-goat-chunk-SQSSNQPE.mjs} +2295 -1718
- package/dist/{token-goat-chunk-2AWQ2R5X.mjs → token-goat-chunk-T4FK7VOV.mjs} +2 -2
- package/dist/token-goat-chunk-U4N3BN2W.mjs +92 -0
- package/dist/token-goat-chunk-UA5V6P3P.mjs +122 -0
- package/dist/{token-goat-chunk-UA5BKWWQ.mjs → token-goat-chunk-UQ5UK2T7.mjs} +15 -4
- package/dist/token-goat-chunk-USILZ3T3.mjs +53 -0
- package/dist/{token-goat-chunk-MELOKFDJ.mjs → token-goat-chunk-VES7EL7O.mjs} +7 -1
- package/dist/{token-goat-chunk-7CPMDFGB.mjs → token-goat-chunk-VL3YIFHZ.mjs} +389 -14
- package/dist/{token-goat-chunk-E5TK5DNO.mjs → token-goat-chunk-VPBBTSJR.mjs} +356 -129
- package/dist/{token-goat-chunk-YOOVFPTP.mjs → token-goat-chunk-W3QCJS6G.mjs} +10 -2
- package/dist/{token-goat-chunk-LZNBQTDK.mjs → token-goat-chunk-WY3L4DVT.mjs} +11 -7
- package/dist/token-goat-chunk-XKI4SEMX.mjs +66 -0
- package/dist/token-goat-chunk-XU4P6Z24.mjs +133 -0
- package/dist/{token-goat-chunk-H5J3C56Q.mjs → token-goat-chunk-Y776AENC.mjs} +112 -26
- package/dist/token-goat-chunk-YARZFCZS.mjs +359 -0
- package/dist/{token-goat-chunk-S4VSXURL.mjs → token-goat-chunk-Z44YO3QZ.mjs} +4 -0
- package/dist/token-goat-chunk-Z57YODA2.mjs +35 -0
- package/dist/{token-goat-chunk-PQ53BSCF.mjs → token-goat-chunk-ZCDTCVIS.mjs} +48 -29
- package/dist/token-goat-chunk-ZEJVMUQH.mjs +48 -0
- package/dist/{token-goat-chunk-BGHSSJUA.mjs → token-goat-chunk-ZFOBKUWH.mjs} +1 -1
- package/dist/token-goat-chunk-ZMBL6UVV.mjs +110 -0
- package/dist/{token-goat-chunk-PKRWMHVP.mjs → token-goat-chunk-ZQSJMO2R.mjs} +338 -170
- package/dist/token-goat-hook-client.cjs +87 -23
- package/dist/token-goat-hook-client.mjs +3 -3
- package/dist/token-goat-hook.mjs +46 -30
- package/dist/token-goat.core.mjs +6 -6
- package/docs/C4_RUNTIME_ARCHITECTURE.md +1 -1
- package/docs/cli.md +80 -46
- package/docs/install.md +47 -14
- package/docs/security.md +7 -7
- package/package.json +17 -7
- package/scripts/verify-native-dist.mjs +386 -0
- package/dist/token-goat-chunk-2NNUA2LR.mjs +0 -143
- package/dist/token-goat-chunk-44BM7DDQ.mjs +0 -294
- package/dist/token-goat-chunk-C5YPNZKQ.mjs +0 -318
- package/dist/token-goat-chunk-CIQ2FTY3.mjs +0 -1990
- package/dist/token-goat-chunk-EUSDXRXU.mjs +0 -1429
- package/dist/token-goat-chunk-G7IWXCFF.mjs +0 -456
- package/dist/token-goat-chunk-JTKCQMQA.mjs +0 -418
- package/dist/token-goat-chunk-ORNFMIER.mjs +0 -295
- package/dist/token-goat-chunk-VQ6F6T7X.mjs +0 -36
- package/dist/token-goat-chunk-YAGLESS3.mjs +0 -23
- package/dist/token-goat-chunk-YKSRAWUU.mjs +0 -33
- package/dist/token-goat-chunk-Z6KBMOBI.mjs +0 -53
|
@@ -6,178 +6,32 @@ import {
|
|
|
6
6
|
quotePowershellPath,
|
|
7
7
|
quoteShellPath,
|
|
8
8
|
sleepSync
|
|
9
|
-
} from "./token-goat-chunk-
|
|
9
|
+
} from "./token-goat-chunk-AM5V6GSX.mjs";
|
|
10
10
|
import {
|
|
11
11
|
normalizePath
|
|
12
|
-
} from "./token-goat-chunk-
|
|
12
|
+
} from "./token-goat-chunk-FNFBKLRD.mjs";
|
|
13
13
|
import {
|
|
14
14
|
dataDir,
|
|
15
15
|
ensureStorageRootPrivate,
|
|
16
16
|
isTokenGoatStorage
|
|
17
|
-
} from "./token-goat-chunk-
|
|
18
|
-
import {
|
|
19
|
-
compileGuardedRegex
|
|
20
|
-
} from "./token-goat-chunk-JTKCQMQA.mjs";
|
|
17
|
+
} from "./token-goat-chunk-VES7EL7O.mjs";
|
|
21
18
|
import {
|
|
22
19
|
init_define_import_meta_env
|
|
23
20
|
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
24
21
|
|
|
25
|
-
// src/
|
|
22
|
+
// src/bridges/created_configs.ts
|
|
26
23
|
init_define_import_meta_env();
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
function detectSourceEncoding(buf) {
|
|
31
|
-
if (buf.length >= 4) {
|
|
32
|
-
if (buf[0] === 255 && buf[1] === 254 && buf[2] === 0 && buf[3] === 0) return "utf32le";
|
|
33
|
-
if (buf[0] === 0 && buf[1] === 0 && buf[2] === 254 && buf[3] === 255) return "utf32be";
|
|
34
|
-
}
|
|
35
|
-
if (buf.length >= 2) {
|
|
36
|
-
if (buf[0] === 255 && buf[1] === 254) return "utf16le";
|
|
37
|
-
if (buf[0] === 254 && buf[1] === 255) return "utf16be";
|
|
38
|
-
}
|
|
39
|
-
if (buf.length >= 3 && buf[0] === 239 && buf[1] === 187 && buf[2] === 191) return "utf8-bom";
|
|
40
|
-
return "utf8";
|
|
41
|
-
}
|
|
42
|
-
function decodeSource(buf) {
|
|
43
|
-
switch (detectSourceEncoding(buf)) {
|
|
44
|
-
case "utf32le":
|
|
45
|
-
return decodeUtf32(buf.subarray(4), true);
|
|
46
|
-
case "utf32be":
|
|
47
|
-
return decodeUtf32(buf.subarray(4), false);
|
|
48
|
-
case "utf16le":
|
|
49
|
-
return buf.subarray(2).toString("utf16le");
|
|
50
|
-
case "utf16be":
|
|
51
|
-
return swap16(buf.subarray(2)).toString("utf16le");
|
|
52
|
-
case "utf8-bom":
|
|
53
|
-
return buf.subarray(3).toString("utf8");
|
|
54
|
-
default:
|
|
55
|
-
return buf.toString("utf8");
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
function encodeSource(text, encoding) {
|
|
59
|
-
switch (encoding) {
|
|
60
|
-
case "utf32le":
|
|
61
|
-
return Buffer.concat([Buffer.from([255, 254, 0, 0]), encodeUtf32(text, true)]);
|
|
62
|
-
case "utf32be":
|
|
63
|
-
return Buffer.concat([Buffer.from([0, 0, 254, 255]), encodeUtf32(text, false)]);
|
|
64
|
-
case "utf16le":
|
|
65
|
-
return Buffer.concat([Buffer.from([255, 254]), Buffer.from(text, "utf16le")]);
|
|
66
|
-
case "utf16be":
|
|
67
|
-
return Buffer.concat([Buffer.from([254, 255]), swap16(Buffer.from(text, "utf16le"))]);
|
|
68
|
-
case "utf8-bom":
|
|
69
|
-
return Buffer.concat([Buffer.from([239, 187, 191]), Buffer.from(text, "utf8")]);
|
|
70
|
-
default:
|
|
71
|
-
return Buffer.from(text, "utf8");
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
function swap16(buf) {
|
|
75
|
-
const out = Buffer.from(buf);
|
|
76
|
-
return out.subarray(0, out.length - out.length % 2).swap16();
|
|
77
|
-
}
|
|
78
|
-
function decodeUtf32(buf, littleEndian) {
|
|
79
|
-
const points = [];
|
|
80
|
-
for (let i = 0; i + 4 <= buf.length; i += 4) {
|
|
81
|
-
const cp = littleEndian ? buf.readUInt32LE(i) : buf.readUInt32BE(i);
|
|
82
|
-
points.push(cp > 1114111 || cp >= 55296 && cp <= 57343 ? 65533 : cp);
|
|
83
|
-
}
|
|
84
|
-
return String.fromCodePoint(...points);
|
|
85
|
-
}
|
|
86
|
-
function encodeUtf32(text, littleEndian) {
|
|
87
|
-
const points = [...text];
|
|
88
|
-
const out = Buffer.alloc(points.length * 4);
|
|
89
|
-
points.forEach((ch, i) => {
|
|
90
|
-
const cp = ch.codePointAt(0) ?? 65533;
|
|
91
|
-
if (littleEndian) out.writeUInt32LE(cp, i * 4);
|
|
92
|
-
else out.writeUInt32BE(cp, i * 4);
|
|
93
|
-
});
|
|
94
|
-
return out;
|
|
95
|
-
}
|
|
24
|
+
import * as fs from "fs";
|
|
25
|
+
import * as path4 from "path";
|
|
96
26
|
|
|
97
27
|
// src/util.ts
|
|
98
28
|
init_define_import_meta_env();
|
|
99
|
-
import { chmodSync, closeSync, constants as fsConstants, copyFileSync, existsSync
|
|
100
|
-
import * as
|
|
101
|
-
|
|
102
|
-
// src/bridges/created_configs.ts
|
|
103
|
-
init_define_import_meta_env();
|
|
104
|
-
import * as fs from "fs";
|
|
105
|
-
import * as path from "path";
|
|
106
|
-
function ledgerPath() {
|
|
107
|
-
return path.join(dataDir(), "created-configs.json");
|
|
108
|
-
}
|
|
109
|
-
function keyOf(filePath) {
|
|
110
|
-
return normalizePath(path.resolve(filePath));
|
|
111
|
-
}
|
|
112
|
-
function foldKey(key) {
|
|
113
|
-
return foldPath(key);
|
|
114
|
-
}
|
|
115
|
-
function readLedger() {
|
|
116
|
-
try {
|
|
117
|
-
const parsed = JSON.parse(fs.readFileSync(ledgerPath(), "utf8"));
|
|
118
|
-
return Array.isArray(parsed) ? parsed.filter((entry) => typeof entry === "string") : [];
|
|
119
|
-
} catch {
|
|
120
|
-
return [];
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
function writeLedger(entries) {
|
|
124
|
-
try {
|
|
125
|
-
ensureDirSync(path.dirname(ledgerPath()));
|
|
126
|
-
atomicWriteText(ledgerPath(), `${JSON.stringify(entries)}
|
|
127
|
-
`);
|
|
128
|
-
} catch {
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
function recordCreatedConfig(filePath) {
|
|
132
|
-
const key = keyOf(filePath);
|
|
133
|
-
const entries = readLedger();
|
|
134
|
-
if (entries.some((entry) => foldKey(entry) === foldKey(key))) return;
|
|
135
|
-
writeLedger([...entries, key]);
|
|
136
|
-
}
|
|
137
|
-
function hasCreatedConfig(filePath) {
|
|
138
|
-
const key = foldKey(keyOf(filePath));
|
|
139
|
-
return readLedger().some((entry) => foldKey(entry) === key);
|
|
140
|
-
}
|
|
141
|
-
function takeCreatedConfig(filePath) {
|
|
142
|
-
const key = foldKey(keyOf(filePath));
|
|
143
|
-
const entries = readLedger();
|
|
144
|
-
if (!entries.some((entry) => foldKey(entry) === key)) return false;
|
|
145
|
-
writeLedger(entries.filter((entry) => foldKey(entry) !== key));
|
|
146
|
-
return true;
|
|
147
|
-
}
|
|
148
|
-
function recordCreatedBackup(backupPath) {
|
|
149
|
-
recordCreatedConfig(backupPath);
|
|
150
|
-
}
|
|
151
|
-
function forgetCreatedBackup(backupPath) {
|
|
152
|
-
takeCreatedConfig(backupPath);
|
|
153
|
-
}
|
|
154
|
-
function createdBackupsFor(configPath) {
|
|
155
|
-
const prefix = foldKey(`${keyOf(configPath)}.bak.`);
|
|
156
|
-
return readLedger().filter((entry) => foldKey(entry).startsWith(prefix)).sort();
|
|
157
|
-
}
|
|
158
|
-
function removeCreatedBackups(configPath) {
|
|
159
|
-
const prefix = foldKey(`${keyOf(configPath)}.bak.`);
|
|
160
|
-
const entries = readLedger();
|
|
161
|
-
const ours = entries.filter((entry) => foldKey(entry).startsWith(prefix));
|
|
162
|
-
if (ours.length === 0) return 0;
|
|
163
|
-
const failed = /* @__PURE__ */ new Set();
|
|
164
|
-
let removed = 0;
|
|
165
|
-
for (const target of ours) {
|
|
166
|
-
try {
|
|
167
|
-
if (fs.existsSync(target) && removeFileInScope(target)) {
|
|
168
|
-
removed++;
|
|
169
|
-
}
|
|
170
|
-
} catch {
|
|
171
|
-
failed.add(target);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
writeLedger(entries.filter((entry) => !ours.includes(entry) || failed.has(entry)));
|
|
175
|
-
return removed;
|
|
176
|
-
}
|
|
29
|
+
import { chmodSync, closeSync, constants as fsConstants, copyFileSync, existsSync, lstatSync, mkdirSync, openSync, readdirSync, readFileSync as readFileSync2, readlinkSync, renameSync, rmdirSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
30
|
+
import * as path3 from "node:path";
|
|
177
31
|
|
|
178
32
|
// src/bridges/project_scope_guard.ts
|
|
179
33
|
init_define_import_meta_env();
|
|
180
|
-
import * as
|
|
34
|
+
import * as path from "node:path";
|
|
181
35
|
function assertProjectScopeTarget(target, projectRoot) {
|
|
182
36
|
if (projectRoot === void 0) return;
|
|
183
37
|
if (isInsideRoot(target, projectRoot)) return;
|
|
@@ -188,7 +42,7 @@ function assertProjectScopeTarget(target, projectRoot) {
|
|
|
188
42
|
var installProjectRoot;
|
|
189
43
|
function withInstallScope(projectRoot, fn) {
|
|
190
44
|
const previous = installProjectRoot;
|
|
191
|
-
installProjectRoot = projectRoot === void 0 ? void 0 :
|
|
45
|
+
installProjectRoot = projectRoot === void 0 ? void 0 : path.resolve(projectRoot);
|
|
192
46
|
try {
|
|
193
47
|
const result = fn();
|
|
194
48
|
if (typeof result?.then === "function") {
|
|
@@ -204,7 +58,7 @@ function withInstallScope(projectRoot, fn) {
|
|
|
204
58
|
function projectScopeRoot(opts) {
|
|
205
59
|
if (opts === void 0) return void 0;
|
|
206
60
|
if (opts.project !== true && opts.local !== true) return void 0;
|
|
207
|
-
return
|
|
61
|
+
return path.resolve(opts.projectRoot ?? process.cwd());
|
|
208
62
|
}
|
|
209
63
|
function assertWriteInScope(target) {
|
|
210
64
|
const root = installProjectRoot;
|
|
@@ -219,10 +73,425 @@ function projectPathIsConsultable(target, projectRoot) {
|
|
|
219
73
|
// src/util.ts
|
|
220
74
|
import { spawnSync } from "node:child_process";
|
|
221
75
|
|
|
76
|
+
// src/regex_guard.ts
|
|
77
|
+
init_define_import_meta_env();
|
|
78
|
+
var GROUP_PREFIX = String.raw`\((?:\?(?::|<?[=!]|<\w+>|[a-z]*(?:-[a-z]*)?:))?`;
|
|
79
|
+
var NESTED_QUANTIFIER = new RegExp(GROUP_PREFIX + String.raw`[^()*+]*(?:[*+]|\{\d+,\d*\})[^()]*\)\s*(?:[*+]|\{\d+,\d*\})`);
|
|
80
|
+
function hasNestedQuantifier(source) {
|
|
81
|
+
return NESTED_QUANTIFIER.test(source);
|
|
82
|
+
}
|
|
83
|
+
var PROBE_ALPHABETS = ["a", "0", "a0"];
|
|
84
|
+
var PROBE_STEP = 4;
|
|
85
|
+
var PROBE_MAX_LENGTH = 512;
|
|
86
|
+
var PROBE_LENGTHS = Array.from({ length: PROBE_MAX_LENGTH / PROBE_STEP }, (_, i) => (i + 1) * PROBE_STEP);
|
|
87
|
+
var PROJECTED_LINE_LENGTH = 1e4;
|
|
88
|
+
var PROJECTION_BUDGET_MS = 1e3;
|
|
89
|
+
var TIMING_SIGNAL_MS = 1;
|
|
90
|
+
var PROBE_GROWTH_FACTOR = 12;
|
|
91
|
+
function climbsBetweenRungs(previous, elapsed) {
|
|
92
|
+
return previous !== void 0 && elapsed > TIMING_SIGNAL_MS && elapsed > previous * PROBE_GROWTH_FACTOR;
|
|
93
|
+
}
|
|
94
|
+
var PROBE_TERMINATORS = ["!", "a", "0", " ", "\uFFFF", "\n", "\u2028"];
|
|
95
|
+
var PROBE_BUDGET_MS = 25;
|
|
96
|
+
var LINEAR_BY_CONSTRUCTION_EXCLUDES = /[*+?{|]/;
|
|
97
|
+
var MAX_COUNTED_REPEAT = 8;
|
|
98
|
+
var LITERAL_RUN_ATOM = /[^\\()[\]{}|^$*+?]/;
|
|
99
|
+
var QUANTIFIER_AT = /^[*+?{]/;
|
|
100
|
+
function timeMatch(re, input) {
|
|
101
|
+
const probe = new RegExp(re.source, re.flags.replace("g", ""));
|
|
102
|
+
const started = performance.now();
|
|
103
|
+
const matched = probe.test(input);
|
|
104
|
+
const first = performance.now() - started;
|
|
105
|
+
if (first <= TIMING_SIGNAL_MS) return { ms: first, matched };
|
|
106
|
+
const again = new RegExp(re.source, re.flags.replace("g", ""));
|
|
107
|
+
const restarted = performance.now();
|
|
108
|
+
again.test(input);
|
|
109
|
+
return { ms: Math.min(first, performance.now() - restarted), matched };
|
|
110
|
+
}
|
|
111
|
+
function confirmed(re, input, first) {
|
|
112
|
+
const again = timeMatch(re, input);
|
|
113
|
+
return again.ms < first.ms ? { ms: again.ms, matched: first.matched } : first;
|
|
114
|
+
}
|
|
115
|
+
function remeasuredForProjection(re, timings, inputs) {
|
|
116
|
+
const hi = timings.length - 1;
|
|
117
|
+
const hiLength = PROBE_LENGTHS[hi];
|
|
118
|
+
const lo = hiLength === void 0 ? -1 : PROBE_LENGTHS.findIndex((l) => l * 2 >= hiLength);
|
|
119
|
+
const out = [...timings];
|
|
120
|
+
for (const i of /* @__PURE__ */ new Set([lo, hi])) {
|
|
121
|
+
const input = inputs[i];
|
|
122
|
+
const ms = out[i];
|
|
123
|
+
if (input !== void 0 && ms !== void 0) out[i] = Math.min(ms, timeMatch(re, input).ms);
|
|
124
|
+
}
|
|
125
|
+
return out;
|
|
126
|
+
}
|
|
127
|
+
var ESCAPE_SAMPLES = {
|
|
128
|
+
s: " ",
|
|
129
|
+
S: "a",
|
|
130
|
+
d: "0",
|
|
131
|
+
D: "a",
|
|
132
|
+
w: "a",
|
|
133
|
+
W: "-",
|
|
134
|
+
t: " ",
|
|
135
|
+
n: "\n",
|
|
136
|
+
r: "\r",
|
|
137
|
+
f: "\f",
|
|
138
|
+
v: "\v",
|
|
139
|
+
"0": "\0",
|
|
140
|
+
b: "",
|
|
141
|
+
B: ""
|
|
142
|
+
};
|
|
143
|
+
var LOOKAROUND_AT = /^\(\?<?[=!]/;
|
|
144
|
+
var CLASS_CANDIDATES = ["a", "0", " ", "x", "-", "!", "~", " ", "\n", "A", "\xE9", "\u03B1", "\u0434", "\u05D0", "\u0627", "\u4E2D", "\u3042", "\u{1F600}"];
|
|
145
|
+
function firstMatch(source, flags, candidates) {
|
|
146
|
+
let re;
|
|
147
|
+
try {
|
|
148
|
+
re = new RegExp(source, flags);
|
|
149
|
+
} catch {
|
|
150
|
+
return "";
|
|
151
|
+
}
|
|
152
|
+
for (const candidate of candidates) if (re.test(candidate)) return candidate;
|
|
153
|
+
return "";
|
|
154
|
+
}
|
|
155
|
+
function classEnd(source, start) {
|
|
156
|
+
let i = start + 1;
|
|
157
|
+
if (source[i] === "^") i++;
|
|
158
|
+
if (source[i] === "]") i++;
|
|
159
|
+
for (; i < source.length; i++) {
|
|
160
|
+
if (source[i] === "\\") {
|
|
161
|
+
i++;
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
if (source[i] === "]") return i;
|
|
165
|
+
}
|
|
166
|
+
return -1;
|
|
167
|
+
}
|
|
168
|
+
var CLASS_SWEEP = [
|
|
169
|
+
...Array.from({ length: 95 }, (_, i) => String.fromCharCode(32 + i)),
|
|
170
|
+
...Array.from({ length: 1024 }, (_, i) => String.fromCharCode(160 + i * 63))
|
|
171
|
+
];
|
|
172
|
+
var SWEEP_TAILS = CLASS_SWEEP.flatMap((c, i) => {
|
|
173
|
+
const other = CLASS_SWEEP[(i + 1) % CLASS_SWEEP.length];
|
|
174
|
+
return [c.repeat(MAX_COUNTED_REPEAT + 1), c.repeat(MAX_COUNTED_REPEAT) + other];
|
|
175
|
+
});
|
|
176
|
+
var MAX_SWEEPS = 3;
|
|
177
|
+
var SWEEP_BUDGET_MS = 150;
|
|
178
|
+
var QUANTIFIED_GROUP = /\)\s*(?:[*+]|\{\d+(?:,\d*)?\})/;
|
|
179
|
+
function sampleClass(cls) {
|
|
180
|
+
const named = sampleCharacters(cls.slice(1, -1));
|
|
181
|
+
return firstMatch(cls, "", [...named, ...CLASS_CANDIDATES]) || firstMatch(cls, "", CLASS_SWEEP);
|
|
182
|
+
}
|
|
183
|
+
function sampleCharacters(source) {
|
|
184
|
+
const out = [];
|
|
185
|
+
const seen = /* @__PURE__ */ new Set();
|
|
186
|
+
const push = (c) => {
|
|
187
|
+
if (c === "" || seen.has(c)) return;
|
|
188
|
+
seen.add(c);
|
|
189
|
+
out.push(c);
|
|
190
|
+
};
|
|
191
|
+
for (let i = 0; i < source.length; i++) {
|
|
192
|
+
const c = source[i];
|
|
193
|
+
if (c === "[") {
|
|
194
|
+
const end = classEnd(source, i);
|
|
195
|
+
if (end !== -1) {
|
|
196
|
+
push(sampleClass(source.slice(i, end + 1)));
|
|
197
|
+
i = end;
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (c !== "\\") {
|
|
202
|
+
if (/[^\s()[\]{}|^$*+?.-]/.test(c)) push(c);
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
const next = source[i + 1] ?? "";
|
|
206
|
+
i++;
|
|
207
|
+
if (next >= "0" && next <= "7") {
|
|
208
|
+
let digits = /^[0-7]{1,3}/.exec(source.slice(i))[0];
|
|
209
|
+
if (parseInt(digits, 8) > 255) digits = digits.slice(0, 2);
|
|
210
|
+
push(String.fromCharCode(parseInt(digits, 8)));
|
|
211
|
+
if (digits.length === 1 && next !== "0") push(next);
|
|
212
|
+
i += digits.length - 1;
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
if (next === "x" || next === "u") {
|
|
216
|
+
if (next === "u" && source[i + 1] === "{") {
|
|
217
|
+
const close = source.indexOf("}", i + 2);
|
|
218
|
+
const digits2 = close === -1 ? "" : source.slice(i + 2, close);
|
|
219
|
+
if (/^[0-9a-fA-F]{1,6}$/.test(digits2)) {
|
|
220
|
+
push(String.fromCodePoint(parseInt(digits2, 16)));
|
|
221
|
+
i = close;
|
|
222
|
+
}
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
const width = next === "x" ? 2 : 4;
|
|
226
|
+
const digits = source.slice(i + 1, i + 1 + width);
|
|
227
|
+
i += width;
|
|
228
|
+
if (/^[0-9a-fA-F]+$/.test(digits) && digits.length === width) push(String.fromCharCode(parseInt(digits, 16)));
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
if (next === "c" && /[a-zA-Z]/.test(source[i + 1] ?? "")) {
|
|
232
|
+
push(String.fromCharCode(source[i + 1].toUpperCase().charCodeAt(0) % 32));
|
|
233
|
+
i++;
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
if ((next === "p" || next === "P") && source[i + 1] === "{") {
|
|
237
|
+
const close = source.indexOf("}", i + 2);
|
|
238
|
+
if (close !== -1) {
|
|
239
|
+
push(firstMatch(source.slice(i - 1, close + 1), "u", CLASS_CANDIDATES));
|
|
240
|
+
i = close;
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const sample = ESCAPE_SAMPLES[next];
|
|
245
|
+
push(sample ?? next);
|
|
246
|
+
}
|
|
247
|
+
return out;
|
|
248
|
+
}
|
|
249
|
+
var MAX_PATTERN_ALPHABETS = 12;
|
|
250
|
+
function probeAlphabets(source) {
|
|
251
|
+
const samples = sampleCharacters(source);
|
|
252
|
+
const counts = /* @__PURE__ */ new Map();
|
|
253
|
+
for (const ch of source) counts.set(ch, (counts.get(ch) ?? 0) + 1);
|
|
254
|
+
const counted = samples.map((c, i) => ({ c, i, n: counts.get(c) ?? 0 }));
|
|
255
|
+
counted.sort((a, b) => b.n - a.n || a.i - b.i);
|
|
256
|
+
const kept = counted.slice(0, MAX_PATTERN_ALPHABETS).map((s) => s.c);
|
|
257
|
+
const extra = kept.length > 1 ? [kept.join("")] : [];
|
|
258
|
+
return [...PROBE_ALPHABETS, ...kept, ...extra];
|
|
259
|
+
}
|
|
260
|
+
function growsExponentially(re) {
|
|
261
|
+
const relaxed = detune(re.source);
|
|
262
|
+
if (relaxed === null || !relaxed.hadLookaround) {
|
|
263
|
+
const cause = climbsPastBudget(re);
|
|
264
|
+
if (cause !== null) return cause;
|
|
265
|
+
}
|
|
266
|
+
if (relaxed === null) return null;
|
|
267
|
+
for (const body of relaxed.negativeBodies) {
|
|
268
|
+
let inner;
|
|
269
|
+
try {
|
|
270
|
+
inner = new RegExp(body, re.flags);
|
|
271
|
+
} catch {
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
const innerCause = growsExponentially(inner);
|
|
275
|
+
if (innerCause !== null) return innerCause;
|
|
276
|
+
}
|
|
277
|
+
let widened;
|
|
278
|
+
try {
|
|
279
|
+
widened = new RegExp(relaxed.source, re.flags);
|
|
280
|
+
} catch {
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
return growsExponentially(widened);
|
|
284
|
+
}
|
|
285
|
+
function climbsPastBudget(re) {
|
|
286
|
+
const probe = new RegExp(re.source, re.flags.replace("g", ""));
|
|
287
|
+
let sweptMs = 0;
|
|
288
|
+
let falsified = false;
|
|
289
|
+
for (const alphabet of probeAlphabets(re.source)) {
|
|
290
|
+
let sweeps = 0;
|
|
291
|
+
const body = (n) => alphabet.repeat(Math.ceil(n / alphabet.length)).slice(0, n);
|
|
292
|
+
const tail = PROBE_TERMINATORS.find((t) => !probe.test(body(PROBE_STEP) + t)) ?? PROBE_TERMINATORS[0];
|
|
293
|
+
const candidates = [tail, ...PROBE_TERMINATORS.filter((t) => t !== tail)];
|
|
294
|
+
let swept;
|
|
295
|
+
const timings = [];
|
|
296
|
+
const inputs = [];
|
|
297
|
+
let previous;
|
|
298
|
+
for (const length of PROBE_LENGTHS) {
|
|
299
|
+
let failing;
|
|
300
|
+
let last;
|
|
301
|
+
let failingInput = "";
|
|
302
|
+
let lastInput = "";
|
|
303
|
+
const attempt = (candidate) => {
|
|
304
|
+
const input = body(length) + candidate;
|
|
305
|
+
let m = timeMatch(re, input);
|
|
306
|
+
if (m.ms > PROBE_BUDGET_MS) m = confirmed(re, input, m);
|
|
307
|
+
last = m;
|
|
308
|
+
lastInput = input;
|
|
309
|
+
if (m.ms > PROBE_BUDGET_MS) return "over-budget";
|
|
310
|
+
if (!m.matched) {
|
|
311
|
+
failing = m;
|
|
312
|
+
failingInput = input;
|
|
313
|
+
}
|
|
314
|
+
return m;
|
|
315
|
+
};
|
|
316
|
+
for (const candidate of swept === void 0 ? candidates : [swept, ...candidates]) {
|
|
317
|
+
if (attempt(candidate) === "over-budget") return "over-budget";
|
|
318
|
+
if (failing !== void 0) break;
|
|
319
|
+
}
|
|
320
|
+
if (failing === void 0 && sweeps < MAX_SWEEPS && sweptMs < SWEEP_BUDGET_MS) {
|
|
321
|
+
sweeps++;
|
|
322
|
+
const sweepStarted = Date.now();
|
|
323
|
+
for (const candidate of SWEEP_TAILS) {
|
|
324
|
+
if (attempt(candidate) === "over-budget") return "over-budget";
|
|
325
|
+
if (failing !== void 0) {
|
|
326
|
+
swept = candidate;
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
sweptMs += Date.now() - sweepStarted;
|
|
331
|
+
}
|
|
332
|
+
if (failing !== void 0) falsified = true;
|
|
333
|
+
let elapsed = (failing ?? last).ms;
|
|
334
|
+
const rungInput = failing !== void 0 ? failingInput : lastInput;
|
|
335
|
+
if (climbsBetweenRungs(previous, elapsed)) {
|
|
336
|
+
elapsed = confirmed(re, rungInput, { ms: elapsed, matched: false }).ms;
|
|
337
|
+
if (climbsBetweenRungs(previous, elapsed)) return "ratio";
|
|
338
|
+
}
|
|
339
|
+
previous = elapsed;
|
|
340
|
+
timings.push(elapsed);
|
|
341
|
+
inputs.push(rungInput);
|
|
342
|
+
}
|
|
343
|
+
if (projectsPastBudget(timings) && projectsPastBudget(remeasuredForProjection(re, timings, inputs))) return "projection";
|
|
344
|
+
}
|
|
345
|
+
if (!falsified && QUANTIFIED_GROUP.test(re.source)) return "unfalsifiable";
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
348
|
+
function groupEnd(source, start) {
|
|
349
|
+
let depth = 0;
|
|
350
|
+
let inClass = false;
|
|
351
|
+
for (let i = start; i < source.length; i++) {
|
|
352
|
+
const c = source[i];
|
|
353
|
+
if (c === "\\") {
|
|
354
|
+
i++;
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
if (inClass) {
|
|
358
|
+
if (c === "]") inClass = false;
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
if (c === "[") inClass = true;
|
|
362
|
+
else if (c === "(") depth++;
|
|
363
|
+
else if (c === ")" && --depth === 0) return i;
|
|
364
|
+
}
|
|
365
|
+
return -1;
|
|
366
|
+
}
|
|
367
|
+
function detune(source) {
|
|
368
|
+
let out = "";
|
|
369
|
+
let changed = false;
|
|
370
|
+
let hadLookaround = false;
|
|
371
|
+
const negativeBodies = [];
|
|
372
|
+
let inClass = false;
|
|
373
|
+
for (let i = 0; i < source.length; i++) {
|
|
374
|
+
const c = source[i];
|
|
375
|
+
if (c === "\\") {
|
|
376
|
+
out += c + (source[i + 1] ?? "");
|
|
377
|
+
i++;
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
if (inClass) {
|
|
381
|
+
out += c;
|
|
382
|
+
if (c === "]") inClass = false;
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
if (c === "[") {
|
|
386
|
+
out += c;
|
|
387
|
+
inClass = true;
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
if (c === "{") {
|
|
391
|
+
const counted = /^\{(\d+)(,(\d*))?\}/.exec(source.slice(i));
|
|
392
|
+
if (counted !== null) {
|
|
393
|
+
const min = Math.min(parseInt(counted[1], 10), MAX_COUNTED_REPEAT);
|
|
394
|
+
const upper = counted[3];
|
|
395
|
+
const max = upper === void 0 || upper === "" ? "" : String(Math.min(parseInt(upper, 10), MAX_COUNTED_REPEAT));
|
|
396
|
+
const rebuilt = counted[2] === void 0 ? `{${min}}` : `{${min},${max}}`;
|
|
397
|
+
if (rebuilt !== counted[0]) changed = true;
|
|
398
|
+
out += rebuilt;
|
|
399
|
+
i += counted[0].length - 1;
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
if (c === "(" && LOOKAROUND_AT.test(source.slice(i, i + 4))) {
|
|
404
|
+
const end = groupEnd(source, i);
|
|
405
|
+
if (end === -1) return null;
|
|
406
|
+
const behind = source[i + 2] === "<";
|
|
407
|
+
const negative = source[i + (behind ? 3 : 2)] === "!";
|
|
408
|
+
const body = source.slice(i + (behind ? 4 : 3), end);
|
|
409
|
+
if (negative) negativeBodies.push(body);
|
|
410
|
+
else out += `(?:${body})`;
|
|
411
|
+
i = end;
|
|
412
|
+
changed = true;
|
|
413
|
+
hadLookaround = true;
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
if (LITERAL_RUN_ATOM.test(c)) {
|
|
417
|
+
let run = 1;
|
|
418
|
+
while (source[i + run] === c) run++;
|
|
419
|
+
const quantified = QUANTIFIER_AT.test(source.slice(i + run, i + run + 1));
|
|
420
|
+
const collapsible = quantified ? run - 1 : run;
|
|
421
|
+
if (collapsible > MAX_COUNTED_REPEAT) {
|
|
422
|
+
out += c.repeat(MAX_COUNTED_REPEAT) + (quantified ? c : "");
|
|
423
|
+
i += run - 1;
|
|
424
|
+
changed = true;
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
out += c;
|
|
429
|
+
}
|
|
430
|
+
return changed ? { source: out, hadLookaround, negativeBodies } : null;
|
|
431
|
+
}
|
|
432
|
+
function projectsPastBudget(timings) {
|
|
433
|
+
const hi = timings.length - 1;
|
|
434
|
+
const hiLength = PROBE_LENGTHS[hi];
|
|
435
|
+
if (hiLength === void 0) return false;
|
|
436
|
+
const lo = PROBE_LENGTHS.findIndex((l) => l * 2 >= hiLength);
|
|
437
|
+
const loLength = PROBE_LENGTHS[lo];
|
|
438
|
+
const top = timings[hi];
|
|
439
|
+
const prior = timings[lo];
|
|
440
|
+
if (top === void 0 || prior === void 0 || loLength === void 0 || loLength >= hiLength) return false;
|
|
441
|
+
if (top <= TIMING_SIGNAL_MS || prior <= 0) return false;
|
|
442
|
+
const exponent = Math.log2(top / prior) / Math.log2(hiLength / loLength);
|
|
443
|
+
return top * (PROJECTED_LINE_LENGTH / hiLength) ** exponent > PROJECTION_BUDGET_MS;
|
|
444
|
+
}
|
|
445
|
+
var MAX_PATTERN_LENGTH = 4096;
|
|
446
|
+
function compileGuardedRegex(pattern, flags = "") {
|
|
447
|
+
if (pattern.length > MAX_PATTERN_LENGTH) {
|
|
448
|
+
return { ok: false, reason: `is longer than ${MAX_PATTERN_LENGTH} characters, which is past what can be checked for a stall` };
|
|
449
|
+
}
|
|
450
|
+
let re;
|
|
451
|
+
try {
|
|
452
|
+
re = new RegExp(pattern, flags);
|
|
453
|
+
} catch (e) {
|
|
454
|
+
return { ok: false, reason: e instanceof Error ? e.message : "is not a valid regular expression" };
|
|
455
|
+
}
|
|
456
|
+
if (!LINEAR_BY_CONSTRUCTION_EXCLUDES.test(pattern)) return { ok: true, re };
|
|
457
|
+
const cause = growsExponentially(re);
|
|
458
|
+
if (cause !== null) {
|
|
459
|
+
return {
|
|
460
|
+
ok: false,
|
|
461
|
+
reason: hasNestedQuantifier(pattern) ? "repeats a group that already repeats, which can take exponential time to match" : "takes time that climbs steeply with the length of the line, which can stall on ordinary text",
|
|
462
|
+
cause
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
return { ok: true, re };
|
|
466
|
+
}
|
|
467
|
+
var GUARDED_CACHE_LIMIT = 64;
|
|
468
|
+
var guardedCache = /* @__PURE__ */ new Map();
|
|
469
|
+
function compileGuardedRegexCached(pattern, flags = "") {
|
|
470
|
+
const key = `${flags}/${pattern}`;
|
|
471
|
+
const hit = guardedCache.get(key);
|
|
472
|
+
if (hit !== void 0) return hit;
|
|
473
|
+
const result = compileGuardedRegex(pattern, flags);
|
|
474
|
+
if (guardedCache.size >= GUARDED_CACHE_LIMIT) {
|
|
475
|
+
const oldest = guardedCache.keys().next();
|
|
476
|
+
if (!oldest.done) guardedCache.delete(oldest.value);
|
|
477
|
+
}
|
|
478
|
+
guardedCache.set(key, result);
|
|
479
|
+
return result;
|
|
480
|
+
}
|
|
481
|
+
|
|
222
482
|
// src/util_config.ts
|
|
223
483
|
init_define_import_meta_env();
|
|
224
|
-
import { readFileSync
|
|
225
|
-
import * as
|
|
484
|
+
import { readFileSync } from "node:fs";
|
|
485
|
+
import * as path2 from "node:path";
|
|
486
|
+
function commandHookFields(h) {
|
|
487
|
+
if (typeof h?.command !== "string") return void 0;
|
|
488
|
+
const args = Array.isArray(h.args) && h.args.every((a) => typeof a === "string") ? h.args : void 0;
|
|
489
|
+
return { command: h.command, args };
|
|
490
|
+
}
|
|
491
|
+
function isOwnHookEntry(h, isOurs) {
|
|
492
|
+
const fields = commandHookFields(h);
|
|
493
|
+
return fields !== void 0 && isOurs(fields.command, fields.args);
|
|
494
|
+
}
|
|
226
495
|
function stripOwnHooksFromMap(hooks, isOurs) {
|
|
227
496
|
let removed = false;
|
|
228
497
|
for (const eventKey of Object.keys(hooks)) {
|
|
@@ -231,7 +500,7 @@ function stripOwnHooksFromMap(hooks, isOurs) {
|
|
|
231
500
|
const kept = [];
|
|
232
501
|
for (const group of groups) {
|
|
233
502
|
const keptHooks = (group.hooks ?? []).filter((h) => {
|
|
234
|
-
const isOur =
|
|
503
|
+
const isOur = isOwnHookEntry(h, isOurs);
|
|
235
504
|
if (isOur) removed = true;
|
|
236
505
|
return !isOur;
|
|
237
506
|
});
|
|
@@ -257,7 +526,7 @@ function stripStaleGroupHooks(groups, isOurs, matcherFilter) {
|
|
|
257
526
|
next.push(group);
|
|
258
527
|
continue;
|
|
259
528
|
}
|
|
260
|
-
const keptHooks = (group.hooks ?? []).filter((h) => !
|
|
529
|
+
const keptHooks = (group.hooks ?? []).filter((h) => !isOwnHookEntry(h, isOurs));
|
|
261
530
|
if (keptHooks.length > 0) {
|
|
262
531
|
next.push({ ...group, hooks: keptHooks });
|
|
263
532
|
} else if ((group.hooks ?? []).length === 0) {
|
|
@@ -266,10 +535,13 @@ function stripStaleGroupHooks(groups, isOurs, matcherFilter) {
|
|
|
266
535
|
}
|
|
267
536
|
return next;
|
|
268
537
|
}
|
|
538
|
+
function detectEol(text) {
|
|
539
|
+
return text.includes("\r\n") ? "\r\n" : "\n";
|
|
540
|
+
}
|
|
269
541
|
function stripDelimitedBlock(p, beginMarker, endMarker, keepBackups = false) {
|
|
270
542
|
let existing;
|
|
271
543
|
try {
|
|
272
|
-
existing =
|
|
544
|
+
existing = readFileSync(p, "utf8");
|
|
273
545
|
} catch {
|
|
274
546
|
return false;
|
|
275
547
|
}
|
|
@@ -279,29 +551,29 @@ function stripDelimitedBlock(p, beginMarker, endMarker, keepBackups = false) {
|
|
|
279
551
|
const before = existing.slice(0, beginIdx).replace(/\s+$/, "");
|
|
280
552
|
const after = existing.slice(endIdx + endMarker.length).replace(/^\s+/, "");
|
|
281
553
|
let next;
|
|
554
|
+
const eol = detectEol(existing);
|
|
282
555
|
if (before.length > 0 && after.length > 0) {
|
|
283
|
-
next = `${before}
|
|
284
|
-
|
|
285
|
-
${after}`;
|
|
556
|
+
next = `${before}${eol}${eol}${after}`;
|
|
286
557
|
} else if (before.length > 0) {
|
|
287
|
-
next = `${before}
|
|
288
|
-
`;
|
|
558
|
+
next = `${before}${eol}`;
|
|
289
559
|
} else {
|
|
290
560
|
next = after;
|
|
291
561
|
}
|
|
292
562
|
backupFile(p);
|
|
293
|
-
atomicWriteText(p, next);
|
|
563
|
+
atomicWriteText(p, keepBom(existing, next));
|
|
294
564
|
if (!keepBackups) removeCreatedBackups(p);
|
|
295
565
|
return true;
|
|
296
566
|
}
|
|
297
|
-
function upsertDelimitedBlock(p, beginMarker, endMarker,
|
|
567
|
+
function upsertDelimitedBlock(p, beginMarker, endMarker, blockText) {
|
|
298
568
|
assertWriteInScope(p);
|
|
299
569
|
let existing;
|
|
300
570
|
try {
|
|
301
|
-
existing =
|
|
571
|
+
existing = readFileSync(p, "utf8");
|
|
302
572
|
} catch {
|
|
303
573
|
existing = "";
|
|
304
574
|
}
|
|
575
|
+
const eol = detectEol(existing);
|
|
576
|
+
const block = eol === "\n" ? blockText : blockText.replace(/\r?\n/g, eol);
|
|
305
577
|
const beginIdx = existing.indexOf(beginMarker);
|
|
306
578
|
const endIdx = existing.indexOf(endMarker);
|
|
307
579
|
if (beginIdx !== -1 && endIdx !== -1 && endIdx > beginIdx) {
|
|
@@ -309,42 +581,136 @@ function upsertDelimitedBlock(p, beginMarker, endMarker, block) {
|
|
|
309
581
|
const after = existing.slice(endIdx + endMarker.length);
|
|
310
582
|
const current = existing.slice(beginIdx, endIdx + endMarker.length);
|
|
311
583
|
if (current === block) return false;
|
|
312
|
-
ensureDirSync(
|
|
584
|
+
ensureDirSync(path2.dirname(p));
|
|
313
585
|
backupFile(p);
|
|
314
586
|
atomicWriteText(p, `${before}${block}${after}`);
|
|
315
587
|
return true;
|
|
316
588
|
}
|
|
317
589
|
const trimmed = existing.replace(/\s+$/, "");
|
|
318
|
-
const next = trimmed.length > 0 ? `${trimmed}
|
|
319
|
-
|
|
320
|
-
${block}
|
|
321
|
-
` : `${block}
|
|
322
|
-
`;
|
|
323
|
-
ensureDirSync(path3.dirname(p));
|
|
590
|
+
const next = trimmed.length > 0 ? `${trimmed}${eol}${eol}${block}${eol}` : `${block}${eol}`;
|
|
591
|
+
ensureDirSync(path2.dirname(p));
|
|
324
592
|
backupFile(p);
|
|
325
|
-
atomicWriteText(p, next);
|
|
593
|
+
atomicWriteText(p, keepBom(existing, next));
|
|
326
594
|
return true;
|
|
327
595
|
}
|
|
328
596
|
function writeJsonSettings(p, settings) {
|
|
329
|
-
ensureDirSync(
|
|
597
|
+
ensureDirSync(path2.dirname(p));
|
|
598
|
+
let existing = "";
|
|
599
|
+
try {
|
|
600
|
+
existing = readFileSync(p, "utf8");
|
|
601
|
+
} catch {
|
|
602
|
+
}
|
|
330
603
|
backupFile(p);
|
|
331
|
-
|
|
332
|
-
|
|
604
|
+
const eol = detectEol(existing);
|
|
605
|
+
const body = JSON.stringify(settings, null, detectJsonIndent(existing)).replace(/\n/g, eol);
|
|
606
|
+
atomicWriteText(p, keepBom(existing, existing.length > 0 && !existing.endsWith("\n") ? body : `${body}${eol}`));
|
|
607
|
+
}
|
|
608
|
+
var BOM = String.fromCharCode(65279);
|
|
609
|
+
function keepBom(existing, next) {
|
|
610
|
+
return existing?.startsWith(BOM) && !next.startsWith(BOM) ? `${BOM}${next}` : next;
|
|
611
|
+
}
|
|
612
|
+
function writeConfigText(p, next) {
|
|
613
|
+
let existing;
|
|
614
|
+
try {
|
|
615
|
+
existing = readFileSync(p, "utf8");
|
|
616
|
+
} catch {
|
|
617
|
+
existing = void 0;
|
|
618
|
+
}
|
|
619
|
+
atomicWriteText(p, keepBom(existing, next));
|
|
620
|
+
}
|
|
621
|
+
function detectJsonIndent(text) {
|
|
622
|
+
const lead = /^([ \t]+)\S/m.exec(text)?.[1];
|
|
623
|
+
if (lead === void 0) return " ";
|
|
624
|
+
return lead.startsWith(" ") ? " " : lead.slice(0, 10);
|
|
333
625
|
}
|
|
334
626
|
function writeIfDifferent(p, content, backup = false) {
|
|
335
627
|
let existing;
|
|
336
628
|
try {
|
|
337
|
-
existing =
|
|
629
|
+
existing = readFileSync(p, "utf8");
|
|
338
630
|
} catch {
|
|
339
631
|
existing = void 0;
|
|
340
632
|
}
|
|
341
633
|
if (existing === content) return false;
|
|
342
634
|
if (backup) backupFile(p);
|
|
343
|
-
ensureDirSync(
|
|
635
|
+
ensureDirSync(path2.dirname(p));
|
|
344
636
|
atomicWriteText(p, content);
|
|
345
637
|
return true;
|
|
346
638
|
}
|
|
347
639
|
|
|
640
|
+
// src/encoding.ts
|
|
641
|
+
init_define_import_meta_env();
|
|
642
|
+
function stripBom(text) {
|
|
643
|
+
return text.charCodeAt(0) === 65279 ? text.slice(1) : text;
|
|
644
|
+
}
|
|
645
|
+
function detectSourceEncoding(buf) {
|
|
646
|
+
if (buf.length >= 4) {
|
|
647
|
+
if (buf[0] === 255 && buf[1] === 254 && buf[2] === 0 && buf[3] === 0) return "utf32le";
|
|
648
|
+
if (buf[0] === 0 && buf[1] === 0 && buf[2] === 254 && buf[3] === 255) return "utf32be";
|
|
649
|
+
}
|
|
650
|
+
if (buf.length >= 2) {
|
|
651
|
+
if (buf[0] === 255 && buf[1] === 254) return "utf16le";
|
|
652
|
+
if (buf[0] === 254 && buf[1] === 255) return "utf16be";
|
|
653
|
+
}
|
|
654
|
+
if (buf.length >= 3 && buf[0] === 239 && buf[1] === 187 && buf[2] === 191) return "utf8-bom";
|
|
655
|
+
return "utf8";
|
|
656
|
+
}
|
|
657
|
+
function decodeSource(buf) {
|
|
658
|
+
switch (detectSourceEncoding(buf)) {
|
|
659
|
+
case "utf32le":
|
|
660
|
+
return decodeUtf32(buf.subarray(4), true);
|
|
661
|
+
case "utf32be":
|
|
662
|
+
return decodeUtf32(buf.subarray(4), false);
|
|
663
|
+
case "utf16le":
|
|
664
|
+
return buf.subarray(2).toString("utf16le");
|
|
665
|
+
case "utf16be":
|
|
666
|
+
return swap16(buf.subarray(2)).toString("utf16le");
|
|
667
|
+
case "utf8-bom":
|
|
668
|
+
return buf.subarray(3).toString("utf8");
|
|
669
|
+
default:
|
|
670
|
+
return buf.toString("utf8");
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
function encodeSource(text, encoding) {
|
|
674
|
+
switch (encoding) {
|
|
675
|
+
case "utf32le":
|
|
676
|
+
return Buffer.concat([Buffer.from([255, 254, 0, 0]), encodeUtf32(text, true)]);
|
|
677
|
+
case "utf32be":
|
|
678
|
+
return Buffer.concat([Buffer.from([0, 0, 254, 255]), encodeUtf32(text, false)]);
|
|
679
|
+
case "utf16le":
|
|
680
|
+
return Buffer.concat([Buffer.from([255, 254]), Buffer.from(text, "utf16le")]);
|
|
681
|
+
case "utf16be":
|
|
682
|
+
return Buffer.concat([Buffer.from([254, 255]), swap16(Buffer.from(text, "utf16le"))]);
|
|
683
|
+
case "utf8-bom":
|
|
684
|
+
return Buffer.concat([Buffer.from([239, 187, 191]), Buffer.from(text, "utf8")]);
|
|
685
|
+
default:
|
|
686
|
+
return Buffer.from(text, "utf8");
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
function swap16(buf) {
|
|
690
|
+
const out = Buffer.from(buf);
|
|
691
|
+
return out.subarray(0, out.length - out.length % 2).swap16();
|
|
692
|
+
}
|
|
693
|
+
function decodeUtf32(buf, littleEndian) {
|
|
694
|
+
const points = [];
|
|
695
|
+
for (let i = 0; i + 4 <= buf.length; i += 4) {
|
|
696
|
+
const cp = littleEndian ? buf.readUInt32LE(i) : buf.readUInt32BE(i);
|
|
697
|
+
points.push(cp > 1114111 || cp >= 55296 && cp <= 57343 ? 65533 : cp);
|
|
698
|
+
}
|
|
699
|
+
let out = "";
|
|
700
|
+
for (let i = 0; i < points.length; i += 8192) out += String.fromCodePoint(...points.slice(i, i + 8192));
|
|
701
|
+
return out;
|
|
702
|
+
}
|
|
703
|
+
function encodeUtf32(text, littleEndian) {
|
|
704
|
+
const points = [...text];
|
|
705
|
+
const out = Buffer.alloc(points.length * 4);
|
|
706
|
+
points.forEach((ch, i) => {
|
|
707
|
+
const cp = ch.codePointAt(0) ?? 65533;
|
|
708
|
+
if (littleEndian) out.writeUInt32LE(cp, i * 4);
|
|
709
|
+
else out.writeUInt32BE(cp, i * 4);
|
|
710
|
+
});
|
|
711
|
+
return out;
|
|
712
|
+
}
|
|
713
|
+
|
|
348
714
|
// src/util.ts
|
|
349
715
|
function runGit(args, opts = {}) {
|
|
350
716
|
const subArgs = args[0] === "diff" ? [args[0], "--no-ext-diff", "--no-textconv", ...args.slice(1)] : args;
|
|
@@ -387,8 +753,10 @@ function isRetryable(err) {
|
|
|
387
753
|
return typeof code === "string" && RETRYABLE_ERRNO.has(code);
|
|
388
754
|
}
|
|
389
755
|
function isEExist(err) {
|
|
390
|
-
|
|
391
|
-
|
|
756
|
+
return errnoCode(err) === "EEXIST";
|
|
757
|
+
}
|
|
758
|
+
function errnoCode(err) {
|
|
759
|
+
return typeof err === "object" && err !== null ? err.code : void 0;
|
|
392
760
|
}
|
|
393
761
|
function ensureDirSync(dir) {
|
|
394
762
|
assertWriteInScope(dir);
|
|
@@ -415,10 +783,28 @@ function withRetryOnLock(fn) {
|
|
|
415
783
|
}
|
|
416
784
|
throw lastErr;
|
|
417
785
|
}
|
|
418
|
-
function
|
|
419
|
-
|
|
786
|
+
function resolveSymlinkChain(p) {
|
|
787
|
+
const uid = typeof process.getuid === "function" ? process.getuid() : void 0;
|
|
788
|
+
let current = p;
|
|
789
|
+
for (let hops = 0; hops < 40; hops++) {
|
|
790
|
+
let st;
|
|
791
|
+
try {
|
|
792
|
+
st = lstatSync(current);
|
|
793
|
+
} catch (err) {
|
|
794
|
+
if (err.code === "ENOENT") return current;
|
|
795
|
+
throw err;
|
|
796
|
+
}
|
|
797
|
+
if (!st.isSymbolicLink() || uid !== void 0 && st.uid !== uid && st.uid !== 0) return current;
|
|
798
|
+
current = path3.resolve(path3.dirname(current), readlinkSync(current));
|
|
799
|
+
}
|
|
800
|
+
throw Object.assign(new Error(`ELOOP: too many levels of symbolic links, resolving ${p}`), { code: "ELOOP" });
|
|
801
|
+
}
|
|
802
|
+
function atomicWriteCore(requested, content) {
|
|
803
|
+
assertWriteInScope(requested);
|
|
804
|
+
const dest = resolveSymlinkChain(requested);
|
|
805
|
+
if (dest !== requested) assertWriteInScope(dest);
|
|
420
806
|
const tmp = `${dest}.${process.pid}.${process.hrtime.bigint().toString()}.tmp`;
|
|
421
|
-
ensureDirSync(
|
|
807
|
+
ensureDirSync(path3.dirname(dest));
|
|
422
808
|
try {
|
|
423
809
|
const fd = openSync(tmp, "w", 384);
|
|
424
810
|
try {
|
|
@@ -431,8 +817,8 @@ function atomicWriteCore(dest, content) {
|
|
|
431
817
|
closeSync(fd);
|
|
432
818
|
}
|
|
433
819
|
try {
|
|
434
|
-
const
|
|
435
|
-
chmodSync(tmp,
|
|
820
|
+
const destStat = lstatSync(dest);
|
|
821
|
+
if (!destStat.isSymbolicLink()) chmodSync(tmp, destStat.mode);
|
|
436
822
|
} catch (e) {
|
|
437
823
|
if (e.code !== "ENOENT") throw e;
|
|
438
824
|
}
|
|
@@ -454,19 +840,19 @@ function atomicWriteBytes(filePath, content) {
|
|
|
454
840
|
function installSingleFilePlugin(filePath, sidecarPath, template) {
|
|
455
841
|
let existing;
|
|
456
842
|
try {
|
|
457
|
-
existing =
|
|
843
|
+
existing = readFileSync2(filePath, "utf8");
|
|
458
844
|
} catch {
|
|
459
845
|
existing = void 0;
|
|
460
846
|
}
|
|
461
847
|
const entryPath = process.argv[1];
|
|
462
848
|
if (entryPath) {
|
|
463
|
-
ensureDirSync(
|
|
849
|
+
ensureDirSync(path3.dirname(filePath));
|
|
464
850
|
atomicWriteText(sidecarPath, JSON.stringify({ entryPath }));
|
|
465
851
|
}
|
|
466
852
|
if (existing === template) {
|
|
467
853
|
return { filePath, alreadyInstalled: true };
|
|
468
854
|
}
|
|
469
|
-
ensureDirSync(
|
|
855
|
+
ensureDirSync(path3.dirname(filePath));
|
|
470
856
|
atomicWriteText(filePath, template);
|
|
471
857
|
return { filePath, alreadyInstalled: false };
|
|
472
858
|
}
|
|
@@ -500,7 +886,7 @@ var MAX_BACKUPS_PER_FILE = 5;
|
|
|
500
886
|
var MAX_BACKUP_NAME_ATTEMPTS = 16;
|
|
501
887
|
function backupFile(p) {
|
|
502
888
|
assertWriteInScope(p);
|
|
503
|
-
if (!
|
|
889
|
+
if (!existsSync(p)) return;
|
|
504
890
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
505
891
|
let backupPath;
|
|
506
892
|
for (let attempt = 0; ; attempt++) {
|
|
@@ -541,6 +927,7 @@ var LOCK_WAIT_MS = 2e3;
|
|
|
541
927
|
var LOCK_STALE_MS = 5e3;
|
|
542
928
|
var LOCK_WAIT_MS_HARDENED = 15e3;
|
|
543
929
|
var LOCK_LIVE_HOLDER_MAX_MS = 6e4;
|
|
930
|
+
var LOCK_EPERM_RUN_MS = 1e3;
|
|
544
931
|
function lockHolderAlive(token) {
|
|
545
932
|
const pid = Number(/^(\d+):/.exec(token)?.[1]);
|
|
546
933
|
if (!Number.isSafeInteger(pid) || pid <= 0 || pid === process.pid) return false;
|
|
@@ -551,33 +938,61 @@ function lockHolderAlive(token) {
|
|
|
551
938
|
return err.code === "EPERM";
|
|
552
939
|
}
|
|
553
940
|
}
|
|
941
|
+
function lockAbandoned(lockPath, staleMs) {
|
|
942
|
+
const age = Date.now() - statSync(lockPath).mtimeMs;
|
|
943
|
+
return age > staleMs && (age > Math.max(staleMs, LOCK_LIVE_HOLDER_MAX_MS) || !lockHolderAlive(readFileSync2(lockPath, "utf8")));
|
|
944
|
+
}
|
|
945
|
+
function stealAbandoned(lockPath, staleMs) {
|
|
946
|
+
const guardPath = `${lockPath}.steal`;
|
|
947
|
+
try {
|
|
948
|
+
writeFileSync(guardPath, "", { flag: "wx" });
|
|
949
|
+
} catch (err) {
|
|
950
|
+
try {
|
|
951
|
+
if (isEExist(err) && Date.now() - statSync(guardPath).mtimeMs > staleMs) unlinkSync(guardPath);
|
|
952
|
+
} catch {
|
|
953
|
+
}
|
|
954
|
+
return false;
|
|
955
|
+
}
|
|
956
|
+
try {
|
|
957
|
+
if (lockAbandoned(lockPath, staleMs)) unlinkSync(lockPath);
|
|
958
|
+
} catch {
|
|
959
|
+
} finally {
|
|
960
|
+
try {
|
|
961
|
+
unlinkSync(guardPath);
|
|
962
|
+
} catch {
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
return true;
|
|
966
|
+
}
|
|
554
967
|
function withFileLock(lockPath, fn, opts = {}) {
|
|
555
968
|
const waitMs = opts.waitMs ?? LOCK_WAIT_MS;
|
|
556
969
|
const staleMs = opts.staleMs ?? LOCK_STALE_MS;
|
|
557
970
|
const token = `${process.pid}:${process.hrtime.bigint().toString()}`;
|
|
558
971
|
const deadline = Date.now() + waitMs;
|
|
559
972
|
let attempt = 0;
|
|
973
|
+
let epermSince;
|
|
560
974
|
for (; ; ) {
|
|
561
975
|
try {
|
|
562
976
|
writeFileSync(lockPath, token, { flag: "wx" });
|
|
563
977
|
break;
|
|
564
978
|
} catch (err) {
|
|
979
|
+
if (process.platform === "win32" && errnoCode(err) === "EPERM") {
|
|
980
|
+
epermSince ??= Date.now();
|
|
981
|
+
if (Date.now() >= deadline || Date.now() - epermSince >= LOCK_EPERM_RUN_MS) return void 0;
|
|
982
|
+
sleepSync(Math.min(20 * ++attempt, 200));
|
|
983
|
+
continue;
|
|
984
|
+
}
|
|
565
985
|
if (!isEExist(err)) return void 0;
|
|
986
|
+
epermSince = void 0;
|
|
566
987
|
}
|
|
567
988
|
let stale;
|
|
568
989
|
try {
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
stale =
|
|
573
|
-
}
|
|
574
|
-
if (stale) {
|
|
575
|
-
try {
|
|
576
|
-
unlinkSync(lockPath);
|
|
577
|
-
} catch {
|
|
578
|
-
}
|
|
579
|
-
continue;
|
|
990
|
+
stale = lockAbandoned(lockPath, staleMs);
|
|
991
|
+
} catch (err) {
|
|
992
|
+
if (errnoCode(err) === "ENOENT") continue;
|
|
993
|
+
stale = false;
|
|
580
994
|
}
|
|
995
|
+
if (stale && stealAbandoned(lockPath, staleMs)) continue;
|
|
581
996
|
if (Date.now() >= deadline) return void 0;
|
|
582
997
|
sleepSync(Math.min(20 * ++attempt, 200));
|
|
583
998
|
}
|
|
@@ -585,7 +1000,7 @@ function withFileLock(lockPath, fn, opts = {}) {
|
|
|
585
1000
|
return fn();
|
|
586
1001
|
} finally {
|
|
587
1002
|
try {
|
|
588
|
-
if (
|
|
1003
|
+
if (readFileSync2(lockPath, "utf8") === token) unlinkSync(lockPath);
|
|
589
1004
|
} catch {
|
|
590
1005
|
}
|
|
591
1006
|
}
|
|
@@ -643,9 +1058,9 @@ function redactUrlQuery(raw) {
|
|
|
643
1058
|
}
|
|
644
1059
|
function withExtension(filePath, format) {
|
|
645
1060
|
const ext = format === "jpeg" ? ".jpg" : `.${format}`;
|
|
646
|
-
const dir =
|
|
647
|
-
const base =
|
|
648
|
-
return
|
|
1061
|
+
const dir = path3.dirname(filePath);
|
|
1062
|
+
const base = path3.basename(filePath, path3.extname(filePath));
|
|
1063
|
+
return path3.join(dir, `${base}${ext}`);
|
|
649
1064
|
}
|
|
650
1065
|
function ensureNewline(text) {
|
|
651
1066
|
return text.endsWith("\n") ? text : text + "\n";
|
|
@@ -704,10 +1119,10 @@ function isTestFile(p) {
|
|
|
704
1119
|
}
|
|
705
1120
|
function isUnderBlockedRoot(filePath, blockedRoots) {
|
|
706
1121
|
if (blockedRoots.length === 0) return false;
|
|
707
|
-
const target = foldPath(normalizePath(
|
|
1122
|
+
const target = foldPath(normalizePath(path3.resolve(filePath)));
|
|
708
1123
|
for (const root of blockedRoots) {
|
|
709
1124
|
if (!root) continue;
|
|
710
|
-
const normRoot = foldPath(normalizePath(
|
|
1125
|
+
const normRoot = foldPath(normalizePath(path3.resolve(root)));
|
|
711
1126
|
if (target === normRoot) return true;
|
|
712
1127
|
const boundary = normRoot.endsWith("/") ? normRoot : `${normRoot}/`;
|
|
713
1128
|
if (target.startsWith(boundary)) return true;
|
|
@@ -740,21 +1155,158 @@ function hookPowershellCommand(scriptPath, event) {
|
|
|
740
1155
|
return `${quotePowershellPath(process.execPath)} ${quotePowershellPath(scriptPath)} ${event}${entryArg}`;
|
|
741
1156
|
}
|
|
742
1157
|
|
|
1158
|
+
// src/bridges/created_configs.ts
|
|
1159
|
+
function ledgerPath() {
|
|
1160
|
+
return path4.join(dataDir(), "created-configs.json");
|
|
1161
|
+
}
|
|
1162
|
+
function keyOf(filePath) {
|
|
1163
|
+
return normalizePath(path4.resolve(filePath));
|
|
1164
|
+
}
|
|
1165
|
+
function foldKey(key) {
|
|
1166
|
+
return foldPath(key);
|
|
1167
|
+
}
|
|
1168
|
+
function readLedger() {
|
|
1169
|
+
try {
|
|
1170
|
+
const parsed = JSON.parse(fs.readFileSync(ledgerPath(), "utf8"));
|
|
1171
|
+
return Array.isArray(parsed) ? parsed.filter((entry) => typeof entry === "string") : [];
|
|
1172
|
+
} catch {
|
|
1173
|
+
return [];
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
function writeLedger(entries) {
|
|
1177
|
+
try {
|
|
1178
|
+
ensureDirSync(path4.dirname(ledgerPath()));
|
|
1179
|
+
atomicWriteText(ledgerPath(), `${JSON.stringify(entries)}
|
|
1180
|
+
`);
|
|
1181
|
+
} catch {
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
function recordCreatedConfig(filePath) {
|
|
1185
|
+
const key = keyOf(filePath);
|
|
1186
|
+
const entries = readLedger();
|
|
1187
|
+
if (entries.some((entry) => foldKey(entry) === foldKey(key))) return;
|
|
1188
|
+
writeLedger([...entries, key]);
|
|
1189
|
+
}
|
|
1190
|
+
function hasCreatedConfig(filePath) {
|
|
1191
|
+
const key = foldKey(keyOf(filePath));
|
|
1192
|
+
return readLedger().some((entry) => foldKey(entry) === key);
|
|
1193
|
+
}
|
|
1194
|
+
function takeCreatedConfig(filePath) {
|
|
1195
|
+
const key = foldKey(keyOf(filePath));
|
|
1196
|
+
const entries = readLedger();
|
|
1197
|
+
if (!entries.some((entry) => foldKey(entry) === key)) return false;
|
|
1198
|
+
writeLedger(entries.filter((entry) => foldKey(entry) !== key));
|
|
1199
|
+
return true;
|
|
1200
|
+
}
|
|
1201
|
+
function rootKeyMarker(filePath, rootKey) {
|
|
1202
|
+
return `${filePath}#root-key=${rootKey}`;
|
|
1203
|
+
}
|
|
1204
|
+
function recordCreatedRootKey(filePath, rootKey) {
|
|
1205
|
+
recordCreatedConfig(rootKeyMarker(filePath, rootKey));
|
|
1206
|
+
}
|
|
1207
|
+
function takeCreatedRootKey(filePath, rootKey) {
|
|
1208
|
+
return takeCreatedConfig(rootKeyMarker(filePath, rootKey));
|
|
1209
|
+
}
|
|
1210
|
+
function recordCreatedBackup(backupPath) {
|
|
1211
|
+
recordCreatedConfig(backupPath);
|
|
1212
|
+
}
|
|
1213
|
+
function forgetCreatedBackup(backupPath) {
|
|
1214
|
+
takeCreatedConfig(backupPath);
|
|
1215
|
+
}
|
|
1216
|
+
function createdBackupsFor(configPath) {
|
|
1217
|
+
const prefix = foldKey(`${keyOf(configPath)}.bak.`);
|
|
1218
|
+
return readLedger().filter((entry) => foldKey(entry).startsWith(prefix)).sort();
|
|
1219
|
+
}
|
|
1220
|
+
function removeCreatedBackups(configPath) {
|
|
1221
|
+
const prefix = foldKey(`${keyOf(configPath)}.bak.`);
|
|
1222
|
+
const entries = readLedger();
|
|
1223
|
+
const ours = entries.filter((entry) => foldKey(entry).startsWith(prefix));
|
|
1224
|
+
if (ours.length === 0) return 0;
|
|
1225
|
+
const failed = /* @__PURE__ */ new Set();
|
|
1226
|
+
let removed = 0;
|
|
1227
|
+
for (const target of ours) {
|
|
1228
|
+
try {
|
|
1229
|
+
if (fs.existsSync(target) && removeFileInScope(target)) {
|
|
1230
|
+
removed++;
|
|
1231
|
+
}
|
|
1232
|
+
} catch {
|
|
1233
|
+
failed.add(target);
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
writeLedger(entries.filter((entry) => !ours.includes(entry) || failed.has(entry)));
|
|
1237
|
+
return removed;
|
|
1238
|
+
}
|
|
1239
|
+
function ensureDirRecordingCreation(dir) {
|
|
1240
|
+
const existed = fs.existsSync(dir);
|
|
1241
|
+
ensureDirSync(dir);
|
|
1242
|
+
if (!existed) recordCreatedConfig(dir);
|
|
1243
|
+
}
|
|
1244
|
+
function holdsNothing(text) {
|
|
1245
|
+
const trimmed = text.trim();
|
|
1246
|
+
return trimmed === "" || /^\{\s*\}$/.test(trimmed);
|
|
1247
|
+
}
|
|
1248
|
+
function removeCreatedIfEmpty(target) {
|
|
1249
|
+
if (!hasCreatedConfig(target)) return;
|
|
1250
|
+
let removed = false;
|
|
1251
|
+
try {
|
|
1252
|
+
removed = fs.lstatSync(target).isDirectory() ? removeEmptyDirInScope(target) : holdsNothing(fs.readFileSync(target, "utf8")) && removeFileInScope(target);
|
|
1253
|
+
} catch {
|
|
1254
|
+
}
|
|
1255
|
+
if (removed) takeCreatedConfig(target);
|
|
1256
|
+
}
|
|
1257
|
+
function recordCreatedBy(targets, work) {
|
|
1258
|
+
const absent = /* @__PURE__ */ new Set();
|
|
1259
|
+
for (const target of targets) {
|
|
1260
|
+
for (let p = path4.resolve(target); !fs.existsSync(p) && !absent.has(p); p = path4.dirname(p)) absent.add(p);
|
|
1261
|
+
}
|
|
1262
|
+
try {
|
|
1263
|
+
return work();
|
|
1264
|
+
} finally {
|
|
1265
|
+
for (const p of absent) if (fs.existsSync(p)) recordCreatedConfig(p);
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
function removeCreatedTree(targets) {
|
|
1269
|
+
const paths = /* @__PURE__ */ new Set();
|
|
1270
|
+
for (const target of targets) {
|
|
1271
|
+
for (let p = path4.resolve(target); !paths.has(p); p = path4.dirname(p)) {
|
|
1272
|
+
paths.add(p);
|
|
1273
|
+
if (path4.dirname(p) === p) break;
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
for (const p of [...paths].sort((a, b) => b.length - a.length)) {
|
|
1277
|
+
if (fs.existsSync(p)) removeCreatedIfEmpty(p);
|
|
1278
|
+
else if (hasCreatedConfig(p)) takeCreatedConfig(p);
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
|
|
743
1282
|
export {
|
|
744
1283
|
recordCreatedConfig,
|
|
745
1284
|
hasCreatedConfig,
|
|
746
1285
|
takeCreatedConfig,
|
|
1286
|
+
recordCreatedRootKey,
|
|
1287
|
+
takeCreatedRootKey,
|
|
747
1288
|
removeCreatedBackups,
|
|
1289
|
+
ensureDirRecordingCreation,
|
|
1290
|
+
removeCreatedIfEmpty,
|
|
1291
|
+
recordCreatedBy,
|
|
1292
|
+
removeCreatedTree,
|
|
748
1293
|
assertProjectScopeTarget,
|
|
749
1294
|
withInstallScope,
|
|
750
1295
|
projectScopeRoot,
|
|
751
1296
|
assertWriteInScope,
|
|
752
1297
|
projectPathIsConsultable,
|
|
1298
|
+
hasNestedQuantifier,
|
|
1299
|
+
growsExponentially,
|
|
1300
|
+
compileGuardedRegex,
|
|
1301
|
+
compileGuardedRegexCached,
|
|
1302
|
+
commandHookFields,
|
|
1303
|
+
isOwnHookEntry,
|
|
753
1304
|
stripOwnHooksFromMap,
|
|
754
1305
|
stripStaleGroupHooks,
|
|
755
1306
|
stripDelimitedBlock,
|
|
756
1307
|
upsertDelimitedBlock,
|
|
757
1308
|
writeJsonSettings,
|
|
1309
|
+
writeConfigText,
|
|
758
1310
|
writeIfDifferent,
|
|
759
1311
|
stripBom,
|
|
760
1312
|
detectSourceEncoding,
|