openapi-typesafe-migrate 1.0.0-rc.10 → 1.0.0-rc.12
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/CHANGELOG.md +124 -0
- package/README.md +41 -9
- package/dist/cli/main.mjs +1487 -745
- package/dist/cli/main.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli/main.mjs
CHANGED
|
@@ -910,12 +910,19 @@ function optionsOf(argument, bindings) {
|
|
|
910
910
|
}
|
|
911
911
|
return ts.isIdentifier(value) ? constantOptions(value, bindings, types) : { kind: "unknown", expression: argument };
|
|
912
912
|
}
|
|
913
|
+
const UNDEFINED = "undefined";
|
|
914
|
+
function isNoValue(argument, bindings) {
|
|
915
|
+
const { value } = unwrapped(argument);
|
|
916
|
+
const isUndefined = ts.isIdentifier(value) && value.text === UNDEFINED && bindings.declarationOf(value) === void 0;
|
|
917
|
+
return isUndefined || ts.isVoidExpression(value);
|
|
918
|
+
}
|
|
913
919
|
function generatorCalls(file, bindings) {
|
|
914
920
|
const calls = [];
|
|
915
921
|
const visit = (node) => {
|
|
916
922
|
if (ts.isCallExpression(node) && isGenerator(node.expression, bindings)) {
|
|
917
923
|
const argument = node.arguments[1];
|
|
918
|
-
const
|
|
924
|
+
const isOmitted = argument === void 0 || isNoValue(argument, bindings);
|
|
925
|
+
const options = isOmitted ? void 0 : optionsOf(argument, bindings);
|
|
919
926
|
calls.push({ call: node, options });
|
|
920
927
|
}
|
|
921
928
|
ts.forEachChild(node, visit);
|
|
@@ -949,7 +956,7 @@ function importTypeName(node) {
|
|
|
949
956
|
const isOptions = !node.isTypeOf && qualifier !== void 0 && ts.isIdentifier(qualifier) && qualifier.text === TS_NODE_OPTIONS;
|
|
950
957
|
return isGeneratorModule && isOptions ? qualifier : void 0;
|
|
951
958
|
}
|
|
952
|
-
function referencedName$
|
|
959
|
+
function referencedName$2(node) {
|
|
953
960
|
if (ts.isTypeReferenceNode(node)) {
|
|
954
961
|
return node.typeName;
|
|
955
962
|
}
|
|
@@ -965,7 +972,7 @@ function optionsTypeName(node, bindings) {
|
|
|
965
972
|
if (ts.isImportTypeNode(node)) {
|
|
966
973
|
return importTypeName(node);
|
|
967
974
|
}
|
|
968
|
-
const name = referencedName$
|
|
975
|
+
const name = referencedName$2(node);
|
|
969
976
|
if (name !== void 0 && ts.isIdentifier(name)) {
|
|
970
977
|
const binding = bindings.bindingOf(name);
|
|
971
978
|
return binding?.kind === "helper-import" && binding.name === TS_NODE_OPTIONS ? name : void 0;
|
|
@@ -978,7 +985,7 @@ function optionsTypeName(node, bindings) {
|
|
|
978
985
|
return isGeneratorModule && parts.right.text === TS_NODE_OPTIONS ? parts.right : void 0;
|
|
979
986
|
}
|
|
980
987
|
function localTypeOf(node, bindings) {
|
|
981
|
-
const name = referencedName$
|
|
988
|
+
const name = referencedName$2(node);
|
|
982
989
|
const binding = name !== void 0 && ts.isIdentifier(name) ? bindings.bindingOf(name) : void 0;
|
|
983
990
|
return binding?.kind === "local-type" ? binding.declaration : void 0;
|
|
984
991
|
}
|
|
@@ -2072,10 +2079,10 @@ const PNPM_SETTINGS_FIELD = "pnpm";
|
|
|
2072
2079
|
const OLD_PEER_DEPENDENTS = /* @__PURE__ */ new Map([
|
|
2073
2080
|
["swr-openapi", { peer: "openapi-fetch", range: ">=0.15" }]
|
|
2074
2081
|
]);
|
|
2075
|
-
const PATH_SEPARATOR$
|
|
2082
|
+
const PATH_SEPARATOR$b = "/";
|
|
2076
2083
|
const QUERY_START = "?";
|
|
2077
2084
|
function renamedSpecifier(value) {
|
|
2078
|
-
const ends = [value.indexOf(PATH_SEPARATOR$
|
|
2085
|
+
const ends = [value.indexOf(PATH_SEPARATOR$b), value.indexOf(QUERY_START)].filter(
|
|
2079
2086
|
(at) => at !== -1
|
|
2080
2087
|
);
|
|
2081
2088
|
const name = value.slice(0, ends.length === 0 ? value.length : Math.min(...ends));
|
|
@@ -2085,12 +2092,12 @@ function renamedSpecifier(value) {
|
|
|
2085
2092
|
}
|
|
2086
2093
|
const rest = value.slice(name.length);
|
|
2087
2094
|
const subpath = rest.split(QUERY_START, 1)[0] ?? rest;
|
|
2088
|
-
return { to: `${renamed}${rest}`, isDeep: subpath !== "" && subpath !== PATH_SEPARATOR$
|
|
2095
|
+
return { to: `${renamed}${rest}`, isDeep: subpath !== "" && subpath !== PATH_SEPARATOR$b };
|
|
2089
2096
|
}
|
|
2090
2097
|
const NODE_MODULES_FOLDER = "node_modules/";
|
|
2091
2098
|
function oldPackageInNodeModules(path) {
|
|
2092
2099
|
return [...PACKAGE_RENAMES.keys()].find(
|
|
2093
|
-
(name) => path.includes(`${NODE_MODULES_FOLDER}${name}${PATH_SEPARATOR$
|
|
2100
|
+
(name) => path.includes(`${NODE_MODULES_FOLDER}${name}${PATH_SEPARATOR$b}`) || path.endsWith(`${NODE_MODULES_FOLDER}${name}`)
|
|
2094
2101
|
);
|
|
2095
2102
|
}
|
|
2096
2103
|
|
|
@@ -2203,22 +2210,166 @@ function referencedFiles(path, documents) {
|
|
|
2203
2210
|
});
|
|
2204
2211
|
}
|
|
2205
2212
|
|
|
2213
|
+
const NONE = /* @__PURE__ */ new Set();
|
|
2214
|
+
const PACKAGE_OPTIONS = /* @__PURE__ */ new Set(["-p", "--package"]);
|
|
2215
|
+
const PACKAGE_MANAGER_OPTIONS = /* @__PURE__ */ new Set([
|
|
2216
|
+
"--filter",
|
|
2217
|
+
"-F",
|
|
2218
|
+
"--dir",
|
|
2219
|
+
"-C",
|
|
2220
|
+
"--prefix",
|
|
2221
|
+
"--cwd",
|
|
2222
|
+
"--workspace"
|
|
2223
|
+
]);
|
|
2224
|
+
const launcher = (words, packageOptions = NONE, valueOptions = NONE) => {
|
|
2225
|
+
const allValueOptions = /* @__PURE__ */ new Set([...valueOptions, ...packageOptions]);
|
|
2226
|
+
return { words, packageOptions, valueOptions: allValueOptions, operands: 0 };
|
|
2227
|
+
};
|
|
2228
|
+
const CONTAINER_OPTIONS = /* @__PURE__ */ new Set([
|
|
2229
|
+
"-e",
|
|
2230
|
+
"--env",
|
|
2231
|
+
"--env-file",
|
|
2232
|
+
"-v",
|
|
2233
|
+
"--volume",
|
|
2234
|
+
"--mount",
|
|
2235
|
+
"-p",
|
|
2236
|
+
"--publish",
|
|
2237
|
+
"-w",
|
|
2238
|
+
"--workdir",
|
|
2239
|
+
"-u",
|
|
2240
|
+
"--user",
|
|
2241
|
+
"--name",
|
|
2242
|
+
"--network",
|
|
2243
|
+
"--entrypoint",
|
|
2244
|
+
"--platform",
|
|
2245
|
+
"-l",
|
|
2246
|
+
"--label",
|
|
2247
|
+
"-h",
|
|
2248
|
+
"--hostname",
|
|
2249
|
+
"--add-host"
|
|
2250
|
+
]);
|
|
2251
|
+
const container = (words) => ({
|
|
2252
|
+
...launcher(words, NONE, CONTAINER_OPTIONS),
|
|
2253
|
+
operands: 1
|
|
2254
|
+
});
|
|
2255
|
+
const withOperands = (words, operands, valueOptions = NONE) => ({ ...launcher(words, NONE, valueOptions), operands });
|
|
2256
|
+
const XARGS_OPTIONS = /* @__PURE__ */ new Set([
|
|
2257
|
+
"-I",
|
|
2258
|
+
"-J",
|
|
2259
|
+
"-L",
|
|
2260
|
+
"-n",
|
|
2261
|
+
"-P",
|
|
2262
|
+
"-R",
|
|
2263
|
+
"-S",
|
|
2264
|
+
"-s",
|
|
2265
|
+
"-d",
|
|
2266
|
+
"-E",
|
|
2267
|
+
"-a",
|
|
2268
|
+
"--max-args",
|
|
2269
|
+
"--max-procs",
|
|
2270
|
+
"--max-lines",
|
|
2271
|
+
"--delimiter",
|
|
2272
|
+
"--arg-file"
|
|
2273
|
+
]);
|
|
2274
|
+
const NODE_OPTIONS = /* @__PURE__ */ new Set([
|
|
2275
|
+
"-r",
|
|
2276
|
+
"--require",
|
|
2277
|
+
"--import",
|
|
2278
|
+
"--loader",
|
|
2279
|
+
"--env-file"
|
|
2280
|
+
]);
|
|
2281
|
+
const LAUNCHERS = [
|
|
2282
|
+
launcher(["npm", "exec"], PACKAGE_OPTIONS),
|
|
2283
|
+
launcher(["npm", "x"], PACKAGE_OPTIONS),
|
|
2284
|
+
launcher(["pnpm", "exec"], NONE, PACKAGE_MANAGER_OPTIONS),
|
|
2285
|
+
launcher(["pnpm", "dlx"], /* @__PURE__ */ new Set(["--package"])),
|
|
2286
|
+
launcher(["yarn", "dlx"], PACKAGE_OPTIONS),
|
|
2287
|
+
launcher(["yarn", "exec"]),
|
|
2288
|
+
launcher(["bun", "x"], PACKAGE_OPTIONS),
|
|
2289
|
+
withOperands(["yarn", "workspace"], 1),
|
|
2290
|
+
launcher(["dotenvx", "run"], NONE, /* @__PURE__ */ new Set(["-f", "--env-file", "-e", "--env", "--convention"])),
|
|
2291
|
+
launcher(
|
|
2292
|
+
["doppler", "run"],
|
|
2293
|
+
NONE,
|
|
2294
|
+
/* @__PURE__ */ new Set(["-p", "--project", "-c", "--config", "--token", "--mount", "--scope"])
|
|
2295
|
+
),
|
|
2296
|
+
launcher(["nx", "exec"], NONE, /* @__PURE__ */ new Set(["--projects", "-p", "--exclude"])),
|
|
2297
|
+
launcher(["deno", "run"], NONE, /* @__PURE__ */ new Set(["--config", "-c", "--import-map", "--location"])),
|
|
2298
|
+
launcher(["deno", "x"]),
|
|
2299
|
+
launcher(["npx"], PACKAGE_OPTIONS, /* @__PURE__ */ new Set(["-c", "--call"])),
|
|
2300
|
+
launcher(["pnpx"], PACKAGE_OPTIONS),
|
|
2301
|
+
launcher(["bunx"], PACKAGE_OPTIONS),
|
|
2302
|
+
// Like a bare `pnpm <name>`, a bare `bun <name>` runs the binary when no script has the name.
|
|
2303
|
+
launcher(["bun"], NONE, /* @__PURE__ */ new Set(["--cwd", "--filter", "-F"])),
|
|
2304
|
+
launcher(["corepack"]),
|
|
2305
|
+
launcher(["pnpm"], NONE, PACKAGE_MANAGER_OPTIONS),
|
|
2306
|
+
launcher(["yarn"], NONE, PACKAGE_MANAGER_OPTIONS),
|
|
2307
|
+
launcher(["node"], NONE, NODE_OPTIONS),
|
|
2308
|
+
launcher(["tsx"], NONE, NODE_OPTIONS),
|
|
2309
|
+
launcher(["ts-node"], NONE, /* @__PURE__ */ new Set([...NODE_OPTIONS, "-P", "--project", "-O", "--compiler"])),
|
|
2310
|
+
launcher(["cross-env"]),
|
|
2311
|
+
launcher(["dotenv"], NONE, /* @__PURE__ */ new Set(["-e", "-c", "-v"])),
|
|
2312
|
+
launcher(["env"], NONE, /* @__PURE__ */ new Set(["-u", "--unset", "-C", "--chdir"])),
|
|
2313
|
+
launcher(["exec"], NONE, /* @__PURE__ */ new Set(["-a"])),
|
|
2314
|
+
launcher(["command"]),
|
|
2315
|
+
launcher(["time"]),
|
|
2316
|
+
launcher(["nice"], NONE, /* @__PURE__ */ new Set(["-n", "--adjustment"])),
|
|
2317
|
+
withOperands(["timeout"], 1, /* @__PURE__ */ new Set(["-s", "--signal", "-k", "--kill-after"])),
|
|
2318
|
+
launcher(["xargs"], NONE, XARGS_OPTIONS),
|
|
2319
|
+
launcher(["nohup"]),
|
|
2320
|
+
launcher(["sudo"], NONE, /* @__PURE__ */ new Set(["-u", "-g"])),
|
|
2321
|
+
// The init programs of containers run their arguments as the container's command, so an
|
|
2322
|
+
// entrypoint `["tini", "--"]` gives the generator the command's flags.
|
|
2323
|
+
launcher(["tini"], NONE, /* @__PURE__ */ new Set(["-p", "-e"])),
|
|
2324
|
+
launcher(["docker-init"], NONE, /* @__PURE__ */ new Set(["-p", "-e"])),
|
|
2325
|
+
launcher(["dumb-init"], NONE, /* @__PURE__ */ new Set(["-r", "--rewrite"])),
|
|
2326
|
+
launcher(["catatonit"]),
|
|
2327
|
+
withOperands(["gosu"], 1),
|
|
2328
|
+
withOperands(["su-exec"], 1),
|
|
2329
|
+
// The shell form of Dockerfile instructions runs the rest of the line in a shell.
|
|
2330
|
+
launcher(["RUN"], NONE, /* @__PURE__ */ new Set(["--mount", "--network", "--security"])),
|
|
2331
|
+
launcher(["CMD"]),
|
|
2332
|
+
launcher(["ENTRYPOINT"]),
|
|
2333
|
+
container(["docker", "run"]),
|
|
2334
|
+
container(["docker", "exec"]),
|
|
2335
|
+
container(["docker", "compose", "run"]),
|
|
2336
|
+
container(["docker", "compose", "exec"]),
|
|
2337
|
+
container(["podman", "run"]),
|
|
2338
|
+
container(["podman", "exec"])
|
|
2339
|
+
];
|
|
2340
|
+
const installers = (manager, subcommands) => subcommands.map((subcommand) => ({ words: [manager, subcommand] }));
|
|
2341
|
+
const NPM_INSTALL = ["install", "i", "add", "update", "up", "uninstall", "remove", "rm", "un"];
|
|
2342
|
+
const INSTALLERS = [
|
|
2343
|
+
...installers("npm", NPM_INSTALL),
|
|
2344
|
+
...installers("pnpm", ["add", "update", "up", "remove", "rm", "uninstall", "un"]),
|
|
2345
|
+
...installers("yarn", ["add", "upgrade", "up", "remove"]),
|
|
2346
|
+
// Yarn 1 installs global packages with `yarn global add`.
|
|
2347
|
+
{ words: ["yarn", "global", "add"] },
|
|
2348
|
+
{ words: ["yarn", "global", "remove"] },
|
|
2349
|
+
...installers("bun", ["add", "a", "update", "remove", "rm", "install", "i"]),
|
|
2350
|
+
...installers("deno", ["add", "install", "i", "remove", "uninstall"])
|
|
2351
|
+
];
|
|
2352
|
+
const NPM_SPECIFIER_PREFIX = "npm:";
|
|
2353
|
+
|
|
2206
2354
|
const EXPRESSION_OPEN = "${{";
|
|
2207
|
-
const EXPRESSION_CLOSE = "}}";
|
|
2355
|
+
const EXPRESSION_CLOSE$1 = "}}";
|
|
2208
2356
|
const LITERAL_QUOTE = "'";
|
|
2209
2357
|
const SHELL_SINGLE_QUOTE = "'";
|
|
2210
2358
|
const BACKSLASH$3 = "\\";
|
|
2211
|
-
const DOUBLE_QUOTE$
|
|
2359
|
+
const DOUBLE_QUOTE$2 = '"';
|
|
2212
2360
|
function expressionEnd(text, start) {
|
|
2213
2361
|
for (let index = start + EXPRESSION_OPEN.length; index < text.length; ) {
|
|
2214
|
-
if (text.startsWith(EXPRESSION_CLOSE, index)) {
|
|
2215
|
-
return index + EXPRESSION_CLOSE.length;
|
|
2362
|
+
if (text.startsWith(EXPRESSION_CLOSE$1, index)) {
|
|
2363
|
+
return index + EXPRESSION_CLOSE$1.length;
|
|
2216
2364
|
}
|
|
2217
2365
|
const close = text[index] === LITERAL_QUOTE ? text.indexOf(LITERAL_QUOTE, index + 1) : index;
|
|
2218
2366
|
index = close === -1 ? text.length : close + 1;
|
|
2219
2367
|
}
|
|
2220
2368
|
return void 0;
|
|
2221
2369
|
}
|
|
2370
|
+
const INDEX_OPEN = "[";
|
|
2371
|
+
const TRAILING_BLANKS_RE = /[ \t]*$/;
|
|
2372
|
+
const isIndexKey = (raw, open) => raw.slice(0, open).replace(TRAILING_BLANKS_RE, "").endsWith(INDEX_OPEN);
|
|
2222
2373
|
function literalsIn(raw, start, end) {
|
|
2223
2374
|
const found = [];
|
|
2224
2375
|
let open = raw.indexOf(LITERAL_QUOTE, start);
|
|
@@ -2232,7 +2383,8 @@ function literalsIn(raw, start, end) {
|
|
|
2232
2383
|
if (close === -1) {
|
|
2233
2384
|
break;
|
|
2234
2385
|
}
|
|
2235
|
-
|
|
2386
|
+
const isValue = !isEscaped && !isIndexKey(raw, open);
|
|
2387
|
+
found.push(...isValue ? [{ text: raw.slice(open + 1, close), start: open + 1 }] : []);
|
|
2236
2388
|
open = raw.indexOf(LITERAL_QUOTE, close + 1);
|
|
2237
2389
|
}
|
|
2238
2390
|
return found;
|
|
@@ -2255,8 +2407,20 @@ function expressionLiterals(raw) {
|
|
|
2255
2407
|
}
|
|
2256
2408
|
return found;
|
|
2257
2409
|
}
|
|
2410
|
+
function mapExpressions(text, map) {
|
|
2411
|
+
const parts = [];
|
|
2412
|
+
let copiedUpTo = 0;
|
|
2413
|
+
for (let open = text.indexOf(EXPRESSION_OPEN); open !== -1; ) {
|
|
2414
|
+
const end = expressionEnd(text, open) ?? text.length;
|
|
2415
|
+
parts.push(text.slice(copiedUpTo, open), map(text.slice(open, end)));
|
|
2416
|
+
copiedUpTo = end;
|
|
2417
|
+
open = text.indexOf(EXPRESSION_OPEN, end);
|
|
2418
|
+
}
|
|
2419
|
+
parts.push(text.slice(copiedUpTo));
|
|
2420
|
+
return parts.join("");
|
|
2421
|
+
}
|
|
2258
2422
|
function isWholeExpression(raw) {
|
|
2259
|
-
const isQuoted = raw.length > 1 && raw.startsWith(DOUBLE_QUOTE$
|
|
2423
|
+
const isQuoted = raw.length > 1 && raw.startsWith(DOUBLE_QUOTE$2) && raw.endsWith(DOUBLE_QUOTE$2);
|
|
2260
2424
|
const inner = isQuoted ? 1 : 0;
|
|
2261
2425
|
return raw.startsWith(EXPRESSION_OPEN, inner) && expressionEnd(raw, inner) === raw.length - inner;
|
|
2262
2426
|
}
|
|
@@ -2272,7 +2436,7 @@ const COMMAND_SEPARATORS = /* @__PURE__ */ new Set([
|
|
|
2272
2436
|
]);
|
|
2273
2437
|
const WORD_BREAKS = /* @__PURE__ */ new Set([" ", " ", "\r", "<", ">"]);
|
|
2274
2438
|
const BACKSLASH$2 = "\\";
|
|
2275
|
-
const DOUBLE_QUOTE_ESCAPES = /* @__PURE__ */ new Set(["$", "`", '"', BACKSLASH$2, "\n"]);
|
|
2439
|
+
const DOUBLE_QUOTE_ESCAPES$1 = /* @__PURE__ */ new Set(["$", "`", '"', BACKSLASH$2, "\n"]);
|
|
2276
2440
|
function singleQuoted(text, start) {
|
|
2277
2441
|
const close = text.indexOf("'", start + 1);
|
|
2278
2442
|
const end = close === -1 ? text.length : close + 1;
|
|
@@ -2283,7 +2447,7 @@ function doubleQuoted(text, start) {
|
|
|
2283
2447
|
let index = start + 1;
|
|
2284
2448
|
while (index < text.length && text[index] !== '"') {
|
|
2285
2449
|
const next = text[index + 1] ?? "";
|
|
2286
|
-
const isEscape = text[index] === BACKSLASH$2 && DOUBLE_QUOTE_ESCAPES.has(next);
|
|
2450
|
+
const isEscape = text[index] === BACKSLASH$2 && DOUBLE_QUOTE_ESCAPES$1.has(next);
|
|
2287
2451
|
value += isEscape ? next === "\n" ? "" : next : text[index];
|
|
2288
2452
|
index += isEscape ? 2 : 1;
|
|
2289
2453
|
}
|
|
@@ -2360,6 +2524,37 @@ function wordPart(text, index) {
|
|
|
2360
2524
|
}
|
|
2361
2525
|
return { end: index + 1, value: char };
|
|
2362
2526
|
}
|
|
2527
|
+
function doubleQuotedOffsets(text, start, end) {
|
|
2528
|
+
const offsets = [];
|
|
2529
|
+
for (let index = start + 1; index < end && text[index] !== '"'; index++) {
|
|
2530
|
+
const isEscape = text[index] === BACKSLASH$2 && DOUBLE_QUOTE_ESCAPES$1.has(text[index + 1] ?? "");
|
|
2531
|
+
index += isEscape ? 1 : 0;
|
|
2532
|
+
if (text[index] !== "\n" || !isEscape) {
|
|
2533
|
+
offsets.push(index);
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
return offsets;
|
|
2537
|
+
}
|
|
2538
|
+
function partOffsets(text, start, part) {
|
|
2539
|
+
const char = text[start];
|
|
2540
|
+
if (char === '"') {
|
|
2541
|
+
return doubleQuotedOffsets(text, start, part.end);
|
|
2542
|
+
}
|
|
2543
|
+
const isOpened = char === "'" || char === BACKSLASH$2 && part.end - start > 1;
|
|
2544
|
+
const first = isOpened ? start + 1 : start;
|
|
2545
|
+
return Array.from(part.value, (_, index) => first + index);
|
|
2546
|
+
}
|
|
2547
|
+
function unquotedText(text) {
|
|
2548
|
+
let value = "";
|
|
2549
|
+
const offsets = [];
|
|
2550
|
+
for (let index = 0; index < text.length; ) {
|
|
2551
|
+
const part = wordPart(text, index);
|
|
2552
|
+
value += part.value;
|
|
2553
|
+
offsets.push(...partOffsets(text, index, part));
|
|
2554
|
+
index = part.end;
|
|
2555
|
+
}
|
|
2556
|
+
return { value, offsets };
|
|
2557
|
+
}
|
|
2363
2558
|
const ARRAY_HEAD_RE = /^[A-Za-z_][A-Za-z0-9_]*\+?=$/;
|
|
2364
2559
|
function arrayListEnd(text, index) {
|
|
2365
2560
|
let depth = 0;
|
|
@@ -2392,6 +2587,42 @@ function readWord(text, start) {
|
|
|
2392
2587
|
return { start, end: index, value, raw: text.slice(start, index) };
|
|
2393
2588
|
}
|
|
2394
2589
|
|
|
2590
|
+
const writtenOffset = (word, index) => word.written?.[index] ?? word.start + index;
|
|
2591
|
+
function rawText(word, from, text) {
|
|
2592
|
+
return { text, offsets: Array.from(text, (_, index) => writtenOffset(word, from + index)) };
|
|
2593
|
+
}
|
|
2594
|
+
function unquotedRawText(word, from) {
|
|
2595
|
+
const { value, offsets } = unquotedText(word.raw.slice(from));
|
|
2596
|
+
return { text: value, offsets: offsets.map((index) => writtenOffset(word, from + index)) };
|
|
2597
|
+
}
|
|
2598
|
+
function placedWord(word, { offsets }) {
|
|
2599
|
+
const written = Array.from(word.raw, (_, index) => {
|
|
2600
|
+
return offsets[writtenOffset(word, index)];
|
|
2601
|
+
});
|
|
2602
|
+
const start = written[0] ?? offsets[word.start];
|
|
2603
|
+
const end = (written.at(-1) ?? start - 1) + 1;
|
|
2604
|
+
const isInOnePiece = written.every((offset, index) => offset === start + index);
|
|
2605
|
+
const placed = { start, end, value: word.value, raw: word.raw };
|
|
2606
|
+
return isInOnePiece ? placed : { ...placed, written };
|
|
2607
|
+
}
|
|
2608
|
+
function movedWord(word, offset) {
|
|
2609
|
+
const moved = { ...word, start: word.start + offset, end: word.end + offset };
|
|
2610
|
+
return word.written === void 0 ? moved : { ...moved, written: word.written.map((at) => at + offset) };
|
|
2611
|
+
}
|
|
2612
|
+
function writtenSpan(word, from, length) {
|
|
2613
|
+
const first = writtenOffset(word, from);
|
|
2614
|
+
const last = writtenOffset(word, from + length - 1);
|
|
2615
|
+
return last - first === length - 1 ? { start: first, end: last + 1 } : void 0;
|
|
2616
|
+
}
|
|
2617
|
+
function placedSpan({ offsets }, length) {
|
|
2618
|
+
const first = offsets[0];
|
|
2619
|
+
const last = offsets[length - 1];
|
|
2620
|
+
if (first === void 0 || last === void 0 || last - first !== length - 1) {
|
|
2621
|
+
return void 0;
|
|
2622
|
+
}
|
|
2623
|
+
return { start: first, end: last + 1 };
|
|
2624
|
+
}
|
|
2625
|
+
|
|
2395
2626
|
const ASSIGNMENT_RE$2 = /^([A-Za-z_][A-Za-z0-9_]*)(\+?=)/;
|
|
2396
2627
|
const APPEND_OPERATOR$1 = "+=";
|
|
2397
2628
|
const DECLARATION_BUILTINS = /* @__PURE__ */ new Set([
|
|
@@ -2401,99 +2632,257 @@ const DECLARATION_BUILTINS = /* @__PURE__ */ new Set([
|
|
|
2401
2632
|
"declare",
|
|
2402
2633
|
"typeset"
|
|
2403
2634
|
]);
|
|
2404
|
-
const QUOTES$3 = /* @__PURE__ */ new Set(["'", '"']);
|
|
2405
|
-
const UNPLAIN_RE = /['"\\$`]/;
|
|
2406
2635
|
function leadingAssignments(command) {
|
|
2407
2636
|
const index = command.findIndex((word) => !ASSIGNMENT_RE$2.test(word.raw));
|
|
2408
2637
|
return index === -1 ? command.length : index;
|
|
2409
2638
|
}
|
|
2639
|
+
const ARGUMENT_ASSIGNMENT_RE = /^([A-Za-z_][A-Za-z0-9_.-]*)(:::=|::=|:=|\?=|!=|\+?=)/;
|
|
2640
|
+
function assignmentOf(word, pattern = ASSIGNMENT_RE$2) {
|
|
2641
|
+
const match = pattern.exec(word.raw);
|
|
2642
|
+
const name = match?.[1];
|
|
2643
|
+
if (match === null || name === void 0) {
|
|
2644
|
+
return [];
|
|
2645
|
+
}
|
|
2646
|
+
const head = match[0].length;
|
|
2647
|
+
const isAppend = match[2] === APPEND_OPERATOR$1;
|
|
2648
|
+
return [{ name, value: word.value.slice(head), word, isAppend, head }];
|
|
2649
|
+
}
|
|
2410
2650
|
function shellAssignments(command) {
|
|
2411
2651
|
const count = leadingAssignments(command);
|
|
2412
2652
|
const isDeclaration = DECLARATION_BUILTINS.has(command[count]?.value ?? "");
|
|
2413
2653
|
const words = [...command.slice(0, count), ...isDeclaration ? command.slice(count + 1) : []];
|
|
2414
|
-
return words.flatMap((word) =>
|
|
2415
|
-
const match = ASSIGNMENT_RE$2.exec(word.raw);
|
|
2416
|
-
const name = match?.[1];
|
|
2417
|
-
if (match === null || name === void 0) {
|
|
2418
|
-
return [];
|
|
2419
|
-
}
|
|
2420
|
-
const head = match[0].length;
|
|
2421
|
-
const isAppend = match[2] === APPEND_OPERATOR$1;
|
|
2422
|
-
return [{ name, value: word.value.slice(head), word, isAppend, head }];
|
|
2423
|
-
});
|
|
2654
|
+
return words.flatMap((word) => assignmentOf(word));
|
|
2424
2655
|
}
|
|
2656
|
+
function argumentAssignments(command) {
|
|
2657
|
+
const own = new Set(shellAssignments(command).map(({ word }) => word));
|
|
2658
|
+
return command.slice(leadingAssignments(command)).filter((word) => !own.has(word)).flatMap((word) => assignmentOf(word, ARGUMENT_ASSIGNMENT_RE));
|
|
2659
|
+
}
|
|
2660
|
+
const COMMAND_LINE_RE = /[\s;&|()`]/;
|
|
2661
|
+
const holdsCommandLine = (assignment) => COMMAND_LINE_RE.test(assignment.value);
|
|
2425
2662
|
const ARRAY_OPEN = "(";
|
|
2426
|
-
const ARRAY_CLOSE = ")";
|
|
2427
2663
|
const isArrayAssignment = (assignment) => assignment.word.raw.startsWith(ARRAY_OPEN, assignment.head);
|
|
2428
|
-
function
|
|
2429
|
-
const
|
|
2430
|
-
|
|
2431
|
-
const start = assignment.word.start + at;
|
|
2432
|
-
const quote = raw[0] ?? "";
|
|
2433
|
-
if (isArrayAssignment(assignment)) {
|
|
2434
|
-
return raw.endsWith(ARRAY_CLOSE) ? { text: raw.slice(1, -1), start: start + 1 } : void 0;
|
|
2435
|
-
}
|
|
2436
|
-
if (QUOTES$3.has(quote)) {
|
|
2437
|
-
const isOneString = raw.length > 1 && raw.endsWith(quote) && wordPart(raw, 0).end === raw.length;
|
|
2438
|
-
return isOneString ? { text: raw.slice(1, -1), start: start + 1 } : void 0;
|
|
2439
|
-
}
|
|
2440
|
-
return UNPLAIN_RE.test(raw) ? void 0 : { text: raw, start };
|
|
2664
|
+
function assignmentValue(assignment) {
|
|
2665
|
+
const { word, head } = assignment;
|
|
2666
|
+
return isArrayAssignment(assignment) ? rawText(word, head + 1, word.raw.slice(head + 1, -1)) : unquotedRawText(word, head);
|
|
2441
2667
|
}
|
|
2442
2668
|
|
|
2443
|
-
const
|
|
2444
|
-
const
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
function heredocAt(text, index, where) {
|
|
2450
|
-
if (text.startsWith(HERE_STRING_OPERATOR, index)) {
|
|
2451
|
-
return { end: index + HERE_STRING_OPERATOR.length };
|
|
2452
|
-
}
|
|
2453
|
-
if (!text.startsWith(HEREDOC_OPERATOR, index)) {
|
|
2454
|
-
return void 0;
|
|
2455
|
-
}
|
|
2456
|
-
let start = index + HEREDOC_OPERATOR.length;
|
|
2457
|
-
const isTabStripped = text[start] === STRIP_TABS;
|
|
2458
|
-
start += isTabStripped ? 1 : 0;
|
|
2459
|
-
while (text[start] === " " || text[start] === " ") {
|
|
2460
|
-
start++;
|
|
2669
|
+
const END_OF_OPTIONS$1 = "--";
|
|
2670
|
+
const isOption$1 = (word) => word.value.startsWith("-") && word.value.length > 1;
|
|
2671
|
+
function skipAssignments(words, start) {
|
|
2672
|
+
let index = start;
|
|
2673
|
+
while (index < words.length && ASSIGNMENT_RE$2.test(words[index].raw)) {
|
|
2674
|
+
index++;
|
|
2461
2675
|
}
|
|
2462
|
-
|
|
2463
|
-
const pending = { delimiter: word.value, isTabStripped, ...where };
|
|
2464
|
-
return word.value === "" ? void 0 : { pending, end: word.end };
|
|
2676
|
+
return index;
|
|
2465
2677
|
}
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2678
|
+
const WINDOWS_PROGRAM_SUFFIX_RE = /\.(?:cmd|exe|ps1)$/i;
|
|
2679
|
+
const windowsSuffix = (value) => WINDOWS_PROGRAM_SUFFIX_RE.exec(value)?.[0] ?? "";
|
|
2680
|
+
const withoutWindowsSuffix = (value) => value.slice(0, value.length - windowsSuffix(value).length);
|
|
2681
|
+
const FOLDERS_RE = /^.*[/\\]/;
|
|
2682
|
+
const entryWord = (word) => word === void 0 ? void 0 : withoutWindowsSuffix(word.value.replace(FOLDERS_RE, ""));
|
|
2683
|
+
function matchingPrefix(entries, words, index) {
|
|
2684
|
+
return entries.find(
|
|
2685
|
+
(entry) => entry.words.every((name, offset) => entryWord(words[index + offset]) === name)
|
|
2686
|
+
);
|
|
2474
2687
|
}
|
|
2475
|
-
function
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
const end = lineEnd === -1 ? text.length : lineEnd;
|
|
2480
|
-
if (isDelimiterLine(text, lineStart, end, heredoc)) {
|
|
2481
|
-
const body = { command: heredoc.command, start, text: text.slice(start, lineStart) };
|
|
2482
|
-
return { body, end: Math.min(end + 1, text.length) };
|
|
2483
|
-
}
|
|
2484
|
-
lineStart = end + 1;
|
|
2485
|
-
}
|
|
2486
|
-
return { body: { command: heredoc.command, start, text: text.slice(start) }, end: text.length };
|
|
2688
|
+
function inlineOptionPackage(word, launcher) {
|
|
2689
|
+
const equals = word.value.indexOf("=");
|
|
2690
|
+
const name = word.value.slice(0, equals);
|
|
2691
|
+
return launcher.packageOptions.has(name) ? { word, value: word.value.slice(equals + 1) } : void 0;
|
|
2487
2692
|
}
|
|
2488
|
-
function
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2693
|
+
function launchedProgram(words, start, launcher, packages) {
|
|
2694
|
+
let index = start;
|
|
2695
|
+
while (index < words.length && isOption$1(words[index])) {
|
|
2696
|
+
const option = words[index++];
|
|
2697
|
+
if (option.value === END_OF_OPTIONS$1) {
|
|
2698
|
+
break;
|
|
2699
|
+
}
|
|
2700
|
+
const inline = option.value.includes("=") ? inlineOptionPackage(option, launcher) : void 0;
|
|
2701
|
+
if (inline !== void 0) {
|
|
2702
|
+
packages.push(inline);
|
|
2703
|
+
}
|
|
2704
|
+
const value = words[index];
|
|
2705
|
+
if (!option.value.includes("=") && launcher.valueOptions.has(option.value) && value) {
|
|
2706
|
+
if (launcher.packageOptions.has(option.value)) {
|
|
2707
|
+
packages.push({ word: value, value: value.value });
|
|
2708
|
+
}
|
|
2709
|
+
index++;
|
|
2710
|
+
}
|
|
2495
2711
|
}
|
|
2496
|
-
return
|
|
2712
|
+
return index;
|
|
2713
|
+
}
|
|
2714
|
+
const installArguments = (words, start) => words.slice(start).filter((word) => !isOption$1(word)).map((word) => ({ word, value: word.value }));
|
|
2715
|
+
function commandRoles(words) {
|
|
2716
|
+
const packages = [];
|
|
2717
|
+
let index = skipAssignments(words, 0);
|
|
2718
|
+
while (index < words.length) {
|
|
2719
|
+
const installer = matchingPrefix(INSTALLERS, words, index);
|
|
2720
|
+
if (installer !== void 0) {
|
|
2721
|
+
packages.push(...installArguments(words, index + installer.words.length));
|
|
2722
|
+
return { program: void 0, packages };
|
|
2723
|
+
}
|
|
2724
|
+
const launcher = matchingPrefix(LAUNCHERS, words, index);
|
|
2725
|
+
if (launcher === void 0) {
|
|
2726
|
+
return { program: index, packages };
|
|
2727
|
+
}
|
|
2728
|
+
const start = index + launcher.words.length;
|
|
2729
|
+
const afterOptions = launchedProgram(words, start, launcher, packages);
|
|
2730
|
+
index = skipAssignments(words, afterOptions + launcher.operands);
|
|
2731
|
+
}
|
|
2732
|
+
return { program: void 0, packages };
|
|
2733
|
+
}
|
|
2734
|
+
|
|
2735
|
+
function packageReference(value) {
|
|
2736
|
+
const bare = value.startsWith(NPM_SPECIFIER_PREFIX) ? value.slice(NPM_SPECIFIER_PREFIX.length) : value;
|
|
2737
|
+
const at = bare.indexOf("@", 1);
|
|
2738
|
+
return { name: at === -1 ? bare : bare.slice(0, at), isPinned: at !== -1 };
|
|
2739
|
+
}
|
|
2740
|
+
function namesOldPackage(value) {
|
|
2741
|
+
return PACKAGE_RENAMES.has(packageReference(value).name) || oldPackageInNodeModules(value) !== void 0 || value.endsWith(`/${GENERATOR_COMMAND}`);
|
|
2742
|
+
}
|
|
2743
|
+
const unreadArgumentValues = (words) => new Map(
|
|
2744
|
+
argumentAssignments(words).filter((assignment) => !holdsCommandLine(assignment)).map(({ word, value }) => [word, value])
|
|
2745
|
+
);
|
|
2746
|
+
function unmigratedWordFindings(words, handledOffsets, locate) {
|
|
2747
|
+
const values = unreadArgumentValues(words);
|
|
2748
|
+
const assignments = new Set(shellAssignments(words).map(({ word }) => word));
|
|
2749
|
+
const namesOld = (word) => namesOldPackage(word.value) || namesOldPackage(values.get(word) ?? "");
|
|
2750
|
+
return words.filter((word) => !handledOffsets.has(word.start) && !assignments.has(word) && namesOld(word)).map((word) => ({
|
|
2751
|
+
offset: word.start,
|
|
2752
|
+
manualStep: { kind: "old-name-in-command", location: locate(word.start), word: word.value }
|
|
2753
|
+
}));
|
|
2754
|
+
}
|
|
2755
|
+
|
|
2756
|
+
const PATH_SEPARATOR$a = "/";
|
|
2757
|
+
const WINDOWS_SEPARATOR_RE = /\\/g;
|
|
2758
|
+
const QUOTE_RE = /["']/g;
|
|
2759
|
+
const WINDOWS_PATH_RE = /^[^/]*[^\\/\s]\\[^\\/\s][^/]*$/;
|
|
2760
|
+
function programPath(word) {
|
|
2761
|
+
const suffix = windowsSuffix(word.value);
|
|
2762
|
+
const written = word.raw.replace(QUOTE_RE, "");
|
|
2763
|
+
const isWindowsPath = suffix !== "" || WINDOWS_PATH_RE.test(written);
|
|
2764
|
+
if (!isWindowsPath) {
|
|
2765
|
+
return { path: word.value, suffix, written: word.value };
|
|
2766
|
+
}
|
|
2767
|
+
return { path: written.replace(WINDOWS_SEPARATOR_RE, PATH_SEPARATOR$a), suffix, written };
|
|
2768
|
+
}
|
|
2769
|
+
|
|
2770
|
+
const RECIPE_PREFIX_RE$1 = /^[@+-]+(?=.)/;
|
|
2771
|
+
function withoutRecipePrefix(words) {
|
|
2772
|
+
const [first, ...rest] = words;
|
|
2773
|
+
if (first === void 0 || !RECIPE_PREFIX_RE$1.test(first.value)) {
|
|
2774
|
+
return words;
|
|
2775
|
+
}
|
|
2776
|
+
return [{ ...first, value: first.value.replace(RECIPE_PREFIX_RE$1, "") }, ...rest];
|
|
2777
|
+
}
|
|
2778
|
+
const NO_VARIABLES = {
|
|
2779
|
+
programAt: () => void 0,
|
|
2780
|
+
referenceAt: () => void 0
|
|
2781
|
+
};
|
|
2782
|
+
const PATH_SEPARATOR$9 = "/";
|
|
2783
|
+
const BIN_FOLDER$1 = "/.bin/";
|
|
2784
|
+
function namesGenerator(word) {
|
|
2785
|
+
const { path, suffix } = programPath(word);
|
|
2786
|
+
if (path.includes(PATH_SEPARATOR$9)) {
|
|
2787
|
+
return path.endsWith(`${BIN_FOLDER$1}${GENERATOR_COMMAND}${suffix}`);
|
|
2788
|
+
}
|
|
2789
|
+
return packageReference(path.slice(0, path.length - suffix.length)).name === GENERATOR_COMMAND;
|
|
2790
|
+
}
|
|
2791
|
+
function runsGenerator(command) {
|
|
2792
|
+
const words = withoutRecipePrefix(command);
|
|
2793
|
+
const { program } = commandRoles(words);
|
|
2794
|
+
const word = program === void 0 ? void 0 : words[program];
|
|
2795
|
+
return word !== void 0 && namesGenerator(word);
|
|
2796
|
+
}
|
|
2797
|
+
|
|
2798
|
+
const COMMAND_PREFIX_WORDS = /* @__PURE__ */ new Set([
|
|
2799
|
+
"if",
|
|
2800
|
+
"then",
|
|
2801
|
+
"elif",
|
|
2802
|
+
"else",
|
|
2803
|
+
"fi",
|
|
2804
|
+
"while",
|
|
2805
|
+
"until",
|
|
2806
|
+
"do",
|
|
2807
|
+
"done",
|
|
2808
|
+
"!",
|
|
2809
|
+
"{",
|
|
2810
|
+
"}",
|
|
2811
|
+
"esac"
|
|
2812
|
+
]);
|
|
2813
|
+
const CLAUSE_WORDS = /* @__PURE__ */ new Set(["for", "select", "case", "[["]);
|
|
2814
|
+
const FUNCTION_WORD = "function";
|
|
2815
|
+
const FUNCTION_HEADER_LENGTH = 2;
|
|
2816
|
+
const isReserved = (word, words) => word !== void 0 && word.raw === word.value && words.has(word.value);
|
|
2817
|
+
function prefixLength(words, index) {
|
|
2818
|
+
if (isReserved(words[index], COMMAND_PREFIX_WORDS)) {
|
|
2819
|
+
return 1;
|
|
2820
|
+
}
|
|
2821
|
+
const word = words[index];
|
|
2822
|
+
return word?.raw === FUNCTION_WORD ? FUNCTION_HEADER_LENGTH : 0;
|
|
2823
|
+
}
|
|
2824
|
+
function simpleCommand(words) {
|
|
2825
|
+
let first = 0;
|
|
2826
|
+
for (let length = prefixLength(words, 0); length > 0; length = prefixLength(words, first)) {
|
|
2827
|
+
first += length;
|
|
2828
|
+
}
|
|
2829
|
+
return isReserved(words[first], CLAUSE_WORDS) ? [] : words.slice(first);
|
|
2830
|
+
}
|
|
2831
|
+
|
|
2832
|
+
const HEREDOC_OPERATOR = "<<";
|
|
2833
|
+
const HERE_STRING_OPERATOR = "<<<";
|
|
2834
|
+
const STRIP_TABS = "-";
|
|
2835
|
+
const LINE_BREAK$7 = "\n";
|
|
2836
|
+
const LEADING_TABS_RE = /^\t+/;
|
|
2837
|
+
const CARRIAGE_RETURN_RE = /\r$/;
|
|
2838
|
+
function heredocAt(text, index, where) {
|
|
2839
|
+
if (text.startsWith(HERE_STRING_OPERATOR, index)) {
|
|
2840
|
+
return { end: index + HERE_STRING_OPERATOR.length };
|
|
2841
|
+
}
|
|
2842
|
+
if (!text.startsWith(HEREDOC_OPERATOR, index)) {
|
|
2843
|
+
return void 0;
|
|
2844
|
+
}
|
|
2845
|
+
let start = index + HEREDOC_OPERATOR.length;
|
|
2846
|
+
const isTabStripped = text[start] === STRIP_TABS;
|
|
2847
|
+
start += isTabStripped ? 1 : 0;
|
|
2848
|
+
while (text[start] === " " || text[start] === " ") {
|
|
2849
|
+
start++;
|
|
2850
|
+
}
|
|
2851
|
+
const word = readWord(text, start);
|
|
2852
|
+
const pending = { delimiter: word.value, isTabStripped, ...where };
|
|
2853
|
+
return word.value === "" ? void 0 : { pending, end: word.end };
|
|
2854
|
+
}
|
|
2855
|
+
function isDelimiterLine(text, lineStart, end, heredoc) {
|
|
2856
|
+
let first = lineStart;
|
|
2857
|
+
while (first < lineStart + heredoc.indent && text[first] === " ") {
|
|
2858
|
+
first++;
|
|
2859
|
+
}
|
|
2860
|
+
const line = text.slice(first, end).replace(CARRIAGE_RETURN_RE, "");
|
|
2861
|
+
const compared = heredoc.isTabStripped ? line.replace(LEADING_TABS_RE, "") : line;
|
|
2862
|
+
return compared === heredoc.delimiter;
|
|
2863
|
+
}
|
|
2864
|
+
function readBody(text, start, heredoc) {
|
|
2865
|
+
let lineStart = start;
|
|
2866
|
+
while (lineStart < text.length) {
|
|
2867
|
+
const lineEnd = text.indexOf(LINE_BREAK$7, lineStart);
|
|
2868
|
+
const end = lineEnd === -1 ? text.length : lineEnd;
|
|
2869
|
+
if (isDelimiterLine(text, lineStart, end, heredoc)) {
|
|
2870
|
+
const body = { command: heredoc.command, start, text: text.slice(start, lineStart) };
|
|
2871
|
+
return { body, end: Math.min(end + 1, text.length) };
|
|
2872
|
+
}
|
|
2873
|
+
lineStart = end + 1;
|
|
2874
|
+
}
|
|
2875
|
+
return { body: { command: heredoc.command, start, text: text.slice(start) }, end: text.length };
|
|
2876
|
+
}
|
|
2877
|
+
function readBodies(text, start, pending) {
|
|
2878
|
+
const bodies = [];
|
|
2879
|
+
let end = start;
|
|
2880
|
+
for (const heredoc of pending) {
|
|
2881
|
+
const read = readBody(text, end, heredoc);
|
|
2882
|
+
bodies.push(read.body);
|
|
2883
|
+
end = read.end;
|
|
2884
|
+
}
|
|
2885
|
+
return { bodies, end };
|
|
2497
2886
|
}
|
|
2498
2887
|
|
|
2499
2888
|
const CODE_OPTIONS = /* @__PURE__ */ new Map([
|
|
@@ -2544,7 +2933,7 @@ const USES = {
|
|
|
2544
2933
|
"=": "assign",
|
|
2545
2934
|
"+": "alternative"
|
|
2546
2935
|
};
|
|
2547
|
-
const SINGLE_QUOTE = "'";
|
|
2936
|
+
const SINGLE_QUOTE$1 = "'";
|
|
2548
2937
|
const BACKSLASH$1 = "\\";
|
|
2549
2938
|
function expansionAt(text, start) {
|
|
2550
2939
|
const head = EXPANSION_HEAD_RE.exec(text.slice(start));
|
|
@@ -2566,8 +2955,8 @@ function wordExpansions(raw) {
|
|
|
2566
2955
|
const found = [];
|
|
2567
2956
|
for (let index = 0; index < raw.length; ) {
|
|
2568
2957
|
const char = raw[index];
|
|
2569
|
-
if (char === SINGLE_QUOTE) {
|
|
2570
|
-
const close = raw.indexOf(SINGLE_QUOTE, index + 1);
|
|
2958
|
+
if (char === SINGLE_QUOTE$1) {
|
|
2959
|
+
const close = raw.indexOf(SINGLE_QUOTE$1, index + 1);
|
|
2571
2960
|
index = close === -1 ? raw.length : close + 1;
|
|
2572
2961
|
} else if (char === BACKSLASH$1) {
|
|
2573
2962
|
index += 2;
|
|
@@ -2581,17 +2970,45 @@ function wordExpansions(raw) {
|
|
|
2581
2970
|
}
|
|
2582
2971
|
return found;
|
|
2583
2972
|
}
|
|
2584
|
-
const DOUBLE_QUOTE = '"';
|
|
2973
|
+
const DOUBLE_QUOTE$1 = '"';
|
|
2585
2974
|
function wholeWordExpansion(raw) {
|
|
2586
|
-
const isQuoted = raw.length > 1 && raw.startsWith(DOUBLE_QUOTE) && raw.endsWith(DOUBLE_QUOTE);
|
|
2975
|
+
const isQuoted = raw.length > 1 && raw.startsWith(DOUBLE_QUOTE$1) && raw.endsWith(DOUBLE_QUOTE$1);
|
|
2587
2976
|
const inner = isQuoted ? 1 : 0;
|
|
2588
2977
|
const [expansion] = wordExpansions(raw);
|
|
2589
2978
|
const isWhole = expansion?.expansionStart === inner && expansion.expansionEnd === raw.length - inner;
|
|
2590
2979
|
return isWhole ? expansion : void 0;
|
|
2591
2980
|
}
|
|
2592
2981
|
|
|
2982
|
+
const SHELLS = /* @__PURE__ */ new Set(["sh", "bash", "dash", "ash", "zsh", "ksh"]);
|
|
2983
|
+
const OPTION_PREFIXES = ["-", "+"];
|
|
2984
|
+
const SHORT_OPTION_PREFIX = "-";
|
|
2985
|
+
const LONG_OPTION_PREFIX = "--";
|
|
2986
|
+
const END_OF_OPTIONS = "--";
|
|
2987
|
+
const COMMAND_OPTION = "c";
|
|
2988
|
+
const SET_OPTIONS = /* @__PURE__ */ new Set(["-o", "+o"]);
|
|
2989
|
+
const PATH_SEPARATOR$8 = "/";
|
|
2990
|
+
const isShellOption = (word) => OPTION_PREFIXES.some((prefix) => word.startsWith(prefix));
|
|
2991
|
+
function shellScript(words) {
|
|
2992
|
+
const program = words[0]?.value.split(PATH_SEPARATOR$8).at(-1) ?? "";
|
|
2993
|
+
if (!SHELLS.has(program)) {
|
|
2994
|
+
return void 0;
|
|
2995
|
+
}
|
|
2996
|
+
let hasCommandOption = false;
|
|
2997
|
+
let index = 1;
|
|
2998
|
+
for (let word = words[index]?.value; word !== void 0; word = words[index]?.value) {
|
|
2999
|
+
if (word === END_OF_OPTIONS || !isShellOption(word)) {
|
|
3000
|
+
const script = word === END_OF_OPTIONS ? words[index + 1] : words[index];
|
|
3001
|
+
return hasCommandOption ? script : void 0;
|
|
3002
|
+
}
|
|
3003
|
+
const isShort = word.startsWith(SHORT_OPTION_PREFIX) && !word.startsWith(LONG_OPTION_PREFIX);
|
|
3004
|
+
hasCommandOption ||= isShort && word.includes(COMMAND_OPTION);
|
|
3005
|
+
index += SET_OPTIONS.has(word) ? 2 : 1;
|
|
3006
|
+
}
|
|
3007
|
+
return void 0;
|
|
3008
|
+
}
|
|
3009
|
+
|
|
2593
3010
|
const COMMENT = "#";
|
|
2594
|
-
const LINE_BREAK$
|
|
3011
|
+
const LINE_BREAK$6 = "\n";
|
|
2595
3012
|
function skipTrivia(text, index) {
|
|
2596
3013
|
const char = text[index];
|
|
2597
3014
|
if (WORD_BREAKS.has(char)) {
|
|
@@ -2621,7 +3038,7 @@ function topLevelCommands(text, indent) {
|
|
|
2621
3038
|
index = heredoc.end;
|
|
2622
3039
|
} else if (afterTrivia !== index) {
|
|
2623
3040
|
index = afterTrivia;
|
|
2624
|
-
} else if (text[index] === LINE_BREAK$
|
|
3041
|
+
} else if (text[index] === LINE_BREAK$6 && pending.length > 0) {
|
|
2625
3042
|
const read = readBodies(text, index + 1, pending);
|
|
2626
3043
|
heredocs.push(...read.bodies);
|
|
2627
3044
|
pending = [];
|
|
@@ -2641,63 +3058,32 @@ function topLevelCommands(text, indent) {
|
|
|
2641
3058
|
}
|
|
2642
3059
|
return { commands, heredocs, pipes };
|
|
2643
3060
|
}
|
|
2644
|
-
const
|
|
2645
|
-
"if",
|
|
2646
|
-
"then",
|
|
2647
|
-
"elif",
|
|
2648
|
-
"else",
|
|
2649
|
-
"fi",
|
|
2650
|
-
"while",
|
|
2651
|
-
"until",
|
|
2652
|
-
"do",
|
|
2653
|
-
"done",
|
|
2654
|
-
"!",
|
|
2655
|
-
"{",
|
|
2656
|
-
"}",
|
|
2657
|
-
"esac"
|
|
2658
|
-
]);
|
|
2659
|
-
const CLAUSE_WORDS = /* @__PURE__ */ new Set(["for", "select", "case", "[["]);
|
|
2660
|
-
const FUNCTION_WORD = "function";
|
|
2661
|
-
const FUNCTION_HEADER_LENGTH = 2;
|
|
2662
|
-
const isReserved = (word, words) => word !== void 0 && word.raw === word.value && words.has(word.value);
|
|
2663
|
-
function prefixLength(words, index) {
|
|
2664
|
-
if (isReserved(words[index], COMMAND_PREFIX_WORDS)) {
|
|
2665
|
-
return 1;
|
|
2666
|
-
}
|
|
2667
|
-
const word = words[index];
|
|
2668
|
-
return word?.raw === FUNCTION_WORD ? FUNCTION_HEADER_LENGTH : 0;
|
|
2669
|
-
}
|
|
2670
|
-
function simpleCommand(words) {
|
|
2671
|
-
let first = 0;
|
|
2672
|
-
for (let length = prefixLength(words, 0); length > 0; length = prefixLength(words, first)) {
|
|
2673
|
-
first += length;
|
|
2674
|
-
}
|
|
2675
|
-
return isReserved(words[first], CLAUSE_WORDS) ? [] : words.slice(first);
|
|
2676
|
-
}
|
|
2677
|
-
const QUOTES$2 = /* @__PURE__ */ new Set(["'", '"']);
|
|
3061
|
+
const QUOTES$1 = /* @__PURE__ */ new Set(["'", '"']);
|
|
2678
3062
|
const NESTED_COMMAND_RE = /[\s;&|()`]/;
|
|
2679
|
-
function
|
|
3063
|
+
function isQuotedCommandLine(word) {
|
|
2680
3064
|
const quote = word.raw[0];
|
|
2681
|
-
const isOneQuotedString = QUOTES$
|
|
2682
|
-
return isOneQuotedString && NESTED_COMMAND_RE.test(word.value)
|
|
3065
|
+
const isOneQuotedString = QUOTES$1.has(quote) && word.raw.length > 1 && word.raw.endsWith(quote) && wordPart(word.raw, 0).end === word.raw.length;
|
|
3066
|
+
return isOneQuotedString && NESTED_COMMAND_RE.test(word.value);
|
|
3067
|
+
}
|
|
3068
|
+
function nestedCommandText(word, script) {
|
|
3069
|
+
return word === script || isQuotedCommandLine(word) ? unquotedRawText(word, 0) : void 0;
|
|
2683
3070
|
}
|
|
2684
|
-
const SHELLS$1 = /* @__PURE__ */ new Set(["sh", "bash", "dash", "ash", "zsh", "ksh"]);
|
|
2685
3071
|
const DOCKER_RUN = "RUN";
|
|
2686
3072
|
const PASS_THROUGH = "cat";
|
|
2687
|
-
const PATH_SEPARATOR$
|
|
2688
|
-
const OPTION_PREFIX
|
|
2689
|
-
const programName$1 = (command) => command[0]?.value.split(PATH_SEPARATOR$
|
|
2690
|
-
const isOption
|
|
2691
|
-
const isScriptShell = (command) => SHELLS
|
|
3073
|
+
const PATH_SEPARATOR$7 = "/";
|
|
3074
|
+
const OPTION_PREFIX = "-";
|
|
3075
|
+
const programName$1 = (command) => command[0]?.value.split(PATH_SEPARATOR$7).at(-1) ?? "";
|
|
3076
|
+
const isOption = (word) => word.value.startsWith(OPTION_PREFIX);
|
|
3077
|
+
const isScriptShell = (command) => SHELLS.has(programName$1(command)) && command.slice(1).every(isOption);
|
|
2692
3078
|
function readsScript(command) {
|
|
2693
3079
|
if (programName$1(command) !== DOCKER_RUN) {
|
|
2694
3080
|
return isScriptShell(command);
|
|
2695
3081
|
}
|
|
2696
3082
|
const after = command.slice(1);
|
|
2697
|
-
const shell = after.slice(after.findIndex((word) => !isOption
|
|
2698
|
-
return after.every(isOption
|
|
3083
|
+
const shell = after.slice(after.findIndex((word) => !isOption(word)));
|
|
3084
|
+
return after.every(isOption) || isScriptShell(shell);
|
|
2699
3085
|
}
|
|
2700
|
-
const passesThrough = (command) => programName$1(command) === PASS_THROUGH && command.slice(1).every(isOption
|
|
3086
|
+
const passesThrough = (command) => programName$1(command) === PASS_THROUGH && command.slice(1).every(isOption);
|
|
2701
3087
|
function scriptsRunBy(top, index, command) {
|
|
2702
3088
|
const previous = index - 1;
|
|
2703
3089
|
const isPipedScript = top.pipes.has(previous) && isScriptShell(command) && passesThrough(simpleCommand(top.commands[previous] ?? []));
|
|
@@ -2705,9 +3091,11 @@ function scriptsRunBy(top, index, command) {
|
|
|
2705
3091
|
(body) => body.command === index && readsScript(command) || body.command === previous && isPipedScript
|
|
2706
3092
|
);
|
|
2707
3093
|
}
|
|
2708
|
-
const shifted = (words, offset) => words.map((word) => ({ ...word, start: word.start + offset, end: word.end + offset }));
|
|
2709
3094
|
function shellCommandsAt(text, offset, indent = 0) {
|
|
2710
|
-
return shellCommands(text, indent).map((words) =>
|
|
3095
|
+
return shellCommands(text, indent).map((words) => words.map((word) => movedWord(word, offset)));
|
|
3096
|
+
}
|
|
3097
|
+
function placedCommands(placed) {
|
|
3098
|
+
return shellCommands(placed.text).map((words) => words.map((word) => placedWord(word, placed)));
|
|
2711
3099
|
}
|
|
2712
3100
|
function expansionCommands(word) {
|
|
2713
3101
|
const expansions = wordExpansions(word.raw);
|
|
@@ -2715,20 +3103,27 @@ function expansionCommands(word) {
|
|
|
2715
3103
|
({ start }) => expansions.every((expansion) => start < expansion.start || start >= expansion.expansionEnd)
|
|
2716
3104
|
);
|
|
2717
3105
|
return [...expansions, ...literals].flatMap(
|
|
2718
|
-
(part) =>
|
|
3106
|
+
(part) => placedCommands(rawText(word, part.start, part.text))
|
|
2719
3107
|
);
|
|
2720
3108
|
}
|
|
3109
|
+
function commandLineAssignments(command) {
|
|
3110
|
+
const read = [
|
|
3111
|
+
...shellAssignments(command),
|
|
3112
|
+
...argumentAssignments(command).filter(holdsCommandLine)
|
|
3113
|
+
];
|
|
3114
|
+
return new Map(read.map((assignment) => [assignment.word, assignment]));
|
|
3115
|
+
}
|
|
2721
3116
|
function innerCommands(command) {
|
|
2722
|
-
const assignments =
|
|
3117
|
+
const assignments = commandLineAssignments(command);
|
|
2723
3118
|
const code = inlineCode(command)?.code;
|
|
3119
|
+
const script = shellScript(command);
|
|
2724
3120
|
return command.flatMap((word) => {
|
|
2725
|
-
const inner = word === code ? void 0 : nestedCommandText(word);
|
|
3121
|
+
const inner = word === code ? void 0 : nestedCommandText(word, script);
|
|
2726
3122
|
if (inner !== void 0) {
|
|
2727
|
-
return
|
|
3123
|
+
return placedCommands(inner);
|
|
2728
3124
|
}
|
|
2729
3125
|
const assignment = assignments.get(word);
|
|
2730
|
-
|
|
2731
|
-
return value === void 0 ? expansionCommands(word) : shellCommandsAt(value.text, value.start);
|
|
3126
|
+
return assignment === void 0 ? expansionCommands(word) : placedCommands(assignmentValue(assignment));
|
|
2732
3127
|
});
|
|
2733
3128
|
}
|
|
2734
3129
|
function shellCommands(text, indent = 0) {
|
|
@@ -2759,257 +3154,117 @@ function appendedPlace(earlierValues) {
|
|
|
2759
3154
|
function canRunGenerator(definition, generators) {
|
|
2760
3155
|
switch (definition.kind) {
|
|
2761
3156
|
case "command":
|
|
2762
|
-
return definition.runsGenerator;
|
|
2763
|
-
case "reference":
|
|
2764
|
-
return generators.has(definition.target);
|
|
2765
|
-
case "no-program":
|
|
2766
|
-
return false;
|
|
2767
|
-
case "run-time":
|
|
2768
|
-
return true;
|
|
2769
|
-
default:
|
|
2770
|
-
return assertNever(definition);
|
|
2771
|
-
}
|
|
2772
|
-
}
|
|
2773
|
-
function canRunOther(definition, others, defined) {
|
|
2774
|
-
switch (definition.kind) {
|
|
2775
|
-
case "command":
|
|
2776
|
-
return !definition.runsGenerator;
|
|
2777
|
-
case "reference":
|
|
2778
|
-
return others.has(definition.target) || !defined.has(definition.target);
|
|
2779
|
-
case "no-program":
|
|
2780
|
-
return false;
|
|
2781
|
-
case "run-time":
|
|
2782
|
-
return true;
|
|
2783
|
-
default:
|
|
2784
|
-
return assertNever(definition);
|
|
2785
|
-
}
|
|
2786
|
-
}
|
|
2787
|
-
function variablePrograms(definitions) {
|
|
2788
|
-
const defined = new Set(definitions.map((definition) => definition.name));
|
|
2789
|
-
const generators = /* @__PURE__ */ new Set();
|
|
2790
|
-
const others = /* @__PURE__ */ new Set();
|
|
2791
|
-
for (let size = -1; size !== generators.size + others.size; ) {
|
|
2792
|
-
size = generators.size + others.size;
|
|
2793
|
-
for (const definition of definitions) {
|
|
2794
|
-
if (canRunGenerator(definition, generators)) {
|
|
2795
|
-
generators.add(definition.name);
|
|
2796
|
-
}
|
|
2797
|
-
if (canRunOther(definition, others, defined)) {
|
|
2798
|
-
others.add(definition.name);
|
|
2799
|
-
}
|
|
2800
|
-
}
|
|
2801
|
-
}
|
|
2802
|
-
const programOf = (name) => {
|
|
2803
|
-
if (!generators.has(name)) {
|
|
2804
|
-
return "other";
|
|
2805
|
-
}
|
|
2806
|
-
return others.has(name) ? "generator-or-other" : "generator";
|
|
2807
|
-
};
|
|
2808
|
-
return new Map([...defined].map((name) => [name, programOf(name)]));
|
|
2809
|
-
}
|
|
2810
|
-
|
|
2811
|
-
function placedAssignments$1(commands) {
|
|
2812
|
-
const all = commands.flatMap(shellAssignments).sort((left, right) => {
|
|
2813
|
-
return left.word.start - right.word.start;
|
|
2814
|
-
});
|
|
2815
|
-
return all.map((assignment, index) => {
|
|
2816
|
-
if (!assignment.isAppend) {
|
|
2817
|
-
return { assignment, place: void 0 };
|
|
2818
|
-
}
|
|
2819
|
-
const earlier = all.slice(0, index).filter((found) => found.name === assignment.name);
|
|
2820
|
-
return { assignment, place: appendedPlace(earlier.map((found) => found.value)) };
|
|
2821
|
-
});
|
|
2822
|
-
}
|
|
2823
|
-
const isAfterValue = ({ place }) => place === "after-value" || place === "after-outside";
|
|
2824
|
-
function shellAppend(assignment, variables) {
|
|
2825
|
-
const at = assignment.word.start;
|
|
2826
|
-
const written = `$${assignment.name}`;
|
|
2827
|
-
const found = variables.programAt({ raw: written, value: written, start: at, end: at });
|
|
2828
|
-
const program = found ?? { written, program: "generator-or-other" };
|
|
2829
|
-
const text = assignmentValueText(assignment);
|
|
2830
|
-
if (text !== void 0) {
|
|
2831
|
-
const [command] = shellCommandsAt(text.text, text.start);
|
|
2832
|
-
return { value: { words: command ?? [], program }, command };
|
|
2833
|
-
}
|
|
2834
|
-
const words = shellCommands(assignment.value).flat().map((word) => ({ ...word, start: at, end: at }));
|
|
2835
|
-
const isCertain = program.program === "other";
|
|
2836
|
-
const uncertain = { ...program, program: "generator-or-other" };
|
|
2837
|
-
return { value: { words, program: isCertain ? program : uncertain }, command: void 0 };
|
|
2838
|
-
}
|
|
2839
|
-
function shellAppends(commands, variables) {
|
|
2840
|
-
const appends = placedAssignments$1(commands).filter(isAfterValue).map(({ assignment }) => shellAppend(assignment, variables));
|
|
2841
|
-
const taken = new Set(appends.flatMap(({ command }) => command === void 0 ? [] : [command]));
|
|
2842
|
-
const isTaken = (command) => [...taken].some(
|
|
2843
|
-
(found) => found.length === command.length && found[0]?.start === command[0]?.start
|
|
2844
|
-
);
|
|
2845
|
-
return {
|
|
2846
|
-
commands: commands.filter((command) => !isTaken(command)),
|
|
2847
|
-
appended: appends.map(({ value }) => value)
|
|
2848
|
-
};
|
|
2849
|
-
}
|
|
2850
|
-
|
|
2851
|
-
const NONE = /* @__PURE__ */ new Set();
|
|
2852
|
-
const PACKAGE_OPTIONS = /* @__PURE__ */ new Set(["-p", "--package"]);
|
|
2853
|
-
const PACKAGE_MANAGER_OPTIONS = /* @__PURE__ */ new Set([
|
|
2854
|
-
"--filter",
|
|
2855
|
-
"-F",
|
|
2856
|
-
"--dir",
|
|
2857
|
-
"-C",
|
|
2858
|
-
"--prefix",
|
|
2859
|
-
"--cwd",
|
|
2860
|
-
"--workspace"
|
|
2861
|
-
]);
|
|
2862
|
-
const launcher = (words, packageOptions = NONE, valueOptions = NONE) => {
|
|
2863
|
-
const allValueOptions = /* @__PURE__ */ new Set([...valueOptions, ...packageOptions]);
|
|
2864
|
-
return { words, packageOptions, valueOptions: allValueOptions, operands: 0 };
|
|
2865
|
-
};
|
|
2866
|
-
const CONTAINER_OPTIONS = /* @__PURE__ */ new Set([
|
|
2867
|
-
"-e",
|
|
2868
|
-
"--env",
|
|
2869
|
-
"--env-file",
|
|
2870
|
-
"-v",
|
|
2871
|
-
"--volume",
|
|
2872
|
-
"--mount",
|
|
2873
|
-
"-p",
|
|
2874
|
-
"--publish",
|
|
2875
|
-
"-w",
|
|
2876
|
-
"--workdir",
|
|
2877
|
-
"-u",
|
|
2878
|
-
"--user",
|
|
2879
|
-
"--name",
|
|
2880
|
-
"--network",
|
|
2881
|
-
"--entrypoint",
|
|
2882
|
-
"--platform",
|
|
2883
|
-
"-l",
|
|
2884
|
-
"--label",
|
|
2885
|
-
"-h",
|
|
2886
|
-
"--hostname",
|
|
2887
|
-
"--add-host"
|
|
2888
|
-
]);
|
|
2889
|
-
const container = (words) => ({
|
|
2890
|
-
...launcher(words, NONE, CONTAINER_OPTIONS),
|
|
2891
|
-
operands: 1
|
|
2892
|
-
});
|
|
2893
|
-
const withOperands = (words, operands, valueOptions = NONE) => ({ ...launcher(words, NONE, valueOptions), operands });
|
|
2894
|
-
const XARGS_OPTIONS = /* @__PURE__ */ new Set([
|
|
2895
|
-
"-I",
|
|
2896
|
-
"-J",
|
|
2897
|
-
"-L",
|
|
2898
|
-
"-n",
|
|
2899
|
-
"-P",
|
|
2900
|
-
"-R",
|
|
2901
|
-
"-S",
|
|
2902
|
-
"-s",
|
|
2903
|
-
"-d",
|
|
2904
|
-
"-E",
|
|
2905
|
-
"-a",
|
|
2906
|
-
"--max-args",
|
|
2907
|
-
"--max-procs",
|
|
2908
|
-
"--max-lines",
|
|
2909
|
-
"--delimiter",
|
|
2910
|
-
"--arg-file"
|
|
2911
|
-
]);
|
|
2912
|
-
const NODE_OPTIONS = /* @__PURE__ */ new Set([
|
|
2913
|
-
"-r",
|
|
2914
|
-
"--require",
|
|
2915
|
-
"--import",
|
|
2916
|
-
"--loader",
|
|
2917
|
-
"--env-file"
|
|
2918
|
-
]);
|
|
2919
|
-
const LAUNCHERS = [
|
|
2920
|
-
launcher(["npm", "exec"], PACKAGE_OPTIONS),
|
|
2921
|
-
launcher(["npm", "x"], PACKAGE_OPTIONS),
|
|
2922
|
-
launcher(["pnpm", "exec"], NONE, PACKAGE_MANAGER_OPTIONS),
|
|
2923
|
-
launcher(["pnpm", "dlx"], /* @__PURE__ */ new Set(["--package"])),
|
|
2924
|
-
launcher(["yarn", "dlx"], PACKAGE_OPTIONS),
|
|
2925
|
-
launcher(["yarn", "exec"]),
|
|
2926
|
-
launcher(["bun", "x"], PACKAGE_OPTIONS),
|
|
2927
|
-
withOperands(["yarn", "workspace"], 1),
|
|
2928
|
-
launcher(["dotenvx", "run"], NONE, /* @__PURE__ */ new Set(["-f", "--env-file", "-e", "--env", "--convention"])),
|
|
2929
|
-
launcher(
|
|
2930
|
-
["doppler", "run"],
|
|
2931
|
-
NONE,
|
|
2932
|
-
/* @__PURE__ */ new Set(["-p", "--project", "-c", "--config", "--token", "--mount", "--scope"])
|
|
2933
|
-
),
|
|
2934
|
-
launcher(["nx", "exec"], NONE, /* @__PURE__ */ new Set(["--projects", "-p", "--exclude"])),
|
|
2935
|
-
launcher(["deno", "run"], NONE, /* @__PURE__ */ new Set(["--config", "-c", "--import-map", "--location"])),
|
|
2936
|
-
launcher(["deno", "x"]),
|
|
2937
|
-
launcher(["npx"], PACKAGE_OPTIONS, /* @__PURE__ */ new Set(["-c", "--call"])),
|
|
2938
|
-
launcher(["pnpx"], PACKAGE_OPTIONS),
|
|
2939
|
-
launcher(["bunx"], PACKAGE_OPTIONS),
|
|
2940
|
-
// Like a bare `pnpm <name>`, a bare `bun <name>` runs the binary when no script has the name.
|
|
2941
|
-
launcher(["bun"], NONE, /* @__PURE__ */ new Set(["--cwd", "--filter", "-F"])),
|
|
2942
|
-
launcher(["corepack"]),
|
|
2943
|
-
launcher(["pnpm"], NONE, PACKAGE_MANAGER_OPTIONS),
|
|
2944
|
-
launcher(["yarn"], NONE, PACKAGE_MANAGER_OPTIONS),
|
|
2945
|
-
launcher(["node"], NONE, NODE_OPTIONS),
|
|
2946
|
-
launcher(["tsx"], NONE, NODE_OPTIONS),
|
|
2947
|
-
launcher(["ts-node"], NONE, /* @__PURE__ */ new Set([...NODE_OPTIONS, "-P", "--project", "-O", "--compiler"])),
|
|
2948
|
-
launcher(["cross-env"]),
|
|
2949
|
-
launcher(["dotenv"], NONE, /* @__PURE__ */ new Set(["-e", "-c", "-v"])),
|
|
2950
|
-
launcher(["env"], NONE, /* @__PURE__ */ new Set(["-u", "--unset", "-C", "--chdir"])),
|
|
2951
|
-
launcher(["exec"], NONE, /* @__PURE__ */ new Set(["-a"])),
|
|
2952
|
-
launcher(["command"]),
|
|
2953
|
-
launcher(["time"]),
|
|
2954
|
-
launcher(["nice"], NONE, /* @__PURE__ */ new Set(["-n", "--adjustment"])),
|
|
2955
|
-
withOperands(["timeout"], 1, /* @__PURE__ */ new Set(["-s", "--signal", "-k", "--kill-after"])),
|
|
2956
|
-
launcher(["xargs"], NONE, XARGS_OPTIONS),
|
|
2957
|
-
launcher(["nohup"]),
|
|
2958
|
-
launcher(["sudo"], NONE, /* @__PURE__ */ new Set(["-u", "-g"])),
|
|
2959
|
-
// The shell form of Dockerfile instructions runs the rest of the line in a shell.
|
|
2960
|
-
launcher(["RUN"], NONE, /* @__PURE__ */ new Set(["--mount", "--network", "--security"])),
|
|
2961
|
-
launcher(["CMD"]),
|
|
2962
|
-
launcher(["ENTRYPOINT"]),
|
|
2963
|
-
container(["docker", "run"]),
|
|
2964
|
-
container(["docker", "exec"]),
|
|
2965
|
-
container(["docker", "compose", "run"]),
|
|
2966
|
-
container(["docker", "compose", "exec"]),
|
|
2967
|
-
container(["podman", "run"]),
|
|
2968
|
-
container(["podman", "exec"])
|
|
2969
|
-
];
|
|
2970
|
-
const installers = (manager, subcommands) => subcommands.map((subcommand) => ({ words: [manager, subcommand] }));
|
|
2971
|
-
const NPM_INSTALL = ["install", "i", "add", "update", "up", "uninstall", "remove", "rm", "un"];
|
|
2972
|
-
const INSTALLERS = [
|
|
2973
|
-
...installers("npm", NPM_INSTALL),
|
|
2974
|
-
...installers("pnpm", ["add", "update", "up", "remove", "rm", "uninstall", "un"]),
|
|
2975
|
-
...installers("yarn", ["add", "upgrade", "up", "remove"]),
|
|
2976
|
-
// Yarn 1 installs global packages with `yarn global add`.
|
|
2977
|
-
{ words: ["yarn", "global", "add"] },
|
|
2978
|
-
{ words: ["yarn", "global", "remove"] },
|
|
2979
|
-
...installers("bun", ["add", "a", "update", "remove", "rm", "install", "i"]),
|
|
2980
|
-
...installers("deno", ["add", "install", "i", "remove", "uninstall"])
|
|
2981
|
-
];
|
|
2982
|
-
const NPM_SPECIFIER_PREFIX = "npm:";
|
|
3157
|
+
return definition.runsGenerator;
|
|
3158
|
+
case "reference":
|
|
3159
|
+
return generators.has(definition.target);
|
|
3160
|
+
case "no-program":
|
|
3161
|
+
return false;
|
|
3162
|
+
case "run-time":
|
|
3163
|
+
return true;
|
|
3164
|
+
default:
|
|
3165
|
+
return assertNever(definition);
|
|
3166
|
+
}
|
|
3167
|
+
}
|
|
3168
|
+
function canRunOther(definition, others, defined) {
|
|
3169
|
+
switch (definition.kind) {
|
|
3170
|
+
case "command":
|
|
3171
|
+
return !definition.runsGenerator;
|
|
3172
|
+
case "reference":
|
|
3173
|
+
return others.has(definition.target) || !defined.has(definition.target);
|
|
3174
|
+
case "no-program":
|
|
3175
|
+
return false;
|
|
3176
|
+
case "run-time":
|
|
3177
|
+
return true;
|
|
3178
|
+
default:
|
|
3179
|
+
return assertNever(definition);
|
|
3180
|
+
}
|
|
3181
|
+
}
|
|
3182
|
+
function variablePrograms(definitions) {
|
|
3183
|
+
const defined = new Set(definitions.map((definition) => definition.name));
|
|
3184
|
+
const generators = /* @__PURE__ */ new Set();
|
|
3185
|
+
const others = /* @__PURE__ */ new Set();
|
|
3186
|
+
for (let size = -1; size !== generators.size + others.size; ) {
|
|
3187
|
+
size = generators.size + others.size;
|
|
3188
|
+
for (const definition of definitions) {
|
|
3189
|
+
if (canRunGenerator(definition, generators)) {
|
|
3190
|
+
generators.add(definition.name);
|
|
3191
|
+
}
|
|
3192
|
+
if (canRunOther(definition, others, defined)) {
|
|
3193
|
+
others.add(definition.name);
|
|
3194
|
+
}
|
|
3195
|
+
}
|
|
3196
|
+
}
|
|
3197
|
+
const programOf = (name) => {
|
|
3198
|
+
if (!generators.has(name)) {
|
|
3199
|
+
return "other";
|
|
3200
|
+
}
|
|
3201
|
+
return others.has(name) ? "generator-or-other" : "generator";
|
|
3202
|
+
};
|
|
3203
|
+
return new Map([...defined].map((name) => [name, programOf(name)]));
|
|
3204
|
+
}
|
|
2983
3205
|
|
|
2984
|
-
function
|
|
2985
|
-
const
|
|
2986
|
-
|
|
2987
|
-
|
|
3206
|
+
function placedAssignments$1(commands) {
|
|
3207
|
+
const all = commands.flatMap(shellAssignments).sort((left, right) => {
|
|
3208
|
+
return left.word.start - right.word.start;
|
|
3209
|
+
});
|
|
3210
|
+
return all.map((assignment, index) => {
|
|
3211
|
+
if (!assignment.isAppend) {
|
|
3212
|
+
return { assignment, place: void 0 };
|
|
3213
|
+
}
|
|
3214
|
+
const earlier = all.slice(0, index).filter((found) => found.name === assignment.name);
|
|
3215
|
+
return { assignment, place: appendedPlace(earlier.map((found) => found.value)) };
|
|
3216
|
+
});
|
|
2988
3217
|
}
|
|
2989
|
-
|
|
2990
|
-
|
|
3218
|
+
const isAfterValue = ({ place }) => place === "after-value" || place === "after-outside";
|
|
3219
|
+
function shellAppend(assignment, variables) {
|
|
3220
|
+
const at = assignment.word.start;
|
|
3221
|
+
const written = `$${assignment.name}`;
|
|
3222
|
+
const found = variables.programAt({ raw: written, value: written, start: at, end: at });
|
|
3223
|
+
const program = found ?? { written, program: "generator-or-other" };
|
|
3224
|
+
const [command] = appendedText(assignment);
|
|
3225
|
+
return { value: { words: command ?? [], program }, command };
|
|
2991
3226
|
}
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
3227
|
+
const isOwnGeneratorCommand = (place, command) => place === "after-outside" && command !== void 0 && runsGenerator(command);
|
|
3228
|
+
function appendedText(assignment) {
|
|
3229
|
+
return placedCommands(assignmentValue(assignment));
|
|
3230
|
+
}
|
|
3231
|
+
const appendsOwnGenerator = ({ assignment, place }) => isOwnGeneratorCommand(place, appendedText(assignment)[0]);
|
|
3232
|
+
function setsKnownProgram(placed, all) {
|
|
3233
|
+
const chain = all.slice(0, all.indexOf(placed) + 1).filter((earlier) => earlier.assignment.name === placed.assignment.name);
|
|
3234
|
+
return chain.some((part) => part.place !== "after-outside" || appendsOwnGenerator(part));
|
|
3235
|
+
}
|
|
3236
|
+
function shellAppends(commands, variables) {
|
|
3237
|
+
const appends = placedAssignments$1(commands).filter(isAfterValue).filter((placed) => !appendsOwnGenerator(placed)).map(({ assignment }) => shellAppend(assignment, variables));
|
|
3238
|
+
const taken = new Set(appends.flatMap(({ command }) => command === void 0 ? [] : [command]));
|
|
3239
|
+
const isTaken = (command) => [...taken].some(
|
|
3240
|
+
(found) => found.length === command.length && found[0]?.start === command[0]?.start
|
|
3241
|
+
);
|
|
3242
|
+
return {
|
|
3243
|
+
commands: commands.filter((command) => !isTaken(command)),
|
|
3244
|
+
appended: appends.map(({ value }) => value)
|
|
3245
|
+
};
|
|
2997
3246
|
}
|
|
2998
3247
|
|
|
3248
|
+
const passedFlag = (text) => text.split("=", 1)[0];
|
|
2999
3249
|
function flagFindings(word, locate) {
|
|
3000
|
-
const
|
|
3250
|
+
const passed = unquotedRawText(word, 0);
|
|
3251
|
+
const flag = passedFlag(passed.text);
|
|
3001
3252
|
const to = FLAG_RENAMES.get(flag);
|
|
3002
3253
|
if (to === void 0) {
|
|
3003
3254
|
return [];
|
|
3004
3255
|
}
|
|
3005
3256
|
const offset = word.start;
|
|
3006
|
-
const
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3257
|
+
const location = locate(offset);
|
|
3258
|
+
const span = placedSpan(passed, flag.length);
|
|
3259
|
+
if (span === void 0) {
|
|
3260
|
+
const manualStep = { kind: "split-flag", location, flag };
|
|
3261
|
+
return [{ offset, manualStep }];
|
|
3262
|
+
}
|
|
3263
|
+
const edit = { ...span, text: to };
|
|
3264
|
+
return [{ offset, edit, change: { kind: "flag-renamed", location, from: flag, to } }];
|
|
3010
3265
|
}
|
|
3011
3266
|
function renamedFlags(value) {
|
|
3012
|
-
const flags = shellCommands(value).flat().map((word) => word.
|
|
3267
|
+
const flags = shellCommands(value).flat().map((word) => passedFlag(word.value));
|
|
3013
3268
|
return [...new Set(flags.filter((flag) => FLAG_RENAMES.has(flag)))];
|
|
3014
3269
|
}
|
|
3015
3270
|
function argumentFindings(word, locate, variables) {
|
|
@@ -3060,102 +3315,6 @@ function appendedValueFindings({ words, program }, locate, variables) {
|
|
|
3060
3315
|
return [...found, ...unmigratedWordFindings(words, handled, locate)];
|
|
3061
3316
|
}
|
|
3062
3317
|
|
|
3063
|
-
const END_OF_OPTIONS = "--";
|
|
3064
|
-
const isOption = (word) => word.value.startsWith("-") && word.value.length > 1;
|
|
3065
|
-
function skipAssignments(words, start) {
|
|
3066
|
-
let index = start;
|
|
3067
|
-
while (index < words.length && ASSIGNMENT_RE$2.test(words[index].raw)) {
|
|
3068
|
-
index++;
|
|
3069
|
-
}
|
|
3070
|
-
return index;
|
|
3071
|
-
}
|
|
3072
|
-
const WINDOWS_PROGRAM_SUFFIX_RE = /\.(?:cmd|exe|ps1)$/i;
|
|
3073
|
-
const windowsSuffix = (value) => WINDOWS_PROGRAM_SUFFIX_RE.exec(value)?.[0] ?? "";
|
|
3074
|
-
const withoutWindowsSuffix = (value) => value.slice(0, value.length - windowsSuffix(value).length);
|
|
3075
|
-
const entryWord = (word) => word === void 0 ? void 0 : withoutWindowsSuffix(word.value);
|
|
3076
|
-
function matchingPrefix(entries, words, index) {
|
|
3077
|
-
return entries.find(
|
|
3078
|
-
(entry) => entry.words.every((name, offset) => entryWord(words[index + offset]) === name)
|
|
3079
|
-
);
|
|
3080
|
-
}
|
|
3081
|
-
function inlineOptionPackage(word, launcher) {
|
|
3082
|
-
const equals = word.value.indexOf("=");
|
|
3083
|
-
const name = word.value.slice(0, equals);
|
|
3084
|
-
return launcher.packageOptions.has(name) ? { word, value: word.value.slice(equals + 1) } : void 0;
|
|
3085
|
-
}
|
|
3086
|
-
function launchedProgram(words, start, launcher, packages) {
|
|
3087
|
-
let index = start;
|
|
3088
|
-
while (index < words.length && isOption(words[index])) {
|
|
3089
|
-
const option = words[index++];
|
|
3090
|
-
if (option.value === END_OF_OPTIONS) {
|
|
3091
|
-
break;
|
|
3092
|
-
}
|
|
3093
|
-
const inline = option.value.includes("=") ? inlineOptionPackage(option, launcher) : void 0;
|
|
3094
|
-
if (inline !== void 0) {
|
|
3095
|
-
packages.push(inline);
|
|
3096
|
-
}
|
|
3097
|
-
const value = words[index];
|
|
3098
|
-
if (!option.value.includes("=") && launcher.valueOptions.has(option.value) && value) {
|
|
3099
|
-
if (launcher.packageOptions.has(option.value)) {
|
|
3100
|
-
packages.push({ word: value, value: value.value });
|
|
3101
|
-
}
|
|
3102
|
-
index++;
|
|
3103
|
-
}
|
|
3104
|
-
}
|
|
3105
|
-
return index;
|
|
3106
|
-
}
|
|
3107
|
-
const installArguments = (words, start) => words.slice(start).filter((word) => !isOption(word)).map((word) => ({ word, value: word.value }));
|
|
3108
|
-
function commandRoles(words) {
|
|
3109
|
-
const packages = [];
|
|
3110
|
-
let index = skipAssignments(words, 0);
|
|
3111
|
-
while (index < words.length) {
|
|
3112
|
-
const installer = matchingPrefix(INSTALLERS, words, index);
|
|
3113
|
-
if (installer !== void 0) {
|
|
3114
|
-
packages.push(...installArguments(words, index + installer.words.length));
|
|
3115
|
-
return { program: void 0, packages };
|
|
3116
|
-
}
|
|
3117
|
-
const launcher = matchingPrefix(LAUNCHERS, words, index);
|
|
3118
|
-
if (launcher === void 0) {
|
|
3119
|
-
return { program: index, packages };
|
|
3120
|
-
}
|
|
3121
|
-
const start = index + launcher.words.length;
|
|
3122
|
-
const afterOptions = launchedProgram(words, start, launcher, packages);
|
|
3123
|
-
index = skipAssignments(words, afterOptions + launcher.operands);
|
|
3124
|
-
}
|
|
3125
|
-
return { program: void 0, packages };
|
|
3126
|
-
}
|
|
3127
|
-
|
|
3128
|
-
const RECIPE_PREFIX_RE$1 = /^[@+-]+(?=.)/;
|
|
3129
|
-
function withoutRecipePrefix(words) {
|
|
3130
|
-
const [first, ...rest] = words;
|
|
3131
|
-
if (first === void 0 || !RECIPE_PREFIX_RE$1.test(first.value)) {
|
|
3132
|
-
return words;
|
|
3133
|
-
}
|
|
3134
|
-
return [{ ...first, value: first.value.replace(RECIPE_PREFIX_RE$1, "") }, ...rest];
|
|
3135
|
-
}
|
|
3136
|
-
const NO_VARIABLES = {
|
|
3137
|
-
programAt: () => void 0,
|
|
3138
|
-
referenceAt: () => void 0
|
|
3139
|
-
};
|
|
3140
|
-
function runsGenerator(command) {
|
|
3141
|
-
const words = withoutRecipePrefix(command);
|
|
3142
|
-
const { program } = commandRoles(words);
|
|
3143
|
-
const word = program === void 0 ? void 0 : words[program];
|
|
3144
|
-
return word !== void 0 && packageReference(withoutWindowsSuffix(word.value)).name === GENERATOR_COMMAND;
|
|
3145
|
-
}
|
|
3146
|
-
|
|
3147
|
-
const PATH_SEPARATOR$8 = "/";
|
|
3148
|
-
const WINDOWS_SEPARATOR_RE = /\\/g;
|
|
3149
|
-
const QUOTE_RE = /["']/g;
|
|
3150
|
-
const WINDOWS_PATH_RE = /^[^/]*[^\\/\s]\\[^\\/\s][^/]*$/;
|
|
3151
|
-
function programPath(word) {
|
|
3152
|
-
const suffix = windowsSuffix(word.value);
|
|
3153
|
-
const written = word.raw.replace(QUOTE_RE, "");
|
|
3154
|
-
const isWindowsPath = suffix !== "" || WINDOWS_PATH_RE.test(written);
|
|
3155
|
-
const windowsPath = written.replace(WINDOWS_SEPARATOR_RE, PATH_SEPARATOR$8);
|
|
3156
|
-
return { path: isWindowsPath ? windowsPath : word.value, suffix };
|
|
3157
|
-
}
|
|
3158
|
-
|
|
3159
3318
|
const SHELL_VARIABLE_RE$1 = /^"?\$(?:([A-Za-z_][A-Za-z0-9_]*)|\{([A-Za-z_][A-Za-z0-9_]*)\})"?$/;
|
|
3160
3319
|
function expandedName$1(text) {
|
|
3161
3320
|
const match = SHELL_VARIABLE_RE$1.exec(text);
|
|
@@ -3180,8 +3339,12 @@ function expansionDefinitions(name, expansion) {
|
|
|
3180
3339
|
const variable = isOutside ? { name, kind: "command", runsGenerator: false } : { name, kind: "reference", target: expansion.name };
|
|
3181
3340
|
return [word, variable];
|
|
3182
3341
|
}
|
|
3183
|
-
function programDefinitions$1(
|
|
3184
|
-
|
|
3342
|
+
function programDefinitions$1(definition) {
|
|
3343
|
+
const { name, value } = definition;
|
|
3344
|
+
if (definition.isAfterOutside === true) {
|
|
3345
|
+
return [{ name, kind: "run-time" }];
|
|
3346
|
+
}
|
|
3347
|
+
if (definition.isAppended === true) {
|
|
3185
3348
|
return [{ name, kind: "no-program" }];
|
|
3186
3349
|
}
|
|
3187
3350
|
const expansion = wholeWordExpansion(value.trim());
|
|
@@ -3220,12 +3383,14 @@ function assignedByExpansions(commands) {
|
|
|
3220
3383
|
]);
|
|
3221
3384
|
}
|
|
3222
3385
|
function withShellAssignments(commands, file) {
|
|
3223
|
-
const
|
|
3224
|
-
|
|
3225
|
-
|
|
3386
|
+
const placed = placedAssignments$1(commands);
|
|
3387
|
+
const assigned = placed.flatMap((entry) => {
|
|
3388
|
+
const { assignment } = entry;
|
|
3389
|
+
if (isArrayAssignment(assignment) || !setsKnownProgram(entry, placed)) {
|
|
3226
3390
|
return [];
|
|
3227
3391
|
}
|
|
3228
|
-
|
|
3392
|
+
const { name, value } = assignment;
|
|
3393
|
+
return appendsOwnGenerator(entry) ? [{ name, value, isAfterOutside: true }] : [{ name, value, isAppended: isAfterValue(entry) }];
|
|
3229
3394
|
});
|
|
3230
3395
|
const definitions = [...assigned, ...assignedByExpansions(commands)];
|
|
3231
3396
|
if (definitions.length === 0) {
|
|
@@ -3273,18 +3438,19 @@ function withUnreadVariables(variables) {
|
|
|
3273
3438
|
};
|
|
3274
3439
|
}
|
|
3275
3440
|
|
|
3276
|
-
const QUOTES
|
|
3277
|
-
const PATH_SEPARATOR$
|
|
3441
|
+
const QUOTES = /* @__PURE__ */ new Set(["'", '"']);
|
|
3442
|
+
const PATH_SEPARATOR$6 = "/";
|
|
3278
3443
|
const BIN_FOLDER = "/.bin/";
|
|
3279
3444
|
const OLD_PACKAGE_FOLDER = `node_modules/${GENERATOR_COMMAND}/`;
|
|
3280
3445
|
function renameAtEnd(word, name, to, suffix = "") {
|
|
3281
3446
|
const at = word.raw.lastIndexOf(name);
|
|
3282
3447
|
const tail = word.raw.slice(at + name.length);
|
|
3283
3448
|
const quote = tail.slice(suffix.length);
|
|
3284
|
-
if (at === -1 || quote !== "" && !QUOTES
|
|
3449
|
+
if (at === -1 || quote !== "" && !QUOTES.has(quote)) {
|
|
3285
3450
|
return void 0;
|
|
3286
3451
|
}
|
|
3287
|
-
|
|
3452
|
+
const span = writtenSpan(word, at, name.length);
|
|
3453
|
+
return span === void 0 ? void 0 : { ...span, text: to };
|
|
3288
3454
|
}
|
|
3289
3455
|
function packageFindings(found, locate) {
|
|
3290
3456
|
const { name, isPinned } = packageReference(found.value);
|
|
@@ -3301,19 +3467,23 @@ function packageFindings(found, locate) {
|
|
|
3301
3467
|
const change = { kind: "package-name-renamed", location, from: name, to };
|
|
3302
3468
|
return edit === void 0 ? [] : [{ offset, edit, change }];
|
|
3303
3469
|
}
|
|
3304
|
-
function programPathFindings(word,
|
|
3470
|
+
function programPathFindings(word, program, location) {
|
|
3471
|
+
const { path, suffix, written } = program;
|
|
3305
3472
|
const offset = word.start;
|
|
3306
3473
|
if (path.includes(OLD_PACKAGE_FOLDER)) {
|
|
3307
3474
|
return [{ offset, manualStep: { kind: "old-package-file", location, path } }];
|
|
3308
3475
|
}
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3476
|
+
if (!path.endsWith(`${BIN_FOLDER}${GENERATOR_COMMAND}${suffix}`)) {
|
|
3477
|
+
const manualStep = { kind: "old-name-in-command", location, word: written };
|
|
3478
|
+
const isGenerator = path.endsWith(`${PATH_SEPARATOR$6}${GENERATOR_COMMAND}${suffix}`);
|
|
3479
|
+
return isGenerator ? [{ offset, manualStep }] : [];
|
|
3480
|
+
}
|
|
3481
|
+
const edit = renameAtEnd(word, GENERATOR_COMMAND, MIGRATED_GENERATOR_COMMAND, suffix);
|
|
3312
3482
|
return edit === void 0 ? [] : [{ offset, edit, change: { kind: "command-renamed", location } }];
|
|
3313
3483
|
}
|
|
3314
3484
|
function programFindings(word, location) {
|
|
3315
3485
|
const program = programPath(word);
|
|
3316
|
-
if (program.path.includes(PATH_SEPARATOR$
|
|
3486
|
+
if (program.path.includes(PATH_SEPARATOR$6)) {
|
|
3317
3487
|
return programPathFindings(word, program, location);
|
|
3318
3488
|
}
|
|
3319
3489
|
const { path, suffix } = program;
|
|
@@ -3371,12 +3541,24 @@ function shellTextFindings(text, locate) {
|
|
|
3371
3541
|
function commandWordFindings(commands, locate, variables = NO_VARIABLES, appended = []) {
|
|
3372
3542
|
const known = withUnreadVariables(withWordExpansions(withShellAssignments(commands, variables)));
|
|
3373
3543
|
const shell = shellAppends(commands, known);
|
|
3374
|
-
|
|
3544
|
+
return textFindings([
|
|
3375
3545
|
...shell.commands.flatMap((words) => commandFindings(words, locate, known)),
|
|
3376
3546
|
...[...appended, ...shell.appended].flatMap(
|
|
3377
3547
|
(value) => appendedValueFindings(value, locate, known)
|
|
3378
3548
|
)
|
|
3379
|
-
]
|
|
3549
|
+
]);
|
|
3550
|
+
}
|
|
3551
|
+
function uniqueFindings(found) {
|
|
3552
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3553
|
+
return found.filter((finding) => {
|
|
3554
|
+
const key = JSON.stringify(finding);
|
|
3555
|
+
const isNew = !seen.has(key);
|
|
3556
|
+
seen.add(key);
|
|
3557
|
+
return isNew;
|
|
3558
|
+
});
|
|
3559
|
+
}
|
|
3560
|
+
function textFindings(found) {
|
|
3561
|
+
const findings = uniqueFindings(found).sort((left, right) => left.offset - right.offset);
|
|
3380
3562
|
return {
|
|
3381
3563
|
edits: findings.flatMap((finding) => finding.edit === void 0 ? [] : [finding.edit]),
|
|
3382
3564
|
changes: findings.flatMap((finding) => finding.change === void 0 ? [] : [finding.change]),
|
|
@@ -3497,15 +3679,17 @@ function rangeStyle(spec) {
|
|
|
3497
3679
|
return isHyphenRange ? "^" : versionStyle(first[2], first[3], first[4]);
|
|
3498
3680
|
}
|
|
3499
3681
|
const isLocalPackageSpec = (spec) => LOCAL_PROTOCOLS.some((protocol) => spec.startsWith(protocol));
|
|
3682
|
+
const NPM_PROTOCOL$1 = "npm:";
|
|
3500
3683
|
function migrateVersionSpec(spec, version) {
|
|
3501
|
-
if (KEPT_PROTOCOLS.some((
|
|
3684
|
+
if (KEPT_PROTOCOLS.some((protocol2) => spec.startsWith(protocol2))) {
|
|
3502
3685
|
return { kind: "kept", spec, isReported: false };
|
|
3503
3686
|
}
|
|
3504
|
-
const
|
|
3687
|
+
const protocol = spec.startsWith(NPM_PROTOCOL$1) ? NPM_PROTOCOL$1 : "";
|
|
3688
|
+
const style = rangeStyle(spec.slice(protocol.length));
|
|
3505
3689
|
if (style === void 0) {
|
|
3506
3690
|
return { kind: "kept", spec, isReported: true };
|
|
3507
3691
|
}
|
|
3508
|
-
return { kind: "replaced", spec: `${style}${version}` };
|
|
3692
|
+
return { kind: "replaced", spec: `${protocol}${style}${version}` };
|
|
3509
3693
|
}
|
|
3510
3694
|
|
|
3511
3695
|
const NO_LONGER_INSTALLED = /* @__PURE__ */ new Map([
|
|
@@ -3514,13 +3698,13 @@ const NO_LONGER_INSTALLED = /* @__PURE__ */ new Map([
|
|
|
3514
3698
|
const ORIGINAL_NAMES = new Map(
|
|
3515
3699
|
[...PACKAGE_RENAMES].map(([original, successor]) => [successor, original])
|
|
3516
3700
|
);
|
|
3517
|
-
const PATH_SEPARATOR$
|
|
3701
|
+
const PATH_SEPARATOR$5 = "/";
|
|
3518
3702
|
function namesUninstalledPackage(text) {
|
|
3519
3703
|
return [...NO_LONGER_INSTALLED.keys()].some(
|
|
3520
3704
|
(name) => text.includes(name) || text.includes(ORIGINAL_NAMES.get(name) ?? name)
|
|
3521
3705
|
);
|
|
3522
3706
|
}
|
|
3523
|
-
const directoryOf = (path) => path.slice(0, path.lastIndexOf(PATH_SEPARATOR$
|
|
3707
|
+
const directoryOf = (path) => path.slice(0, path.lastIndexOf(PATH_SEPARATOR$5) + 1);
|
|
3524
3708
|
const isAtOrAbove = (path, filePath) => filePath.startsWith(directoryOf(path));
|
|
3525
3709
|
function declaredNames(manifest) {
|
|
3526
3710
|
return DEPENDENCY_FIELDS.flatMap((field) => mapsAt(manifest, field)).flatMap(textEntries).map(({ key }) => key.value);
|
|
@@ -3545,7 +3729,7 @@ function isDeclaredFor(manifests, filePath, name) {
|
|
|
3545
3729
|
return containing.length === 0 || containing.some(declares);
|
|
3546
3730
|
}
|
|
3547
3731
|
const packageOfSpecifier = (specifier) => {
|
|
3548
|
-
const slash = specifier.indexOf(PATH_SEPARATOR$
|
|
3732
|
+
const slash = specifier.indexOf(PATH_SEPARATOR$5);
|
|
3549
3733
|
return slash === -1 ? specifier : specifier.slice(0, slash);
|
|
3550
3734
|
};
|
|
3551
3735
|
function undeclaredImportSteps(imports, filePath, manifests) {
|
|
@@ -3556,22 +3740,225 @@ function undeclaredImportSteps(imports, filePath, manifests) {
|
|
|
3556
3740
|
});
|
|
3557
3741
|
}
|
|
3558
3742
|
|
|
3743
|
+
const ARGUMENTS_WORDS = new Set(
|
|
3744
|
+
["$", "$$"].flatMap(
|
|
3745
|
+
(dollar) => ["@", "{@}"].flatMap((name) => ["", '"'].map((quote) => `${quote}${dollar}${name}${quote}`))
|
|
3746
|
+
)
|
|
3747
|
+
);
|
|
3748
|
+
function runsArguments(script) {
|
|
3749
|
+
return shellCommands(script).some((words) => {
|
|
3750
|
+
const { program } = commandRoles(words);
|
|
3751
|
+
return program !== void 0 && ARGUMENTS_WORDS.has(words[program]?.raw ?? "");
|
|
3752
|
+
});
|
|
3753
|
+
}
|
|
3754
|
+
function runsItsCommand(entrypoint) {
|
|
3755
|
+
const script = shellScript(entrypoint);
|
|
3756
|
+
return script === void 0 || runsArguments(script.value);
|
|
3757
|
+
}
|
|
3758
|
+
function containerCommand(entrypoint, command) {
|
|
3759
|
+
return runsGenerator(command) && runsItsCommand(entrypoint) ? [entrypoint, command] : [[...entrypoint, ...command]];
|
|
3760
|
+
}
|
|
3761
|
+
function entrypointProgram(entrypoint) {
|
|
3762
|
+
const script = shellScript(entrypoint);
|
|
3763
|
+
if (script !== void 0) {
|
|
3764
|
+
return shellCommands(script.value).some(runsGenerator) ? "generator-or-other" : "other";
|
|
3765
|
+
}
|
|
3766
|
+
const { changes } = commandWordFindings([entrypoint], () => "");
|
|
3767
|
+
return changes.some((change) => change.kind === "command-renamed") ? "generator" : "other";
|
|
3768
|
+
}
|
|
3769
|
+
function entrypointArgumentFindings({ entrypoint, command, written, isPlaced = true }, locate) {
|
|
3770
|
+
const program = entrypointProgram(entrypoint);
|
|
3771
|
+
const first = command[0];
|
|
3772
|
+
if (program === "other" || first === void 0 || entrypointProgram(command) !== "other") {
|
|
3773
|
+
return [];
|
|
3774
|
+
}
|
|
3775
|
+
const use = { written, program: isPlaced ? program : "generator-or-other" };
|
|
3776
|
+
return programArgumentFindings(command, { offset: first.start, use }, locate, NO_VARIABLES);
|
|
3777
|
+
}
|
|
3778
|
+
|
|
3779
|
+
const STAGE_INSTRUCTION_RE = /^[ \t]*(FROM|CMD|ENTRYPOINT)\b(.*)$/gm;
|
|
3780
|
+
const FROM_RE = /^[ \t]+(?:--\S+[ \t]+)*(\S+)(?:[ \t]+AS[ \t]+(\S+))?/i;
|
|
3781
|
+
const FROM = "FROM";
|
|
3782
|
+
const CMD = "CMD";
|
|
3783
|
+
const ENTRYPOINT_WRITTEN = "ENTRYPOINT";
|
|
3784
|
+
function dockerStages(text, forms) {
|
|
3785
|
+
const formAt = new Map(forms.map((form) => [form.lineStart, form]));
|
|
3786
|
+
const stages = [];
|
|
3787
|
+
for (const match of text.matchAll(STAGE_INSTRUCTION_RE)) {
|
|
3788
|
+
const [, keyword, rest] = match;
|
|
3789
|
+
const stage = stages.at(-1);
|
|
3790
|
+
if (keyword === FROM) {
|
|
3791
|
+
const from = FROM_RE.exec(rest ?? "");
|
|
3792
|
+
const name = from?.[2]?.toLowerCase();
|
|
3793
|
+
stages.push({ base: from?.[1] ?? "", name, entrypoint: void 0, command: void 0 });
|
|
3794
|
+
} else if (stage !== void 0) {
|
|
3795
|
+
const instruction = { form: formAt.get(match.index) };
|
|
3796
|
+
stage[keyword === CMD ? "command" : "entrypoint"] = instruction;
|
|
3797
|
+
}
|
|
3798
|
+
}
|
|
3799
|
+
return stages;
|
|
3800
|
+
}
|
|
3801
|
+
function baseStage(stages, index) {
|
|
3802
|
+
const base = stages[index]?.base.toLowerCase();
|
|
3803
|
+
return stages.findIndex((stage, at) => at < index && (stage.name === base || `${at}` === base));
|
|
3804
|
+
}
|
|
3805
|
+
function entrypointOf(stages, index) {
|
|
3806
|
+
const own = stages[index]?.entrypoint;
|
|
3807
|
+
const base = baseStage(stages, index);
|
|
3808
|
+
return own ?? (base === -1 ? void 0 : entrypointOf(stages, base));
|
|
3809
|
+
}
|
|
3810
|
+
function entrypointPairs(text, forms) {
|
|
3811
|
+
const stages = dockerStages(text, forms);
|
|
3812
|
+
return stages.flatMap((stage, index) => {
|
|
3813
|
+
const entrypoint = entrypointOf(stages, index)?.form;
|
|
3814
|
+
const command = stage.command?.form;
|
|
3815
|
+
return entrypoint === void 0 || command === void 0 ? [] : [{ entrypoint, command }];
|
|
3816
|
+
});
|
|
3817
|
+
}
|
|
3818
|
+
function entrypointCommandFindings(pairs, locate) {
|
|
3819
|
+
return pairs.flatMap(({ entrypoint, command }) => {
|
|
3820
|
+
if (shellScript(entrypoint.words) === void 0) {
|
|
3821
|
+
return [];
|
|
3822
|
+
}
|
|
3823
|
+
const pair = { entrypoint: entrypoint.words, command: command.words };
|
|
3824
|
+
return entrypointArgumentFindings({ ...pair, written: ENTRYPOINT_WRITTEN }, locate);
|
|
3825
|
+
});
|
|
3826
|
+
}
|
|
3827
|
+
|
|
3828
|
+
const DEFAULT_ESCAPE = "\\";
|
|
3829
|
+
const DIRECTIVE_RE = /^#[ \t]*([A-Za-z]+)[ \t]*=[ \t]*(\S+)[ \t]*$/;
|
|
3830
|
+
const ESCAPE_DIRECTIVE = "escape";
|
|
3831
|
+
const LINE_BREAK$5 = "\n";
|
|
3832
|
+
const CARRIAGE_RETURN = "\r";
|
|
3833
|
+
const BLANKS = /* @__PURE__ */ new Set([" ", " ", CARRIAGE_RETURN, LINE_BREAK$5]);
|
|
3834
|
+
const SINGLE_QUOTE = "'";
|
|
3835
|
+
const DOUBLE_QUOTE = '"';
|
|
3836
|
+
const DOUBLE_QUOTE_ESCAPES = /* @__PURE__ */ new Set([DOUBLE_QUOTE, "$"]);
|
|
3837
|
+
const ASSIGNMENT$1 = "=";
|
|
3838
|
+
const VARIABLE_INSTRUCTIONS = /* @__PURE__ */ new Set(["ARG", "ENV"]);
|
|
3839
|
+
const LEGACY_ENV_INSTRUCTION = "ENV";
|
|
3840
|
+
function escapeCharacter(text) {
|
|
3841
|
+
for (const line of text.split(LINE_BREAK$5)) {
|
|
3842
|
+
const directive = DIRECTIVE_RE.exec(line.replace(CARRIAGE_RETURN, ""));
|
|
3843
|
+
if (directive === null) {
|
|
3844
|
+
return DEFAULT_ESCAPE;
|
|
3845
|
+
}
|
|
3846
|
+
if (directive[1]?.toLowerCase() === ESCAPE_DIRECTIVE) {
|
|
3847
|
+
return directive[2];
|
|
3848
|
+
}
|
|
3849
|
+
}
|
|
3850
|
+
return DEFAULT_ESCAPE;
|
|
3851
|
+
}
|
|
3852
|
+
function instructionEnd(text, index, escapeMark) {
|
|
3853
|
+
for (let end = text.indexOf(LINE_BREAK$5, index); end !== -1; ) {
|
|
3854
|
+
if (!text.slice(index, end).trimEnd().endsWith(escapeMark)) {
|
|
3855
|
+
return end;
|
|
3856
|
+
}
|
|
3857
|
+
index = end + 1;
|
|
3858
|
+
end = text.indexOf(LINE_BREAK$5, index);
|
|
3859
|
+
}
|
|
3860
|
+
return text.length;
|
|
3861
|
+
}
|
|
3862
|
+
const add = (word, text, index) => {
|
|
3863
|
+
word.value += text[index];
|
|
3864
|
+
word.offsets.push(index);
|
|
3865
|
+
};
|
|
3866
|
+
function isContinuation(text, index, escapeMark) {
|
|
3867
|
+
const lineEnd = text.indexOf(LINE_BREAK$5, index);
|
|
3868
|
+
return text[index] === escapeMark && lineEnd !== -1 && text.slice(index + 1, lineEnd).trim() === "";
|
|
3869
|
+
}
|
|
3870
|
+
function isQuotedEscape(text, index, escapeMark) {
|
|
3871
|
+
const next = text[index + 1] ?? "";
|
|
3872
|
+
return text[index] === escapeMark && (DOUBLE_QUOTE_ESCAPES.has(next) || next === escapeMark);
|
|
3873
|
+
}
|
|
3874
|
+
function readQuoted(text, index, word, escapeMark) {
|
|
3875
|
+
const quote = text[index];
|
|
3876
|
+
let at = index + 1;
|
|
3877
|
+
for (; at < text.length && text[at] !== quote; at++) {
|
|
3878
|
+
if (isContinuation(text, at, escapeMark)) {
|
|
3879
|
+
at = text.indexOf(LINE_BREAK$5, at);
|
|
3880
|
+
} else {
|
|
3881
|
+
at += quote === DOUBLE_QUOTE && isQuotedEscape(text, at, escapeMark) ? 1 : 0;
|
|
3882
|
+
add(word, text, at);
|
|
3883
|
+
}
|
|
3884
|
+
}
|
|
3885
|
+
return at + 1;
|
|
3886
|
+
}
|
|
3887
|
+
function readPart(text, index, word, escapeMark) {
|
|
3888
|
+
const char = text[index];
|
|
3889
|
+
if (char === SINGLE_QUOTE || char === DOUBLE_QUOTE) {
|
|
3890
|
+
return readQuoted(text, index, word, escapeMark);
|
|
3891
|
+
}
|
|
3892
|
+
const end = index + (char === escapeMark && index + 1 < text.length ? 2 : 1);
|
|
3893
|
+
add(word, text, end - 1);
|
|
3894
|
+
return end;
|
|
3895
|
+
}
|
|
3896
|
+
function endWord(word, words) {
|
|
3897
|
+
const value = word.value.trimEnd();
|
|
3898
|
+
if (value !== "") {
|
|
3899
|
+
words.push({ text: value, offsets: word.offsets.slice(0, value.length) });
|
|
3900
|
+
}
|
|
3901
|
+
return { value: "", offsets: [] };
|
|
3902
|
+
}
|
|
3903
|
+
function dockerWords(text, range, escapeMark, isWhole = false) {
|
|
3904
|
+
const words = [];
|
|
3905
|
+
const instruction = text.slice(0, range.end);
|
|
3906
|
+
let word = { value: "", offsets: [] };
|
|
3907
|
+
for (let index = range.start; index < range.end; ) {
|
|
3908
|
+
if (isContinuation(text, index, escapeMark)) {
|
|
3909
|
+
index = text.indexOf(LINE_BREAK$5, index) + 1;
|
|
3910
|
+
} else if (BLANKS.has(text[index]) && (!isWhole || word.value === "")) {
|
|
3911
|
+
word = endWord(word, words);
|
|
3912
|
+
index++;
|
|
3913
|
+
} else {
|
|
3914
|
+
index = readPart(instruction, index, word, escapeMark);
|
|
3915
|
+
}
|
|
3916
|
+
}
|
|
3917
|
+
endWord(word, words);
|
|
3918
|
+
return words;
|
|
3919
|
+
}
|
|
3920
|
+
function assignedVariable({ text, offsets }) {
|
|
3921
|
+
const at = text.indexOf(ASSIGNMENT$1);
|
|
3922
|
+
if (at <= 0) {
|
|
3923
|
+
return [];
|
|
3924
|
+
}
|
|
3925
|
+
return [
|
|
3926
|
+
{
|
|
3927
|
+
name: text.slice(0, at),
|
|
3928
|
+
value: { text: text.slice(at + 1), offsets: offsets.slice(at + 1) }
|
|
3929
|
+
}
|
|
3930
|
+
];
|
|
3931
|
+
}
|
|
3932
|
+
function instructionVariables(text, keyword, range, escapeMark) {
|
|
3933
|
+
const [first, ...rest] = dockerWords(text, range, escapeMark);
|
|
3934
|
+
if (first === void 0) {
|
|
3935
|
+
return [];
|
|
3936
|
+
}
|
|
3937
|
+
if (keyword === LEGACY_ENV_INSTRUCTION && !first.text.includes(ASSIGNMENT$1)) {
|
|
3938
|
+
const valueStart = rest[0]?.offsets[0] ?? range.end;
|
|
3939
|
+
const [value] = dockerWords(text, { start: valueStart, end: range.end }, escapeMark, true);
|
|
3940
|
+
return [{ name: first.text, value: value ?? { text: "", offsets: [] } }];
|
|
3941
|
+
}
|
|
3942
|
+
return [first, ...rest].flatMap(assignedVariable);
|
|
3943
|
+
}
|
|
3944
|
+
function variableInstructions(text, commands) {
|
|
3945
|
+
const escapeMark = escapeCharacter(text);
|
|
3946
|
+
return commands.flatMap(([keyword]) => {
|
|
3947
|
+
if (keyword === void 0 || !VARIABLE_INSTRUCTIONS.has(keyword.value)) {
|
|
3948
|
+
return [];
|
|
3949
|
+
}
|
|
3950
|
+
const range = { start: keyword.end, end: instructionEnd(text, keyword.end, escapeMark) };
|
|
3951
|
+
const variables = instructionVariables(text, keyword.value, range, escapeMark);
|
|
3952
|
+
return [{ start: keyword.start, end: range.end, variables }];
|
|
3953
|
+
});
|
|
3954
|
+
}
|
|
3955
|
+
|
|
3559
3956
|
const EXEC_FORM_START_RE = /^[ \t]*(?:RUN|CMD|ENTRYPOINT)(?:[ \t]+--\S+)*[ \t]+\[/gm;
|
|
3560
|
-
const SHELLS = /* @__PURE__ */ new Set(["sh", "bash", "dash", "ash", "zsh"]);
|
|
3561
|
-
const OPTION_PREFIX = "-";
|
|
3562
|
-
const LONG_OPTION_PREFIX = "--";
|
|
3563
|
-
const COMMAND_OPTION = "c";
|
|
3564
|
-
const SET_OPTION = "-o";
|
|
3565
|
-
const PATH_SEPARATOR$5 = "/";
|
|
3566
3957
|
const ARRAY_BLANK_RE = /(?:[ \t\r\n]|\\\r?\n)*/y;
|
|
3567
3958
|
const QUOTED_RE = /"(?:[^"\\\n]|\\.)*"/y;
|
|
3568
3959
|
const ITEM_SEPARATOR = ",";
|
|
3569
3960
|
const NOT_LINE_BREAK_RE$1 = /[^\n]/g;
|
|
3570
3961
|
const ARRAY_END = "]";
|
|
3571
|
-
const VARIABLE_INSTRUCTIONS = /* @__PURE__ */ new Set(["ARG", "ENV"]);
|
|
3572
|
-
const LEGACY_ENV_INSTRUCTION = "ENV";
|
|
3573
|
-
const ASSIGNMENT$1 = "=";
|
|
3574
|
-
const QUOTES = /* @__PURE__ */ new Set(['"', "'"]);
|
|
3575
3962
|
function matchAt(pattern, text, index) {
|
|
3576
3963
|
pattern.lastIndex = index;
|
|
3577
3964
|
return pattern.exec(text)?.[0];
|
|
@@ -3615,30 +4002,18 @@ function execFormAt(text, start) {
|
|
|
3615
4002
|
function execForms(text) {
|
|
3616
4003
|
return [...text.matchAll(EXEC_FORM_START_RE)].flatMap((match) => {
|
|
3617
4004
|
const form = execFormAt(text, match.index + match[0].length - 1);
|
|
3618
|
-
return form === void 0 ? [] : [form];
|
|
4005
|
+
return form === void 0 ? [] : [{ ...form, lineStart: match.index }];
|
|
3619
4006
|
});
|
|
3620
4007
|
}
|
|
3621
|
-
function
|
|
3622
|
-
const
|
|
3623
|
-
if (!SHELLS.has(program)) {
|
|
3624
|
-
return void 0;
|
|
3625
|
-
}
|
|
3626
|
-
let index = 1;
|
|
3627
|
-
for (let option = words[index]?.value; option !== void 0; option = words[index]?.value) {
|
|
3628
|
-
if (!option.startsWith(OPTION_PREFIX)) {
|
|
3629
|
-
return void 0;
|
|
3630
|
-
}
|
|
3631
|
-
if (!option.startsWith(LONG_OPTION_PREFIX) && option.includes(COMMAND_OPTION)) {
|
|
3632
|
-
return words[index + 1];
|
|
3633
|
-
}
|
|
3634
|
-
index += option === SET_OPTION ? 2 : 1;
|
|
3635
|
-
}
|
|
3636
|
-
return void 0;
|
|
3637
|
-
}
|
|
3638
|
-
function execCommands(forms) {
|
|
4008
|
+
function execCommands(forms, pairs) {
|
|
4009
|
+
const paired = new Set(pairs.map((pair) => pair.command));
|
|
3639
4010
|
const commands = [];
|
|
3640
4011
|
const escaped = [];
|
|
3641
|
-
|
|
4012
|
+
const read = [
|
|
4013
|
+
...forms.filter((form) => !paired.has(form)).map((form) => form.words),
|
|
4014
|
+
...pairs.flatMap((pair) => containerCommand(pair.entrypoint.words, pair.command.words))
|
|
4015
|
+
];
|
|
4016
|
+
for (const words of read) {
|
|
3642
4017
|
commands.push(words);
|
|
3643
4018
|
const script = shellScript(words);
|
|
3644
4019
|
if (script !== void 0 && script.raw === script.value) {
|
|
@@ -3647,7 +4022,8 @@ function execCommands(forms) {
|
|
|
3647
4022
|
escaped.push(script);
|
|
3648
4023
|
}
|
|
3649
4024
|
}
|
|
3650
|
-
|
|
4025
|
+
const scripts = new Map(escaped.map((script) => [script.start, script]));
|
|
4026
|
+
return { commands, escaped: [...scripts.values()] };
|
|
3651
4027
|
}
|
|
3652
4028
|
function withoutExecForms(text, forms) {
|
|
3653
4029
|
const parts = [];
|
|
@@ -3668,39 +4044,6 @@ function escapedScriptSteps(scripts, lineOf) {
|
|
|
3668
4044
|
return migrated === script.value ? [] : [{ kind: "command-string", line: lineOf(script.start), to: migrated }];
|
|
3669
4045
|
});
|
|
3670
4046
|
}
|
|
3671
|
-
function assignedVariable(word) {
|
|
3672
|
-
const at = word.raw.indexOf(ASSIGNMENT$1);
|
|
3673
|
-
if (at <= 0) {
|
|
3674
|
-
return void 0;
|
|
3675
|
-
}
|
|
3676
|
-
const raw = word.raw.slice(at + 1);
|
|
3677
|
-
const isQuoted = raw.length >= 2 && QUOTES.has(raw[0]) && raw.at(-1) === raw[0];
|
|
3678
|
-
const value = isQuoted ? raw.slice(1, -1) : raw;
|
|
3679
|
-
const start = word.start + at + 1 + (isQuoted ? 1 : 0);
|
|
3680
|
-
return { name: word.raw.slice(0, at), value, start };
|
|
3681
|
-
}
|
|
3682
|
-
function instructionVariables(text, words) {
|
|
3683
|
-
const [instruction, first, ...rest] = words;
|
|
3684
|
-
const last = rest.at(-1);
|
|
3685
|
-
if (instruction.value === LEGACY_ENV_INSTRUCTION && !first.raw.includes(ASSIGNMENT$1)) {
|
|
3686
|
-
const value = last === void 0 ? "" : text.slice(rest[0]?.start, last.end);
|
|
3687
|
-
return [{ name: first.value, value, start: rest[0]?.start ?? first.end }];
|
|
3688
|
-
}
|
|
3689
|
-
return [first, ...rest].flatMap((word) => assignedVariable(word) ?? []);
|
|
3690
|
-
}
|
|
3691
|
-
function variableInstructions(text, commands) {
|
|
3692
|
-
return commands.flatMap((words) => {
|
|
3693
|
-
const [instruction, first] = words;
|
|
3694
|
-
if (instruction === void 0 || first === void 0) {
|
|
3695
|
-
return [];
|
|
3696
|
-
}
|
|
3697
|
-
if (!VARIABLE_INSTRUCTIONS.has(instruction.value)) {
|
|
3698
|
-
return [];
|
|
3699
|
-
}
|
|
3700
|
-
const end = words.at(-1).end;
|
|
3701
|
-
return [{ start: instruction.start, end, variables: instructionVariables(text, words) }];
|
|
3702
|
-
});
|
|
3703
|
-
}
|
|
3704
4047
|
function withoutVariableInstructions(commands, instructions) {
|
|
3705
4048
|
const isInInstruction = (words) => {
|
|
3706
4049
|
const start = words[0]?.start ?? -1;
|
|
@@ -3710,22 +4053,29 @@ function withoutVariableInstructions(commands, instructions) {
|
|
|
3710
4053
|
};
|
|
3711
4054
|
return commands.filter((words) => !isInInstruction(words));
|
|
3712
4055
|
}
|
|
3713
|
-
const valueCommands = ({ value, start }) => shellCommandsAt(value, start);
|
|
3714
4056
|
function migrateDockerfile(text, file) {
|
|
3715
4057
|
const lineOf = lineLocator(text);
|
|
3716
4058
|
const locate = (offset) => `${file}:${lineOf(offset)}`;
|
|
3717
4059
|
const forms = execForms(text);
|
|
3718
|
-
const
|
|
4060
|
+
const pairs = entrypointPairs(text, forms);
|
|
4061
|
+
const exec = execCommands(forms, pairs);
|
|
3719
4062
|
const shellForm = shellCommands(withoutExecForms(text, forms));
|
|
3720
4063
|
const instructions = variableInstructions(text, shellForm);
|
|
3721
|
-
const
|
|
3722
|
-
const
|
|
4064
|
+
const variables = instructions.flatMap((instruction) => instruction.variables);
|
|
4065
|
+
const definitions = variables.map(({ name, value }) => ({ name, value: value.text }));
|
|
4066
|
+
const values = variables.flatMap(({ value }) => placedCommands(value));
|
|
3723
4067
|
const run = withoutVariableInstructions(shellForm, instructions);
|
|
3724
4068
|
const commands = [...run, ...values, ...exec.commands];
|
|
3725
|
-
const
|
|
3726
|
-
const
|
|
3727
|
-
const
|
|
3728
|
-
|
|
4069
|
+
const found = commandWordFindings(commands, locate, shellVariables(definitions));
|
|
4070
|
+
const entry = textFindings(entrypointCommandFindings(pairs, locate));
|
|
4071
|
+
const edits = [...found.edits, ...entry.edits];
|
|
4072
|
+
const changes = [...found.changes, ...entry.changes];
|
|
4073
|
+
const steps = [...found.manualSteps, ...entry.manualSteps];
|
|
4074
|
+
return {
|
|
4075
|
+
text: applyTextEdits(text, edits),
|
|
4076
|
+
changes,
|
|
4077
|
+
manualSteps: [...steps, ...escapedScriptSteps(exec.escaped, lineOf)]
|
|
4078
|
+
};
|
|
3729
4079
|
}
|
|
3730
4080
|
|
|
3731
4081
|
const CATALOG_PROTOCOL = "catalog:";
|
|
@@ -4291,7 +4641,7 @@ const BACKTICK = "`";
|
|
|
4291
4641
|
const ESCAPING_DELIMITER = '"';
|
|
4292
4642
|
const ESCAPE = "\\";
|
|
4293
4643
|
const COMMENT_START$1 = "#";
|
|
4294
|
-
const LINE_BREAK$
|
|
4644
|
+
const LINE_BREAK$4 = "\n";
|
|
4295
4645
|
function closingOffset(text, delimiter, from) {
|
|
4296
4646
|
if (delimiter !== ESCAPING_DELIMITER) {
|
|
4297
4647
|
const close = text.indexOf(delimiter, from);
|
|
@@ -4301,7 +4651,7 @@ function closingOffset(text, delimiter, from) {
|
|
|
4301
4651
|
const char = text[index];
|
|
4302
4652
|
if (char === ESCAPE) {
|
|
4303
4653
|
index += 1;
|
|
4304
|
-
} else if (char === ESCAPING_DELIMITER || char === LINE_BREAK$
|
|
4654
|
+
} else if (char === ESCAPING_DELIMITER || char === LINE_BREAK$4) {
|
|
4305
4655
|
return char === ESCAPING_DELIMITER ? index : void 0;
|
|
4306
4656
|
}
|
|
4307
4657
|
}
|
|
@@ -4324,7 +4674,7 @@ function literalAt(text, offset) {
|
|
|
4324
4674
|
function expressionAt(text, start) {
|
|
4325
4675
|
const literals = [];
|
|
4326
4676
|
let index = start;
|
|
4327
|
-
while (index < text.length && text[index] !== LINE_BREAK$
|
|
4677
|
+
while (index < text.length && text[index] !== LINE_BREAK$4 && text[index] !== COMMENT_START$1) {
|
|
4328
4678
|
const literal = literalAt(text, index);
|
|
4329
4679
|
literals.push(...literal === void 0 ? [] : [literal]);
|
|
4330
4680
|
index = literal?.end ?? index + 1;
|
|
@@ -4348,7 +4698,7 @@ function interpolationAt(text, start) {
|
|
|
4348
4698
|
if (text.startsWith(INTERPOLATION_CLOSE, index)) {
|
|
4349
4699
|
return { start, end: index + INTERPOLATION_CLOSE.length, literals };
|
|
4350
4700
|
}
|
|
4351
|
-
if (text[index] === LINE_BREAK$
|
|
4701
|
+
if (text[index] === LINE_BREAK$4) {
|
|
4352
4702
|
return void 0;
|
|
4353
4703
|
}
|
|
4354
4704
|
const literal = literalAt(text, index);
|
|
@@ -4377,11 +4727,11 @@ const EQUALS = "=";
|
|
|
4377
4727
|
const OPEN_PAREN = "(";
|
|
4378
4728
|
const CLOSE_PAREN = ")";
|
|
4379
4729
|
const COMMENT_START = "#";
|
|
4380
|
-
const LINE_BREAK$
|
|
4730
|
+
const LINE_BREAK$3 = "\n";
|
|
4381
4731
|
const BLANK_RE = /[ \t]/;
|
|
4382
4732
|
const depthChange = (char) => char === OPEN_PAREN ? 1 : char === CLOSE_PAREN ? -1 : 0;
|
|
4383
4733
|
function headerColon(text, from) {
|
|
4384
|
-
for (let index = from; index < text.length && text[index] !== LINE_BREAK$
|
|
4734
|
+
for (let index = from; index < text.length && text[index] !== LINE_BREAK$3; ) {
|
|
4385
4735
|
const literal = literalAt(text, index);
|
|
4386
4736
|
const char = text[index];
|
|
4387
4737
|
if (literal !== void 0) {
|
|
@@ -4485,7 +4835,7 @@ function shellProgram(shell) {
|
|
|
4485
4835
|
const isCommandLineShell = (shell) => COMMAND_LINE_SHELLS.has(shellProgram(shell));
|
|
4486
4836
|
const endsWith = (path, keys) => keys.every((key, index) => path[path.length - keys.length + index] === key);
|
|
4487
4837
|
const isDefaultShell = (value) => endsWith(value.path, DEFAULT_SHELL_PATH);
|
|
4488
|
-
function scopeOf(value) {
|
|
4838
|
+
function scopeOf$1(value) {
|
|
4489
4839
|
const keys = isDefaultShell(value) ? DEFAULT_SHELL_PATH.length : 1;
|
|
4490
4840
|
return JSON.stringify(value.path.slice(0, -keys));
|
|
4491
4841
|
}
|
|
@@ -4516,7 +4866,7 @@ function stepShells(strings) {
|
|
|
4516
4866
|
const ordered = [...shells.filter(isDefaultShell), ...shells.filter(isOwnShell)];
|
|
4517
4867
|
const byScope = new Map([
|
|
4518
4868
|
...inheritedShells(strings, shells),
|
|
4519
|
-
...ordered.map((value) => [scopeOf(value), value.value])
|
|
4869
|
+
...ordered.map((value) => [scopeOf$1(value), value.value])
|
|
4520
4870
|
]);
|
|
4521
4871
|
return (value) => {
|
|
4522
4872
|
for (let depth = value.path.length - 1; depth >= 0; depth -= 1) {
|
|
@@ -4536,18 +4886,18 @@ function otherShellFindings(values, shellOf, locate) {
|
|
|
4536
4886
|
return { edits: [], changes: [], manualSteps };
|
|
4537
4887
|
}
|
|
4538
4888
|
|
|
4539
|
-
const LINE_BREAK$
|
|
4889
|
+
const LINE_BREAK$2 = "\n";
|
|
4540
4890
|
const SHEBANG = "#!";
|
|
4541
4891
|
const BODY_LINE_RE = /^(?:[ \t][^\n]*|[ \t]*\r?)$/;
|
|
4542
4892
|
function nextLineStart(text, offset) {
|
|
4543
|
-
const lineBreak = text.indexOf(LINE_BREAK$
|
|
4893
|
+
const lineBreak = text.indexOf(LINE_BREAK$2, offset);
|
|
4544
4894
|
return lineBreak === -1 ? text.length : lineBreak + 1;
|
|
4545
4895
|
}
|
|
4546
4896
|
function bodyEnd(text, start) {
|
|
4547
4897
|
let end = start;
|
|
4548
4898
|
while (end < text.length) {
|
|
4549
4899
|
const lineEnd = nextLineStart(text, end);
|
|
4550
|
-
if (!BODY_LINE_RE.test(text.slice(end, lineEnd).replace(LINE_BREAK$
|
|
4900
|
+
if (!BODY_LINE_RE.test(text.slice(end, lineEnd).replace(LINE_BREAK$2, ""))) {
|
|
4551
4901
|
break;
|
|
4552
4902
|
}
|
|
4553
4903
|
end = lineEnd;
|
|
@@ -4557,7 +4907,7 @@ function bodyEnd(text, start) {
|
|
|
4557
4907
|
function shebangRecipe(text, header) {
|
|
4558
4908
|
const start = nextLineStart(text, header.end);
|
|
4559
4909
|
const end = bodyEnd(text, start);
|
|
4560
|
-
const firstLine = text.slice(start, end).split(LINE_BREAK$
|
|
4910
|
+
const firstLine = text.slice(start, end).split(LINE_BREAK$2).map((line) => line.trim()).find((line) => line.length > 0);
|
|
4561
4911
|
if (firstLine === void 0 || !firstLine.startsWith(SHEBANG)) {
|
|
4562
4912
|
return [];
|
|
4563
4913
|
}
|
|
@@ -4760,7 +5110,7 @@ const VALUE_ARGUMENTS = /* @__PURE__ */ new Map([
|
|
|
4760
5110
|
["and", 0]
|
|
4761
5111
|
]);
|
|
4762
5112
|
const WHOLE_TEXT_FUNCTIONS = /* @__PURE__ */ new Set(["strip"]);
|
|
4763
|
-
const FUNCTION_HEAD_RE = /^\$[({]([a-z]+)[ \t]+/;
|
|
5113
|
+
const FUNCTION_HEAD_RE = /^\$[({]([a-z]+(?:-[a-z]+)*)[ \t]+/;
|
|
4764
5114
|
const OPENING = new Set(Object.keys(CLOSING));
|
|
4765
5115
|
const CLOSINGS = new Set(Object.values(CLOSING));
|
|
4766
5116
|
function callArguments(text, start, end) {
|
|
@@ -4824,14 +5174,14 @@ const ASSIGNMENT_RE = new RegExp(
|
|
|
4824
5174
|
const VARIABLE_REFERENCE_RE = /^\$(?:\(([A-Za-z_][A-Za-z0-9_.-]*)\)|\{([A-Za-z_][A-Za-z0-9_.-]*)\}|([A-Za-z_]))$/;
|
|
4825
5175
|
const RECIPE_PREFIX_RE = /^[@+-]+/;
|
|
4826
5176
|
const NOT_LINE_BREAK_RE = /[^\n]/g;
|
|
4827
|
-
const LINE_BREAK = "\n";
|
|
5177
|
+
const LINE_BREAK$1 = "\n";
|
|
4828
5178
|
const BACKSLASH = "\\";
|
|
4829
5179
|
const APPEND_OPERATOR = "+=";
|
|
4830
5180
|
const CONDITIONAL_OPERATOR = "?=";
|
|
4831
5181
|
function logicalLineEnd(text, index) {
|
|
4832
|
-
let end = text.indexOf(LINE_BREAK, index);
|
|
5182
|
+
let end = text.indexOf(LINE_BREAK$1, index);
|
|
4833
5183
|
while (end !== -1 && text[end - 1] === BACKSLASH) {
|
|
4834
|
-
end = text.indexOf(LINE_BREAK, end + 1);
|
|
5184
|
+
end = text.indexOf(LINE_BREAK$1, end + 1);
|
|
4835
5185
|
}
|
|
4836
5186
|
return end === -1 ? text.length : end;
|
|
4837
5187
|
}
|
|
@@ -4857,7 +5207,7 @@ function withoutAssignmentHeads(text, assignments) {
|
|
|
4857
5207
|
}
|
|
4858
5208
|
const COMPUTED_RE = /^\$[({]/;
|
|
4859
5209
|
const isComputed = (written) => COMPUTED_RE.test(written.trim().replace(RECIPE_PREFIX_RE, ""));
|
|
4860
|
-
function referencedName(written) {
|
|
5210
|
+
function referencedName$1(written) {
|
|
4861
5211
|
const match = VARIABLE_REFERENCE_RE.exec(written.trim().replace(RECIPE_PREFIX_RE, ""));
|
|
4862
5212
|
return match === null ? void 0 : match[1] ?? match[2] ?? match[3];
|
|
4863
5213
|
}
|
|
@@ -4875,7 +5225,7 @@ function valueDefinition(text, { name, valueStart, valueEnd }, commands) {
|
|
|
4875
5225
|
return { name, kind: "no-program" };
|
|
4876
5226
|
}
|
|
4877
5227
|
const program = programWritten(text, first);
|
|
4878
|
-
const target = referencedName(program);
|
|
5228
|
+
const target = referencedName$1(program);
|
|
4879
5229
|
if (target !== void 0) {
|
|
4880
5230
|
return { name, kind: "reference", target };
|
|
4881
5231
|
}
|
|
@@ -4911,9 +5261,12 @@ const startsIn = (command, { valueStart, valueEnd }) => {
|
|
|
4911
5261
|
return valueStart <= start && start < valueEnd;
|
|
4912
5262
|
};
|
|
4913
5263
|
function appendedCommands(commands, placed, programs) {
|
|
4914
|
-
const
|
|
5264
|
+
const commandsIn = (assignment) => commands.filter((command) => startsIn(command, assignment)).sort((left, right) => (left[0]?.start ?? 0) - (right[0]?.start ?? 0));
|
|
5265
|
+
const appends = placed.filter(
|
|
5266
|
+
({ assignment, place }) => place !== void 0 && place !== "start" && !isOwnGeneratorCommand(place, commandsIn(assignment)[0])
|
|
5267
|
+
);
|
|
4915
5268
|
const appended = appends.map(({ assignment }) => {
|
|
4916
|
-
const words =
|
|
5269
|
+
const words = commandsIn(assignment).flat().sort((left, right) => left.start - right.start);
|
|
4917
5270
|
const written = `$(${assignment.name})`;
|
|
4918
5271
|
const program = programs.get(assignment.name) ?? "generator-or-other";
|
|
4919
5272
|
return { words, program: { written, program } };
|
|
@@ -4931,7 +5284,7 @@ function variableValues(text, assignments) {
|
|
|
4931
5284
|
}
|
|
4932
5285
|
function makefileVariables(text, assignments, programs) {
|
|
4933
5286
|
const values = variableValues(text, assignments);
|
|
4934
|
-
const nameAt = (word) => referencedName(text.slice(word.start, word.end));
|
|
5287
|
+
const nameAt = (word) => referencedName$1(text.slice(word.start, word.end));
|
|
4935
5288
|
const variables = {
|
|
4936
5289
|
programAt: (program) => {
|
|
4937
5290
|
const written = text.slice(program.start, program.end);
|
|
@@ -5241,12 +5594,18 @@ const PNPM_SETTINGS = {
|
|
|
5241
5594
|
overrideSections: /* @__PURE__ */ new Set(["overrides", "patchedDependencies"]),
|
|
5242
5595
|
prefix: `${PNPM_SETTINGS_FIELD}.`
|
|
5243
5596
|
};
|
|
5597
|
+
const BUN_SETTING_FIELDS = ["trustedDependencies"];
|
|
5244
5598
|
function reportSettings(manifest, findings) {
|
|
5245
5599
|
for (const field of OVERRIDE_FIELDS) {
|
|
5246
5600
|
for (const name of valuesAt(manifest, field).flatMap(overriddenOldPackages)) {
|
|
5247
5601
|
findings.manualSteps.push({ kind: "override-names-package", field, name });
|
|
5248
5602
|
}
|
|
5249
5603
|
}
|
|
5604
|
+
for (const field of BUN_SETTING_FIELDS) {
|
|
5605
|
+
for (const name of valuesAt(manifest, field).flatMap(oldPackagesNamedBy)) {
|
|
5606
|
+
findings.manualSteps.push({ kind: "setting-names-package", field, name });
|
|
5607
|
+
}
|
|
5608
|
+
}
|
|
5250
5609
|
for (const settings of mapsAt(manifest, PNPM_SETTINGS_FIELD)) {
|
|
5251
5610
|
reportSettingSections(settings, PNPM_SETTINGS, findings);
|
|
5252
5611
|
}
|
|
@@ -5308,18 +5667,12 @@ function oldPackagePatchSteps(fileName) {
|
|
|
5308
5667
|
return name === void 0 || to === void 0 ? [] : [{ kind: "old-package-patch", name, to }];
|
|
5309
5668
|
}
|
|
5310
5669
|
|
|
5311
|
-
const INPUTS_KEY = "inputs";
|
|
5312
|
-
const DEFAULT_KEY = "default";
|
|
5313
|
-
const INPUT_DEFAULT_DEPTH = 3;
|
|
5314
|
-
const INPUT_NAME_INDEX = -2;
|
|
5315
5670
|
const BLANK = " ";
|
|
5316
5671
|
const SURROUNDING_QUOTES_RE = /^"(.*)"$/s;
|
|
5317
|
-
const
|
|
5318
|
-
|
|
5319
|
-
function inputDefaults(strings) {
|
|
5672
|
+
const INPUT_REFERENCE_RE = /(?<![\w.-])(?:github\.event\.)?inputs(?:\.([A-Za-z_][A-Za-z0-9_-]*)|\[[ \t]*'([^']*)'[ \t]*\])/g;
|
|
5673
|
+
function inputValues(defaults) {
|
|
5320
5674
|
const values = /* @__PURE__ */ new Map();
|
|
5321
|
-
for (const value of
|
|
5322
|
-
const name = String(value.path.at(INPUT_NAME_INDEX));
|
|
5675
|
+
for (const [value, name] of defaults) {
|
|
5323
5676
|
values.set(
|
|
5324
5677
|
name,
|
|
5325
5678
|
[values.get(name), value.value].filter((part) => part !== void 0).join(BLANK)
|
|
@@ -5329,27 +5682,14 @@ function inputDefaults(strings) {
|
|
|
5329
5682
|
}
|
|
5330
5683
|
function expressionValue(expression, defaults) {
|
|
5331
5684
|
const inputs = [...expression.matchAll(INPUT_REFERENCE_RE)].flatMap((match) => {
|
|
5332
|
-
const value = defaults.get(match[1]);
|
|
5685
|
+
const value = defaults.get(match[1] ?? match[2] ?? "");
|
|
5333
5686
|
return value === void 0 ? [] : [value];
|
|
5334
5687
|
});
|
|
5335
5688
|
const literals = expressionLiterals(expression).map((literal) => literal.text);
|
|
5336
5689
|
return [...inputs, ...literals].join(BLANK);
|
|
5337
5690
|
}
|
|
5338
|
-
function
|
|
5339
|
-
const
|
|
5340
|
-
let copiedUpTo = 0;
|
|
5341
|
-
for (let open = text.indexOf(EXPRESSION_OPEN); open !== -1; ) {
|
|
5342
|
-
const end = expressionEnd(text, open) ?? text.length;
|
|
5343
|
-
parts.push(text.slice(copiedUpTo, open), expressionValue(text.slice(open, end), defaults));
|
|
5344
|
-
copiedUpTo = end;
|
|
5345
|
-
open = text.indexOf(EXPRESSION_OPEN, end);
|
|
5346
|
-
}
|
|
5347
|
-
parts.push(text.slice(copiedUpTo));
|
|
5348
|
-
return parts.join("");
|
|
5349
|
-
}
|
|
5350
|
-
function withInputDefaults(variables, strings) {
|
|
5351
|
-
const defaults = inputDefaults(strings);
|
|
5352
|
-
const expressionsRead = (text) => withExpressionValues(text, defaults);
|
|
5691
|
+
function withInputDefaults(variables, defaults) {
|
|
5692
|
+
const expressionsRead = (text) => mapExpressions(text, (expression) => expressionValue(expression, defaults));
|
|
5353
5693
|
return {
|
|
5354
5694
|
programAt: (program) => variables.programAt(program),
|
|
5355
5695
|
referenceAt: (word) => {
|
|
@@ -5364,6 +5704,135 @@ function withInputDefaults(variables, strings) {
|
|
|
5364
5704
|
};
|
|
5365
5705
|
}
|
|
5366
5706
|
|
|
5707
|
+
const ARGUMENT_KEYS = /* @__PURE__ */ new Map([
|
|
5708
|
+
["entrypoint", ["command", "args"]],
|
|
5709
|
+
["command", ["args"]]
|
|
5710
|
+
]);
|
|
5711
|
+
const PAIRED_KEYS = /* @__PURE__ */ new Set([
|
|
5712
|
+
...ARGUMENT_KEYS.keys(),
|
|
5713
|
+
...[...ARGUMENT_KEYS.values()].flat()
|
|
5714
|
+
]);
|
|
5715
|
+
const MERGE_KEY = "<<";
|
|
5716
|
+
const LINE_BREAK = "\n";
|
|
5717
|
+
const isItem = (string) => typeof string.path.at(-1) === "number";
|
|
5718
|
+
const isContainerListItem = (string) => isItem(string) && PAIRED_KEYS.has(String(string.path.at(-2)));
|
|
5719
|
+
const isList = (value) => value.strings[0] !== void 0 && isItem(value.strings[0]);
|
|
5720
|
+
function mapOf(string) {
|
|
5721
|
+
const path = string.path.slice(0, isItem(string) ? -2 : -1);
|
|
5722
|
+
let isMerged = false;
|
|
5723
|
+
for (; ; ) {
|
|
5724
|
+
if (path.at(-1) === MERGE_KEY) {
|
|
5725
|
+
path.pop();
|
|
5726
|
+
} else if (typeof path.at(-1) === "number" && path.at(-2) === MERGE_KEY) {
|
|
5727
|
+
path.splice(-2);
|
|
5728
|
+
} else {
|
|
5729
|
+
return { map: JSON.stringify(path), isMerged };
|
|
5730
|
+
}
|
|
5731
|
+
isMerged = true;
|
|
5732
|
+
}
|
|
5733
|
+
}
|
|
5734
|
+
function isNextItem(value, string) {
|
|
5735
|
+
const last = value?.strings.at(-1);
|
|
5736
|
+
return last !== void 0 && isItem(last) && isItem(string) && JSON.stringify(last.path.slice(0, -1)) === JSON.stringify(string.path.slice(0, -1)) && Number(string.path.at(-1)) > Number(last.path.at(-1));
|
|
5737
|
+
}
|
|
5738
|
+
function keyValues(strings) {
|
|
5739
|
+
const values = [];
|
|
5740
|
+
for (const string of strings) {
|
|
5741
|
+
const key = ownerKey(string.path) ?? "";
|
|
5742
|
+
const isValue = isItem(string) ? string.path.at(-2) === key : string.path.at(-1) === key;
|
|
5743
|
+
if (!PAIRED_KEYS.has(key) || !isValue) {
|
|
5744
|
+
continue;
|
|
5745
|
+
}
|
|
5746
|
+
const last = values.at(-1);
|
|
5747
|
+
if (last !== void 0 && isNextItem(last, string)) {
|
|
5748
|
+
last.strings.push(string);
|
|
5749
|
+
} else {
|
|
5750
|
+
values.push({ ...mapOf(string), key, strings: [string] });
|
|
5751
|
+
}
|
|
5752
|
+
}
|
|
5753
|
+
return values;
|
|
5754
|
+
}
|
|
5755
|
+
function mapValues(values) {
|
|
5756
|
+
const maps = [];
|
|
5757
|
+
const latest = /* @__PURE__ */ new Map();
|
|
5758
|
+
for (const value of values) {
|
|
5759
|
+
let map = latest.get(value.map);
|
|
5760
|
+
if (map === void 0 || !value.isMerged && map.own.has(value.key)) {
|
|
5761
|
+
map = { own: /* @__PURE__ */ new Map(), merged: /* @__PURE__ */ new Map() };
|
|
5762
|
+
maps.push(map);
|
|
5763
|
+
latest.set(value.map, map);
|
|
5764
|
+
}
|
|
5765
|
+
const values2 = value.isMerged ? map.merged : map.own;
|
|
5766
|
+
if (!values2.has(value.key)) {
|
|
5767
|
+
values2.set(value.key, value);
|
|
5768
|
+
}
|
|
5769
|
+
}
|
|
5770
|
+
return maps;
|
|
5771
|
+
}
|
|
5772
|
+
function containerOf({ own, merged }) {
|
|
5773
|
+
const keyValue = (key) => own.get(key) ?? merged.get(key);
|
|
5774
|
+
for (const [key, argumentKeys] of ARGUMENT_KEYS) {
|
|
5775
|
+
const entrypoint = keyValue(key);
|
|
5776
|
+
if (entrypoint !== void 0) {
|
|
5777
|
+
const argumentKey = argumentKeys.find((found) => keyValue(found) !== void 0);
|
|
5778
|
+
return [
|
|
5779
|
+
{ entrypoint, command: argumentKey === void 0 ? void 0 : keyValue(argumentKey) }
|
|
5780
|
+
];
|
|
5781
|
+
}
|
|
5782
|
+
}
|
|
5783
|
+
return [];
|
|
5784
|
+
}
|
|
5785
|
+
const isPlaceable = (string, text) => !string.isEscaped && !(string.isFolded && text.slice(string.content.start, string.content.end).includes(LINE_BREAK));
|
|
5786
|
+
function scalarWords(scalar, text) {
|
|
5787
|
+
const { start, end } = scalar.content;
|
|
5788
|
+
const isPlaced = isPlaceable(scalar, text);
|
|
5789
|
+
const commands = shellCommands(isPlaced ? text.slice(start, end) : scalar.value);
|
|
5790
|
+
const at = (word) => isPlaced ? movedWord(word, start) : { ...word, start: scalar.start, end: scalar.start };
|
|
5791
|
+
return { words: (commands[0] ?? []).map(at), isPlaced, isWhole: commands.length <= 1 };
|
|
5792
|
+
}
|
|
5793
|
+
function valueWords(value, text) {
|
|
5794
|
+
const [first] = value.strings;
|
|
5795
|
+
if (first !== void 0 && !isItem(first)) {
|
|
5796
|
+
return scalarWords(first, text);
|
|
5797
|
+
}
|
|
5798
|
+
const words = value.strings.map((item) => {
|
|
5799
|
+
const { start, end } = item.content;
|
|
5800
|
+
return { start, end, value: item.value, raw: text.slice(start, end), item };
|
|
5801
|
+
});
|
|
5802
|
+
return { words, isPlaced: true, isWhole: true };
|
|
5803
|
+
}
|
|
5804
|
+
const isJoinable = (words) => words.isPlaced && words.isWhole;
|
|
5805
|
+
function containerReading({ entrypoint, command }, text, locate) {
|
|
5806
|
+
const first = valueWords(entrypoint, text);
|
|
5807
|
+
if (command === void 0) {
|
|
5808
|
+
return { commands: isList(entrypoint) ? [first.words] : [], flags: [], scalars: [] };
|
|
5809
|
+
}
|
|
5810
|
+
const args = valueWords(command, text);
|
|
5811
|
+
const pair = { entrypoint: first.words, command: args.words, written: entrypoint.key };
|
|
5812
|
+
if (isJoinable(first) && isJoinable(args)) {
|
|
5813
|
+
const isScript = shellScript(first.words) !== void 0;
|
|
5814
|
+
return {
|
|
5815
|
+
commands: containerCommand(first.words, args.words),
|
|
5816
|
+
flags: isScript ? entrypointArgumentFindings(pair, locate) : [],
|
|
5817
|
+
scalars: [entrypoint, command].filter((part) => !isList(part)).flatMap((part) => part.strings)
|
|
5818
|
+
};
|
|
5819
|
+
}
|
|
5820
|
+
const lists = [entrypoint, command].filter(isList).map((part) => valueWords(part, text).words);
|
|
5821
|
+
const flags = entrypointArgumentFindings({ ...pair, isPlaced: args.isPlaced }, locate);
|
|
5822
|
+
return { commands: lists, flags, scalars: [] };
|
|
5823
|
+
}
|
|
5824
|
+
function containerCommands(text, strings, locate) {
|
|
5825
|
+
const found = mapValues(keyValues(strings)).flatMap(containerOf).map((container) => containerReading(container, text, locate));
|
|
5826
|
+
const commands = found.flatMap((reading) => reading.commands);
|
|
5827
|
+
const scripts = commands.flatMap((words) => shellScript(words)?.item ?? []);
|
|
5828
|
+
const flags = found.flatMap((reading) => reading.flags);
|
|
5829
|
+
return {
|
|
5830
|
+
findings: [commandWordFindings(commands, locate), textFindings(flags)],
|
|
5831
|
+
scripts: new Set(scripts),
|
|
5832
|
+
commandStrings: new Set(found.flatMap((reading) => reading.scalars.map(({ start }) => start)))
|
|
5833
|
+
};
|
|
5834
|
+
}
|
|
5835
|
+
|
|
5367
5836
|
const YAML_COMMAND_KEYS = /* @__PURE__ */ new Set([
|
|
5368
5837
|
"run",
|
|
5369
5838
|
"script",
|
|
@@ -5388,34 +5857,161 @@ const TASKFILE_COMMAND_KEYS = /* @__PURE__ */ new Set([
|
|
|
5388
5857
|
"status"
|
|
5389
5858
|
]);
|
|
5390
5859
|
|
|
5860
|
+
const ROOT_PREFIX = "/";
|
|
5861
|
+
const NOT_A_PROJECT_PATH_RE = /\{\{|\$|^[a-z][a-z\d+.-]*:/i;
|
|
5862
|
+
const LEADING_ROOT_RE = /^\/+/;
|
|
5863
|
+
const YAML_FILE_RE = /\.ya?ml$/;
|
|
5864
|
+
const NO_INCLUDES = {
|
|
5865
|
+
isIncludeAt: () => false,
|
|
5866
|
+
isFromRoot: () => false
|
|
5867
|
+
};
|
|
5868
|
+
const TASKFILE_INCLUDES_KEY = "includes";
|
|
5869
|
+
const TASKFILE_KEY = "taskfile";
|
|
5870
|
+
const TASKFILE_INCLUDES = {
|
|
5871
|
+
isIncludeAt: ([key, name, field]) => key === TASKFILE_INCLUDES_KEY && typeof name === "string" && (field === void 0 || field === TASKFILE_KEY),
|
|
5872
|
+
isFromRoot: () => false
|
|
5873
|
+
};
|
|
5874
|
+
const GITLAB_INCLUDE_KEY = "include";
|
|
5875
|
+
const GITLAB_LOCAL_KEY = "local";
|
|
5876
|
+
const GITLAB_INCLUDES = {
|
|
5877
|
+
isIncludeAt: ([key, ...rest]) => {
|
|
5878
|
+
const [first] = typeof rest[0] === "number" ? rest.slice(1) : rest;
|
|
5879
|
+
const isLocal = first === void 0 || first === GITLAB_LOCAL_KEY;
|
|
5880
|
+
return key === GITLAB_INCLUDE_KEY && isLocal;
|
|
5881
|
+
},
|
|
5882
|
+
isFromRoot: () => true
|
|
5883
|
+
};
|
|
5884
|
+
const AZURE_TEMPLATE_KEY = "template";
|
|
5885
|
+
const AZURE_TEMPLATES = {
|
|
5886
|
+
isIncludeAt: (path) => path.at(-1) === AZURE_TEMPLATE_KEY,
|
|
5887
|
+
isFromRoot: (reference) => reference.startsWith(ROOT_PREFIX)
|
|
5888
|
+
};
|
|
5889
|
+
function includedPaths(fromPath, strings, includes) {
|
|
5890
|
+
return strings.flatMap((string) => {
|
|
5891
|
+
const reference = string.value.trim();
|
|
5892
|
+
if (!includes.isIncludeAt(string.path) || NOT_A_PROJECT_PATH_RE.test(reference)) {
|
|
5893
|
+
return [];
|
|
5894
|
+
}
|
|
5895
|
+
const path = includes.isFromRoot(reference) ? referencedProjectPath("", reference.replace(LEADING_ROOT_RE, "")) : referencedProjectPath(fromPath, reference);
|
|
5896
|
+
return path !== void 0 && YAML_FILE_RE.test(path) ? [path] : [];
|
|
5897
|
+
});
|
|
5898
|
+
}
|
|
5899
|
+
|
|
5900
|
+
const NAME_KEY = "name";
|
|
5901
|
+
function itemName(strings, index) {
|
|
5902
|
+
const item = strings[index]?.path.slice(0, -1) ?? [];
|
|
5903
|
+
const isInItem = (string) => string !== void 0 && item.every((part, at) => string.path[at] === part);
|
|
5904
|
+
const isName = (string) => string.path.length === item.length + 1 && string.path.at(-1) === NAME_KEY;
|
|
5905
|
+
let [first, last] = [index, index];
|
|
5906
|
+
while (isInItem(strings[first - 1])) {
|
|
5907
|
+
first -= 1;
|
|
5908
|
+
}
|
|
5909
|
+
while (isInItem(strings[last + 1])) {
|
|
5910
|
+
last += 1;
|
|
5911
|
+
}
|
|
5912
|
+
return strings.slice(first, last + 1).find(isName)?.value;
|
|
5913
|
+
}
|
|
5914
|
+
|
|
5915
|
+
const DEFAULT_KEY = "default";
|
|
5916
|
+
const INPUTS_KEY = "inputs";
|
|
5917
|
+
const PARAMETERS_KEY = "parameters";
|
|
5918
|
+
const SPEC_KEY = "spec";
|
|
5919
|
+
const SPEC_INPUT_DEPTH = 4;
|
|
5920
|
+
const PATH_TAIL$1 = [-1, -2, -3];
|
|
5921
|
+
function defaultUnder(key, value) {
|
|
5922
|
+
const [last, name, owner] = PATH_TAIL$1.map((at) => value?.path.at(at));
|
|
5923
|
+
return last === DEFAULT_KEY && owner === key && typeof name === "string" ? name : void 0;
|
|
5924
|
+
}
|
|
5925
|
+
const NO_PARAMETERS = {
|
|
5926
|
+
defaultOf: () => void 0,
|
|
5927
|
+
asExpressions: (text) => text
|
|
5928
|
+
};
|
|
5929
|
+
const GITHUB_INPUTS = {
|
|
5930
|
+
defaultOf: (strings, index) => defaultUnder(INPUTS_KEY, strings[index]),
|
|
5931
|
+
asExpressions: (text) => text
|
|
5932
|
+
};
|
|
5933
|
+
const GITLAB_INTERPOLATION_RE = /\$\[\[(.*?)\]\]/g;
|
|
5934
|
+
const GITLAB_INPUTS = {
|
|
5935
|
+
defaultOf: (strings, index) => {
|
|
5936
|
+
const value = strings[index];
|
|
5937
|
+
const isSpec = value?.path.length === SPEC_INPUT_DEPTH && value.path[0] === SPEC_KEY;
|
|
5938
|
+
return isSpec ? defaultUnder(INPUTS_KEY, value) : void 0;
|
|
5939
|
+
},
|
|
5940
|
+
asExpressions: (text) => text.replace(GITLAB_INTERPOLATION_RE, "$${{$1}}")
|
|
5941
|
+
};
|
|
5942
|
+
const CIRCLECI_PARAMETER_RE = /<<[ \t]*(?:pipeline\.)?parameters\.([A-Za-z_][A-Za-z0-9_-]*)[ \t]*>>/g;
|
|
5943
|
+
const EXPRESSION_CLOSE = "}}";
|
|
5944
|
+
const asInputExpression = (written, name) => `${EXPRESSION_OPEN} ${INPUTS_KEY}.${name}`.padEnd(written.length - EXPRESSION_CLOSE.length, " ") + EXPRESSION_CLOSE;
|
|
5945
|
+
const CIRCLECI_PARAMETERS = {
|
|
5946
|
+
defaultOf: (strings, index) => defaultUnder(PARAMETERS_KEY, strings[index]),
|
|
5947
|
+
asExpressions: (text) => text.replace(CIRCLECI_PARAMETER_RE, asInputExpression)
|
|
5948
|
+
};
|
|
5949
|
+
const AZURE_PARAMETERS_RE = /(?<![\w.-])parameters(?=\.|\[)/g;
|
|
5950
|
+
const AZURE_AS_INPUTS = INPUTS_KEY.padStart(PARAMETERS_KEY.length, " ");
|
|
5951
|
+
const AZURE_PARAMETERS = {
|
|
5952
|
+
defaultOf: (strings, index) => {
|
|
5953
|
+
const [last, item, owner] = PATH_TAIL$1.map((at) => strings[index]?.path.at(at));
|
|
5954
|
+
const isDefault = last === DEFAULT_KEY && typeof item === "number" && owner === PARAMETERS_KEY;
|
|
5955
|
+
return isDefault ? itemName(strings, index) : void 0;
|
|
5956
|
+
},
|
|
5957
|
+
asExpressions: (text) => mapExpressions(text, (expression) => expression.replace(AZURE_PARAMETERS_RE, AZURE_AS_INPUTS))
|
|
5958
|
+
};
|
|
5959
|
+
function parameterDefaults(strings, parameters) {
|
|
5960
|
+
return new Map(
|
|
5961
|
+
strings.flatMap((value, index) => {
|
|
5962
|
+
const name = parameters.defaultOf(strings, index);
|
|
5963
|
+
return name === void 0 ? [] : [[value, name]];
|
|
5964
|
+
})
|
|
5965
|
+
);
|
|
5966
|
+
}
|
|
5967
|
+
|
|
5391
5968
|
const ENV_KEY = "env";
|
|
5392
5969
|
const ENVIRONMENT_KEY = "environment";
|
|
5393
5970
|
const VARIABLES_KEY = "variables";
|
|
5394
5971
|
const VARS_KEY = "vars";
|
|
5395
|
-
const VALUE_KEY = "value";
|
|
5396
|
-
const NAME_KEY = "name";
|
|
5397
5972
|
const PLAIN = {
|
|
5398
5973
|
hasValueMaps: false,
|
|
5399
5974
|
hasListItems: false,
|
|
5400
5975
|
hasNamedItems: false,
|
|
5401
5976
|
reference: void 0,
|
|
5402
|
-
shellName: (name) => name
|
|
5977
|
+
shellName: (name) => name,
|
|
5978
|
+
hasDollarEscapes: false
|
|
5403
5979
|
};
|
|
5404
5980
|
const DEFAULT_YAML_FILE = {
|
|
5405
5981
|
commandKeys: YAML_COMMAND_KEYS,
|
|
5406
|
-
environment: { ...PLAIN, keys: /* @__PURE__ */ new Set([ENV_KEY]) }
|
|
5982
|
+
environment: { ...PLAIN, keys: /* @__PURE__ */ new Set([ENV_KEY]) },
|
|
5983
|
+
parameters: GITHUB_INPUTS,
|
|
5984
|
+
includes: NO_INCLUDES
|
|
5407
5985
|
};
|
|
5408
5986
|
const GITLAB_CI_FILE = {
|
|
5409
5987
|
commandKeys: YAML_COMMAND_KEYS,
|
|
5410
|
-
environment: { ...PLAIN, keys: /* @__PURE__ */ new Set([ENV_KEY, VARIABLES_KEY]), hasValueMaps: true }
|
|
5988
|
+
environment: { ...PLAIN, keys: /* @__PURE__ */ new Set([ENV_KEY, VARIABLES_KEY]), hasValueMaps: true },
|
|
5989
|
+
parameters: GITLAB_INPUTS,
|
|
5990
|
+
includes: GITLAB_INCLUDES
|
|
5411
5991
|
};
|
|
5992
|
+
const CI_ENVIRONMENT = { ...PLAIN, keys: /* @__PURE__ */ new Set([ENV_KEY, ENVIRONMENT_KEY]) };
|
|
5412
5993
|
const CI_ENVIRONMENT_FILE = {
|
|
5413
5994
|
commandKeys: YAML_COMMAND_KEYS,
|
|
5414
|
-
environment:
|
|
5995
|
+
environment: CI_ENVIRONMENT,
|
|
5996
|
+
parameters: NO_PARAMETERS,
|
|
5997
|
+
includes: NO_INCLUDES
|
|
5998
|
+
};
|
|
5999
|
+
const CIRCLECI_FILE = {
|
|
6000
|
+
commandKeys: YAML_COMMAND_KEYS,
|
|
6001
|
+
environment: CI_ENVIRONMENT,
|
|
6002
|
+
parameters: CIRCLECI_PARAMETERS,
|
|
6003
|
+
includes: NO_INCLUDES
|
|
5415
6004
|
};
|
|
5416
6005
|
const COMPOSE_FILE = {
|
|
5417
6006
|
commandKeys: YAML_COMMAND_KEYS,
|
|
5418
|
-
environment: {
|
|
6007
|
+
environment: {
|
|
6008
|
+
...PLAIN,
|
|
6009
|
+
keys: /* @__PURE__ */ new Set([ENV_KEY, ENVIRONMENT_KEY]),
|
|
6010
|
+
hasListItems: true,
|
|
6011
|
+
hasDollarEscapes: true
|
|
6012
|
+
},
|
|
6013
|
+
parameters: NO_PARAMETERS,
|
|
6014
|
+
includes: NO_INCLUDES
|
|
5419
6015
|
};
|
|
5420
6016
|
const TASKFILE = {
|
|
5421
6017
|
commandKeys: TASKFILE_COMMAND_KEYS,
|
|
@@ -5423,7 +6019,9 @@ const TASKFILE = {
|
|
|
5423
6019
|
...PLAIN,
|
|
5424
6020
|
keys: /* @__PURE__ */ new Set([ENV_KEY, VARS_KEY]),
|
|
5425
6021
|
reference: /\{\{-?[ \t]*\.([A-Za-z_][A-Za-z0-9_]*)[ \t]*-?\}\}/g
|
|
5426
|
-
}
|
|
6022
|
+
},
|
|
6023
|
+
parameters: NO_PARAMETERS,
|
|
6024
|
+
includes: TASKFILE_INCLUDES
|
|
5427
6025
|
};
|
|
5428
6026
|
const AZURE_NAME_SEPARATOR_RE = /\./g;
|
|
5429
6027
|
const AZURE_SHELL_SEPARATOR = "_";
|
|
@@ -5435,49 +6033,109 @@ const AZURE_PIPELINES_FILE = {
|
|
|
5435
6033
|
hasNamedItems: true,
|
|
5436
6034
|
reference: /\$\(([A-Za-z_][A-Za-z0-9_.]*)\)|\$\{\{[ \t]*variables\.([A-Za-z_][A-Za-z0-9_.]*)[ \t]*\}\}/g,
|
|
5437
6035
|
shellName: (name, key) => key === VARIABLES_KEY ? name.replace(AZURE_NAME_SEPARATOR_RE, AZURE_SHELL_SEPARATOR).toUpperCase() : name
|
|
5438
|
-
}
|
|
6036
|
+
},
|
|
6037
|
+
parameters: AZURE_PARAMETERS,
|
|
6038
|
+
includes: AZURE_TEMPLATES
|
|
5439
6039
|
};
|
|
5440
|
-
const
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
6040
|
+
const ENV_EXPRESSION_RE = /\$\{\{[ \t]*env\.([A-Za-z_][A-Za-z0-9_]*)[ \t]*\}\}/g;
|
|
6041
|
+
const WORKFLOW_ENVIRONMENT = {
|
|
6042
|
+
...PLAIN,
|
|
6043
|
+
keys: /* @__PURE__ */ new Set(),
|
|
6044
|
+
reference: ENV_EXPRESSION_RE
|
|
6045
|
+
};
|
|
6046
|
+
const asShellVariable = (reference, name) => `$${name}`.padEnd(reference.length, " ");
|
|
6047
|
+
const YAML_FILE_KINDS = [
|
|
6048
|
+
DEFAULT_YAML_FILE,
|
|
6049
|
+
GITLAB_CI_FILE,
|
|
6050
|
+
CI_ENVIRONMENT_FILE,
|
|
6051
|
+
CIRCLECI_FILE,
|
|
6052
|
+
COMPOSE_FILE,
|
|
6053
|
+
TASKFILE,
|
|
6054
|
+
AZURE_PIPELINES_FILE
|
|
6055
|
+
];
|
|
6056
|
+
const referencedName = (environment, groups) => environment.shellName(
|
|
6057
|
+
groups.find((part) => typeof part === "string") ?? "",
|
|
6058
|
+
VARIABLES_KEY
|
|
6059
|
+
);
|
|
6060
|
+
function referencedVariables(text) {
|
|
6061
|
+
const environments = [...YAML_FILE_KINDS.map((kind) => kind.environment), WORKFLOW_ENVIRONMENT];
|
|
6062
|
+
return environments.flatMap(
|
|
6063
|
+
(environment) => environment.reference === void 0 ? [] : [...text.matchAll(environment.reference)].map(
|
|
6064
|
+
(match) => referencedName(environment, match.slice(1))
|
|
6065
|
+
)
|
|
6066
|
+
);
|
|
6067
|
+
}
|
|
6068
|
+
function withToolReferences(text, { environment, names }) {
|
|
6069
|
+
const { reference } = environment;
|
|
6070
|
+
if (reference === void 0) {
|
|
6071
|
+
return text;
|
|
5448
6072
|
}
|
|
5449
|
-
|
|
5450
|
-
|
|
6073
|
+
return text.replace(reference, (written, ...groups) => {
|
|
6074
|
+
const name = referencedName(environment, groups);
|
|
6075
|
+
return names.has(name) ? asShellVariable(written, name) : written;
|
|
6076
|
+
});
|
|
6077
|
+
}
|
|
6078
|
+
const DOLLAR_ESCAPE_RE = /\$\$([A-Za-z_][A-Za-z0-9_]*|\{[^}]*\})/g;
|
|
6079
|
+
const withoutDollarEscapes = (text) => text.replace(
|
|
6080
|
+
DOLLAR_ESCAPE_RE,
|
|
6081
|
+
(written, name) => `$${name}`.padEnd(written.length, " ")
|
|
6082
|
+
);
|
|
6083
|
+
function withVariableReferences(text, references) {
|
|
6084
|
+
const parameters = references?.parameters.asExpressions(text) ?? text;
|
|
6085
|
+
const expressions = parameters.replace(ENV_EXPRESSION_RE, asShellVariable);
|
|
6086
|
+
if (references === void 0) {
|
|
6087
|
+
return expressions;
|
|
5451
6088
|
}
|
|
5452
|
-
|
|
6089
|
+
const escaped = references.environment.hasDollarEscapes ? withoutDollarEscapes(expressions) : expressions;
|
|
6090
|
+
return withToolReferences(escaped, references);
|
|
5453
6091
|
}
|
|
6092
|
+
|
|
6093
|
+
const VALUE_KEY = "value";
|
|
6094
|
+
const OPTIONS_KEY = "options";
|
|
6095
|
+
const LIST_ITEM_RE = /^([A-Za-z_][A-Za-z0-9_]*)=/;
|
|
6096
|
+
const PATH_TAIL = [-1, -2, -3, -4];
|
|
5454
6097
|
const isNamedItemValue = (value, keys) => value.path.at(-1) === VALUE_KEY && typeof value.path.at(-2) === "number" && keys.has(String(value.path.at(-3)));
|
|
5455
|
-
function
|
|
6098
|
+
function entryPlace(strings, index, { keys, hasValueMaps, hasListItems, hasNamedItems }) {
|
|
5456
6099
|
const value = strings[index];
|
|
5457
|
-
const
|
|
5458
|
-
const
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
6100
|
+
const [last, owner, outer, optionOf] = PATH_TAIL.map((at) => value.path.at(at));
|
|
6101
|
+
const isKey = (part) => keys.has(String(part));
|
|
6102
|
+
if (typeof last === "string" && isKey(owner)) {
|
|
6103
|
+
return { name: last, key: owner };
|
|
6104
|
+
}
|
|
6105
|
+
if (hasValueMaps && last === VALUE_KEY && typeof owner === "string" && isKey(outer)) {
|
|
6106
|
+
return { name: owner, key: outer };
|
|
5462
6107
|
}
|
|
5463
|
-
|
|
5464
|
-
|
|
6108
|
+
const isOption = typeof last === "number" && owner === OPTIONS_KEY && typeof outer === "string";
|
|
6109
|
+
if (hasValueMaps && isOption && isKey(optionOf)) {
|
|
6110
|
+
return { name: outer, key: optionOf };
|
|
5465
6111
|
}
|
|
5466
6112
|
if (hasNamedItems && isNamedItemValue(value, keys)) {
|
|
5467
|
-
return
|
|
6113
|
+
return { name: itemName(strings, index), key: String(outer) };
|
|
5468
6114
|
}
|
|
5469
|
-
const
|
|
5470
|
-
const name =
|
|
5471
|
-
|
|
6115
|
+
const isItem = hasListItems && typeof last === "number" && isKey(owner);
|
|
6116
|
+
const name = isItem ? LIST_ITEM_RE.exec(value.value)?.[1] : void 0;
|
|
6117
|
+
const head = (name?.length ?? 0) + 1;
|
|
6118
|
+
return name === void 0 ? void 0 : { name, key: String(owner), head };
|
|
6119
|
+
}
|
|
6120
|
+
function scopeOf(path, key) {
|
|
6121
|
+
const owner = path.slice(0, path.lastIndexOf(key));
|
|
6122
|
+
return owner.slice(0, owner.findLastIndex((part) => typeof part === "number") + 1);
|
|
5472
6123
|
}
|
|
5473
6124
|
function environmentEntries(strings, environment) {
|
|
5474
6125
|
return new Map(
|
|
5475
6126
|
strings.flatMap((value, index) => {
|
|
5476
|
-
const
|
|
5477
|
-
|
|
6127
|
+
const place = entryPlace(strings, index, environment);
|
|
6128
|
+
if (place?.name === void 0) {
|
|
6129
|
+
return [];
|
|
6130
|
+
}
|
|
6131
|
+
const name = environment.shellName(place.name, place.key);
|
|
6132
|
+
const head = place.head ?? 0;
|
|
6133
|
+
const scope = scopeOf(value.path, place.key);
|
|
6134
|
+
return [[value, { name, head, scope }]];
|
|
5478
6135
|
})
|
|
5479
6136
|
);
|
|
5480
6137
|
}
|
|
6138
|
+
const isInScope = (path, entry) => entry.scope.every((part, at) => path[at] === part);
|
|
5481
6139
|
const ENV_ITEM_KEYS = /* @__PURE__ */ new Set([ENV_KEY]);
|
|
5482
6140
|
function environmentItemSteps(strings, entries, locate) {
|
|
5483
6141
|
return strings.filter((value) => isNamedItemValue(value, ENV_ITEM_KEYS) && !entries.has(value)).filter((value) => namesOriginalPackage(value.value)).map((value) => ({
|
|
@@ -5486,43 +6144,35 @@ function environmentItemSteps(strings, entries, locate) {
|
|
|
5486
6144
|
word: value.value
|
|
5487
6145
|
}));
|
|
5488
6146
|
}
|
|
5489
|
-
|
|
5490
|
-
const
|
|
5491
|
-
function
|
|
5492
|
-
const
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
}
|
|
5496
|
-
return text.replace(reference, (written, ...groups) => {
|
|
5497
|
-
const group = groups.find((part) => typeof part === "string") ?? "";
|
|
5498
|
-
const name = shellName(group, VARIABLES_KEY);
|
|
5499
|
-
return names.has(name) ? asShellVariable(written, name) : written;
|
|
5500
|
-
});
|
|
5501
|
-
}
|
|
5502
|
-
function withVariableReferences(text, references) {
|
|
5503
|
-
const expressions = text.replace(ENV_EXPRESSION_RE, asShellVariable);
|
|
5504
|
-
return references === void 0 ? expressions : withToolReferences(expressions, references);
|
|
6147
|
+
|
|
6148
|
+
const FOLDED_LINE_BREAK_RE = /(?<=\S[^\S\n]*)\n(?=[^\S\n]*\S)/g;
|
|
6149
|
+
function shellText(text, value, references) {
|
|
6150
|
+
const slice = text.slice(value.content.start, value.content.end);
|
|
6151
|
+
const unfolded = value.isFolded ? slice.replace(FOLDED_LINE_BREAK_RE, " ") : slice;
|
|
6152
|
+
return withVariableReferences(unfolded, references);
|
|
5505
6153
|
}
|
|
5506
6154
|
|
|
5507
|
-
function
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
)
|
|
6155
|
+
function scopedVariables({
|
|
6156
|
+
text,
|
|
6157
|
+
entries,
|
|
6158
|
+
inputs,
|
|
6159
|
+
references
|
|
6160
|
+
}) {
|
|
6161
|
+
const definitions = [...entries].map(([value, entry]) => {
|
|
6162
|
+
const shell = value.isEscaped ? withVariableReferences(value.value, references) : shellText(text, value, references);
|
|
6163
|
+
return { entry, name: entry.name, value: shell.slice(entry.head) };
|
|
6164
|
+
});
|
|
6165
|
+
return (value) => {
|
|
6166
|
+
const reaching = definitions.filter(({ entry }) => isInScope(value.path, entry));
|
|
6167
|
+
return withInputDefaults(shellVariables(reaching), inputs);
|
|
6168
|
+
};
|
|
5514
6169
|
}
|
|
6170
|
+
|
|
5515
6171
|
const DEPENDABOT_NAME_KEYS = /* @__PURE__ */ new Set([
|
|
5516
6172
|
"dependency-name",
|
|
5517
6173
|
"patterns",
|
|
5518
6174
|
"exclude-patterns"
|
|
5519
6175
|
]);
|
|
5520
|
-
const FOLDED_LINE_BREAK_RE = /(?<=\S[^\S\n]*)\n(?=[^\S\n]*\S)/g;
|
|
5521
|
-
function shellText(text, value, references) {
|
|
5522
|
-
const slice = text.slice(value.content.start, value.content.end);
|
|
5523
|
-
const unfolded = value.isFolded ? slice.replace(FOLDED_LINE_BREAK_RE, " ") : slice;
|
|
5524
|
-
return withVariableReferences(unfolded, references);
|
|
5525
|
-
}
|
|
5526
6176
|
const LEADING_SPACES_RE = /^ */;
|
|
5527
6177
|
function blockIndent(shell) {
|
|
5528
6178
|
const lines = shell.split("\n").slice(1).filter((line) => line.trim() !== "");
|
|
@@ -5538,33 +6188,32 @@ function oncePerPlace(strings) {
|
|
|
5538
6188
|
});
|
|
5539
6189
|
}
|
|
5540
6190
|
const valuesOf = (strings, keys) => oncePerPlace(strings.filter((string) => keys.has(ownerKey(string.path) ?? "")));
|
|
5541
|
-
const EXEC_FORM_KEYS = /* @__PURE__ */ new Set(["command", "entrypoint"]);
|
|
5542
|
-
const isExecFormItem = (value) => typeof value.path.at(-1) === "number" && EXEC_FORM_KEYS.has(String(value.path.at(-2)));
|
|
5543
|
-
const listOf = (item) => item.path.slice(0, -1).join(".");
|
|
5544
|
-
const isNextItem = (previous, item) => listOf(previous) === listOf(item) && Number(item.path.at(-1)) > Number(previous.path.at(-1));
|
|
5545
|
-
function execFormCommands(text, items) {
|
|
5546
|
-
const commands = [];
|
|
5547
|
-
let previous;
|
|
5548
|
-
let command = [];
|
|
5549
|
-
for (const item of items) {
|
|
5550
|
-
if (previous === void 0 || !isNextItem(previous, item)) {
|
|
5551
|
-
command = [];
|
|
5552
|
-
commands.push(command);
|
|
5553
|
-
}
|
|
5554
|
-
const { start, end } = item.content;
|
|
5555
|
-
command.push({ start, end, value: item.value, raw: text.slice(start, end) });
|
|
5556
|
-
previous = item;
|
|
5557
|
-
}
|
|
5558
|
-
return commands;
|
|
5559
|
-
}
|
|
5560
6191
|
function escapedValueFindings(value, encode, { locate, variables, references }) {
|
|
5561
|
-
const
|
|
5562
|
-
const
|
|
6192
|
+
const read = withVariableReferences(value.value, references);
|
|
6193
|
+
const commands = shellCommands(read);
|
|
6194
|
+
const findings = commandWordFindings(commands, () => locate(value.start), variables);
|
|
6195
|
+
const found = withWrittenWords(findings, commands, { read, written: value.value });
|
|
5563
6196
|
const migrated = applyTextEdits(value.value, found.edits);
|
|
5564
6197
|
const isChanged = migrated !== value.value;
|
|
5565
6198
|
const edits = isChanged ? [{ start: value.start, end: value.end, text: encode(migrated) }] : [];
|
|
5566
6199
|
return { ...found, edits };
|
|
5567
6200
|
}
|
|
6201
|
+
const PADDING = " ";
|
|
6202
|
+
function writtenWord({ read, written }, word) {
|
|
6203
|
+
let blanks = word.end;
|
|
6204
|
+
while (read[blanks] === PADDING) {
|
|
6205
|
+
blanks += 1;
|
|
6206
|
+
}
|
|
6207
|
+
const covered = written.slice(word.end, blanks).trimEnd();
|
|
6208
|
+
return written.slice(word.start, word.end + covered.length);
|
|
6209
|
+
}
|
|
6210
|
+
function withWrittenWords(found, commands, value) {
|
|
6211
|
+
const words = new Map(commands.flat().map((word) => [word.raw, writtenWord(value, word)]));
|
|
6212
|
+
const manualSteps = found.manualSteps.map(
|
|
6213
|
+
(step) => "variable" in step ? { ...step, variable: words.get(step.variable) ?? step.variable } : step
|
|
6214
|
+
);
|
|
6215
|
+
return { ...found, manualSteps };
|
|
6216
|
+
}
|
|
5568
6217
|
function valueFindings(value, context) {
|
|
5569
6218
|
if (value.isEscaped && value.encode !== void 0) {
|
|
5570
6219
|
return escapedValueFindings(value, value.encode, context);
|
|
@@ -5573,7 +6222,9 @@ function valueFindings(value, context) {
|
|
|
5573
6222
|
const { start } = value.content;
|
|
5574
6223
|
const shell = shellText(text, value, references);
|
|
5575
6224
|
const commands = shellCommands(shell, blockIndent(shell));
|
|
5576
|
-
const
|
|
6225
|
+
const findings = commandWordFindings(commands, (offset) => locate(start + offset), variables);
|
|
6226
|
+
const written = text.slice(start, value.content.end);
|
|
6227
|
+
const found = withWrittenWords(findings, commands, { read: shell, written });
|
|
5577
6228
|
return { ...found, edits: shiftedEdits(found.edits, start) };
|
|
5578
6229
|
}
|
|
5579
6230
|
const shiftedEdits = (edits, offset) => edits.map((edit) => ({ ...edit, start: edit.start + offset, end: edit.end + offset }));
|
|
@@ -5587,27 +6238,31 @@ function appliedFindings(text, found) {
|
|
|
5587
6238
|
manualSteps: found.flatMap((findings) => findings.manualSteps)
|
|
5588
6239
|
};
|
|
5589
6240
|
}
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
const
|
|
5593
|
-
const fileVariables = environmentVariables(text, entries, references);
|
|
5594
|
-
return { text, locate, variables: withInputDefaults(fileVariables, strings), references };
|
|
5595
|
-
}
|
|
5596
|
-
function migrateYamlCommands(text, file, strings, { commandKeys, environment } = DEFAULT_YAML_FILE) {
|
|
6241
|
+
const NO_NAMES = /* @__PURE__ */ new Set();
|
|
6242
|
+
function migrateYamlCommands(text, file, strings, reading = DEFAULT_YAML_FILE) {
|
|
6243
|
+
const { commandKeys, environment, parameters, outsideVariables = NO_NAMES } = reading;
|
|
5597
6244
|
const lineOf = lineLocator(text);
|
|
5598
6245
|
const locate = (offset) => `${file}:${lineOf(offset)}`;
|
|
5599
6246
|
const shellOf = stepShells(strings);
|
|
5600
6247
|
const values = valuesOf(strings, commandKeys).filter((value) => shellOf(value) === void 0);
|
|
5601
|
-
const
|
|
6248
|
+
const { findings, scripts, commandStrings } = containerCommands(text, strings, locate);
|
|
6249
|
+
const isOwnCommand = (value) => !isContainerListItem(value) && !commandStrings.has(value.start);
|
|
6250
|
+
const commandValues = new Set(values.filter(isOwnCommand));
|
|
5602
6251
|
const entries = environmentEntries(strings, environment);
|
|
5603
|
-
const
|
|
5604
|
-
const
|
|
5605
|
-
|
|
5606
|
-
);
|
|
5607
|
-
const
|
|
6252
|
+
const defaults = parameterDefaults(strings, parameters);
|
|
6253
|
+
const isShellText = (value) => commandValues.has(value) || scripts.has(value) || entries.has(value) || defaults.has(value);
|
|
6254
|
+
const shellValues = oncePerPlace(strings.filter(isShellText));
|
|
6255
|
+
const names = /* @__PURE__ */ new Set([...[...entries.values()].map((entry) => entry.name), ...outsideVariables]);
|
|
6256
|
+
const references = { environment, names, parameters };
|
|
6257
|
+
const inputs = inputValues(defaults);
|
|
6258
|
+
const variablesAt = scopedVariables({ text, entries, inputs, references });
|
|
6259
|
+
const contextOf = (value) => ({
|
|
6260
|
+
...{ text, locate, references },
|
|
6261
|
+
variables: variablesAt(value)
|
|
6262
|
+
});
|
|
5608
6263
|
return appliedFindings(text, [
|
|
5609
|
-
...shellValues.map((value) => valueFindings(value,
|
|
5610
|
-
|
|
6264
|
+
...shellValues.map((value) => valueFindings(value, contextOf(value))),
|
|
6265
|
+
...findings,
|
|
5611
6266
|
otherShellFindings(valuesOf(strings, commandKeys), shellOf, locate),
|
|
5612
6267
|
{ edits: [], changes: [], manualSteps: environmentItemSteps(strings, entries, locate) }
|
|
5613
6268
|
]);
|
|
@@ -5654,7 +6309,7 @@ function listsByHook(strings, key) {
|
|
|
5654
6309
|
}
|
|
5655
6310
|
function entryWords(text, entry) {
|
|
5656
6311
|
const { start } = entry.content;
|
|
5657
|
-
return shellCommands(shellText(text, entry)).flat().map((word) => (
|
|
6312
|
+
return shellCommands(shellText(text, entry)).flat().map((word) => movedWord(word, start));
|
|
5658
6313
|
}
|
|
5659
6314
|
const itemWord = (text, item) => {
|
|
5660
6315
|
const { start, end } = item.content;
|
|
@@ -5760,6 +6415,25 @@ function migrateWorkspaceCatalogs(text, read, target, file) {
|
|
|
5760
6415
|
return { text: applyTextEdits(text, edits), changes, manualSteps };
|
|
5761
6416
|
}
|
|
5762
6417
|
|
|
6418
|
+
function generatorVariables(text, strings, { environment }) {
|
|
6419
|
+
const entries = environmentEntries(strings, environment);
|
|
6420
|
+
return [...entries].flatMap(([value, entry]) => {
|
|
6421
|
+
const shell = value.isEscaped ? value.value : shellText(text, value);
|
|
6422
|
+
return shellCommands(shell.slice(entry.head)).some(runsGenerator) ? [entry.name] : [];
|
|
6423
|
+
});
|
|
6424
|
+
}
|
|
6425
|
+
const NAME_END = "(?![A-Za-z0-9_])";
|
|
6426
|
+
const SPECIAL_CHARACTERS_RE$1 = /[.*+?^${}()|[\]\\]/g;
|
|
6427
|
+
function usesVariable(text, names) {
|
|
6428
|
+
if (names.size === 0) {
|
|
6429
|
+
return false;
|
|
6430
|
+
}
|
|
6431
|
+
const alternatives = [...names].map((name2) => name2.replace(SPECIAL_CHARACTERS_RE$1, "\\$&"));
|
|
6432
|
+
const name = `(?:${alternatives.join("|")})`;
|
|
6433
|
+
const expansion = `\\$(?:\\{|\\(|env:)?${name}${NAME_END}|%${name}%`;
|
|
6434
|
+
return new RegExp(expansion).test(text) || referencedVariables(text).some((found) => names.has(found));
|
|
6435
|
+
}
|
|
6436
|
+
|
|
5763
6437
|
const withSteps = (migration, steps) => ({
|
|
5764
6438
|
...migration,
|
|
5765
6439
|
manualSteps: [...migration.manualSteps, ...steps]
|
|
@@ -5784,7 +6458,7 @@ const stringsStep = (migrate) => (text, read) => read.kind === "unreadable" ? un
|
|
|
5784
6458
|
const usedStringsStep = (migrate) => (text, read) => read.kind === "unreadable" ? unreadableConfig(text, read.offset) : migrate(text, usedDocumentStrings(read.documents));
|
|
5785
6459
|
const jsonConfig = (steps) => (text, path, context) => migrateConfig(text, (current) => context.readers.json.read(current), steps(context, path));
|
|
5786
6460
|
const yamlConfig = (steps) => (text, path, context) => migrateConfig(text, (current) => context.readers.yaml.read(current), steps(context, path));
|
|
5787
|
-
const whenNamed = (migrate) => (text, path, context) => namesOriginalPackage(text) ? migrate(text, path, context) : unchanged(text);
|
|
6461
|
+
const whenNamed = (migrate) => (text, path, context) => namesOriginalPackage(text) || usesVariable(text, context.yamlReach.generatorVariables) ? migrate(text, path, context) : unchanged(text);
|
|
5788
6462
|
|
|
5789
6463
|
const SHELL_EXTENSIONS = /* @__PURE__ */ new Set([".sh", ".bash", ".zsh"]);
|
|
5790
6464
|
const MAKEFILE_EXTENSION = ".mk";
|
|
@@ -5909,15 +6583,18 @@ const CI_ENVIRONMENT_FILES = /* @__PURE__ */ new Set([
|
|
|
5909
6583
|
".woodpecker.yml",
|
|
5910
6584
|
".woodpecker.yaml"
|
|
5911
6585
|
]);
|
|
5912
|
-
const
|
|
6586
|
+
const CIRCLECI_FOLDER = ".circleci/";
|
|
6587
|
+
const WOODPECKER_FOLDER = ".woodpecker/";
|
|
5913
6588
|
const COMPOSE_FILE_RE = /^(?:docker-)?compose(?:\.[^/]+)?\.ya?ml$/;
|
|
5914
6589
|
function yamlCommandFileFor(path) {
|
|
5915
6590
|
const name = baseName(path);
|
|
5916
6591
|
if (GITLAB_FILES.has(name) || isInFolder(path, GITLAB_FOLDER)) {
|
|
5917
6592
|
return GITLAB_CI_FILE;
|
|
5918
6593
|
}
|
|
5919
|
-
|
|
5920
|
-
|
|
6594
|
+
if (isInFolder(path, CIRCLECI_FOLDER)) {
|
|
6595
|
+
return CIRCLECI_FILE;
|
|
6596
|
+
}
|
|
6597
|
+
if (CI_ENVIRONMENT_FILES.has(name) || isInFolder(path, WOODPECKER_FOLDER)) {
|
|
5921
6598
|
return CI_ENVIRONMENT_FILE;
|
|
5922
6599
|
}
|
|
5923
6600
|
if (isAzurePipelinesFile(path)) {
|
|
@@ -5926,6 +6603,58 @@ function yamlCommandFileFor(path) {
|
|
|
5926
6603
|
return COMPOSE_FILE_RE.test(name) ? COMPOSE_FILE : DEFAULT_YAML_FILE;
|
|
5927
6604
|
}
|
|
5928
6605
|
|
|
6606
|
+
const yamlKindOf = (reach, path) => reach.kinds.get(path) ?? yamlCommandFileFor(path);
|
|
6607
|
+
const namedKindOf = (path) => TASKFILE_NAMES.has(baseName(path)) ? TASKFILE : yamlCommandFileFor(path);
|
|
6608
|
+
async function textOf$1(path, { files }) {
|
|
6609
|
+
const read = await files.read(path);
|
|
6610
|
+
return read.kind === "read" ? read.text : void 0;
|
|
6611
|
+
}
|
|
6612
|
+
function stringsOf(text, { readers }) {
|
|
6613
|
+
const parsed = text === void 0 ? void 0 : readers.yaml.read(text);
|
|
6614
|
+
return parsed?.kind === "read" ? usedDocumentStrings(parsed.documents) : [];
|
|
6615
|
+
}
|
|
6616
|
+
const ANY_FOLDERS_WILDCARD = "**";
|
|
6617
|
+
const WILDCARD_RE = /\*\*?/g;
|
|
6618
|
+
const SPECIAL_CHARACTERS_RE = /[.+?^${}()|[\]\\]/g;
|
|
6619
|
+
const ANY_FOLDERS = ".*";
|
|
6620
|
+
const ANY_NAME = "[^/]*";
|
|
6621
|
+
function matchingPaths(pattern, listed) {
|
|
6622
|
+
const source = pattern.replace(SPECIAL_CHARACTERS_RE, "\\$&").replace(WILDCARD_RE, (star) => star === ANY_FOLDERS_WILDCARD ? ANY_FOLDERS : ANY_NAME);
|
|
6623
|
+
const matches = new RegExp(`^${source}$`);
|
|
6624
|
+
return listed.filter((path) => matches.test(path));
|
|
6625
|
+
}
|
|
6626
|
+
async function includedKinds(paths, dependencies) {
|
|
6627
|
+
const kinds = /* @__PURE__ */ new Map();
|
|
6628
|
+
const pending = paths.map((path) => ({ path, kind: namedKindOf(path) })).filter(({ kind }) => kind.includes !== NO_INCLUDES);
|
|
6629
|
+
for (let next = pending.pop(); next !== void 0; next = pending.pop()) {
|
|
6630
|
+
const strings = stringsOf(await textOf$1(next.path, dependencies), dependencies);
|
|
6631
|
+
const included = includedPaths(next.path, strings, next.kind.includes);
|
|
6632
|
+
for (const path of included.flatMap((pattern) => matchingPaths(pattern, paths))) {
|
|
6633
|
+
if (!kinds.has(path) && namedKindOf(path) === DEFAULT_YAML_FILE) {
|
|
6634
|
+
kinds.set(path, next.kind);
|
|
6635
|
+
pending.push({ path, kind: next.kind });
|
|
6636
|
+
}
|
|
6637
|
+
}
|
|
6638
|
+
}
|
|
6639
|
+
return kinds;
|
|
6640
|
+
}
|
|
6641
|
+
const isVariableSource = (path, text) => namesOriginalPackage(text) && (isCiConfigFile(path) || !mayBeApiDescription(text));
|
|
6642
|
+
async function planYamlReach(paths, dependencies) {
|
|
6643
|
+
const yamlPaths = paths.filter((path) => YAML_EXTENSIONS.has(extensionOf(path)));
|
|
6644
|
+
const kinds = await includedKinds(yamlPaths, dependencies);
|
|
6645
|
+
const names = /* @__PURE__ */ new Set();
|
|
6646
|
+
for (const path of yamlPaths) {
|
|
6647
|
+
const text = await textOf$1(path, dependencies);
|
|
6648
|
+
if (text !== void 0 && isVariableSource(path, text)) {
|
|
6649
|
+
const kind = kinds.get(path) ?? namedKindOf(path);
|
|
6650
|
+
for (const name of generatorVariables(text, stringsOf(text, dependencies), kind)) {
|
|
6651
|
+
names.add(name);
|
|
6652
|
+
}
|
|
6653
|
+
}
|
|
6654
|
+
}
|
|
6655
|
+
return { kinds, generatorVariables: names };
|
|
6656
|
+
}
|
|
6657
|
+
|
|
5929
6658
|
const isHuskyHook = (path) => (path.startsWith(HUSKY_FOLDER) || path.includes(`/${HUSKY_FOLDER}`)) && !path.includes(HUSKY_INTERNALS);
|
|
5930
6659
|
const isDependabotConfig = (path) => [...DEPENDABOT_FILES].some((file) => path === file || path.endsWith(`/${file}`));
|
|
5931
6660
|
function migrateSource(text, path, context) {
|
|
@@ -5968,8 +6697,13 @@ const COMMAND_CONFIG_KINDS = [
|
|
|
5968
6697
|
{
|
|
5969
6698
|
matches: (path) => TASKFILE_NAMES.has(baseName(path)),
|
|
5970
6699
|
migrate: whenNamed(
|
|
5971
|
-
yamlConfig((
|
|
5972
|
-
usedStringsStep(
|
|
6700
|
+
yamlConfig((context, path) => [
|
|
6701
|
+
usedStringsStep(
|
|
6702
|
+
(text, strings) => migrateYamlCommands(text, path, strings, {
|
|
6703
|
+
...TASKFILE,
|
|
6704
|
+
outsideVariables: context.yamlReach.generatorVariables
|
|
6705
|
+
})
|
|
6706
|
+
)
|
|
5973
6707
|
])
|
|
5974
6708
|
)
|
|
5975
6709
|
},
|
|
@@ -5982,9 +6716,16 @@ const COMMAND_CONFIG_KINDS = [
|
|
|
5982
6716
|
)
|
|
5983
6717
|
}
|
|
5984
6718
|
];
|
|
5985
|
-
const yamlCommandsStep = (path,
|
|
5986
|
-
|
|
5987
|
-
|
|
6719
|
+
const yamlCommandsStep = (path, { apiDescriptionParts, yamlReach }) => (text, read) => {
|
|
6720
|
+
const isCiFile = isCiConfigFile(path) || yamlReach.kinds.has(path);
|
|
6721
|
+
const isApi = !isCiFile && read.kind === "read" && isApiDescription(read.documents);
|
|
6722
|
+
return apiDescriptionParts.has(path) || isApi ? unchanged(text) : usedStringsStep(
|
|
6723
|
+
(current, strings) => migrateYamlCommands(current, path, strings, {
|
|
6724
|
+
...yamlKindOf(yamlReach, path),
|
|
6725
|
+
outsideVariables: yamlReach.generatorVariables
|
|
6726
|
+
})
|
|
6727
|
+
)(text, read);
|
|
6728
|
+
};
|
|
5988
6729
|
const manifestTarget = ({ version, catalogs, aliases }, path) => ({
|
|
5989
6730
|
version,
|
|
5990
6731
|
catalogs,
|
|
@@ -6060,11 +6801,7 @@ const FILE_KINDS = [
|
|
|
6060
6801
|
},
|
|
6061
6802
|
{
|
|
6062
6803
|
matches: (path) => YAML_EXTENSIONS.has(extensionOf(path)),
|
|
6063
|
-
migrate: whenNamed(
|
|
6064
|
-
yamlConfig((context, path) => [
|
|
6065
|
-
yamlCommandsStep(path, context.apiDescriptionParts.has(path))
|
|
6066
|
-
])
|
|
6067
|
-
)
|
|
6804
|
+
migrate: whenNamed(yamlConfig((context, path) => [yamlCommandsStep(path, context)]))
|
|
6068
6805
|
},
|
|
6069
6806
|
{
|
|
6070
6807
|
matches: (path) => DOCKERFILE_NAMES.has(baseName(path)),
|
|
@@ -6226,9 +6963,10 @@ async function planProjectTarget(paths, dependencies, version) {
|
|
|
6226
6963
|
});
|
|
6227
6964
|
const declarations = withNamedImportMaps(manifests, importMaps);
|
|
6228
6965
|
const parts = await apiDescriptionParts(paths, dependencies);
|
|
6966
|
+
const yamlReach = await planYamlReach(paths, dependencies);
|
|
6229
6967
|
return {
|
|
6230
6968
|
...{ version, catalogs, manifests: declarations, aliases, importMaps },
|
|
6231
|
-
apiDescriptionParts: parts
|
|
6969
|
+
...{ apiDescriptionParts: parts, yamlReach }
|
|
6232
6970
|
};
|
|
6233
6971
|
}
|
|
6234
6972
|
|
|
@@ -6252,9 +6990,9 @@ async function planFile(path, dependencies, target) {
|
|
|
6252
6990
|
return read;
|
|
6253
6991
|
}
|
|
6254
6992
|
const { rewriter, scanner, readers } = dependencies;
|
|
6255
|
-
const { version, catalogs, manifests, aliases, apiDescriptionParts } = target;
|
|
6993
|
+
const { version, catalogs, manifests, aliases, apiDescriptionParts, yamlReach } = target;
|
|
6256
6994
|
const context = {
|
|
6257
|
-
...{ version, catalogs, manifests, aliases, apiDescriptionParts },
|
|
6995
|
+
...{ version, catalogs, manifests, aliases, apiDescriptionParts, yamlReach },
|
|
6258
6996
|
...{ rewriter, scanner, readers }
|
|
6259
6997
|
};
|
|
6260
6998
|
const attempt = attemptMigration(() => migrate(read.text, path, context));
|
|
@@ -6352,6 +7090,7 @@ const NOT_ONLY_GENERATOR_NOTE = "may run openapi-typescript or another program (
|
|
|
6352
7090
|
const OLD_NAME_IN_COMMAND_NOTE = "names an old package where the tool cannot tell what runs it (a script name, an argument of a program it does not know), so it was kept: migrate it by hand";
|
|
6353
7091
|
const SCRIPT_NOT_SHELL_NOTE = "so the tool does not read it as commands: migrate the old package names in it by hand";
|
|
6354
7092
|
const COMMAND_STRING_NOTE = "a string runs openapi-typescript, so it was kept; change it to";
|
|
7093
|
+
const SPLIT_FLAG_NOTE = "is an old flag of the generator that quotes split where it is written, so it was kept: rename";
|
|
6355
7094
|
function pinnedPackageMessage(step) {
|
|
6356
7095
|
const successor = PACKAGE_RENAMES.get(step.name) ?? step.name;
|
|
6357
7096
|
return `${step.location} names a pinned ${step.name}@<version>: change it to ${successor}@<version>`;
|
|
@@ -6370,6 +7109,7 @@ const COMMAND_STEP_KINDS = /* @__PURE__ */ new Set([
|
|
|
6370
7109
|
"pinned-package",
|
|
6371
7110
|
"old-package-file",
|
|
6372
7111
|
"old-name-in-command",
|
|
7112
|
+
"split-flag",
|
|
6373
7113
|
"script-not-shell",
|
|
6374
7114
|
"command-string"
|
|
6375
7115
|
]);
|
|
@@ -6388,6 +7128,8 @@ function commandStepMessage(step) {
|
|
|
6388
7128
|
return `${step.location}: ${step.path} ${OLD_FILE_NOTE$1}`;
|
|
6389
7129
|
case "old-name-in-command":
|
|
6390
7130
|
return `${step.location}: "${step.word}" ${OLD_NAME_IN_COMMAND_NOTE}`;
|
|
7131
|
+
case "split-flag":
|
|
7132
|
+
return `${step.location}: ${step.flag} ${SPLIT_FLAG_NOTE} ${flagRenames([step.flag])}`;
|
|
6391
7133
|
case "script-not-shell":
|
|
6392
7134
|
return `${step.location}: the script runs with ${step.shell}, ${SCRIPT_NOT_SHELL_NOTE}`;
|
|
6393
7135
|
case "command-string":
|