openapi-typesafe-migrate 1.0.0-rc.5 → 1.0.0-rc.7
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 +95 -0
- package/README.md +49 -22
- package/dist/cli/main.mjs +1673 -908
- package/dist/cli/main.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli/main.mjs
CHANGED
|
@@ -560,6 +560,21 @@ async function inspectProjectRoot(root) {
|
|
|
560
560
|
}
|
|
561
561
|
}
|
|
562
562
|
|
|
563
|
+
const BROKEN_PIPE = "EPIPE";
|
|
564
|
+
function isBrokenPipe(error) {
|
|
565
|
+
return error.code === BROKEN_PIPE;
|
|
566
|
+
}
|
|
567
|
+
function createPipeSafeWriter(stream) {
|
|
568
|
+
stream.on("error", (error) => {
|
|
569
|
+
if (!isBrokenPipe(error)) {
|
|
570
|
+
throw error;
|
|
571
|
+
}
|
|
572
|
+
});
|
|
573
|
+
return (text) => {
|
|
574
|
+
stream.write(text);
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
|
|
563
578
|
function unchanged(text) {
|
|
564
579
|
return { text, changes: [], manualSteps: [] };
|
|
565
580
|
}
|
|
@@ -610,6 +625,7 @@ function applyTextEdits(text, edits) {
|
|
|
610
625
|
return edited + text.slice(copiedUpTo);
|
|
611
626
|
}
|
|
612
627
|
|
|
628
|
+
const hasExportModifier = (declaration) => (ts.getCombinedModifierFlags(declaration) & ts.ModifierFlags.Export) !== 0;
|
|
613
629
|
const GENERATOR_MODULES = /* @__PURE__ */ new Set([
|
|
614
630
|
"openapi-typesafe",
|
|
615
631
|
"openapi-typescript"
|
|
@@ -692,7 +708,13 @@ function createChecker(file) {
|
|
|
692
708
|
}
|
|
693
709
|
function symbolOf(checker, identifier) {
|
|
694
710
|
const parent = identifier.parent;
|
|
695
|
-
|
|
711
|
+
if (ts.isShorthandPropertyAssignment(parent) && parent.name === identifier) {
|
|
712
|
+
return checker.getShorthandAssignmentValueSymbol(parent);
|
|
713
|
+
}
|
|
714
|
+
if (ts.isExportSpecifier(parent)) {
|
|
715
|
+
return checker.getExportSpecifierLocalTargetSymbol(parent);
|
|
716
|
+
}
|
|
717
|
+
return checker.getSymbolAtLocation(identifier);
|
|
696
718
|
}
|
|
697
719
|
function isDeclaredName(identifier, declaration) {
|
|
698
720
|
const declaredName = declaration.name;
|
|
@@ -715,7 +737,9 @@ function indexUses(file, bindings) {
|
|
|
715
737
|
if (declaration !== void 0 && !isDeclaredName(node, declaration)) {
|
|
716
738
|
uses.set(declaration, [...uses.get(declaration) ?? [], node]);
|
|
717
739
|
}
|
|
718
|
-
|
|
740
|
+
for (const child of node.getChildren(file)) {
|
|
741
|
+
visit(child);
|
|
742
|
+
}
|
|
719
743
|
};
|
|
720
744
|
visit(file);
|
|
721
745
|
return uses;
|
|
@@ -778,7 +802,6 @@ function unwrapped(expression, types = []) {
|
|
|
778
802
|
}
|
|
779
803
|
return { value: expression, types };
|
|
780
804
|
}
|
|
781
|
-
const isExported$1 = (declaration) => (ts.getCombinedModifierFlags(declaration) & ts.ModifierFlags.Export) !== 0;
|
|
782
805
|
function constantOptions(name, bindings, outerTypes) {
|
|
783
806
|
const binding = bindings.bindingOf(name);
|
|
784
807
|
const declaration = bindings.declarationOf(name);
|
|
@@ -786,23 +809,28 @@ function constantOptions(name, bindings, outerTypes) {
|
|
|
786
809
|
if (found === void 0 || !ts.isObjectLiteralExpression(found.value)) {
|
|
787
810
|
return { kind: "unknown", expression: name };
|
|
788
811
|
}
|
|
789
|
-
const isOwn = bindings.usesOf(declaration).length === 1 && !
|
|
812
|
+
const isOwn = bindings.usesOf(declaration).length === 1 && !hasExportModifier(declaration);
|
|
790
813
|
if (!isOwn) {
|
|
791
814
|
return { kind: "shared", options: found.value };
|
|
792
815
|
}
|
|
793
816
|
const declared = declaration.type;
|
|
794
|
-
const
|
|
795
|
-
...outerTypes,
|
|
817
|
+
const ownTypes = [
|
|
796
818
|
...found.types,
|
|
797
819
|
...declared === void 0 ? [] : [declared],
|
|
798
820
|
...jsDocTypes(declaration)
|
|
799
821
|
];
|
|
800
|
-
|
|
822
|
+
const annotations = [...outerTypes, ...ownTypes];
|
|
823
|
+
return {
|
|
824
|
+
kind: "own",
|
|
825
|
+
options: found.value,
|
|
826
|
+
annotations,
|
|
827
|
+
isContextuallyTyped: ownTypes.length > 0
|
|
828
|
+
};
|
|
801
829
|
}
|
|
802
830
|
function optionsOf(argument, bindings) {
|
|
803
831
|
const { value, types } = unwrapped(argument);
|
|
804
832
|
if (ts.isObjectLiteralExpression(value)) {
|
|
805
|
-
return { kind: "own", options: value, annotations: types };
|
|
833
|
+
return { kind: "own", options: value, annotations: types, isContextuallyTyped: true };
|
|
806
834
|
}
|
|
807
835
|
return ts.isIdentifier(value) ? constantOptions(value, bindings, types) : { kind: "unknown", expression: argument };
|
|
808
836
|
}
|
|
@@ -1086,7 +1114,7 @@ function callbackAnnotations(property, names) {
|
|
|
1086
1114
|
function isSharedFunction(property, names) {
|
|
1087
1115
|
const name = namedValue(property);
|
|
1088
1116
|
const declaration = name === void 0 ? void 0 : names.bindings.declarationOf(name);
|
|
1089
|
-
return declaration !== void 0 && names.bindings.usesOf(declaration).length > 1;
|
|
1117
|
+
return declaration !== void 0 && (names.bindings.usesOf(declaration).length > 1 || hasExportModifier(declaration));
|
|
1090
1118
|
}
|
|
1091
1119
|
|
|
1092
1120
|
const KEYWORDS = /* @__PURE__ */ new Map([
|
|
@@ -1305,7 +1333,6 @@ function returnEdits(expression, names) {
|
|
|
1305
1333
|
return typeTextEdit(expression, names);
|
|
1306
1334
|
}
|
|
1307
1335
|
|
|
1308
|
-
const isExported = (node) => (ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) !== 0;
|
|
1309
1336
|
function isRemovable(node, binding, names) {
|
|
1310
1337
|
switch (binding.kind) {
|
|
1311
1338
|
case "typescript-module":
|
|
@@ -1313,7 +1340,7 @@ function isRemovable(node, binding, names) {
|
|
|
1313
1340
|
case "helper-import":
|
|
1314
1341
|
return true;
|
|
1315
1342
|
case "constant":
|
|
1316
|
-
return !
|
|
1343
|
+
return !hasExportModifier(node) && typeTextOf(binding.initializer, names) !== void 0;
|
|
1317
1344
|
default:
|
|
1318
1345
|
return false;
|
|
1319
1346
|
}
|
|
@@ -1414,6 +1441,9 @@ function removalEdits(removed, text) {
|
|
|
1414
1441
|
const TRANSFORM = "transform";
|
|
1415
1442
|
const LEGACY_ONLY_CALLBACKS = ["postTransform", "transformProperty"];
|
|
1416
1443
|
const IR_CALLBACKS_OPTION = "irCallbacks";
|
|
1444
|
+
const IR_CALLBACKS_TRUE = "true";
|
|
1445
|
+
const IR_CALLBACKS_TRUE_CONST = "true as const";
|
|
1446
|
+
const IR_CALLBACKS_TRUE_CONST_JS = "/** @type {const} */ (true)";
|
|
1417
1447
|
const noFindings = () => ({
|
|
1418
1448
|
edits: [],
|
|
1419
1449
|
changes: [],
|
|
@@ -1452,10 +1482,17 @@ function transformEdits(property, names, text) {
|
|
|
1452
1482
|
}
|
|
1453
1483
|
return edits;
|
|
1454
1484
|
}
|
|
1455
|
-
function
|
|
1485
|
+
function irCallbacksValue(options) {
|
|
1486
|
+
if (options.isContextuallyTyped) {
|
|
1487
|
+
return IR_CALLBACKS_TRUE;
|
|
1488
|
+
}
|
|
1489
|
+
const isJavaScript = (options.options.flags & ts.NodeFlags.JavaScriptFile) !== 0;
|
|
1490
|
+
return isJavaScript ? IR_CALLBACKS_TRUE_CONST_JS : IR_CALLBACKS_TRUE_CONST;
|
|
1491
|
+
}
|
|
1492
|
+
function irCallbacksOption(text, transformStart, value) {
|
|
1456
1493
|
const lineStart = text.lastIndexOf("\n", transformStart - 1) + 1;
|
|
1457
1494
|
const before = text.slice(lineStart, transformStart);
|
|
1458
|
-
const option = `${IR_CALLBACKS_OPTION}:
|
|
1495
|
+
const option = `${IR_CALLBACKS_OPTION}: ${value},`;
|
|
1459
1496
|
return /^\s*$/.test(before) ? `${option}
|
|
1460
1497
|
${before}` : `${option} `;
|
|
1461
1498
|
}
|
|
@@ -1498,7 +1535,9 @@ function migrateOptions(options, text, names) {
|
|
|
1498
1535
|
findings.manualSteps.push({ kind: "transform-not-rewritten", line, reason: result });
|
|
1499
1536
|
return findings;
|
|
1500
1537
|
}
|
|
1501
|
-
|
|
1538
|
+
const at = transform.getStart(void 0, true);
|
|
1539
|
+
const option = irCallbacksOption(text, at, irCallbacksValue(options));
|
|
1540
|
+
findings.edits.push({ start: at, end: at, text: option }, ...result.edits);
|
|
1502
1541
|
findings.typeReferences.push(...result.typeReferences);
|
|
1503
1542
|
findings.changes.push({ kind: "transform-rewritten", line });
|
|
1504
1543
|
return findings;
|
|
@@ -1867,30 +1906,6 @@ function createYamlTextReader() {
|
|
|
1867
1906
|
return { read };
|
|
1868
1907
|
}
|
|
1869
1908
|
|
|
1870
|
-
const CATALOG_PROTOCOL = "catalog:";
|
|
1871
|
-
const DEFAULT_CATALOG = "default";
|
|
1872
|
-
function catalogOfSpec(spec) {
|
|
1873
|
-
if (!spec.startsWith(CATALOG_PROTOCOL)) {
|
|
1874
|
-
return void 0;
|
|
1875
|
-
}
|
|
1876
|
-
return spec.slice(CATALOG_PROTOCOL.length).trim() || DEFAULT_CATALOG;
|
|
1877
|
-
}
|
|
1878
|
-
class CatalogEntries {
|
|
1879
|
-
#keys = /* @__PURE__ */ new Set();
|
|
1880
|
-
add(catalog, name) {
|
|
1881
|
-
this.#keys.add(JSON.stringify([catalog, name]));
|
|
1882
|
-
}
|
|
1883
|
-
has(catalog, name) {
|
|
1884
|
-
return this.#keys.has(JSON.stringify([catalog, name]));
|
|
1885
|
-
}
|
|
1886
|
-
}
|
|
1887
|
-
const NO_CATALOG_PLAN = {
|
|
1888
|
-
inUse: new CatalogEntries(),
|
|
1889
|
-
kept: new CatalogEntries(),
|
|
1890
|
-
defined: new CatalogEntries(),
|
|
1891
|
-
isWorkspaceRoot: false
|
|
1892
|
-
};
|
|
1893
|
-
|
|
1894
1909
|
const PACKAGE_RENAMES = /* @__PURE__ */ new Map([
|
|
1895
1910
|
["openapi-typescript", "openapi-typesafe"],
|
|
1896
1911
|
["openapi-fetch", "openapi-typesafe-fetch"],
|
|
@@ -1986,477 +2001,69 @@ function unreadableConfig(text, offset) {
|
|
|
1986
2001
|
return { ...unchanged(text), manualSteps: [{ kind: "config-unreadable", position }] };
|
|
1987
2002
|
}
|
|
1988
2003
|
|
|
1989
|
-
const
|
|
1990
|
-
const
|
|
1991
|
-
const
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
const
|
|
1995
|
-
const
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
}
|
|
2000
|
-
function overriddenPackages(keys) {
|
|
2001
|
-
const targets = keys.map(overrideTarget);
|
|
2002
|
-
return [...new Set(targets.filter((target) => PACKAGE_RENAMES.has(target)))];
|
|
2003
|
-
}
|
|
2004
|
-
|
|
2005
|
-
const isEditable = (node) => node.kind === "scalar" && node.encode !== void 0;
|
|
2006
|
-
const replaceScalar = (scalar, value) => ({
|
|
2007
|
-
start: scalar.start,
|
|
2008
|
-
end: scalar.end,
|
|
2009
|
-
text: scalar.encode(value)
|
|
2010
|
-
});
|
|
2011
|
-
function specEntries(map) {
|
|
2012
|
-
return textEntries(map).flatMap(({ key, value }) => {
|
|
2013
|
-
if (!isEditable(key)) {
|
|
2014
|
-
return [];
|
|
2015
|
-
}
|
|
2016
|
-
const spec = isEditable(value) ? { value: value.value, replace: (to) => replaceScalar(value, to) } : void 0;
|
|
2017
|
-
return [{ name: key.value, spec, renameKey: (name) => replaceScalar(key, name) }];
|
|
2018
|
-
});
|
|
2019
|
-
}
|
|
2020
|
-
function keyEntries(map) {
|
|
2021
|
-
return textEntries(map).map(({ key }) => key).filter(isEditable).map((key) => ({ name: key.value, rename: (name) => replaceScalar(key, name) }));
|
|
2022
|
-
}
|
|
2023
|
-
function itemEntries(list) {
|
|
2024
|
-
return list.items.filter(isEditable).map((item) => ({ name: item.value, rename: (name) => replaceScalar(item, name) }));
|
|
2025
|
-
}
|
|
2026
|
-
function nestedKeys(node) {
|
|
2027
|
-
if (node.kind !== "map") {
|
|
2028
|
-
return [];
|
|
2029
|
-
}
|
|
2030
|
-
return textEntries(node).flatMap(({ key, value }) => [key.value, ...nestedKeys(value)]);
|
|
2031
|
-
}
|
|
2032
|
-
|
|
2033
|
-
const PATH_SEPARATOR$7 = ".";
|
|
2034
|
-
function catalogMaps(root, prefix = "") {
|
|
2035
|
-
const maps = mapsAt(root, CATALOG_FIELD).map((map) => ({
|
|
2036
|
-
name: DEFAULT_CATALOG,
|
|
2037
|
-
label: `${prefix}${CATALOG_FIELD}`,
|
|
2038
|
-
map
|
|
2039
|
-
}));
|
|
2040
|
-
for (const catalogs of mapsAt(root, NAMED_CATALOGS_FIELD)) {
|
|
2041
|
-
for (const { key, value } of textEntries(catalogs)) {
|
|
2042
|
-
if (isMap(value)) {
|
|
2043
|
-
const label = [prefix + NAMED_CATALOGS_FIELD, key.value].join(PATH_SEPARATOR$7);
|
|
2044
|
-
maps.push({ name: key.value, label, map: value });
|
|
2045
|
-
}
|
|
2046
|
-
}
|
|
2047
|
-
}
|
|
2048
|
-
return maps;
|
|
2049
|
-
}
|
|
2050
|
-
const manifestCatalogMaps = (manifest) => [
|
|
2051
|
-
...catalogMaps(manifest),
|
|
2052
|
-
...mapsAt(manifest, WORKSPACES_FIELD).flatMap(
|
|
2053
|
-
(workspaces) => catalogMaps(workspaces, `${WORKSPACES_FIELD}${PATH_SEPARATOR$7}`)
|
|
2054
|
-
)
|
|
2055
|
-
];
|
|
2056
|
-
function entriesInUse(manifests) {
|
|
2057
|
-
const inUse = new CatalogEntries();
|
|
2058
|
-
const fields = manifests.flatMap(
|
|
2059
|
-
(manifest) => DEPENDENCY_FIELDS.flatMap((field) => mapsAt(manifest, field))
|
|
2060
|
-
);
|
|
2061
|
-
for (const dependencies of fields) {
|
|
2062
|
-
const entries = specEntries(dependencies);
|
|
2063
|
-
const names = new Set(entries.map((entry) => entry.name));
|
|
2064
|
-
for (const { name, spec } of entries) {
|
|
2065
|
-
const catalog = spec === void 0 ? void 0 : catalogOfSpec(spec.value);
|
|
2066
|
-
const to = PACKAGE_RENAMES.get(name);
|
|
2067
|
-
if (catalog !== void 0 && to !== void 0 && names.has(to)) {
|
|
2068
|
-
inUse.add(catalog, name);
|
|
2004
|
+
const SEPARATOR = "/";
|
|
2005
|
+
const CURRENT_FOLDER = ".";
|
|
2006
|
+
const PARENT_FOLDER = "..";
|
|
2007
|
+
const URL_SCHEME = /^[a-z][a-z\d+.-]*:/i;
|
|
2008
|
+
function resolvedPath(fromPath, reference) {
|
|
2009
|
+
const parts = fromPath.split(SEPARATOR).slice(0, -1);
|
|
2010
|
+
for (const part of reference.split(SEPARATOR)) {
|
|
2011
|
+
if (part === PARENT_FOLDER) {
|
|
2012
|
+
if (parts.pop() === void 0) {
|
|
2013
|
+
return void 0;
|
|
2069
2014
|
}
|
|
2015
|
+
} else if (part !== CURRENT_FOLDER && part !== "") {
|
|
2016
|
+
parts.push(part);
|
|
2070
2017
|
}
|
|
2071
2018
|
}
|
|
2072
|
-
return
|
|
2073
|
-
}
|
|
2074
|
-
function nestedTexts(node) {
|
|
2075
|
-
if (node.kind !== "map") {
|
|
2076
|
-
return [];
|
|
2077
|
-
}
|
|
2078
|
-
return textEntries(node).flatMap(
|
|
2079
|
-
({ key, value }) => value.kind === "scalar" ? [{ key: key.value, value: value.value }] : nestedTexts(value)
|
|
2080
|
-
);
|
|
2081
|
-
}
|
|
2082
|
-
function addOverrideUses(documents, inUse) {
|
|
2083
|
-
const sections = documents.flatMap(
|
|
2084
|
-
(document) => [...OVERRIDE_FIELDS, PNPM_SETTINGS_FIELD].flatMap((field) => valuesAt(document, field))
|
|
2085
|
-
);
|
|
2086
|
-
for (const { key, value } of sections.flatMap(nestedTexts)) {
|
|
2087
|
-
const catalog = catalogOfSpec(value);
|
|
2088
|
-
const name = overrideTarget(key);
|
|
2089
|
-
if (catalog !== void 0 && PACKAGE_RENAMES.has(name)) {
|
|
2090
|
-
inUse.add(catalog, name);
|
|
2091
|
-
}
|
|
2092
|
-
}
|
|
2019
|
+
return parts.join(SEPARATOR);
|
|
2093
2020
|
}
|
|
2094
|
-
function
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
}) {
|
|
2099
|
-
const inUse = entriesInUse(manifests);
|
|
2100
|
-
addOverrideUses([...manifests, ...catalogFiles], inUse);
|
|
2101
|
-
const kept = new CatalogEntries();
|
|
2102
|
-
const defined = new CatalogEntries();
|
|
2103
|
-
const catalogs = [
|
|
2104
|
-
...catalogFiles.flatMap((file) => catalogMaps(file)),
|
|
2105
|
-
...manifests.flatMap(manifestCatalogMaps)
|
|
2106
|
-
];
|
|
2107
|
-
for (const { name: catalog, map } of catalogs) {
|
|
2108
|
-
const entries = specEntries(map);
|
|
2109
|
-
const names = new Set(entries.map((entry) => entry.name));
|
|
2110
|
-
for (const { name, spec } of entries) {
|
|
2111
|
-
defined.add(catalog, name);
|
|
2112
|
-
const to = PACKAGE_RENAMES.get(name);
|
|
2113
|
-
const stays = spec === void 0 || inUse.has(catalog, name);
|
|
2114
|
-
if (to !== void 0 && !names.has(to) && stays) {
|
|
2115
|
-
kept.add(catalog, name);
|
|
2116
|
-
}
|
|
2117
|
-
}
|
|
2118
|
-
}
|
|
2119
|
-
return { inUse, kept, defined, isWorkspaceRoot };
|
|
2021
|
+
function referencedProjectPath(fromPath, reference) {
|
|
2022
|
+
const isOutside = URL_SCHEME.test(reference) || reference.startsWith(SEPARATOR);
|
|
2023
|
+
const path = isOutside ? void 0 : resolvedPath(fromPath, reference);
|
|
2024
|
+
return path === "" ? void 0 : path;
|
|
2120
2025
|
}
|
|
2121
2026
|
|
|
2122
|
-
const
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2027
|
+
const API_DESCRIPTION_KEYS = [
|
|
2028
|
+
"openapi",
|
|
2029
|
+
"swagger",
|
|
2030
|
+
"asyncapi",
|
|
2031
|
+
"overlay",
|
|
2032
|
+
"arazzo"
|
|
2033
|
+
];
|
|
2034
|
+
const API_DESCRIPTION_KEY_SET = new Set(API_DESCRIPTION_KEYS);
|
|
2035
|
+
const DESCRIPTION_KEY_LINE_RE = new RegExp(
|
|
2036
|
+
`^[ \\t{]*["']?(?:${API_DESCRIPTION_KEYS.join("|")})["']?[ \\t]*:`,
|
|
2037
|
+
"m"
|
|
2127
2038
|
);
|
|
2128
|
-
const
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
const original = ORIGINAL_NAMES.get(name);
|
|
2140
|
-
const containing = manifests.filter(({ path }) => filePath.startsWith(directoryOf(path)));
|
|
2141
|
-
const declares = ({ names }) => names === void 0 || names.has(name) || original !== void 0 && names.has(original);
|
|
2142
|
-
return containing.length === 0 || containing.some(declares);
|
|
2143
|
-
}
|
|
2144
|
-
const packageOfSpecifier = (specifier) => {
|
|
2145
|
-
const slash = specifier.indexOf(PATH_SEPARATOR$6);
|
|
2146
|
-
return slash === -1 ? specifier : specifier.slice(0, slash);
|
|
2147
|
-
};
|
|
2148
|
-
function undeclaredImportSteps(imports, filePath, manifests) {
|
|
2149
|
-
return imports.flatMap(({ specifier, line }) => {
|
|
2150
|
-
const name = packageOfSpecifier(specifier);
|
|
2151
|
-
const installers = NO_LONGER_INSTALLED.get(name);
|
|
2152
|
-
return installers === void 0 || isDeclaredFor(manifests, filePath, name) ? [] : [{ kind: "package-not-declared", line, name, installers }];
|
|
2039
|
+
const mayBeApiDescription = (text) => DESCRIPTION_KEY_LINE_RE.test(text);
|
|
2040
|
+
const isApiDescription = (documents) => documents.some(
|
|
2041
|
+
(root) => isMap(root) && textEntries(root).some(({ key }) => API_DESCRIPTION_KEY_SET.has(key.value))
|
|
2042
|
+
);
|
|
2043
|
+
const REF_KEY = "$ref";
|
|
2044
|
+
const FRAGMENT_START = "#";
|
|
2045
|
+
function referencedFiles(path, documents) {
|
|
2046
|
+
return documentStrings(documents).filter((string) => string.path.at(-1) === REF_KEY).flatMap(({ value }) => {
|
|
2047
|
+
const file = value.split(FRAGMENT_START)[0] ?? "";
|
|
2048
|
+
const referenced = referencedProjectPath(path, file);
|
|
2049
|
+
return referenced === void 0 ? [] : [referenced];
|
|
2153
2050
|
});
|
|
2154
2051
|
}
|
|
2155
2052
|
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
const
|
|
2168
|
-
const
|
|
2169
|
-
|
|
2170
|
-
);
|
|
2171
|
-
const NUMBER_RE = /^\d+$/;
|
|
2172
|
-
const OPERATOR_STYLES = {
|
|
2173
|
-
"^": "^",
|
|
2174
|
-
// `>=` means "this or newer"; with a new package line, a caret range says the same safely.
|
|
2175
|
-
">=": "^",
|
|
2176
|
-
">": "^",
|
|
2177
|
-
"~": "~",
|
|
2178
|
-
"~>": "~"
|
|
2179
|
-
};
|
|
2180
|
-
const isNumber = (part) => part !== void 0 && NUMBER_RE.test(part);
|
|
2181
|
-
function versionStyle(major, minor, patch) {
|
|
2182
|
-
if (!isNumber(major)) {
|
|
2183
|
-
return void 0;
|
|
2184
|
-
}
|
|
2185
|
-
if (isNumber(minor) && isNumber(patch)) {
|
|
2186
|
-
return "";
|
|
2187
|
-
}
|
|
2188
|
-
return isNumber(minor) ? "~" : "^";
|
|
2189
|
-
}
|
|
2190
|
-
function rangeStyle(spec) {
|
|
2191
|
-
const sets = spec.replace(SPACED_OPERATOR_RE, "$1").split(RANGE_SEPARATOR);
|
|
2192
|
-
const tokens = sets.map((set) => set.trim().split(WHITE_SPACE_RE));
|
|
2193
|
-
const comparators = tokens.flat().filter((token) => token !== HYPHEN);
|
|
2194
|
-
const matches = comparators.map((comparator) => COMPARATOR_RE.exec(comparator));
|
|
2195
|
-
const first = matches[0];
|
|
2196
|
-
if (first === void 0 || first === null || matches.includes(null)) {
|
|
2197
|
-
return void 0;
|
|
2198
|
-
}
|
|
2199
|
-
const operator = first[1];
|
|
2200
|
-
const isHyphenRange = tokens[0]?.[1] === HYPHEN;
|
|
2201
|
-
if (operator !== void 0 && operator !== "=") {
|
|
2202
|
-
return OPERATOR_STYLES[operator];
|
|
2203
|
-
}
|
|
2204
|
-
return isHyphenRange ? "^" : versionStyle(first[2], first[3], first[4]);
|
|
2205
|
-
}
|
|
2206
|
-
function migrateVersionSpec(spec, version) {
|
|
2207
|
-
if (KEPT_PROTOCOLS.some((protocol) => spec.startsWith(protocol))) {
|
|
2208
|
-
return { kind: "kept", spec, isReported: false };
|
|
2209
|
-
}
|
|
2210
|
-
const style = rangeStyle(spec);
|
|
2211
|
-
if (style === void 0) {
|
|
2212
|
-
return { kind: "kept", spec, isReported: true };
|
|
2213
|
-
}
|
|
2214
|
-
return { kind: "replaced", spec: `${style}${version}` };
|
|
2215
|
-
}
|
|
2216
|
-
|
|
2217
|
-
const NPM_PROTOCOL = "npm:";
|
|
2218
|
-
const SCOPE_PREFIX$1 = "@";
|
|
2219
|
-
const PATH_SEPARATOR$5 = "/";
|
|
2220
|
-
const VERSION_SEPARATOR = "@";
|
|
2221
|
-
function nameEnd(text) {
|
|
2222
|
-
const searchFrom = text.startsWith(SCOPE_PREFIX$1) ? text.indexOf(PATH_SEPARATOR$5) + 1 : 0;
|
|
2223
|
-
const ends = [VERSION_SEPARATOR, PATH_SEPARATOR$5].map((separator) => text.indexOf(separator, Math.max(searchFrom, 1))).filter((index) => index !== -1);
|
|
2224
|
-
return ends.length === 0 ? text.length : Math.min(...ends);
|
|
2225
|
-
}
|
|
2226
|
-
function parseNpmSpec(spec) {
|
|
2227
|
-
if (!spec.startsWith(NPM_PROTOCOL)) {
|
|
2228
|
-
return void 0;
|
|
2229
|
-
}
|
|
2230
|
-
const body = spec.slice(NPM_PROTOCOL.length);
|
|
2231
|
-
const lead = body.startsWith(PATH_SEPARATOR$5) ? PATH_SEPARATOR$5 : "";
|
|
2232
|
-
const text = body.slice(lead.length);
|
|
2233
|
-
const end = nameEnd(text);
|
|
2234
|
-
const name = text.slice(0, end);
|
|
2235
|
-
if (!text.startsWith(VERSION_SEPARATOR, end)) {
|
|
2236
|
-
return { lead, name, range: void 0, rest: text.slice(end) };
|
|
2237
|
-
}
|
|
2238
|
-
const rangeEnd = text.indexOf(PATH_SEPARATOR$5, end);
|
|
2239
|
-
const restStart = rangeEnd === -1 ? text.length : rangeEnd;
|
|
2240
|
-
return { lead, name, range: text.slice(end + 1, restStart), rest: text.slice(restStart) };
|
|
2241
|
-
}
|
|
2242
|
-
function isOldPackageNpmSpec(spec) {
|
|
2243
|
-
const parsed = parseNpmSpec(spec);
|
|
2244
|
-
return parsed !== void 0 && PACKAGE_RENAMES.has(parsed.name);
|
|
2245
|
-
}
|
|
2246
|
-
function migrateNpmSpec(spec, version) {
|
|
2247
|
-
const parsed = parseNpmSpec(spec);
|
|
2248
|
-
const renamed = parsed === void 0 ? void 0 : PACKAGE_RENAMES.get(parsed.name);
|
|
2249
|
-
if (parsed === void 0 || renamed === void 0) {
|
|
2250
|
-
return void 0;
|
|
2251
|
-
}
|
|
2252
|
-
const head = `${NPM_PROTOCOL}${parsed.lead}${renamed}`;
|
|
2253
|
-
const isDeep = parsed.rest !== "" && parsed.rest !== PATH_SEPARATOR$5;
|
|
2254
|
-
if (parsed.range === void 0) {
|
|
2255
|
-
return { spec: `${head}${parsed.rest}`, isReported: false, isDeep };
|
|
2256
|
-
}
|
|
2257
|
-
const decision = migrateVersionSpec(parsed.range, version);
|
|
2258
|
-
const isReported = decision.kind === "kept" && decision.isReported;
|
|
2259
|
-
const migrated = `${head}${VERSION_SEPARATOR}${decision.spec}${parsed.rest}`;
|
|
2260
|
-
return { spec: migrated, isReported, isDeep };
|
|
2261
|
-
}
|
|
2262
|
-
|
|
2263
|
-
const SCHEME_SEPARATOR = "://";
|
|
2264
|
-
const HIDDEN_USERINFO = "***";
|
|
2265
|
-
const USERINFO_END = "@";
|
|
2266
|
-
const AUTHORITY_END_RE = /[/?#"'`\s]/;
|
|
2267
|
-
function scanAuthority(text, start) {
|
|
2268
|
-
let userinfoEnd = -1;
|
|
2269
|
-
let end = start;
|
|
2270
|
-
for (; end < text.length && !AUTHORITY_END_RE.test(text.charAt(end)); end++) {
|
|
2271
|
-
if (text.charAt(end) === USERINFO_END) {
|
|
2272
|
-
userinfoEnd = end;
|
|
2273
|
-
}
|
|
2274
|
-
}
|
|
2275
|
-
return { end, userinfoEnd };
|
|
2276
|
-
}
|
|
2277
|
-
function hideUrlCredentials(text) {
|
|
2278
|
-
let hidden = "";
|
|
2279
|
-
let copiedUpTo = 0;
|
|
2280
|
-
for (let found = text.indexOf(SCHEME_SEPARATOR); found !== -1; ) {
|
|
2281
|
-
const start = found + SCHEME_SEPARATOR.length;
|
|
2282
|
-
const { end, userinfoEnd } = scanAuthority(text, start);
|
|
2283
|
-
if (userinfoEnd !== -1) {
|
|
2284
|
-
hidden += `${text.slice(copiedUpTo, start)}${HIDDEN_USERINFO}`;
|
|
2285
|
-
copiedUpTo = userinfoEnd;
|
|
2286
|
-
}
|
|
2287
|
-
found = text.indexOf(SCHEME_SEPARATOR, end);
|
|
2288
|
-
}
|
|
2289
|
-
return `${hidden}${text.slice(copiedUpTo)}`;
|
|
2290
|
-
}
|
|
2291
|
-
|
|
2292
|
-
const newFindings = () => ({ edits: [], changes: [], manualSteps: [] });
|
|
2293
|
-
const PEER_FIELD = "peerDependencies";
|
|
2294
|
-
const mapLabel = (map) => map.kind === "catalog" ? map.catalog : map.field;
|
|
2295
|
-
const renamedKey = (name, map) => map.kind === "imports" ? renamedSpecifier(name)?.to : PACKAGE_RENAMES.get(name);
|
|
2296
|
-
function migrateSpec(spec, version) {
|
|
2297
|
-
const npm = migrateNpmSpec(spec, version);
|
|
2298
|
-
if (npm !== void 0) {
|
|
2299
|
-
return { spec: npm.spec, isReported: npm.isReported };
|
|
2300
|
-
}
|
|
2301
|
-
const decision = migrateVersionSpec(spec, version);
|
|
2302
|
-
return { spec: decision.spec, isReported: decision.kind === "kept" && decision.isReported };
|
|
2303
|
-
}
|
|
2304
|
-
function isFree({ from, to, field, names }, findings) {
|
|
2305
|
-
if (names.has(to)) {
|
|
2306
|
-
findings.manualSteps.push({ kind: "name-collision", field, from, to });
|
|
2307
|
-
return false;
|
|
2308
|
-
}
|
|
2309
|
-
return true;
|
|
2310
|
-
}
|
|
2311
|
-
function migrateAlias(entry, { map, version, findings }) {
|
|
2312
|
-
const migrated = entry.spec === void 0 ? void 0 : migrateNpmSpec(entry.spec.value, version);
|
|
2313
|
-
if (entry.spec === void 0 || migrated === void 0) {
|
|
2314
|
-
return;
|
|
2315
|
-
}
|
|
2316
|
-
findings.edits.push(entry.spec.replace(migrated.spec));
|
|
2317
|
-
const spec = hideUrlCredentials(migrated.spec);
|
|
2318
|
-
findings.changes.push({ kind: "alias-renamed", field: mapLabel(map), name: entry.name, spec });
|
|
2319
|
-
if (migrated.isReported) {
|
|
2320
|
-
findings.manualSteps.push({ kind: "spec-kept", name: entry.name, spec });
|
|
2321
|
-
}
|
|
2322
|
-
}
|
|
2323
|
-
function renamedChange(map, from, to, spec) {
|
|
2324
|
-
switch (map.kind) {
|
|
2325
|
-
case "dependencies":
|
|
2326
|
-
return { kind: "dependency-renamed", field: map.field, from, to, spec };
|
|
2327
|
-
case "catalog":
|
|
2328
|
-
return { kind: "catalog-entry-renamed", catalog: map.catalog, from, to, spec };
|
|
2329
|
-
case "imports":
|
|
2330
|
-
return { kind: "import-renamed", field: map.field, from, to, target: spec };
|
|
2331
|
-
default:
|
|
2332
|
-
return assertNever(map);
|
|
2333
|
-
}
|
|
2334
|
-
}
|
|
2335
|
-
function migrateEntry(entry, spec, to, { map, version, findings }) {
|
|
2336
|
-
const old = spec.value;
|
|
2337
|
-
const migrated = migrateSpec(old, version);
|
|
2338
|
-
findings.edits.push(entry.renameKey(to));
|
|
2339
|
-
if (migrated.spec !== old) {
|
|
2340
|
-
findings.edits.push(spec.replace(migrated.spec));
|
|
2341
|
-
}
|
|
2342
|
-
findings.changes.push(renamedChange(map, entry.name, to, hideUrlCredentials(migrated.spec)));
|
|
2343
|
-
if (migrated.isReported) {
|
|
2344
|
-
findings.manualSteps.push({ kind: "spec-kept", name: to, spec: hideUrlCredentials(old) });
|
|
2345
|
-
}
|
|
2346
|
-
if (map.kind === "dependencies" && map.field === PEER_FIELD) {
|
|
2347
|
-
findings.manualSteps.push({ kind: "peer-dependency-renamed", name: to });
|
|
2348
|
-
}
|
|
2349
|
-
}
|
|
2350
|
-
function catalogHold(entry, spec, { map, catalogs }) {
|
|
2351
|
-
if (map.kind === "catalog") {
|
|
2352
|
-
const isInUse = catalogs.inUse.has(map.name, entry.name);
|
|
2353
|
-
return isInUse ? { kind: "catalog-entry-in-use", catalog: map.catalog, name: entry.name } : void 0;
|
|
2354
|
-
}
|
|
2355
|
-
const catalog = map.kind === "dependencies" ? catalogOfSpec(spec.value) : void 0;
|
|
2356
|
-
if (catalog === void 0) {
|
|
2357
|
-
return void 0;
|
|
2358
|
-
}
|
|
2359
|
-
const reference = { field: mapLabel(map), name: entry.name, catalog };
|
|
2360
|
-
if (!catalogs.defined.has(catalog, entry.name)) {
|
|
2361
|
-
const kind = catalogs.isWorkspaceRoot ? "catalog-entry-missing" : "catalog-entry-outside";
|
|
2362
|
-
return { kind, ...reference };
|
|
2363
|
-
}
|
|
2364
|
-
return catalogs.kept.has(catalog, entry.name) ? { kind: "catalog-reference-kept", ...reference } : void 0;
|
|
2365
|
-
}
|
|
2366
|
-
function migrateSpecMap(entries, context) {
|
|
2367
|
-
const names = new Set(entries.map((entry) => entry.name));
|
|
2368
|
-
for (const entry of entries) {
|
|
2369
|
-
const to = renamedKey(entry.name, context.map);
|
|
2370
|
-
const field = mapLabel(context.map);
|
|
2371
|
-
if (to === void 0) {
|
|
2372
|
-
migrateAlias(entry, context);
|
|
2373
|
-
continue;
|
|
2374
|
-
}
|
|
2375
|
-
if (!isFree({ from: entry.name, to, field, names }, context.findings)) {
|
|
2376
|
-
continue;
|
|
2377
|
-
}
|
|
2378
|
-
const hold = entry.spec === void 0 ? void 0 : catalogHold(entry, entry.spec, context);
|
|
2379
|
-
if (entry.spec === void 0) {
|
|
2380
|
-
context.findings.manualSteps.push({ kind: "entry-not-edited", field, name: entry.name });
|
|
2381
|
-
} else if (hold !== void 0) {
|
|
2382
|
-
context.findings.manualSteps.push(hold);
|
|
2383
|
-
} else {
|
|
2384
|
-
migrateEntry(entry, entry.spec, to, context);
|
|
2385
|
-
}
|
|
2386
|
-
}
|
|
2387
|
-
}
|
|
2388
|
-
function renameNames(entries, field, findings) {
|
|
2389
|
-
const names = new Set(entries.map((entry) => entry.name));
|
|
2390
|
-
for (const entry of entries) {
|
|
2391
|
-
const to = PACKAGE_RENAMES.get(entry.name);
|
|
2392
|
-
if (to !== void 0 && isFree({ from: entry.name, to, field, names }, findings)) {
|
|
2393
|
-
findings.edits.push(entry.rename(to));
|
|
2394
|
-
findings.changes.push({
|
|
2395
|
-
kind: "package-name-renamed",
|
|
2396
|
-
location: field,
|
|
2397
|
-
from: entry.name,
|
|
2398
|
-
to
|
|
2399
|
-
});
|
|
2400
|
-
}
|
|
2401
|
-
}
|
|
2402
|
-
}
|
|
2403
|
-
|
|
2404
|
-
const IMPORTS_FIELD$1 = "imports";
|
|
2405
|
-
const SCOPES_FIELD = "scopes";
|
|
2406
|
-
const FIELD_SEPARATOR$2 = ".";
|
|
2407
|
-
function migrateImports(config, version, findings) {
|
|
2408
|
-
for (const imports of mapsAt(config, IMPORTS_FIELD$1)) {
|
|
2409
|
-
const map = { kind: "imports", field: IMPORTS_FIELD$1 };
|
|
2410
|
-
migrateSpecMap(specEntries(imports), { map, version, findings, catalogs: NO_CATALOG_PLAN });
|
|
2411
|
-
}
|
|
2412
|
-
for (const scopes of mapsAt(config, SCOPES_FIELD)) {
|
|
2413
|
-
for (const { key, value } of textEntries(scopes)) {
|
|
2414
|
-
if (isMap(value)) {
|
|
2415
|
-
const field = [SCOPES_FIELD, key.value].join(FIELD_SEPARATOR$2);
|
|
2416
|
-
const map = { kind: "imports", field };
|
|
2417
|
-
migrateSpecMap(specEntries(value), { map, version, findings, catalogs: NO_CATALOG_PLAN });
|
|
2418
|
-
}
|
|
2419
|
-
}
|
|
2420
|
-
}
|
|
2421
|
-
}
|
|
2422
|
-
const PATH_SEPARATOR$4 = "/";
|
|
2423
|
-
const SCOPE_PREFIX = "@";
|
|
2424
|
-
function importMapKeys(config) {
|
|
2425
|
-
const scoped = mapsAt(config, SCOPES_FIELD).flatMap(textEntries).flatMap(({ value }) => isMap(value) ? [value] : []);
|
|
2426
|
-
return [...mapsAt(config, IMPORTS_FIELD$1), ...scoped].flatMap(textEntries).map(({ key }) => key.value);
|
|
2427
|
-
}
|
|
2428
|
-
function importMapNames(config) {
|
|
2429
|
-
return importMapKeys(config).map((key) => {
|
|
2430
|
-
const parts = key.split(PATH_SEPARATOR$4);
|
|
2431
|
-
return key.startsWith(SCOPE_PREFIX) ? parts.slice(0, 2).join(PATH_SEPARATOR$4) : parts[0] ?? key;
|
|
2432
|
-
});
|
|
2433
|
-
}
|
|
2434
|
-
function migrateImportMap(text, read, version) {
|
|
2435
|
-
if (read.kind === "unreadable") {
|
|
2436
|
-
return unreadableConfig(text, read.offset);
|
|
2437
|
-
}
|
|
2438
|
-
const findings = newFindings();
|
|
2439
|
-
for (const config of read.documents.filter(isMap)) {
|
|
2440
|
-
migrateImports(config, version, findings);
|
|
2441
|
-
}
|
|
2442
|
-
const { edits, changes, manualSteps } = findings;
|
|
2443
|
-
return { text: applyTextEdits(text, edits), changes, manualSteps };
|
|
2444
|
-
}
|
|
2445
|
-
|
|
2446
|
-
const NONE = /* @__PURE__ */ new Set();
|
|
2447
|
-
const PACKAGE_OPTIONS = /* @__PURE__ */ new Set(["-p", "--package"]);
|
|
2448
|
-
const PACKAGE_MANAGER_OPTIONS = /* @__PURE__ */ new Set([
|
|
2449
|
-
"--filter",
|
|
2450
|
-
"-F",
|
|
2451
|
-
"--dir",
|
|
2452
|
-
"-C",
|
|
2453
|
-
"--prefix",
|
|
2454
|
-
"--cwd",
|
|
2455
|
-
"--workspace"
|
|
2456
|
-
]);
|
|
2457
|
-
const launcher = (words, packageOptions = NONE, valueOptions = NONE) => {
|
|
2458
|
-
const allValueOptions = /* @__PURE__ */ new Set([...valueOptions, ...packageOptions]);
|
|
2459
|
-
return { words, packageOptions, valueOptions: allValueOptions, operands: 0 };
|
|
2053
|
+
const NONE = /* @__PURE__ */ new Set();
|
|
2054
|
+
const PACKAGE_OPTIONS = /* @__PURE__ */ new Set(["-p", "--package"]);
|
|
2055
|
+
const PACKAGE_MANAGER_OPTIONS = /* @__PURE__ */ new Set([
|
|
2056
|
+
"--filter",
|
|
2057
|
+
"-F",
|
|
2058
|
+
"--dir",
|
|
2059
|
+
"-C",
|
|
2060
|
+
"--prefix",
|
|
2061
|
+
"--cwd",
|
|
2062
|
+
"--workspace"
|
|
2063
|
+
]);
|
|
2064
|
+
const launcher = (words, packageOptions = NONE, valueOptions = NONE) => {
|
|
2065
|
+
const allValueOptions = /* @__PURE__ */ new Set([...valueOptions, ...packageOptions]);
|
|
2066
|
+
return { words, packageOptions, valueOptions: allValueOptions, operands: 0 };
|
|
2460
2067
|
};
|
|
2461
2068
|
const CONTAINER_OPTIONS = /* @__PURE__ */ new Set([
|
|
2462
2069
|
"-e",
|
|
@@ -2576,12 +2183,182 @@ const INSTALLERS = [
|
|
|
2576
2183
|
];
|
|
2577
2184
|
const NPM_SPECIFIER_PREFIX = "npm:";
|
|
2578
2185
|
|
|
2579
|
-
const
|
|
2186
|
+
const COMMAND_SEPARATORS = /* @__PURE__ */ new Set([
|
|
2187
|
+
";",
|
|
2188
|
+
"&",
|
|
2189
|
+
"|",
|
|
2190
|
+
"(",
|
|
2191
|
+
")",
|
|
2192
|
+
"`",
|
|
2193
|
+
"\n"
|
|
2194
|
+
]);
|
|
2195
|
+
const WORD_BREAKS = /* @__PURE__ */ new Set([" ", " ", "\r", "<", ">"]);
|
|
2196
|
+
const BACKSLASH$2 = "\\";
|
|
2197
|
+
const DOUBLE_QUOTE_ESCAPES = /* @__PURE__ */ new Set(["$", "`", '"', BACKSLASH$2, "\n"]);
|
|
2198
|
+
function singleQuoted(text, start) {
|
|
2199
|
+
const close = text.indexOf("'", start + 1);
|
|
2200
|
+
const end = close === -1 ? text.length : close + 1;
|
|
2201
|
+
return { end, value: text.slice(start + 1, close === -1 ? text.length : close) };
|
|
2202
|
+
}
|
|
2203
|
+
function doubleQuoted(text, start) {
|
|
2204
|
+
let value = "";
|
|
2205
|
+
let index = start + 1;
|
|
2206
|
+
while (index < text.length && text[index] !== '"') {
|
|
2207
|
+
const next = text[index + 1] ?? "";
|
|
2208
|
+
const isEscape = text[index] === BACKSLASH$2 && DOUBLE_QUOTE_ESCAPES.has(next);
|
|
2209
|
+
value += isEscape ? next === "\n" ? "" : next : text[index];
|
|
2210
|
+
index += isEscape ? 2 : 1;
|
|
2211
|
+
}
|
|
2212
|
+
return { end: Math.min(index + 1, text.length), value };
|
|
2213
|
+
}
|
|
2214
|
+
const isLineContinuation = (text, index) => text[index] === BACKSLASH$2 && (text[index + 1] === "\n" || text.startsWith("\r\n", index + 1));
|
|
2215
|
+
const ARITHMETIC_OPEN = "$((";
|
|
2216
|
+
const NESTING_OPEN = "(";
|
|
2217
|
+
const NESTING_CLOSE = ")";
|
|
2218
|
+
const ARITHMETIC_DEPTH = 2;
|
|
2219
|
+
function arithmeticExpansion(text, start) {
|
|
2220
|
+
let depth = ARITHMETIC_DEPTH;
|
|
2221
|
+
for (let index = start + ARITHMETIC_OPEN.length; index < text.length; index++) {
|
|
2222
|
+
depth += text[index] === NESTING_OPEN ? 1 : text[index] === NESTING_CLOSE ? -1 : 0;
|
|
2223
|
+
if (depth === 0) {
|
|
2224
|
+
return { end: index + 1, value: text.slice(start, index + 1) };
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
return void 0;
|
|
2228
|
+
}
|
|
2229
|
+
const PARAMETER_OPEN = "${";
|
|
2230
|
+
const PARAMETER_CLOSE = "}";
|
|
2231
|
+
function parameterExpansionEnd(text, start) {
|
|
2232
|
+
let depth = 1;
|
|
2233
|
+
for (let index = start + PARAMETER_OPEN.length; index < text.length; ) {
|
|
2234
|
+
if (text.startsWith(PARAMETER_OPEN, index)) {
|
|
2235
|
+
depth += 1;
|
|
2236
|
+
index += PARAMETER_OPEN.length;
|
|
2237
|
+
} else if (text[index] === PARAMETER_CLOSE) {
|
|
2238
|
+
depth -= 1;
|
|
2239
|
+
index += 1;
|
|
2240
|
+
if (depth === 0) {
|
|
2241
|
+
return index;
|
|
2242
|
+
}
|
|
2243
|
+
} else {
|
|
2244
|
+
index = quotedOrEscapedEnd(text, index) ?? index + 1;
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
return void 0;
|
|
2248
|
+
}
|
|
2249
|
+
function quotedOrEscapedEnd(text, index) {
|
|
2250
|
+
const char = text[index];
|
|
2251
|
+
if (char === "'") {
|
|
2252
|
+
return singleQuoted(text, index).end;
|
|
2253
|
+
}
|
|
2254
|
+
if (char === '"') {
|
|
2255
|
+
return doubleQuoted(text, index).end;
|
|
2256
|
+
}
|
|
2257
|
+
return char === BACKSLASH$2 ? index + 2 : void 0;
|
|
2258
|
+
}
|
|
2259
|
+
function expansionPart(text, index) {
|
|
2260
|
+
if (text.startsWith(ARITHMETIC_OPEN, index)) {
|
|
2261
|
+
return arithmeticExpansion(text, index);
|
|
2262
|
+
}
|
|
2263
|
+
const end = text.startsWith(PARAMETER_OPEN, index) ? parameterExpansionEnd(text, index) : void 0;
|
|
2264
|
+
return end === void 0 ? void 0 : { end, value: text.slice(index, end) };
|
|
2265
|
+
}
|
|
2266
|
+
function wordPart(text, index) {
|
|
2267
|
+
const char = text[index];
|
|
2268
|
+
const expansion = expansionPart(text, index);
|
|
2269
|
+
if (expansion !== void 0) {
|
|
2270
|
+
return expansion;
|
|
2271
|
+
}
|
|
2272
|
+
if (char === "'") {
|
|
2273
|
+
return singleQuoted(text, index);
|
|
2274
|
+
}
|
|
2275
|
+
if (char === '"') {
|
|
2276
|
+
return doubleQuoted(text, index);
|
|
2277
|
+
}
|
|
2278
|
+
if (char === BACKSLASH$2 && index + 1 < text.length) {
|
|
2279
|
+
return { end: index + 2, value: text[index + 1] };
|
|
2280
|
+
}
|
|
2281
|
+
return { end: index + 1, value: char };
|
|
2282
|
+
}
|
|
2283
|
+
const ARRAY_HEAD_RE = /^[A-Za-z_][A-Za-z0-9_]*\+?=$/;
|
|
2284
|
+
function arrayListEnd(text, index) {
|
|
2285
|
+
let depth = 0;
|
|
2286
|
+
for (let at = index; at < text.length; ) {
|
|
2287
|
+
depth += text[at] === NESTING_OPEN ? 1 : text[at] === NESTING_CLOSE ? -1 : 0;
|
|
2288
|
+
if (depth === 0) {
|
|
2289
|
+
return at + 1;
|
|
2290
|
+
}
|
|
2291
|
+
at = quotedOrEscapedEnd(text, at) ?? at + 1;
|
|
2292
|
+
}
|
|
2293
|
+
return void 0;
|
|
2294
|
+
}
|
|
2295
|
+
const endsWord = (text, index) => {
|
|
2296
|
+
const char = text[index];
|
|
2297
|
+
return WORD_BREAKS.has(char) || COMMAND_SEPARATORS.has(char) || isLineContinuation(text, index);
|
|
2298
|
+
};
|
|
2299
|
+
function readWord(text, start) {
|
|
2300
|
+
let value = "";
|
|
2301
|
+
let index = start;
|
|
2302
|
+
while (index < text.length) {
|
|
2303
|
+
const isArrayList = text[index] === NESTING_OPEN && ARRAY_HEAD_RE.test(text.slice(start, index));
|
|
2304
|
+
const list = isArrayList ? arrayListEnd(text, index) : void 0;
|
|
2305
|
+
if (list === void 0 && endsWord(text, index)) {
|
|
2306
|
+
break;
|
|
2307
|
+
}
|
|
2308
|
+
const part = list === void 0 ? wordPart(text, index) : { end: list, value: text.slice(index, list) };
|
|
2309
|
+
value += part.value;
|
|
2310
|
+
index = part.end;
|
|
2311
|
+
}
|
|
2312
|
+
return { start, end: index, value, raw: text.slice(start, index) };
|
|
2313
|
+
}
|
|
2314
|
+
|
|
2315
|
+
const ASSIGNMENT_RE$2 = /^([A-Za-z_][A-Za-z0-9_]*)=/;
|
|
2316
|
+
const DECLARATION_BUILTINS = /* @__PURE__ */ new Set([
|
|
2317
|
+
"export",
|
|
2318
|
+
"readonly",
|
|
2319
|
+
"local",
|
|
2320
|
+
"declare",
|
|
2321
|
+
"typeset"
|
|
2322
|
+
]);
|
|
2323
|
+
const QUOTES$3 = /* @__PURE__ */ new Set(["'", '"']);
|
|
2324
|
+
const UNPLAIN_RE = /['"\\$`]/;
|
|
2325
|
+
function leadingAssignments(command) {
|
|
2326
|
+
const index = command.findIndex((word) => !ASSIGNMENT_RE$2.test(word.raw));
|
|
2327
|
+
return index === -1 ? command.length : index;
|
|
2328
|
+
}
|
|
2329
|
+
function shellAssignments(command) {
|
|
2330
|
+
const count = leadingAssignments(command);
|
|
2331
|
+
const isDeclaration = DECLARATION_BUILTINS.has(command[count]?.value ?? "");
|
|
2332
|
+
const words = [...command.slice(0, count), ...isDeclaration ? command.slice(count + 1) : []];
|
|
2333
|
+
return words.flatMap((word) => {
|
|
2334
|
+
const match = ASSIGNMENT_RE$2.exec(word.raw);
|
|
2335
|
+
const name = match?.[1];
|
|
2336
|
+
return name === void 0 ? [] : [{ name, value: word.value.slice(name.length + 1), word }];
|
|
2337
|
+
});
|
|
2338
|
+
}
|
|
2339
|
+
const ARRAY_OPEN = "(";
|
|
2340
|
+
const ARRAY_CLOSE = ")";
|
|
2341
|
+
const isArrayAssignment = (assignment) => assignment.word.raw.startsWith(ARRAY_OPEN, assignment.name.length + 1);
|
|
2342
|
+
function assignmentValueText(assignment) {
|
|
2343
|
+
const at = assignment.name.length + 1;
|
|
2344
|
+
const raw = assignment.word.raw.slice(at);
|
|
2345
|
+
const start = assignment.word.start + at;
|
|
2346
|
+
const quote = raw[0] ?? "";
|
|
2347
|
+
if (isArrayAssignment(assignment)) {
|
|
2348
|
+
return raw.endsWith(ARRAY_CLOSE) ? { text: raw.slice(1, -1), start: start + 1 } : void 0;
|
|
2349
|
+
}
|
|
2350
|
+
if (QUOTES$3.has(quote)) {
|
|
2351
|
+
const isOneString = raw.length > 1 && raw.endsWith(quote) && wordPart(raw, 0).end === raw.length;
|
|
2352
|
+
return isOneString ? { text: raw.slice(1, -1), start: start + 1 } : void 0;
|
|
2353
|
+
}
|
|
2354
|
+
return UNPLAIN_RE.test(raw) ? void 0 : { text: raw, start };
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2580
2357
|
const END_OF_OPTIONS = "--";
|
|
2581
2358
|
const isOption$1 = (word) => word.value.startsWith("-") && word.value.length > 1;
|
|
2582
2359
|
function skipAssignments(words, start) {
|
|
2583
2360
|
let index = start;
|
|
2584
|
-
while (index < words.length && ASSIGNMENT_RE$
|
|
2361
|
+
while (index < words.length && ASSIGNMENT_RE$2.test(words[index].raw)) {
|
|
2585
2362
|
index++;
|
|
2586
2363
|
}
|
|
2587
2364
|
return index;
|
|
@@ -2653,85 +2430,81 @@ function unmigratedWordFindings(words, handledOffsets, locate) {
|
|
|
2653
2430
|
}));
|
|
2654
2431
|
}
|
|
2655
2432
|
|
|
2656
|
-
const
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
")",
|
|
2662
|
-
"`",
|
|
2663
|
-
"\n"
|
|
2664
|
-
]);
|
|
2665
|
-
const WORD_BREAKS = /* @__PURE__ */ new Set([" ", " ", "\r", "<", ">"]);
|
|
2666
|
-
const BACKSLASH$1 = "\\";
|
|
2667
|
-
const DOUBLE_QUOTE_ESCAPES = /* @__PURE__ */ new Set(["$", "`", '"', BACKSLASH$1, "\n"]);
|
|
2668
|
-
function singleQuoted(text, start) {
|
|
2669
|
-
const close = text.indexOf("'", start + 1);
|
|
2670
|
-
const end = close === -1 ? text.length : close + 1;
|
|
2671
|
-
return { end, value: text.slice(start + 1, close === -1 ? text.length : close) };
|
|
2672
|
-
}
|
|
2673
|
-
function doubleQuoted(text, start) {
|
|
2674
|
-
let value = "";
|
|
2675
|
-
let index = start + 1;
|
|
2676
|
-
while (index < text.length && text[index] !== '"') {
|
|
2677
|
-
const next = text[index + 1] ?? "";
|
|
2678
|
-
const isEscape = text[index] === BACKSLASH$1 && DOUBLE_QUOTE_ESCAPES.has(next);
|
|
2679
|
-
value += isEscape ? next === "\n" ? "" : next : text[index];
|
|
2680
|
-
index += isEscape ? 2 : 1;
|
|
2433
|
+
const RECIPE_PREFIX_RE$1 = /^[@+-]+(?=.)/;
|
|
2434
|
+
function withoutRecipePrefix(words) {
|
|
2435
|
+
const [first, ...rest] = words;
|
|
2436
|
+
if (first === void 0 || !RECIPE_PREFIX_RE$1.test(first.value)) {
|
|
2437
|
+
return words;
|
|
2681
2438
|
}
|
|
2682
|
-
return {
|
|
2439
|
+
return [{ ...first, value: first.value.replace(RECIPE_PREFIX_RE$1, "") }, ...rest];
|
|
2683
2440
|
}
|
|
2684
|
-
const
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
if (depth === 0) {
|
|
2694
|
-
return { end: index + 1, value: text.slice(start, index + 1) };
|
|
2695
|
-
}
|
|
2696
|
-
}
|
|
2697
|
-
return void 0;
|
|
2441
|
+
const NO_VARIABLES = {
|
|
2442
|
+
programAt: () => void 0,
|
|
2443
|
+
referenceAt: () => void 0
|
|
2444
|
+
};
|
|
2445
|
+
function runsGenerator(command) {
|
|
2446
|
+
const words = withoutRecipePrefix(command);
|
|
2447
|
+
const { program } = commandRoles(words);
|
|
2448
|
+
const word = program === void 0 ? void 0 : words[program];
|
|
2449
|
+
return word !== void 0 && packageReference(word.value).name === GENERATOR_COMMAND;
|
|
2698
2450
|
}
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
if (
|
|
2712
|
-
return
|
|
2451
|
+
|
|
2452
|
+
const EXPANSION_HEAD_RE = /^\$\{([A-Za-z_][A-Za-z0-9_]*):?([-=+])/;
|
|
2453
|
+
const USES = {
|
|
2454
|
+
"-": "default",
|
|
2455
|
+
"=": "assign",
|
|
2456
|
+
"+": "alternative"
|
|
2457
|
+
};
|
|
2458
|
+
const SINGLE_QUOTE = "'";
|
|
2459
|
+
const BACKSLASH$1 = "\\";
|
|
2460
|
+
function expansionAt(text, start) {
|
|
2461
|
+
const head = EXPANSION_HEAD_RE.exec(text.slice(start));
|
|
2462
|
+
const end = head === null ? void 0 : parameterExpansionEnd(text, start);
|
|
2463
|
+
if (head === null || end === void 0) {
|
|
2464
|
+
return void 0;
|
|
2713
2465
|
}
|
|
2714
|
-
|
|
2466
|
+
const wordStart = start + head[0].length;
|
|
2467
|
+
return {
|
|
2468
|
+
name: head[1],
|
|
2469
|
+
use: USES[head[2]],
|
|
2470
|
+
text: text.slice(wordStart, end - 1),
|
|
2471
|
+
start: wordStart,
|
|
2472
|
+
expansionStart: start,
|
|
2473
|
+
expansionEnd: end
|
|
2474
|
+
};
|
|
2715
2475
|
}
|
|
2716
|
-
|
|
2717
|
-
const
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2476
|
+
function wordExpansions(raw) {
|
|
2477
|
+
const found = [];
|
|
2478
|
+
for (let index = 0; index < raw.length; ) {
|
|
2479
|
+
const char = raw[index];
|
|
2480
|
+
if (char === SINGLE_QUOTE) {
|
|
2481
|
+
const close = raw.indexOf(SINGLE_QUOTE, index + 1);
|
|
2482
|
+
index = close === -1 ? raw.length : close + 1;
|
|
2483
|
+
} else if (char === BACKSLASH$1) {
|
|
2484
|
+
index += 2;
|
|
2485
|
+
} else if (raw.startsWith(PARAMETER_OPEN, index)) {
|
|
2486
|
+
const expansion = expansionAt(raw, index);
|
|
2487
|
+
found.push(...expansion === void 0 ? [] : [expansion]);
|
|
2488
|
+
index = expansion?.expansionEnd ?? index + PARAMETER_OPEN.length;
|
|
2489
|
+
} else {
|
|
2490
|
+
index += 1;
|
|
2491
|
+
}
|
|
2727
2492
|
}
|
|
2728
|
-
return
|
|
2493
|
+
return found;
|
|
2494
|
+
}
|
|
2495
|
+
const DOUBLE_QUOTE = '"';
|
|
2496
|
+
function wholeWordExpansion(raw) {
|
|
2497
|
+
const isQuoted = raw.length > 1 && raw.startsWith(DOUBLE_QUOTE) && raw.endsWith(DOUBLE_QUOTE);
|
|
2498
|
+
const inner = isQuoted ? 1 : 0;
|
|
2499
|
+
const [expansion] = wordExpansions(raw);
|
|
2500
|
+
const isWhole = expansion?.expansionStart === inner && expansion.expansionEnd === raw.length - inner;
|
|
2501
|
+
return isWhole ? expansion : void 0;
|
|
2729
2502
|
}
|
|
2730
2503
|
|
|
2731
2504
|
const HEREDOC_OPERATOR = "<<";
|
|
2732
2505
|
const HERE_STRING_OPERATOR = "<<<";
|
|
2733
2506
|
const STRIP_TABS = "-";
|
|
2734
|
-
const LINE_BREAK$
|
|
2507
|
+
const LINE_BREAK$4 = "\n";
|
|
2735
2508
|
const LEADING_TABS_RE = /^\t+/;
|
|
2736
2509
|
const CARRIAGE_RETURN_RE = /\r$/;
|
|
2737
2510
|
function heredocAt(text, index, where) {
|
|
@@ -2763,7 +2536,7 @@ function isDelimiterLine(text, lineStart, end, heredoc) {
|
|
|
2763
2536
|
function readBody(text, start, heredoc) {
|
|
2764
2537
|
let lineStart = start;
|
|
2765
2538
|
while (lineStart < text.length) {
|
|
2766
|
-
const lineEnd = text.indexOf(LINE_BREAK$
|
|
2539
|
+
const lineEnd = text.indexOf(LINE_BREAK$4, lineStart);
|
|
2767
2540
|
const end = lineEnd === -1 ? text.length : lineEnd;
|
|
2768
2541
|
if (isDelimiterLine(text, lineStart, end, heredoc)) {
|
|
2769
2542
|
const body = { command: heredoc.command, start, text: text.slice(start, lineStart) };
|
|
@@ -2785,7 +2558,7 @@ function readBodies(text, start, pending) {
|
|
|
2785
2558
|
}
|
|
2786
2559
|
|
|
2787
2560
|
const COMMENT = "#";
|
|
2788
|
-
const LINE_BREAK$
|
|
2561
|
+
const LINE_BREAK$3 = "\n";
|
|
2789
2562
|
function skipTrivia(text, index) {
|
|
2790
2563
|
const char = text[index];
|
|
2791
2564
|
if (WORD_BREAKS.has(char)) {
|
|
@@ -2815,7 +2588,7 @@ function topLevelCommands(text, indent) {
|
|
|
2815
2588
|
index = heredoc.end;
|
|
2816
2589
|
} else if (afterTrivia !== index) {
|
|
2817
2590
|
index = afterTrivia;
|
|
2818
|
-
} else if (text[index] === LINE_BREAK$
|
|
2591
|
+
} else if (text[index] === LINE_BREAK$3 && pending.length > 0) {
|
|
2819
2592
|
const read = readBodies(text, index + 1, pending);
|
|
2820
2593
|
heredocs.push(...read.bodies);
|
|
2821
2594
|
pending = [];
|
|
@@ -2878,20 +2651,20 @@ function nestedCommandText(word) {
|
|
|
2878
2651
|
const SHELLS$1 = /* @__PURE__ */ new Set(["sh", "bash", "dash", "ash", "zsh", "ksh"]);
|
|
2879
2652
|
const DOCKER_RUN = "RUN";
|
|
2880
2653
|
const PASS_THROUGH = "cat";
|
|
2881
|
-
const PATH_SEPARATOR$
|
|
2654
|
+
const PATH_SEPARATOR$8 = "/";
|
|
2882
2655
|
const OPTION_PREFIX$1 = "-";
|
|
2883
|
-
const programName = (command) => command[0]?.value.split(PATH_SEPARATOR$
|
|
2656
|
+
const programName$1 = (command) => command[0]?.value.split(PATH_SEPARATOR$8).at(-1) ?? "";
|
|
2884
2657
|
const isOption = (word) => word.value.startsWith(OPTION_PREFIX$1);
|
|
2885
|
-
const isScriptShell = (command) => SHELLS$1.has(programName(command)) && command.slice(1).every(isOption);
|
|
2658
|
+
const isScriptShell = (command) => SHELLS$1.has(programName$1(command)) && command.slice(1).every(isOption);
|
|
2886
2659
|
function readsScript(command) {
|
|
2887
|
-
if (programName(command) !== DOCKER_RUN) {
|
|
2660
|
+
if (programName$1(command) !== DOCKER_RUN) {
|
|
2888
2661
|
return isScriptShell(command);
|
|
2889
2662
|
}
|
|
2890
2663
|
const after = command.slice(1);
|
|
2891
2664
|
const shell = after.slice(after.findIndex((word) => !isOption(word)));
|
|
2892
2665
|
return after.every(isOption) || isScriptShell(shell);
|
|
2893
2666
|
}
|
|
2894
|
-
const passesThrough = (command) => programName(command) === PASS_THROUGH && command.slice(1).every(isOption);
|
|
2667
|
+
const passesThrough = (command) => programName$1(command) === PASS_THROUGH && command.slice(1).every(isOption);
|
|
2895
2668
|
function scriptsRunBy(top, index, command) {
|
|
2896
2669
|
const previous = index - 1;
|
|
2897
2670
|
const isPipedScript = top.pipes.has(previous) && isScriptShell(command) && passesThrough(simpleCommand(top.commands[previous] ?? []));
|
|
@@ -2903,6 +2676,21 @@ const shifted = (words, offset) => words.map((word) => ({ ...word, start: word.s
|
|
|
2903
2676
|
function shellCommandsAt(text, offset, indent = 0) {
|
|
2904
2677
|
return shellCommands(text, indent).map((words) => shifted(words, offset));
|
|
2905
2678
|
}
|
|
2679
|
+
const expansionCommands = (word) => wordExpansions(word.raw).flatMap(
|
|
2680
|
+
(expansion) => shellCommandsAt(expansion.text, word.start + expansion.start)
|
|
2681
|
+
);
|
|
2682
|
+
function innerCommands(command) {
|
|
2683
|
+
const assignments = new Map(shellAssignments(command).map((found) => [found.word, found]));
|
|
2684
|
+
return command.flatMap((word) => {
|
|
2685
|
+
const inner = nestedCommandText(word);
|
|
2686
|
+
if (inner !== void 0) {
|
|
2687
|
+
return shellCommandsAt(inner, word.start + 1);
|
|
2688
|
+
}
|
|
2689
|
+
const assignment = assignments.get(word);
|
|
2690
|
+
const value = assignment === void 0 ? void 0 : assignmentValueText(assignment);
|
|
2691
|
+
return value === void 0 ? expansionCommands(word) : shellCommandsAt(value.text, value.start);
|
|
2692
|
+
});
|
|
2693
|
+
}
|
|
2906
2694
|
function shellCommands(text, indent = 0) {
|
|
2907
2695
|
const top = topLevelCommands(text, indent);
|
|
2908
2696
|
const commands = [];
|
|
@@ -2911,71 +2699,211 @@ function shellCommands(text, indent = 0) {
|
|
|
2911
2699
|
if (command.length > 0) {
|
|
2912
2700
|
commands.push(command);
|
|
2913
2701
|
}
|
|
2914
|
-
|
|
2915
|
-
const inner = nestedCommandText(word);
|
|
2916
|
-
if (inner !== void 0) {
|
|
2917
|
-
const nested = shellCommands(inner).map((found) => shifted(found, word.start + 1));
|
|
2918
|
-
commands.push(...nested);
|
|
2919
|
-
}
|
|
2920
|
-
}
|
|
2702
|
+
commands.push(...innerCommands(command));
|
|
2921
2703
|
const scripts = scriptsRunBy(top, index, command);
|
|
2922
2704
|
commands.push(...scripts.flatMap((body) => shellCommandsAt(body.text, body.start, indent)));
|
|
2923
2705
|
}
|
|
2924
2706
|
return commands;
|
|
2925
2707
|
}
|
|
2926
2708
|
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
const BIN_FOLDER = "/.bin/";
|
|
2930
|
-
const OLD_PACKAGE_FOLDER = `node_modules/${GENERATOR_COMMAND}/`;
|
|
2931
|
-
function renameAtEnd(word, name, to) {
|
|
2932
|
-
const at = word.raw.lastIndexOf(name);
|
|
2933
|
-
const tail = word.raw.slice(at + name.length);
|
|
2934
|
-
if (at === -1 || tail !== "" && !QUOTES$1.has(tail)) {
|
|
2935
|
-
return void 0;
|
|
2936
|
-
}
|
|
2937
|
-
return { start: word.start + at, end: word.start + at + name.length, text: to };
|
|
2938
|
-
}
|
|
2939
|
-
function packageFindings(found, locate) {
|
|
2940
|
-
const { name, isPinned } = packageReference(found.value);
|
|
2941
|
-
const to = PACKAGE_RENAMES.get(name);
|
|
2942
|
-
const offset = found.word.start;
|
|
2943
|
-
if (to === void 0) {
|
|
2944
|
-
return [];
|
|
2945
|
-
}
|
|
2946
|
-
const location = locate(offset);
|
|
2947
|
-
if (isPinned) {
|
|
2948
|
-
return [{ offset, manualStep: { kind: "pinned-package", location, name } }];
|
|
2949
|
-
}
|
|
2950
|
-
const edit = renameAtEnd(found.word, name, to);
|
|
2951
|
-
const change = { kind: "package-name-renamed", location, from: name, to };
|
|
2952
|
-
return edit === void 0 ? [] : [{ offset, edit, change }];
|
|
2709
|
+
function assertNever(value) {
|
|
2710
|
+
throw new Error(`Unexpected variant: ${JSON.stringify(value)}`);
|
|
2953
2711
|
}
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2712
|
+
|
|
2713
|
+
function canRunGenerator(definition, generators) {
|
|
2714
|
+
switch (definition.kind) {
|
|
2715
|
+
case "command":
|
|
2716
|
+
return definition.runsGenerator;
|
|
2717
|
+
case "reference":
|
|
2718
|
+
return generators.has(definition.target);
|
|
2719
|
+
case "append":
|
|
2720
|
+
return false;
|
|
2721
|
+
default:
|
|
2722
|
+
return assertNever(definition);
|
|
2958
2723
|
}
|
|
2959
|
-
const isBin = word.value.endsWith(`${BIN_FOLDER}${GENERATOR_COMMAND}`);
|
|
2960
|
-
const edit = isBin ? renameAtEnd(word, GENERATOR_COMMAND, MIGRATED_GENERATOR_COMMAND) : void 0;
|
|
2961
|
-
return edit === void 0 ? [] : [{ offset, edit, change: { kind: "command-renamed", location } }];
|
|
2962
2724
|
}
|
|
2963
|
-
function
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2725
|
+
function canRunOther(definition, others, defined) {
|
|
2726
|
+
switch (definition.kind) {
|
|
2727
|
+
case "command":
|
|
2728
|
+
return !definition.runsGenerator;
|
|
2729
|
+
case "reference":
|
|
2730
|
+
return others.has(definition.target) || !defined.has(definition.target);
|
|
2731
|
+
case "append":
|
|
2732
|
+
return false;
|
|
2733
|
+
default:
|
|
2734
|
+
return assertNever(definition);
|
|
2973
2735
|
}
|
|
2974
|
-
const edit = renameAtEnd(word, GENERATOR_COMMAND, MIGRATED_GENERATOR_COMMAND);
|
|
2975
|
-
const change = { kind: "command-renamed", location };
|
|
2976
|
-
return edit === void 0 ? [] : [{ offset: word.start, edit, change }];
|
|
2977
2736
|
}
|
|
2978
|
-
function
|
|
2737
|
+
function variablePrograms(definitions) {
|
|
2738
|
+
const defined = new Set(definitions.map((definition) => definition.name));
|
|
2739
|
+
const generators = /* @__PURE__ */ new Set();
|
|
2740
|
+
const others = /* @__PURE__ */ new Set();
|
|
2741
|
+
for (let size = -1; size !== generators.size + others.size; ) {
|
|
2742
|
+
size = generators.size + others.size;
|
|
2743
|
+
for (const definition of definitions) {
|
|
2744
|
+
if (canRunGenerator(definition, generators)) {
|
|
2745
|
+
generators.add(definition.name);
|
|
2746
|
+
}
|
|
2747
|
+
if (canRunOther(definition, others, defined)) {
|
|
2748
|
+
others.add(definition.name);
|
|
2749
|
+
}
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
const programOf = (name) => {
|
|
2753
|
+
if (!generators.has(name)) {
|
|
2754
|
+
return "other";
|
|
2755
|
+
}
|
|
2756
|
+
return others.has(name) ? "generator-or-other" : "generator";
|
|
2757
|
+
};
|
|
2758
|
+
return new Map([...defined].map((name) => [name, programOf(name)]));
|
|
2759
|
+
}
|
|
2760
|
+
|
|
2761
|
+
const SHELL_VARIABLE_RE = /^"?\$(?:([A-Za-z_][A-Za-z0-9_]*)|\{([A-Za-z_][A-Za-z0-9_]*)\})"?$/;
|
|
2762
|
+
function expandedName(text) {
|
|
2763
|
+
const match = SHELL_VARIABLE_RE.exec(text);
|
|
2764
|
+
return match === null ? void 0 : match[1] ?? match[2];
|
|
2765
|
+
}
|
|
2766
|
+
const textRunsGenerator = (text) => shellCommands(text).some(runsGenerator);
|
|
2767
|
+
function textDefinition(name, text) {
|
|
2768
|
+
const target = expandedName(text.trim());
|
|
2769
|
+
return target === void 0 ? { name, kind: "command", runsGenerator: textRunsGenerator(text) } : { name, kind: "reference", target };
|
|
2770
|
+
}
|
|
2771
|
+
function expansionDefinitions(name, expansion) {
|
|
2772
|
+
const word = textDefinition(name, expansion.text);
|
|
2773
|
+
const isOutside = expansion.use === "alternative" || expansion.name === name;
|
|
2774
|
+
const variable = isOutside ? { name, kind: "command", runsGenerator: false } : { name, kind: "reference", target: expansion.name };
|
|
2775
|
+
return [word, variable];
|
|
2776
|
+
}
|
|
2777
|
+
function programDefinitions$1({ name, value }) {
|
|
2778
|
+
const expansion = wholeWordExpansion(value.trim());
|
|
2779
|
+
return expansion === void 0 ? [textDefinition(name, value)] : expansionDefinitions(name, expansion);
|
|
2780
|
+
}
|
|
2781
|
+
function shellVariables(definitions) {
|
|
2782
|
+
const values = /* @__PURE__ */ new Map();
|
|
2783
|
+
for (const { name, value } of definitions) {
|
|
2784
|
+
values.set(name, [values.get(name), value].filter((part) => part !== void 0).join(" "));
|
|
2785
|
+
}
|
|
2786
|
+
const programs = variablePrograms(definitions.flatMap(programDefinitions$1));
|
|
2787
|
+
const nameAt = (word) => expandedName(word.raw);
|
|
2788
|
+
return {
|
|
2789
|
+
programAt: (program) => {
|
|
2790
|
+
const name = nameAt(program);
|
|
2791
|
+
const found = name === void 0 ? void 0 : programs.get(name);
|
|
2792
|
+
return found === void 0 ? void 0 : { written: program.raw, program: found };
|
|
2793
|
+
},
|
|
2794
|
+
referenceAt: (word) => {
|
|
2795
|
+
const name = nameAt(word);
|
|
2796
|
+
const value = name === void 0 ? void 0 : values.get(name);
|
|
2797
|
+
return value === void 0 ? void 0 : { written: word.raw, value };
|
|
2798
|
+
}
|
|
2799
|
+
};
|
|
2800
|
+
}
|
|
2801
|
+
function combinedUse(left, right) {
|
|
2802
|
+
if (left === void 0 || right === void 0) {
|
|
2803
|
+
return left ?? right;
|
|
2804
|
+
}
|
|
2805
|
+
return left.program === right.program ? left : { ...left, program: "generator-or-other" };
|
|
2806
|
+
}
|
|
2807
|
+
function assignedByExpansions(commands) {
|
|
2808
|
+
return commands.flat().flatMap((word) => wordExpansions(word.raw)).filter((expansion) => expansion.use === "assign").flatMap(({ name, text }) => [
|
|
2809
|
+
{ name, value: text },
|
|
2810
|
+
{ name, value: "" }
|
|
2811
|
+
]);
|
|
2812
|
+
}
|
|
2813
|
+
function withShellAssignments(commands, file) {
|
|
2814
|
+
const assigned = commands.flatMap(shellAssignments).filter((found) => !isArrayAssignment(found));
|
|
2815
|
+
const definitions = [...assigned, ...assignedByExpansions(commands)];
|
|
2816
|
+
if (definitions.length === 0) {
|
|
2817
|
+
return file;
|
|
2818
|
+
}
|
|
2819
|
+
const own = shellVariables(definitions);
|
|
2820
|
+
return {
|
|
2821
|
+
programAt: (program) => combinedUse(own.programAt(program), file.programAt(program)),
|
|
2822
|
+
referenceAt: (word) => own.referenceAt(word) ?? file.referenceAt(word)
|
|
2823
|
+
};
|
|
2824
|
+
}
|
|
2825
|
+
const joinedProgram = (left, right) => left === right ? left : "generator-or-other";
|
|
2826
|
+
function expansionUse(word, variables) {
|
|
2827
|
+
const expansion = wholeWordExpansion(word.raw);
|
|
2828
|
+
if (expansion === void 0) {
|
|
2829
|
+
return void 0;
|
|
2830
|
+
}
|
|
2831
|
+
const programOf = (name) => (name === void 0 ? void 0 : variables.programAt({ ...word, raw: `$${name}` })?.program) ?? "other";
|
|
2832
|
+
const target = expandedName(expansion.text.trim());
|
|
2833
|
+
const textProgram = textRunsGenerator(expansion.text) ? "generator" : "other";
|
|
2834
|
+
const own = target === void 0 ? textProgram : programOf(target);
|
|
2835
|
+
const variable = programOf(expansion.use === "alternative" ? void 0 : expansion.name);
|
|
2836
|
+
return { written: word.raw, program: joinedProgram(own, variable) };
|
|
2837
|
+
}
|
|
2838
|
+
function withWordExpansions(variables) {
|
|
2839
|
+
return {
|
|
2840
|
+
programAt: (program) => variables.programAt(program) ?? expansionUse(program, variables),
|
|
2841
|
+
referenceAt: (word) => variables.referenceAt(word)
|
|
2842
|
+
};
|
|
2843
|
+
}
|
|
2844
|
+
const VARIABLE_NAME = "[A-Za-z_][A-Za-z0-9_]*";
|
|
2845
|
+
const VARIABLE_WORD_RE = new RegExp(
|
|
2846
|
+
`^"?\\$\\$?(?:${VARIABLE_NAME}|\\{${VARIABLE_NAME}(?:\\[[^\\]]*\\])?\\})"?$`
|
|
2847
|
+
);
|
|
2848
|
+
function withUnreadVariables(variables) {
|
|
2849
|
+
return {
|
|
2850
|
+
programAt: (program) => variables.programAt(program) ?? (VARIABLE_WORD_RE.test(program.raw) ? { written: program.raw, program: "generator-or-other" } : void 0),
|
|
2851
|
+
referenceAt: (word) => variables.referenceAt(word)
|
|
2852
|
+
};
|
|
2853
|
+
}
|
|
2854
|
+
|
|
2855
|
+
const QUOTES$1 = /* @__PURE__ */ new Set(["'", '"']);
|
|
2856
|
+
const PATH_SEPARATOR$7 = "/";
|
|
2857
|
+
const BIN_FOLDER = "/.bin/";
|
|
2858
|
+
const OLD_PACKAGE_FOLDER = `node_modules/${GENERATOR_COMMAND}/`;
|
|
2859
|
+
function renameAtEnd(word, name, to) {
|
|
2860
|
+
const at = word.raw.lastIndexOf(name);
|
|
2861
|
+
const tail = word.raw.slice(at + name.length);
|
|
2862
|
+
if (at === -1 || tail !== "" && !QUOTES$1.has(tail)) {
|
|
2863
|
+
return void 0;
|
|
2864
|
+
}
|
|
2865
|
+
return { start: word.start + at, end: word.start + at + name.length, text: to };
|
|
2866
|
+
}
|
|
2867
|
+
function packageFindings(found, locate) {
|
|
2868
|
+
const { name, isPinned } = packageReference(found.value);
|
|
2869
|
+
const to = PACKAGE_RENAMES.get(name);
|
|
2870
|
+
const offset = found.word.start;
|
|
2871
|
+
if (to === void 0) {
|
|
2872
|
+
return [];
|
|
2873
|
+
}
|
|
2874
|
+
const location = locate(offset);
|
|
2875
|
+
if (isPinned) {
|
|
2876
|
+
return [{ offset, manualStep: { kind: "pinned-package", location, name } }];
|
|
2877
|
+
}
|
|
2878
|
+
const edit = renameAtEnd(found.word, name, to);
|
|
2879
|
+
const change = { kind: "package-name-renamed", location, from: name, to };
|
|
2880
|
+
return edit === void 0 ? [] : [{ offset, edit, change }];
|
|
2881
|
+
}
|
|
2882
|
+
function programPathFindings(word, location) {
|
|
2883
|
+
const offset = word.start;
|
|
2884
|
+
if (word.value.includes(OLD_PACKAGE_FOLDER)) {
|
|
2885
|
+
return [{ offset, manualStep: { kind: "old-package-file", location, path: word.value } }];
|
|
2886
|
+
}
|
|
2887
|
+
const isBin = word.value.endsWith(`${BIN_FOLDER}${GENERATOR_COMMAND}`);
|
|
2888
|
+
const edit = isBin ? renameAtEnd(word, GENERATOR_COMMAND, MIGRATED_GENERATOR_COMMAND) : void 0;
|
|
2889
|
+
return edit === void 0 ? [] : [{ offset, edit, change: { kind: "command-renamed", location } }];
|
|
2890
|
+
}
|
|
2891
|
+
function programFindings(word, location) {
|
|
2892
|
+
if (word.value.includes(PATH_SEPARATOR$7)) {
|
|
2893
|
+
return programPathFindings(word, location);
|
|
2894
|
+
}
|
|
2895
|
+
const { name, isPinned } = packageReference(word.value);
|
|
2896
|
+
if (name !== GENERATOR_COMMAND) {
|
|
2897
|
+
return [];
|
|
2898
|
+
}
|
|
2899
|
+
if (isPinned) {
|
|
2900
|
+
return [{ offset: word.start, manualStep: { kind: "versioned-command", location } }];
|
|
2901
|
+
}
|
|
2902
|
+
const edit = renameAtEnd(word, GENERATOR_COMMAND, MIGRATED_GENERATOR_COMMAND);
|
|
2903
|
+
const change = { kind: "command-renamed", location };
|
|
2904
|
+
return edit === void 0 ? [] : [{ offset: word.start, edit, change }];
|
|
2905
|
+
}
|
|
2906
|
+
function flagFindings(word, locate) {
|
|
2979
2907
|
const flag = word.raw.split("=", 1)[0];
|
|
2980
2908
|
const to = FLAG_RENAMES.get(flag);
|
|
2981
2909
|
if (to === void 0) {
|
|
@@ -2987,18 +2915,6 @@ function flagFindings(word, locate) {
|
|
|
2987
2915
|
{ offset, edit, change: { kind: "flag-renamed", location: locate(offset), from: flag, to } }
|
|
2988
2916
|
];
|
|
2989
2917
|
}
|
|
2990
|
-
const RECIPE_PREFIX_RE$1 = /^[@+-]+(?=.)/;
|
|
2991
|
-
function withoutRecipePrefix(words) {
|
|
2992
|
-
const [first, ...rest] = words;
|
|
2993
|
-
if (first === void 0 || !RECIPE_PREFIX_RE$1.test(first.value)) {
|
|
2994
|
-
return words;
|
|
2995
|
-
}
|
|
2996
|
-
return [{ ...first, value: first.value.replace(RECIPE_PREFIX_RE$1, "") }, ...rest];
|
|
2997
|
-
}
|
|
2998
|
-
const NO_VARIABLES = {
|
|
2999
|
-
programAt: () => void 0,
|
|
3000
|
-
referenceAt: () => void 0
|
|
3001
|
-
};
|
|
3002
2918
|
function renamedFlags(value) {
|
|
3003
2919
|
const flags = shellCommands(value).flat().map((word) => word.raw.split("=", 1)[0]);
|
|
3004
2920
|
return [...new Set(flags.filter((flag) => FLAG_RENAMES.has(flag)))];
|
|
@@ -3067,17 +2983,12 @@ function knownFindings(words, locate, variables) {
|
|
|
3067
2983
|
);
|
|
3068
2984
|
return findings;
|
|
3069
2985
|
}
|
|
3070
|
-
function runsGenerator(command) {
|
|
3071
|
-
const words = withoutRecipePrefix(command);
|
|
3072
|
-
const { program } = commandRoles(words);
|
|
3073
|
-
const word = program === void 0 ? void 0 : words[program];
|
|
3074
|
-
return word !== void 0 && packageReference(word.value).name === GENERATOR_COMMAND;
|
|
3075
|
-
}
|
|
3076
2986
|
function shellTextFindings(text, locate) {
|
|
3077
2987
|
return commandWordFindings(shellCommands(text), locate);
|
|
3078
2988
|
}
|
|
3079
2989
|
function commandWordFindings(commands, locate, variables = NO_VARIABLES) {
|
|
3080
|
-
const
|
|
2990
|
+
const known = withUnreadVariables(withWordExpansions(withShellAssignments(commands, variables)));
|
|
2991
|
+
const findings = commands.flatMap((words) => commandFindings(words, locate, known)).sort((left, right) => left.offset - right.offset);
|
|
3081
2992
|
return {
|
|
3082
2993
|
edits: findings.flatMap((finding) => finding.edit === void 0 ? [] : [finding.edit]),
|
|
3083
2994
|
changes: findings.flatMap((finding) => finding.change === void 0 ? [] : [finding.change]),
|
|
@@ -3122,6 +3033,7 @@ const NX_WORKSPACE_COMMAND_PATHS = nxTargetPaths([
|
|
|
3122
3033
|
]);
|
|
3123
3034
|
const MANIFEST_COMMAND_PATHS = [
|
|
3124
3035
|
["scripts", ANY],
|
|
3036
|
+
["wireit", ANY, "command"],
|
|
3125
3037
|
...simpleGitHooksPaths(["simple-git-hooks"]),
|
|
3126
3038
|
...lintStagedPaths(["lint-staged"]),
|
|
3127
3039
|
...nxTargetPaths(["nx", "targets"])
|
|
@@ -3149,94 +3061,120 @@ function commandStringSteps(text, strings) {
|
|
|
3149
3061
|
});
|
|
3150
3062
|
}
|
|
3151
3063
|
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3064
|
+
const KEPT_PROTOCOLS = ["catalog:", "workspace:"];
|
|
3065
|
+
const LOCAL_PROTOCOLS = ["workspace:", "link:", "file:", "portal:"];
|
|
3066
|
+
const RANGE_SEPARATOR = "||";
|
|
3067
|
+
const HYPHEN = "-";
|
|
3068
|
+
const WHITE_SPACE_RE = /\s+/;
|
|
3069
|
+
const SPACED_OPERATOR_RE = /(<=|>=|<|>|=|~>|~|\^)\s+/g;
|
|
3070
|
+
const OPERATOR = String.raw`(<=|>=|<|>|=|~>|~|\^)?`;
|
|
3071
|
+
const VERSION_PART = String.raw`(\d+|[xX*])`;
|
|
3072
|
+
const LABELS = String.raw`(?:-[\w.-]+)?(?:\+[\w.-]+)?`;
|
|
3073
|
+
const COMPARATOR_RE = new RegExp(
|
|
3074
|
+
String.raw`^${OPERATOR}v?${VERSION_PART}(?:\.${VERSION_PART})?(?:\.${VERSION_PART})?${LABELS}$`
|
|
3075
|
+
);
|
|
3076
|
+
const NUMBER_RE = /^\d+$/;
|
|
3077
|
+
const OPERATOR_STYLES = {
|
|
3078
|
+
"^": "^",
|
|
3079
|
+
// `>=` means "this or newer"; with a new package line, a caret range says the same safely.
|
|
3080
|
+
">=": "^",
|
|
3081
|
+
">": "^",
|
|
3082
|
+
"~": "~",
|
|
3083
|
+
"~>": "~"
|
|
3084
|
+
};
|
|
3085
|
+
const isNumber = (part) => part !== void 0 && NUMBER_RE.test(part);
|
|
3086
|
+
function versionStyle(major, minor, patch) {
|
|
3087
|
+
if (!isNumber(major)) {
|
|
3088
|
+
return void 0;
|
|
3162
3089
|
}
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
switch (definition.kind) {
|
|
3166
|
-
case "command":
|
|
3167
|
-
return !definition.runsGenerator;
|
|
3168
|
-
case "reference":
|
|
3169
|
-
return others.has(definition.target) || !defined.has(definition.target);
|
|
3170
|
-
case "append":
|
|
3171
|
-
return false;
|
|
3172
|
-
default:
|
|
3173
|
-
return assertNever(definition);
|
|
3090
|
+
if (isNumber(minor) && isNumber(patch)) {
|
|
3091
|
+
return "";
|
|
3174
3092
|
}
|
|
3093
|
+
return isNumber(minor) ? "~" : "^";
|
|
3175
3094
|
}
|
|
3176
|
-
function
|
|
3177
|
-
const
|
|
3178
|
-
const
|
|
3179
|
-
const
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
generators.add(definition.name);
|
|
3185
|
-
}
|
|
3186
|
-
if (canRunOther(definition, others, defined)) {
|
|
3187
|
-
others.add(definition.name);
|
|
3188
|
-
}
|
|
3189
|
-
}
|
|
3095
|
+
function rangeStyle(spec) {
|
|
3096
|
+
const sets = spec.replace(SPACED_OPERATOR_RE, "$1").split(RANGE_SEPARATOR);
|
|
3097
|
+
const tokens = sets.map((set) => set.trim().split(WHITE_SPACE_RE));
|
|
3098
|
+
const comparators = tokens.flat().filter((token) => token !== HYPHEN);
|
|
3099
|
+
const matches = comparators.map((comparator) => COMPARATOR_RE.exec(comparator));
|
|
3100
|
+
const first = matches[0];
|
|
3101
|
+
if (first === void 0 || first === null || matches.includes(null)) {
|
|
3102
|
+
return void 0;
|
|
3190
3103
|
}
|
|
3191
|
-
const
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
return others.has(name) ? "generator-or-other" : "generator";
|
|
3196
|
-
};
|
|
3197
|
-
return new Map([...defined].map((name) => [name, programOf(name)]));
|
|
3198
|
-
}
|
|
3199
|
-
|
|
3200
|
-
const SHELL_VARIABLE_RE = /^"?\$(?:([A-Za-z_][A-Za-z0-9_]*)|\{([A-Za-z_][A-Za-z0-9_]*)\})"?$/;
|
|
3201
|
-
function expandedName(text) {
|
|
3202
|
-
const match = SHELL_VARIABLE_RE.exec(text);
|
|
3203
|
-
return match === null ? void 0 : match[1] ?? match[2];
|
|
3204
|
-
}
|
|
3205
|
-
function programDefinition({ name, value }) {
|
|
3206
|
-
const target = expandedName(value.trim());
|
|
3207
|
-
if (target !== void 0) {
|
|
3208
|
-
return { name, kind: "reference", target };
|
|
3104
|
+
const operator = first[1];
|
|
3105
|
+
const isHyphenRange = tokens[0]?.[1] === HYPHEN;
|
|
3106
|
+
if (operator !== void 0 && operator !== "=") {
|
|
3107
|
+
return OPERATOR_STYLES[operator];
|
|
3209
3108
|
}
|
|
3210
|
-
return
|
|
3109
|
+
return isHyphenRange ? "^" : versionStyle(first[2], first[3], first[4]);
|
|
3211
3110
|
}
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3111
|
+
const isLocalPackageSpec = (spec) => LOCAL_PROTOCOLS.some((protocol) => spec.startsWith(protocol));
|
|
3112
|
+
function migrateVersionSpec(spec, version) {
|
|
3113
|
+
if (KEPT_PROTOCOLS.some((protocol) => spec.startsWith(protocol))) {
|
|
3114
|
+
return { kind: "kept", spec, isReported: false };
|
|
3216
3115
|
}
|
|
3217
|
-
const
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
const found = name === void 0 ? void 0 : programs.get(name);
|
|
3223
|
-
return found === void 0 ? void 0 : { written: program.raw, program: found };
|
|
3224
|
-
},
|
|
3225
|
-
referenceAt: (word) => {
|
|
3226
|
-
const name = nameAt(word);
|
|
3227
|
-
const value = name === void 0 ? void 0 : values.get(name);
|
|
3228
|
-
return value === void 0 ? void 0 : { written: word.raw, value };
|
|
3229
|
-
}
|
|
3230
|
-
};
|
|
3116
|
+
const style = rangeStyle(spec);
|
|
3117
|
+
if (style === void 0) {
|
|
3118
|
+
return { kind: "kept", spec, isReported: true };
|
|
3119
|
+
}
|
|
3120
|
+
return { kind: "replaced", spec: `${style}${version}` };
|
|
3231
3121
|
}
|
|
3232
3122
|
|
|
3233
|
-
const
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
const
|
|
3123
|
+
const NO_LONGER_INSTALLED = /* @__PURE__ */ new Map([
|
|
3124
|
+
["openapi-typesafe-helpers", ["openapi-fetch", "openapi-react-query"]]
|
|
3125
|
+
]);
|
|
3126
|
+
const ORIGINAL_NAMES = new Map(
|
|
3127
|
+
[...PACKAGE_RENAMES].map(([original, successor]) => [successor, original])
|
|
3128
|
+
);
|
|
3129
|
+
const PATH_SEPARATOR$6 = "/";
|
|
3130
|
+
function namesUninstalledPackage(text) {
|
|
3131
|
+
return [...NO_LONGER_INSTALLED.keys()].some(
|
|
3132
|
+
(name) => text.includes(name) || text.includes(ORIGINAL_NAMES.get(name) ?? name)
|
|
3133
|
+
);
|
|
3134
|
+
}
|
|
3135
|
+
const directoryOf = (path) => path.slice(0, path.lastIndexOf(PATH_SEPARATOR$6) + 1);
|
|
3136
|
+
const isAtOrAbove = (path, filePath) => filePath.startsWith(directoryOf(path));
|
|
3137
|
+
function declaredNames(manifest) {
|
|
3138
|
+
return DEPENDENCY_FIELDS.flatMap((field) => mapsAt(manifest, field)).flatMap(textEntries).map(({ key }) => key.value);
|
|
3139
|
+
}
|
|
3140
|
+
function localPackageNames(manifest) {
|
|
3141
|
+
return DEPENDENCY_FIELDS.flatMap((field) => mapsAt(manifest, field)).flatMap(textEntries).flatMap(
|
|
3142
|
+
({ key, value }) => isScalar(value) && isLocalPackageSpec(value.value) ? [key.value] : []
|
|
3143
|
+
);
|
|
3144
|
+
}
|
|
3145
|
+
function localPackagesFor(manifests, filePath) {
|
|
3146
|
+
const nearestFirst = manifests.filter(({ path }) => isAtOrAbove(path, filePath)).sort((left, right) => directoryOf(right.path).length - directoryOf(left.path).length);
|
|
3147
|
+
const candidates = new Set(
|
|
3148
|
+
nearestFirst.flatMap(({ localPackages }) => [...localPackages ?? []])
|
|
3149
|
+
);
|
|
3150
|
+
const isLocal = (name) => nearestFirst.find(({ names }) => names?.has(name) === true)?.localPackages?.has(name) === true;
|
|
3151
|
+
return new Set([...candidates].filter(isLocal));
|
|
3152
|
+
}
|
|
3153
|
+
function isDeclaredFor(manifests, filePath, name) {
|
|
3154
|
+
const original = ORIGINAL_NAMES.get(name);
|
|
3155
|
+
const containing = manifests.filter(({ path }) => isAtOrAbove(path, filePath));
|
|
3156
|
+
const declares = ({ names }) => names === void 0 || names.has(name) || original !== void 0 && names.has(original);
|
|
3157
|
+
return containing.length === 0 || containing.some(declares);
|
|
3158
|
+
}
|
|
3159
|
+
const packageOfSpecifier = (specifier) => {
|
|
3160
|
+
const slash = specifier.indexOf(PATH_SEPARATOR$6);
|
|
3161
|
+
return slash === -1 ? specifier : specifier.slice(0, slash);
|
|
3162
|
+
};
|
|
3163
|
+
function undeclaredImportSteps(imports, filePath, manifests) {
|
|
3164
|
+
return imports.flatMap(({ specifier, line }) => {
|
|
3165
|
+
const name = packageOfSpecifier(specifier);
|
|
3166
|
+
const installers = NO_LONGER_INSTALLED.get(name);
|
|
3167
|
+
return installers === void 0 || isDeclaredFor(manifests, filePath, name) ? [] : [{ kind: "package-not-declared", line, name, installers }];
|
|
3168
|
+
});
|
|
3169
|
+
}
|
|
3170
|
+
|
|
3171
|
+
const EXEC_FORM_START_RE = /^[ \t]*(?:RUN|CMD|ENTRYPOINT)(?:[ \t]+--\S+)*[ \t]+\[/gm;
|
|
3172
|
+
const SHELLS = /* @__PURE__ */ new Set(["sh", "bash", "dash", "ash", "zsh"]);
|
|
3173
|
+
const OPTION_PREFIX = "-";
|
|
3174
|
+
const LONG_OPTION_PREFIX = "--";
|
|
3237
3175
|
const COMMAND_OPTION = "c";
|
|
3238
3176
|
const SET_OPTION = "-o";
|
|
3239
|
-
const PATH_SEPARATOR$
|
|
3177
|
+
const PATH_SEPARATOR$5 = "/";
|
|
3240
3178
|
const ARRAY_BLANK_RE = /(?:[ \t\r\n]|\\\r?\n)*/y;
|
|
3241
3179
|
const QUOTED_RE = /"(?:[^"\\\n]|\\.)*"/y;
|
|
3242
3180
|
const ITEM_SEPARATOR = ",";
|
|
@@ -3244,7 +3182,7 @@ const NOT_LINE_BREAK_RE$1 = /[^\n]/g;
|
|
|
3244
3182
|
const ARRAY_END = "]";
|
|
3245
3183
|
const VARIABLE_INSTRUCTIONS = /* @__PURE__ */ new Set(["ARG", "ENV"]);
|
|
3246
3184
|
const LEGACY_ENV_INSTRUCTION = "ENV";
|
|
3247
|
-
const ASSIGNMENT = "=";
|
|
3185
|
+
const ASSIGNMENT$1 = "=";
|
|
3248
3186
|
const QUOTES = /* @__PURE__ */ new Set(['"', "'"]);
|
|
3249
3187
|
function matchAt(pattern, text, index) {
|
|
3250
3188
|
pattern.lastIndex = index;
|
|
@@ -3286,131 +3224,398 @@ function execFormAt(text, start) {
|
|
|
3286
3224
|
index++;
|
|
3287
3225
|
}
|
|
3288
3226
|
}
|
|
3289
|
-
function execForms(text) {
|
|
3290
|
-
return [...text.matchAll(EXEC_FORM_START_RE)].flatMap((match) => {
|
|
3291
|
-
const form = execFormAt(text, match.index + match[0].length - 1);
|
|
3292
|
-
return form === void 0 ? [] : [form];
|
|
3293
|
-
});
|
|
3227
|
+
function execForms(text) {
|
|
3228
|
+
return [...text.matchAll(EXEC_FORM_START_RE)].flatMap((match) => {
|
|
3229
|
+
const form = execFormAt(text, match.index + match[0].length - 1);
|
|
3230
|
+
return form === void 0 ? [] : [form];
|
|
3231
|
+
});
|
|
3232
|
+
}
|
|
3233
|
+
function shellScript(words) {
|
|
3234
|
+
const program = words[0]?.value.split(PATH_SEPARATOR$5).at(-1) ?? "";
|
|
3235
|
+
if (!SHELLS.has(program)) {
|
|
3236
|
+
return void 0;
|
|
3237
|
+
}
|
|
3238
|
+
let index = 1;
|
|
3239
|
+
for (let option = words[index]?.value; option !== void 0; option = words[index]?.value) {
|
|
3240
|
+
if (!option.startsWith(OPTION_PREFIX)) {
|
|
3241
|
+
return void 0;
|
|
3242
|
+
}
|
|
3243
|
+
if (!option.startsWith(LONG_OPTION_PREFIX) && option.includes(COMMAND_OPTION)) {
|
|
3244
|
+
return words[index + 1];
|
|
3245
|
+
}
|
|
3246
|
+
index += option === SET_OPTION ? 2 : 1;
|
|
3247
|
+
}
|
|
3248
|
+
return void 0;
|
|
3249
|
+
}
|
|
3250
|
+
function execCommands(forms) {
|
|
3251
|
+
const commands = [];
|
|
3252
|
+
const escaped = [];
|
|
3253
|
+
for (const { words } of forms) {
|
|
3254
|
+
commands.push(words);
|
|
3255
|
+
const script = shellScript(words);
|
|
3256
|
+
if (script !== void 0 && script.raw === script.value) {
|
|
3257
|
+
commands.push(...shellCommandsAt(script.value, script.start));
|
|
3258
|
+
} else if (script !== void 0) {
|
|
3259
|
+
escaped.push(script);
|
|
3260
|
+
}
|
|
3261
|
+
}
|
|
3262
|
+
return { commands, escaped };
|
|
3263
|
+
}
|
|
3264
|
+
function withoutExecForms(text, forms) {
|
|
3265
|
+
const parts = [];
|
|
3266
|
+
let copiedUpTo = 0;
|
|
3267
|
+
for (const { start, end } of forms) {
|
|
3268
|
+
parts.push(
|
|
3269
|
+
text.slice(copiedUpTo, start),
|
|
3270
|
+
text.slice(start, end).replace(NOT_LINE_BREAK_RE$1, " ")
|
|
3271
|
+
);
|
|
3272
|
+
copiedUpTo = end;
|
|
3273
|
+
}
|
|
3274
|
+
parts.push(text.slice(copiedUpTo));
|
|
3275
|
+
return parts.join("");
|
|
3276
|
+
}
|
|
3277
|
+
function escapedScriptSteps(scripts, lineOf) {
|
|
3278
|
+
return scripts.flatMap((script) => {
|
|
3279
|
+
const migrated = migrateCommand(script.value, "").text;
|
|
3280
|
+
return migrated === script.value ? [] : [{ kind: "command-string", line: lineOf(script.start), to: migrated }];
|
|
3281
|
+
});
|
|
3282
|
+
}
|
|
3283
|
+
function assignedVariable(word) {
|
|
3284
|
+
const at = word.raw.indexOf(ASSIGNMENT$1);
|
|
3285
|
+
if (at <= 0) {
|
|
3286
|
+
return void 0;
|
|
3287
|
+
}
|
|
3288
|
+
const raw = word.raw.slice(at + 1);
|
|
3289
|
+
const isQuoted = raw.length >= 2 && QUOTES.has(raw[0]) && raw.at(-1) === raw[0];
|
|
3290
|
+
const value = isQuoted ? raw.slice(1, -1) : raw;
|
|
3291
|
+
const start = word.start + at + 1 + (isQuoted ? 1 : 0);
|
|
3292
|
+
return { name: word.raw.slice(0, at), commands: shellCommandsAt(value, start) };
|
|
3293
|
+
}
|
|
3294
|
+
function dockerVariables(commands) {
|
|
3295
|
+
return commands.flatMap(([instruction, first, ...rest]) => {
|
|
3296
|
+
if (instruction === void 0 || first === void 0) {
|
|
3297
|
+
return [];
|
|
3298
|
+
}
|
|
3299
|
+
if (!VARIABLE_INSTRUCTIONS.has(instruction.value)) {
|
|
3300
|
+
return [];
|
|
3301
|
+
}
|
|
3302
|
+
if (instruction.value === LEGACY_ENV_INSTRUCTION && !first.raw.includes(ASSIGNMENT$1)) {
|
|
3303
|
+
return [{ name: first.value, commands: [rest] }];
|
|
3304
|
+
}
|
|
3305
|
+
return [first, ...rest].flatMap((word) => assignedVariable(word) ?? []);
|
|
3306
|
+
});
|
|
3307
|
+
}
|
|
3308
|
+
const definitionOf = ({ name, commands }) => ({
|
|
3309
|
+
name,
|
|
3310
|
+
value: commands.flatMap((words) => words.map((word) => word.raw)).join(" ")
|
|
3311
|
+
});
|
|
3312
|
+
function migrateDockerfile(text, file) {
|
|
3313
|
+
const lineOf = lineLocator(text);
|
|
3314
|
+
const locate = (offset) => `${file}:${lineOf(offset)}`;
|
|
3315
|
+
const forms = execForms(text);
|
|
3316
|
+
const exec = execCommands(forms);
|
|
3317
|
+
const shellForm = shellCommands(withoutExecForms(text, forms));
|
|
3318
|
+
const definitions = dockerVariables(shellForm);
|
|
3319
|
+
const values = definitions.flatMap((variable) => variable.commands);
|
|
3320
|
+
const commands = [...shellForm, ...values, ...exec.commands];
|
|
3321
|
+
const variables = shellVariables(definitions.map(definitionOf));
|
|
3322
|
+
const { edits, changes, manualSteps } = commandWordFindings(commands, locate, variables);
|
|
3323
|
+
const steps = [...manualSteps, ...escapedScriptSteps(exec.escaped, lineOf)];
|
|
3324
|
+
return { text: applyTextEdits(text, edits), changes, manualSteps: steps };
|
|
3325
|
+
}
|
|
3326
|
+
|
|
3327
|
+
const CATALOG_PROTOCOL = "catalog:";
|
|
3328
|
+
const DEFAULT_CATALOG = "default";
|
|
3329
|
+
function catalogOfSpec(spec) {
|
|
3330
|
+
if (!spec.startsWith(CATALOG_PROTOCOL)) {
|
|
3331
|
+
return void 0;
|
|
3332
|
+
}
|
|
3333
|
+
return spec.slice(CATALOG_PROTOCOL.length).trim() || DEFAULT_CATALOG;
|
|
3334
|
+
}
|
|
3335
|
+
class CatalogEntries {
|
|
3336
|
+
#keys = /* @__PURE__ */ new Set();
|
|
3337
|
+
add(catalog, name) {
|
|
3338
|
+
this.#keys.add(JSON.stringify([catalog, name]));
|
|
3339
|
+
}
|
|
3340
|
+
has(catalog, name) {
|
|
3341
|
+
return this.#keys.has(JSON.stringify([catalog, name]));
|
|
3342
|
+
}
|
|
3343
|
+
}
|
|
3344
|
+
const NO_CATALOG_PLAN = {
|
|
3345
|
+
inUse: new CatalogEntries(),
|
|
3346
|
+
kept: new CatalogEntries(),
|
|
3347
|
+
defined: new CatalogEntries(),
|
|
3348
|
+
isWorkspaceRoot: false
|
|
3349
|
+
};
|
|
3350
|
+
|
|
3351
|
+
const NPM_PROTOCOL = "npm:";
|
|
3352
|
+
const SCOPE_PREFIX$2 = "@";
|
|
3353
|
+
const PATH_SEPARATOR$4 = "/";
|
|
3354
|
+
const VERSION_SEPARATOR = "@";
|
|
3355
|
+
function nameEnd(text) {
|
|
3356
|
+
const searchFrom = text.startsWith(SCOPE_PREFIX$2) ? text.indexOf(PATH_SEPARATOR$4) + 1 : 0;
|
|
3357
|
+
const ends = [VERSION_SEPARATOR, PATH_SEPARATOR$4].map((separator) => text.indexOf(separator, Math.max(searchFrom, 1))).filter((index) => index !== -1);
|
|
3358
|
+
return ends.length === 0 ? text.length : Math.min(...ends);
|
|
3359
|
+
}
|
|
3360
|
+
function parseNpmSpec(spec) {
|
|
3361
|
+
if (!spec.startsWith(NPM_PROTOCOL)) {
|
|
3362
|
+
return void 0;
|
|
3363
|
+
}
|
|
3364
|
+
const body = spec.slice(NPM_PROTOCOL.length);
|
|
3365
|
+
const lead = body.startsWith(PATH_SEPARATOR$4) ? PATH_SEPARATOR$4 : "";
|
|
3366
|
+
const text = body.slice(lead.length);
|
|
3367
|
+
const end = nameEnd(text);
|
|
3368
|
+
const name = text.slice(0, end);
|
|
3369
|
+
if (!text.startsWith(VERSION_SEPARATOR, end)) {
|
|
3370
|
+
return { lead, name, range: void 0, rest: text.slice(end) };
|
|
3371
|
+
}
|
|
3372
|
+
const rangeEnd = text.indexOf(PATH_SEPARATOR$4, end);
|
|
3373
|
+
const restStart = rangeEnd === -1 ? text.length : rangeEnd;
|
|
3374
|
+
return { lead, name, range: text.slice(end + 1, restStart), rest: text.slice(restStart) };
|
|
3375
|
+
}
|
|
3376
|
+
function isOldPackageNpmSpec(spec) {
|
|
3377
|
+
const parsed = parseNpmSpec(spec);
|
|
3378
|
+
return parsed !== void 0 && PACKAGE_RENAMES.has(parsed.name);
|
|
3379
|
+
}
|
|
3380
|
+
function migrateNpmSpec(spec, version) {
|
|
3381
|
+
const parsed = parseNpmSpec(spec);
|
|
3382
|
+
const renamed = parsed === void 0 ? void 0 : PACKAGE_RENAMES.get(parsed.name);
|
|
3383
|
+
if (parsed === void 0 || renamed === void 0) {
|
|
3384
|
+
return void 0;
|
|
3385
|
+
}
|
|
3386
|
+
const head = `${NPM_PROTOCOL}${parsed.lead}${renamed}`;
|
|
3387
|
+
const isDeep = parsed.rest !== "" && parsed.rest !== PATH_SEPARATOR$4;
|
|
3388
|
+
if (parsed.range === void 0) {
|
|
3389
|
+
return { spec: `${head}${parsed.rest}`, isReported: false, isDeep };
|
|
3390
|
+
}
|
|
3391
|
+
const decision = migrateVersionSpec(parsed.range, version);
|
|
3392
|
+
const isReported = decision.kind === "kept" && decision.isReported;
|
|
3393
|
+
const migrated = `${head}${VERSION_SEPARATOR}${decision.spec}${parsed.rest}`;
|
|
3394
|
+
return { spec: migrated, isReported, isDeep };
|
|
3395
|
+
}
|
|
3396
|
+
|
|
3397
|
+
const SCHEME_SEPARATOR = "://";
|
|
3398
|
+
const HIDDEN_USERINFO = "***";
|
|
3399
|
+
const USERINFO_END = "@";
|
|
3400
|
+
const AUTHORITY_END_RE = /[/?#"'`\s]/;
|
|
3401
|
+
function scanAuthority(text, start) {
|
|
3402
|
+
let userinfoEnd = -1;
|
|
3403
|
+
let end = start;
|
|
3404
|
+
for (; end < text.length && !AUTHORITY_END_RE.test(text.charAt(end)); end++) {
|
|
3405
|
+
if (text.charAt(end) === USERINFO_END) {
|
|
3406
|
+
userinfoEnd = end;
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3409
|
+
return { end, userinfoEnd };
|
|
3410
|
+
}
|
|
3411
|
+
function hideUrlCredentials(text) {
|
|
3412
|
+
let hidden = "";
|
|
3413
|
+
let copiedUpTo = 0;
|
|
3414
|
+
for (let found = text.indexOf(SCHEME_SEPARATOR); found !== -1; ) {
|
|
3415
|
+
const start = found + SCHEME_SEPARATOR.length;
|
|
3416
|
+
const { end, userinfoEnd } = scanAuthority(text, start);
|
|
3417
|
+
if (userinfoEnd !== -1) {
|
|
3418
|
+
hidden += `${text.slice(copiedUpTo, start)}${HIDDEN_USERINFO}`;
|
|
3419
|
+
copiedUpTo = userinfoEnd;
|
|
3420
|
+
}
|
|
3421
|
+
found = text.indexOf(SCHEME_SEPARATOR, end);
|
|
3422
|
+
}
|
|
3423
|
+
return `${hidden}${text.slice(copiedUpTo)}`;
|
|
3424
|
+
}
|
|
3425
|
+
|
|
3426
|
+
const newFindings = () => ({ edits: [], changes: [], manualSteps: [] });
|
|
3427
|
+
const PEER_FIELD = "peerDependencies";
|
|
3428
|
+
const mapLabel = (map) => map.kind === "catalog" ? map.catalog : map.field;
|
|
3429
|
+
const renamedKey = (name, map) => map.kind === "imports" ? renamedSpecifier(name)?.to : PACKAGE_RENAMES.get(name);
|
|
3430
|
+
function migrateSpec(spec, version) {
|
|
3431
|
+
const npm = migrateNpmSpec(spec, version);
|
|
3432
|
+
if (npm !== void 0) {
|
|
3433
|
+
return { spec: npm.spec, isReported: npm.isReported };
|
|
3434
|
+
}
|
|
3435
|
+
const decision = migrateVersionSpec(spec, version);
|
|
3436
|
+
return { spec: decision.spec, isReported: decision.kind === "kept" && decision.isReported };
|
|
3437
|
+
}
|
|
3438
|
+
function isFree({ from, to, field, names }, findings) {
|
|
3439
|
+
if (names.has(to)) {
|
|
3440
|
+
findings.manualSteps.push({ kind: "name-collision", field, from, to });
|
|
3441
|
+
return false;
|
|
3442
|
+
}
|
|
3443
|
+
return true;
|
|
3444
|
+
}
|
|
3445
|
+
function migrateAlias(entry, { map, version, findings }) {
|
|
3446
|
+
const migrated = entry.spec === void 0 ? void 0 : migrateNpmSpec(entry.spec.value, version);
|
|
3447
|
+
if (entry.spec === void 0 || migrated === void 0) {
|
|
3448
|
+
return;
|
|
3449
|
+
}
|
|
3450
|
+
findings.edits.push(entry.spec.replace(migrated.spec));
|
|
3451
|
+
const spec = hideUrlCredentials(migrated.spec);
|
|
3452
|
+
findings.changes.push({ kind: "alias-renamed", field: mapLabel(map), name: entry.name, spec });
|
|
3453
|
+
if (migrated.isReported) {
|
|
3454
|
+
findings.manualSteps.push({ kind: "spec-kept", name: entry.name, spec });
|
|
3455
|
+
}
|
|
3456
|
+
}
|
|
3457
|
+
function renamedChange(map, from, to, spec) {
|
|
3458
|
+
switch (map.kind) {
|
|
3459
|
+
case "dependencies":
|
|
3460
|
+
return { kind: "dependency-renamed", field: map.field, from, to, spec };
|
|
3461
|
+
case "catalog":
|
|
3462
|
+
return { kind: "catalog-entry-renamed", catalog: map.catalog, from, to, spec };
|
|
3463
|
+
case "imports":
|
|
3464
|
+
return { kind: "import-renamed", field: map.field, from, to, target: spec };
|
|
3465
|
+
default:
|
|
3466
|
+
return assertNever(map);
|
|
3467
|
+
}
|
|
3468
|
+
}
|
|
3469
|
+
function migrateEntry(entry, spec, to, { map, version, findings }) {
|
|
3470
|
+
const old = spec.value;
|
|
3471
|
+
const migrated = migrateSpec(old, version);
|
|
3472
|
+
findings.edits.push(entry.renameKey(to));
|
|
3473
|
+
if (migrated.spec !== old) {
|
|
3474
|
+
findings.edits.push(spec.replace(migrated.spec));
|
|
3475
|
+
}
|
|
3476
|
+
findings.changes.push(renamedChange(map, entry.name, to, hideUrlCredentials(migrated.spec)));
|
|
3477
|
+
if (migrated.isReported) {
|
|
3478
|
+
findings.manualSteps.push({ kind: "spec-kept", name: to, spec: hideUrlCredentials(old) });
|
|
3479
|
+
}
|
|
3480
|
+
if (map.kind === "dependencies" && map.field === PEER_FIELD) {
|
|
3481
|
+
findings.manualSteps.push({ kind: "peer-dependency-renamed", name: to });
|
|
3482
|
+
}
|
|
3483
|
+
}
|
|
3484
|
+
function catalogHold(entry, spec, { map, catalogs }) {
|
|
3485
|
+
if (map.kind === "catalog") {
|
|
3486
|
+
const isInUse = catalogs.inUse.has(map.name, entry.name);
|
|
3487
|
+
return isInUse ? { kind: "catalog-entry-in-use", catalog: map.catalog, name: entry.name } : void 0;
|
|
3488
|
+
}
|
|
3489
|
+
const catalog = map.kind === "dependencies" ? catalogOfSpec(spec.value) : void 0;
|
|
3490
|
+
if (catalog === void 0) {
|
|
3491
|
+
return void 0;
|
|
3492
|
+
}
|
|
3493
|
+
const reference = { field: mapLabel(map), name: entry.name, catalog };
|
|
3494
|
+
if (!catalogs.defined.has(catalog, entry.name)) {
|
|
3495
|
+
const kind = catalogs.isWorkspaceRoot ? "catalog-entry-missing" : "catalog-entry-outside";
|
|
3496
|
+
return { kind, ...reference };
|
|
3497
|
+
}
|
|
3498
|
+
return catalogs.kept.has(catalog, entry.name) ? { kind: "catalog-reference-kept", ...reference } : void 0;
|
|
3499
|
+
}
|
|
3500
|
+
function localPackageHold(entry, spec, { map }) {
|
|
3501
|
+
return map.kind === "dependencies" && isLocalPackageSpec(spec.value) ? { kind: "local-package", field: map.field, name: entry.name, spec: spec.value } : void 0;
|
|
3294
3502
|
}
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3503
|
+
const holdOf = (entry, spec, context) => localPackageHold(entry, spec, context) ?? catalogHold(entry, spec, context);
|
|
3504
|
+
function migrateSpecMap(entries, context) {
|
|
3505
|
+
const names = new Set(entries.map((entry) => entry.name));
|
|
3506
|
+
for (const entry of entries) {
|
|
3507
|
+
const to = renamedKey(entry.name, context.map);
|
|
3508
|
+
const field = mapLabel(context.map);
|
|
3509
|
+
if (to === void 0) {
|
|
3510
|
+
migrateAlias(entry, context);
|
|
3511
|
+
continue;
|
|
3304
3512
|
}
|
|
3305
|
-
if (!
|
|
3306
|
-
|
|
3513
|
+
if (!isFree({ from: entry.name, to, field, names }, context.findings)) {
|
|
3514
|
+
continue;
|
|
3307
3515
|
}
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
}
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
for (const { words } of forms) {
|
|
3316
|
-
commands.push(words);
|
|
3317
|
-
const script = shellScript(words);
|
|
3318
|
-
if (script !== void 0 && script.raw === script.value) {
|
|
3319
|
-
commands.push(...shellCommandsAt(script.value, script.start));
|
|
3320
|
-
} else if (script !== void 0) {
|
|
3321
|
-
escaped.push(script);
|
|
3516
|
+
const hold = entry.spec === void 0 ? void 0 : holdOf(entry, entry.spec, context);
|
|
3517
|
+
if (entry.spec === void 0) {
|
|
3518
|
+
context.findings.manualSteps.push({ kind: "entry-not-edited", field, name: entry.name });
|
|
3519
|
+
} else if (hold !== void 0) {
|
|
3520
|
+
context.findings.manualSteps.push(hold);
|
|
3521
|
+
} else {
|
|
3522
|
+
migrateEntry(entry, entry.spec, to, context);
|
|
3322
3523
|
}
|
|
3323
3524
|
}
|
|
3324
|
-
return { commands, escaped };
|
|
3325
3525
|
}
|
|
3326
|
-
function
|
|
3327
|
-
const
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3526
|
+
function renameNames(entries, field, findings) {
|
|
3527
|
+
const names = new Set(entries.map((entry) => entry.name));
|
|
3528
|
+
for (const entry of entries) {
|
|
3529
|
+
const to = PACKAGE_RENAMES.get(entry.name);
|
|
3530
|
+
if (to !== void 0 && isFree({ from: entry.name, to, field, names }, findings)) {
|
|
3531
|
+
findings.edits.push(entry.rename(to));
|
|
3532
|
+
findings.changes.push({
|
|
3533
|
+
kind: "package-name-renamed",
|
|
3534
|
+
location: field,
|
|
3535
|
+
from: entry.name,
|
|
3536
|
+
to
|
|
3537
|
+
});
|
|
3538
|
+
}
|
|
3335
3539
|
}
|
|
3336
|
-
parts.push(text.slice(copiedUpTo));
|
|
3337
|
-
return parts.join("");
|
|
3338
3540
|
}
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3541
|
+
|
|
3542
|
+
const isEditable = (node) => node.kind === "scalar" && node.encode !== void 0;
|
|
3543
|
+
const replaceScalar = (scalar, value) => ({
|
|
3544
|
+
start: scalar.start,
|
|
3545
|
+
end: scalar.end,
|
|
3546
|
+
text: scalar.encode(value)
|
|
3547
|
+
});
|
|
3548
|
+
function specEntries(map) {
|
|
3549
|
+
return textEntries(map).flatMap(({ key, value }) => {
|
|
3550
|
+
if (!isEditable(key)) {
|
|
3551
|
+
return [];
|
|
3552
|
+
}
|
|
3553
|
+
const spec = isEditable(value) ? { value: value.value, replace: (to) => replaceScalar(value, to) } : void 0;
|
|
3554
|
+
return [{ name: key.value, spec, renameKey: (name) => replaceScalar(key, name) }];
|
|
3343
3555
|
});
|
|
3344
3556
|
}
|
|
3345
|
-
function
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3557
|
+
function keyEntries(map) {
|
|
3558
|
+
return textEntries(map).map(({ key }) => key).filter(isEditable).map((key) => ({ name: key.value, rename: (name) => replaceScalar(key, name) }));
|
|
3559
|
+
}
|
|
3560
|
+
function itemEntries(list) {
|
|
3561
|
+
return list.items.filter(isEditable).map((item) => ({ name: item.value, rename: (name) => replaceScalar(item, name) }));
|
|
3562
|
+
}
|
|
3563
|
+
function nestedKeys(node) {
|
|
3564
|
+
if (node.kind !== "map") {
|
|
3565
|
+
return [];
|
|
3349
3566
|
}
|
|
3350
|
-
|
|
3351
|
-
const isQuoted = raw.length >= 2 && QUOTES.has(raw[0]) && raw.at(-1) === raw[0];
|
|
3352
|
-
const value = isQuoted ? raw.slice(1, -1) : raw;
|
|
3353
|
-
const start = word.start + at + 1 + (isQuoted ? 1 : 0);
|
|
3354
|
-
return { name: word.raw.slice(0, at), commands: shellCommandsAt(value, start) };
|
|
3567
|
+
return textEntries(node).flatMap(({ key, value }) => [key.value, ...nestedKeys(value)]);
|
|
3355
3568
|
}
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
}
|
|
3364
|
-
|
|
3365
|
-
|
|
3569
|
+
|
|
3570
|
+
const IMPORTS_FIELD$1 = "imports";
|
|
3571
|
+
const SCOPES_FIELD = "scopes";
|
|
3572
|
+
const FIELD_SEPARATOR$2 = ".";
|
|
3573
|
+
function migrateImports(config, version, findings) {
|
|
3574
|
+
for (const imports of mapsAt(config, IMPORTS_FIELD$1)) {
|
|
3575
|
+
const map = { kind: "imports", field: IMPORTS_FIELD$1 };
|
|
3576
|
+
migrateSpecMap(specEntries(imports), { map, version, findings, catalogs: NO_CATALOG_PLAN });
|
|
3577
|
+
}
|
|
3578
|
+
for (const scopes of mapsAt(config, SCOPES_FIELD)) {
|
|
3579
|
+
for (const { key, value } of textEntries(scopes)) {
|
|
3580
|
+
if (isMap(value)) {
|
|
3581
|
+
const field = [SCOPES_FIELD, key.value].join(FIELD_SEPARATOR$2);
|
|
3582
|
+
const map = { kind: "imports", field };
|
|
3583
|
+
migrateSpecMap(specEntries(value), { map, version, findings, catalogs: NO_CATALOG_PLAN });
|
|
3584
|
+
}
|
|
3366
3585
|
}
|
|
3367
|
-
|
|
3586
|
+
}
|
|
3587
|
+
}
|
|
3588
|
+
const PATH_SEPARATOR$3 = "/";
|
|
3589
|
+
const SCOPE_PREFIX$1 = "@";
|
|
3590
|
+
function importMapKeys(config) {
|
|
3591
|
+
const scoped = mapsAt(config, SCOPES_FIELD).flatMap(textEntries).flatMap(({ value }) => isMap(value) ? [value] : []);
|
|
3592
|
+
return [...mapsAt(config, IMPORTS_FIELD$1), ...scoped].flatMap(textEntries).map(({ key }) => key.value);
|
|
3593
|
+
}
|
|
3594
|
+
function importMapNames(config) {
|
|
3595
|
+
return importMapKeys(config).map((key) => {
|
|
3596
|
+
const parts = key.split(PATH_SEPARATOR$3);
|
|
3597
|
+
return key.startsWith(SCOPE_PREFIX$1) ? parts.slice(0, 2).join(PATH_SEPARATOR$3) : parts[0] ?? key;
|
|
3368
3598
|
});
|
|
3369
3599
|
}
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
}
|
|
3374
|
-
|
|
3375
|
-
const
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
const
|
|
3379
|
-
|
|
3380
|
-
const definitions = dockerVariables(shellForm);
|
|
3381
|
-
const values = definitions.flatMap((variable) => variable.commands);
|
|
3382
|
-
const commands = [...shellForm, ...values, ...exec.commands];
|
|
3383
|
-
const variables = shellVariables(definitions.map(definitionOf));
|
|
3384
|
-
const { edits, changes, manualSteps } = commandWordFindings(commands, locate, variables);
|
|
3385
|
-
const steps = [...manualSteps, ...escapedScriptSteps(exec.escaped, lineOf)];
|
|
3386
|
-
return { text: applyTextEdits(text, edits), changes, manualSteps: steps };
|
|
3600
|
+
function migrateImportMap(text, read, version) {
|
|
3601
|
+
if (read.kind === "unreadable") {
|
|
3602
|
+
return unreadableConfig(text, read.offset);
|
|
3603
|
+
}
|
|
3604
|
+
const findings = newFindings();
|
|
3605
|
+
for (const config of read.documents.filter(isMap)) {
|
|
3606
|
+
migrateImports(config, version, findings);
|
|
3607
|
+
}
|
|
3608
|
+
const { edits, changes, manualSteps } = findings;
|
|
3609
|
+
return { text: applyTextEdits(text, edits), changes, manualSteps };
|
|
3387
3610
|
}
|
|
3388
3611
|
|
|
3389
3612
|
const IMPORT_MAP_FIELD = "importMap";
|
|
3390
|
-
const SEPARATOR = "/";
|
|
3391
|
-
const CURRENT_FOLDER = ".";
|
|
3392
|
-
const PARENT_FOLDER = "..";
|
|
3393
|
-
const URL_SCHEME = /^[a-z][a-z\d+.-]*:/i;
|
|
3394
3613
|
function importMapReferences(roots) {
|
|
3395
3614
|
return roots.flatMap((root) => valuesAt(root, IMPORT_MAP_FIELD)).flatMap((value) => isScalar(value) ? [value.value] : []);
|
|
3396
3615
|
}
|
|
3397
|
-
function resolvedPath(configPath, reference) {
|
|
3398
|
-
const parts = configPath.split(SEPARATOR).slice(0, -1);
|
|
3399
|
-
for (const part of reference.split(SEPARATOR)) {
|
|
3400
|
-
if (part === PARENT_FOLDER) {
|
|
3401
|
-
if (parts.pop() === void 0) {
|
|
3402
|
-
return void 0;
|
|
3403
|
-
}
|
|
3404
|
-
} else if (part !== CURRENT_FOLDER && part !== "") {
|
|
3405
|
-
parts.push(part);
|
|
3406
|
-
}
|
|
3407
|
-
}
|
|
3408
|
-
return parts.join(SEPARATOR);
|
|
3409
|
-
}
|
|
3410
3616
|
function importMapLocation(configPath, reference) {
|
|
3411
|
-
const
|
|
3412
|
-
|
|
3413
|
-
return path === void 0 || path === "" ? { kind: "not-editable", reference } : { kind: "in-project", path };
|
|
3617
|
+
const path = referencedProjectPath(configPath, reference);
|
|
3618
|
+
return path === void 0 ? { kind: "not-editable", reference } : { kind: "in-project", path };
|
|
3414
3619
|
}
|
|
3415
3620
|
const importMapLocations = (configPath, roots) => importMapReferences(roots).map((reference) => importMapLocation(configPath, reference));
|
|
3416
3621
|
function importMapSteps(configPath, read) {
|
|
@@ -3488,14 +3693,15 @@ function unrenamedSteps(found, line, dynamic) {
|
|
|
3488
3693
|
const to = name === void 0 ? void 0 : PACKAGE_RENAMES.get(name);
|
|
3489
3694
|
return name === void 0 || to === void 0 ? [] : [{ kind: "old-package-import", line, specifier: found.value, name, to }];
|
|
3490
3695
|
}
|
|
3491
|
-
function migrateModuleSpecifiers(text, strings, version) {
|
|
3696
|
+
function migrateModuleSpecifiers(text, strings, version, kept = /* @__PURE__ */ new Set()) {
|
|
3492
3697
|
const changes = [];
|
|
3493
3698
|
const manualSteps = [];
|
|
3494
3699
|
let migrated = "";
|
|
3495
3700
|
let copiedUpTo = 0;
|
|
3496
3701
|
const lineOf = lineLocator(text);
|
|
3497
3702
|
for (const found of distinctStrings(strings)) {
|
|
3498
|
-
const
|
|
3703
|
+
const isKept = kept.has(packageOfSpecifier(found.value));
|
|
3704
|
+
const renamed = isKept ? void 0 : renamedValue(found.value, version);
|
|
3499
3705
|
const line = lineOf(found.start);
|
|
3500
3706
|
const dynamic = found.isModuleSpecifier ? dynamicPackage(found.value) : void 0;
|
|
3501
3707
|
if (renamed === void 0) {
|
|
@@ -3568,23 +3774,281 @@ function textsAt(node, path) {
|
|
|
3568
3774
|
return [];
|
|
3569
3775
|
}
|
|
3570
3776
|
}
|
|
3571
|
-
const jestConfigSteps = (node, path) => textsAt(node, path).flatMap(
|
|
3572
|
-
({ value, path: at }) => patternSteps(value, at.join(FIELD_SEPARATOR$1), false)
|
|
3573
|
-
);
|
|
3574
|
-
const jestJsonSteps = (read) => read.kind === "read" ? read.documents.filter(isMap).flatMap((root) => jestConfigSteps(root, [])) : [];
|
|
3575
|
-
|
|
3576
|
-
function migrateJsonCommands(text, strings, patterns) {
|
|
3577
|
-
const changes = [];
|
|
3578
|
-
const manualSteps = [];
|
|
3579
|
-
const edits = [];
|
|
3580
|
-
for (const found of strings.filter((string) => isCommandPath(string.path, patterns))) {
|
|
3581
|
-
const migrated = migrateCommand(found.value, found.path.join("."));
|
|
3582
|
-
changes.push(...migrated.changes);
|
|
3583
|
-
manualSteps.push(...migrated.manualSteps);
|
|
3584
|
-
if (migrated.text !== found.value) {
|
|
3585
|
-
edits.push({ start: found.start, end: found.end, text: JSON.stringify(migrated.text) });
|
|
3586
|
-
}
|
|
3777
|
+
const jestConfigSteps = (node, path) => textsAt(node, path).flatMap(
|
|
3778
|
+
({ value, path: at }) => patternSteps(value, at.join(FIELD_SEPARATOR$1), false)
|
|
3779
|
+
);
|
|
3780
|
+
const jestJsonSteps = (read) => read.kind === "read" ? read.documents.filter(isMap).flatMap((root) => jestConfigSteps(root, [])) : [];
|
|
3781
|
+
|
|
3782
|
+
function migrateJsonCommands(text, strings, patterns) {
|
|
3783
|
+
const changes = [];
|
|
3784
|
+
const manualSteps = [];
|
|
3785
|
+
const edits = [];
|
|
3786
|
+
for (const found of strings.filter((string) => isCommandPath(string.path, patterns))) {
|
|
3787
|
+
const migrated = migrateCommand(found.value, found.path.join("."));
|
|
3788
|
+
changes.push(...migrated.changes);
|
|
3789
|
+
manualSteps.push(...migrated.manualSteps);
|
|
3790
|
+
if (migrated.text !== found.value) {
|
|
3791
|
+
edits.push({ start: found.start, end: found.end, text: JSON.stringify(migrated.text) });
|
|
3792
|
+
}
|
|
3793
|
+
}
|
|
3794
|
+
return { text: applyTextEdits(text, edits), changes, manualSteps };
|
|
3795
|
+
}
|
|
3796
|
+
|
|
3797
|
+
const DELIMITERS = ['"""', "'''", "```", '"', "'", "`"];
|
|
3798
|
+
const BACKTICK = "`";
|
|
3799
|
+
const ESCAPING_DELIMITER = '"';
|
|
3800
|
+
const ESCAPE = "\\";
|
|
3801
|
+
const COMMENT_START$1 = "#";
|
|
3802
|
+
const LINE_BREAK$2 = "\n";
|
|
3803
|
+
function closingOffset(text, delimiter, from) {
|
|
3804
|
+
if (delimiter !== ESCAPING_DELIMITER) {
|
|
3805
|
+
const close = text.indexOf(delimiter, from);
|
|
3806
|
+
return close === -1 ? void 0 : close;
|
|
3807
|
+
}
|
|
3808
|
+
for (let index = from; index < text.length; index += 1) {
|
|
3809
|
+
const char = text[index];
|
|
3810
|
+
if (char === ESCAPE) {
|
|
3811
|
+
index += 1;
|
|
3812
|
+
} else if (char === ESCAPING_DELIMITER || char === LINE_BREAK$2) {
|
|
3813
|
+
return char === ESCAPING_DELIMITER ? index : void 0;
|
|
3814
|
+
}
|
|
3815
|
+
}
|
|
3816
|
+
return void 0;
|
|
3817
|
+
}
|
|
3818
|
+
function literalAt(text, offset) {
|
|
3819
|
+
const delimiter = DELIMITERS.find((candidate) => text.startsWith(candidate, offset));
|
|
3820
|
+
if (delimiter === void 0) {
|
|
3821
|
+
return void 0;
|
|
3822
|
+
}
|
|
3823
|
+
const contentStart = offset + delimiter.length;
|
|
3824
|
+
const close = closingOffset(text, delimiter, contentStart);
|
|
3825
|
+
if (close === void 0) {
|
|
3826
|
+
return void 0;
|
|
3827
|
+
}
|
|
3828
|
+
const kind = delimiter.startsWith(BACKTICK) ? "backtick" : "string";
|
|
3829
|
+
const content = text.slice(contentStart, close);
|
|
3830
|
+
return { kind, start: offset, end: close + delimiter.length, contentStart, content };
|
|
3831
|
+
}
|
|
3832
|
+
function expressionAt(text, start) {
|
|
3833
|
+
const literals = [];
|
|
3834
|
+
let index = start;
|
|
3835
|
+
while (index < text.length && text[index] !== LINE_BREAK$2 && text[index] !== COMMENT_START$1) {
|
|
3836
|
+
const literal = literalAt(text, index);
|
|
3837
|
+
literals.push(...literal === void 0 ? [] : [literal]);
|
|
3838
|
+
index = literal?.end ?? index + 1;
|
|
3839
|
+
}
|
|
3840
|
+
return { literals, end: index };
|
|
3841
|
+
}
|
|
3842
|
+
function literalsBetween(text, start, end) {
|
|
3843
|
+
const literals = [];
|
|
3844
|
+
for (let index = start; index < end; ) {
|
|
3845
|
+
const literal = literalAt(text, index);
|
|
3846
|
+
literals.push(...literal === void 0 ? [] : [literal]);
|
|
3847
|
+
index = literal?.end ?? index + 1;
|
|
3848
|
+
}
|
|
3849
|
+
return literals;
|
|
3850
|
+
}
|
|
3851
|
+
const INTERPOLATION_OPEN = "{{";
|
|
3852
|
+
const INTERPOLATION_CLOSE = "}}";
|
|
3853
|
+
function interpolationAt(text, start) {
|
|
3854
|
+
const literals = [];
|
|
3855
|
+
for (let index = start + INTERPOLATION_OPEN.length; index < text.length; ) {
|
|
3856
|
+
if (text.startsWith(INTERPOLATION_CLOSE, index)) {
|
|
3857
|
+
return { start, end: index + INTERPOLATION_CLOSE.length, literals };
|
|
3858
|
+
}
|
|
3859
|
+
if (text[index] === LINE_BREAK$2) {
|
|
3860
|
+
return void 0;
|
|
3861
|
+
}
|
|
3862
|
+
const literal = literalAt(text, index);
|
|
3863
|
+
literals.push(...literal === void 0 ? [] : [literal]);
|
|
3864
|
+
index = literal?.end ?? index + 1;
|
|
3865
|
+
}
|
|
3866
|
+
return void 0;
|
|
3867
|
+
}
|
|
3868
|
+
function interpolationsOf(text) {
|
|
3869
|
+
const found = [];
|
|
3870
|
+
for (let open = text.indexOf(INTERPOLATION_OPEN); open !== -1; ) {
|
|
3871
|
+
const interpolation = interpolationAt(text, open);
|
|
3872
|
+
found.push(...interpolation === void 0 ? [] : [interpolation]);
|
|
3873
|
+
const next = interpolation?.end ?? open + INTERPOLATION_OPEN.length;
|
|
3874
|
+
open = text.indexOf(INTERPOLATION_OPEN, next);
|
|
3875
|
+
}
|
|
3876
|
+
return found;
|
|
3877
|
+
}
|
|
3878
|
+
|
|
3879
|
+
const RECIPE_NAME_RE = /^@?[A-Za-z_][A-Za-z0-9_-]*(?=[ \t:])/gm;
|
|
3880
|
+
const PARAMETER_RE = /^[+*$]*([A-Za-z_][A-Za-z0-9_-]*)(?:=([\s\S]*))?$/;
|
|
3881
|
+
const NAME_RE = /^[A-Za-z_][A-Za-z0-9_-]*$/;
|
|
3882
|
+
const COLON = ":";
|
|
3883
|
+
const EQUALS = "=";
|
|
3884
|
+
const OPEN_PAREN = "(";
|
|
3885
|
+
const CLOSE_PAREN = ")";
|
|
3886
|
+
const COMMENT_START = "#";
|
|
3887
|
+
const LINE_BREAK$1 = "\n";
|
|
3888
|
+
const BLANK_RE = /[ \t]/;
|
|
3889
|
+
const depthChange = (char) => char === OPEN_PAREN ? 1 : char === CLOSE_PAREN ? -1 : 0;
|
|
3890
|
+
function headerColon(text, from) {
|
|
3891
|
+
for (let index = from; index < text.length && text[index] !== LINE_BREAK$1; ) {
|
|
3892
|
+
const literal = literalAt(text, index);
|
|
3893
|
+
const char = text[index];
|
|
3894
|
+
if (literal !== void 0) {
|
|
3895
|
+
index = literal.end;
|
|
3896
|
+
continue;
|
|
3897
|
+
}
|
|
3898
|
+
if (char === COMMENT_START || char === COLON && text[index + 1] === EQUALS) {
|
|
3899
|
+
return void 0;
|
|
3900
|
+
}
|
|
3901
|
+
if (char === COLON) {
|
|
3902
|
+
return index;
|
|
3903
|
+
}
|
|
3904
|
+
index += 1;
|
|
3905
|
+
}
|
|
3906
|
+
return void 0;
|
|
3907
|
+
}
|
|
3908
|
+
function parameterWords(text, start, end) {
|
|
3909
|
+
const words = [];
|
|
3910
|
+
let wordStart;
|
|
3911
|
+
let depth = 0;
|
|
3912
|
+
for (let index = start; index < end; ) {
|
|
3913
|
+
const isBreak = depth === 0 && BLANK_RE.test(text[index] ?? "");
|
|
3914
|
+
if (isBreak && wordStart !== void 0) {
|
|
3915
|
+
words.push({ start: wordStart, end: index });
|
|
3916
|
+
}
|
|
3917
|
+
wordStart = isBreak ? void 0 : wordStart ?? index;
|
|
3918
|
+
const literal = isBreak ? void 0 : literalAt(text, index);
|
|
3919
|
+
depth += literal === void 0 ? depthChange(text[index]) : 0;
|
|
3920
|
+
index = literal?.end ?? index + 1;
|
|
3921
|
+
}
|
|
3922
|
+
return wordStart === void 0 ? words : [...words, { start: wordStart, end }];
|
|
3923
|
+
}
|
|
3924
|
+
function parameterDefault(text, word) {
|
|
3925
|
+
const written = text.slice(word.start, word.end);
|
|
3926
|
+
const match = PARAMETER_RE.exec(written);
|
|
3927
|
+
const value = match?.[2];
|
|
3928
|
+
if (match === null || value === void 0) {
|
|
3929
|
+
return [];
|
|
3930
|
+
}
|
|
3931
|
+
const defaultStart = word.end - value.length;
|
|
3932
|
+
const literals = literalsBetween(text, defaultStart, word.end);
|
|
3933
|
+
const target = NAME_RE.test(value) ? value : void 0;
|
|
3934
|
+
return [{ name: match[1], literals, target }];
|
|
3935
|
+
}
|
|
3936
|
+
function recipeHeaders(text) {
|
|
3937
|
+
return [...text.matchAll(RECIPE_NAME_RE)].flatMap((match) => {
|
|
3938
|
+
const nameEnd = match.index + match[0].length;
|
|
3939
|
+
const colon = headerColon(text, nameEnd);
|
|
3940
|
+
if (colon === void 0) {
|
|
3941
|
+
return [];
|
|
3942
|
+
}
|
|
3943
|
+
const words = parameterWords(text, nameEnd, colon);
|
|
3944
|
+
const defaults = words.flatMap((word) => parameterDefault(text, word));
|
|
3945
|
+
return [{ start: match.index, end: colon, defaults }];
|
|
3946
|
+
});
|
|
3947
|
+
}
|
|
3948
|
+
|
|
3949
|
+
const ASSIGNMENT_RE$1 = /^(?:export[ \t]+)?([A-Za-z_][A-Za-z0-9_-]*)[ \t]*:=[ \t]*/gm;
|
|
3950
|
+
const NAME_VALUE_RE = /^[A-Za-z_][A-Za-z0-9_-]*$/;
|
|
3951
|
+
const VARIABLE_INTERPOLATION_RE = /^[@+-]*\{\{[ \t]*([A-Za-z_][A-Za-z0-9_-]*)[ \t]*\}\}$/;
|
|
3952
|
+
const MASK$1 = "_";
|
|
3953
|
+
const BLANK = " ";
|
|
3954
|
+
function assignmentsOf$1(text) {
|
|
3955
|
+
return [...text.matchAll(ASSIGNMENT_RE$1)].map((match) => {
|
|
3956
|
+
const valueStart = match.index + match[0].length;
|
|
3957
|
+
const { literals, end } = expressionAt(text, valueStart);
|
|
3958
|
+
const value = text.slice(valueStart, end).trim();
|
|
3959
|
+
return { name: match[1], value, start: match.index, end, literals };
|
|
3960
|
+
});
|
|
3961
|
+
}
|
|
3962
|
+
function onlyString({ value, literals }) {
|
|
3963
|
+
const [literal] = literals;
|
|
3964
|
+
if (literals.length !== 1 || literal?.kind !== "string") {
|
|
3965
|
+
return void 0;
|
|
3966
|
+
}
|
|
3967
|
+
return value.length === literal.end - literal.start ? literal : void 0;
|
|
3968
|
+
}
|
|
3969
|
+
const stringRunsGenerator = (literal) => literal.kind === "string" && shellCommands(literal.content).some(runsGenerator);
|
|
3970
|
+
function computedDefinitions(name, literals) {
|
|
3971
|
+
const other = { name, kind: "command", runsGenerator: false };
|
|
3972
|
+
const isMaybeGenerator = literals.some(stringRunsGenerator);
|
|
3973
|
+
return isMaybeGenerator ? [{ name, kind: "command", runsGenerator: true }, other] : [other];
|
|
3974
|
+
}
|
|
3975
|
+
function assignmentDefinitions(assignment) {
|
|
3976
|
+
const { name, value } = assignment;
|
|
3977
|
+
if (NAME_VALUE_RE.test(value)) {
|
|
3978
|
+
return [{ name, kind: "reference", target: value }];
|
|
3979
|
+
}
|
|
3980
|
+
const literal = onlyString(assignment);
|
|
3981
|
+
return literal === void 0 ? computedDefinitions(name, assignment.literals) : [{ name, kind: "command", runsGenerator: stringRunsGenerator(literal) }];
|
|
3982
|
+
}
|
|
3983
|
+
function parameterDefinitions({ name, literals, target }) {
|
|
3984
|
+
const fromCommandLine = computedDefinitions(name, literals);
|
|
3985
|
+
return target === void 0 ? fromCommandLine : [{ name, kind: "reference", target }, ...fromCommandLine];
|
|
3986
|
+
}
|
|
3987
|
+
function shellText$1(text, spans) {
|
|
3988
|
+
const parts = [];
|
|
3989
|
+
let copiedUpTo = 0;
|
|
3990
|
+
for (const { start, end } of [...spans].sort((left, right) => left.start - right.start)) {
|
|
3991
|
+
parts.push(text.slice(copiedUpTo, start), BLANK.repeat(end - start));
|
|
3992
|
+
copiedUpTo = end;
|
|
3993
|
+
}
|
|
3994
|
+
parts.push(text.slice(copiedUpTo));
|
|
3995
|
+
const blanked = parts.join("");
|
|
3996
|
+
const interpolations = interpolationsOf(blanked);
|
|
3997
|
+
const masked = interpolations.reduce(
|
|
3998
|
+
(current, { start, end }) => current.slice(0, start) + MASK$1.repeat(end - start) + current.slice(end),
|
|
3999
|
+
blanked
|
|
4000
|
+
);
|
|
4001
|
+
return { text: masked, interpolations };
|
|
4002
|
+
}
|
|
4003
|
+
const literalCommands = (literals) => literals.flatMap((literal) => shellCommandsAt(literal.content, literal.contentStart));
|
|
4004
|
+
function variableValues$1(assignments) {
|
|
4005
|
+
const values = /* @__PURE__ */ new Map();
|
|
4006
|
+
for (const assignment of assignments) {
|
|
4007
|
+
const value = onlyString(assignment)?.content ?? assignment.value;
|
|
4008
|
+
values.set(assignment.name, [values.get(assignment.name), value].join(" ").trim());
|
|
3587
4009
|
}
|
|
4010
|
+
return values;
|
|
4011
|
+
}
|
|
4012
|
+
function computedProgram(written) {
|
|
4013
|
+
const literals = interpolationsOf(written).flatMap((interpolation) => interpolation.literals);
|
|
4014
|
+
return literals.some(stringRunsGenerator) ? "generator-or-other" : void 0;
|
|
4015
|
+
}
|
|
4016
|
+
function justfileVariables(text, values, programs) {
|
|
4017
|
+
const writtenAt = (word) => text.slice(word.start, word.end);
|
|
4018
|
+
const nameAt = (word) => VARIABLE_INTERPOLATION_RE.exec(writtenAt(word))?.[1];
|
|
4019
|
+
return {
|
|
4020
|
+
programAt: (word) => {
|
|
4021
|
+
const name = nameAt(word);
|
|
4022
|
+
const written = writtenAt(word);
|
|
4023
|
+
const found = name === void 0 ? computedProgram(written) : programs.get(name);
|
|
4024
|
+
return found === void 0 ? void 0 : { written, program: found };
|
|
4025
|
+
},
|
|
4026
|
+
referenceAt: (word) => {
|
|
4027
|
+
const name = nameAt(word);
|
|
4028
|
+
const value = name === void 0 ? void 0 : values.get(name);
|
|
4029
|
+
return value === void 0 ? void 0 : { written: writtenAt(word), value };
|
|
4030
|
+
}
|
|
4031
|
+
};
|
|
4032
|
+
}
|
|
4033
|
+
function migrateJustfile(text, file) {
|
|
4034
|
+
const lineOf = lineLocator(text);
|
|
4035
|
+
const assignments = assignmentsOf$1(text);
|
|
4036
|
+
const headers = recipeHeaders(text);
|
|
4037
|
+
const defaults = headers.flatMap((header) => header.defaults);
|
|
4038
|
+
const programs = variablePrograms([
|
|
4039
|
+
...assignments.flatMap(assignmentDefinitions),
|
|
4040
|
+
...defaults.flatMap(parameterDefinitions)
|
|
4041
|
+
]);
|
|
4042
|
+
const variables = justfileVariables(text, variableValues$1(assignments), programs);
|
|
4043
|
+
const shell = shellText$1(text, [...assignments, ...headers]);
|
|
4044
|
+
const commands = [
|
|
4045
|
+
...shellCommands(shell.text),
|
|
4046
|
+
...literalCommands(assignments.flatMap((assignment) => assignment.literals)),
|
|
4047
|
+
...literalCommands(defaults.flatMap((found) => found.literals)),
|
|
4048
|
+
...literalCommands(shell.interpolations.flatMap((found) => found.literals))
|
|
4049
|
+
];
|
|
4050
|
+
const locate = (offset) => `${file}:${lineOf(offset)}`;
|
|
4051
|
+
const { edits, changes, manualSteps } = commandWordFindings(commands, locate, variables);
|
|
3588
4052
|
return { text: applyTextEdits(text, edits), changes, manualSteps };
|
|
3589
4053
|
}
|
|
3590
4054
|
|
|
@@ -3699,7 +4163,7 @@ function makefileVariables(text, assignments, programs) {
|
|
|
3699
4163
|
const variables = {
|
|
3700
4164
|
programAt: (program) => {
|
|
3701
4165
|
const name = nameAt(program);
|
|
3702
|
-
const found = name === void 0 ? void 0 : programs.get(name);
|
|
4166
|
+
const found = name === void 0 ? void 0 : programs.get(name) ?? "generator-or-other";
|
|
3703
4167
|
const written = text.slice(program.start, program.end);
|
|
3704
4168
|
return found === void 0 ? void 0 : { written, program: found };
|
|
3705
4169
|
},
|
|
@@ -3723,6 +4187,140 @@ function migrateMakefile(text, file) {
|
|
|
3723
4187
|
return { text: applyTextEdits(text, edits), changes, manualSteps };
|
|
3724
4188
|
}
|
|
3725
4189
|
|
|
4190
|
+
const PARENT_SEPARATOR = ">";
|
|
4191
|
+
const PATH_SEPARATOR$2 = "/";
|
|
4192
|
+
const SCOPE_PREFIX = "@";
|
|
4193
|
+
function overrideTarget(key) {
|
|
4194
|
+
const child = key.split(PARENT_SEPARATOR).at(-1) ?? key;
|
|
4195
|
+
const segments = child.split(PATH_SEPARATOR$2);
|
|
4196
|
+
const isScoped = segments.length > 1 && segments.at(-2)?.startsWith(SCOPE_PREFIX) === true;
|
|
4197
|
+
const name = isScoped ? segments.slice(-2).join(PATH_SEPARATOR$2) : segments.at(-1) ?? child;
|
|
4198
|
+
const versionAt = name.indexOf(SCOPE_PREFIX, 1);
|
|
4199
|
+
return versionAt === -1 ? name : name.slice(0, versionAt);
|
|
4200
|
+
}
|
|
4201
|
+
function overriddenPackages(keys) {
|
|
4202
|
+
const targets = keys.map(overrideTarget);
|
|
4203
|
+
return [...new Set(targets.filter((target) => PACKAGE_RENAMES.has(target)))];
|
|
4204
|
+
}
|
|
4205
|
+
|
|
4206
|
+
const PATH_SEPARATOR$1 = ".";
|
|
4207
|
+
function catalogMaps(root, prefix = "") {
|
|
4208
|
+
const maps = mapsAt(root, CATALOG_FIELD).map((map) => ({
|
|
4209
|
+
name: DEFAULT_CATALOG,
|
|
4210
|
+
label: `${prefix}${CATALOG_FIELD}`,
|
|
4211
|
+
map
|
|
4212
|
+
}));
|
|
4213
|
+
for (const catalogs of mapsAt(root, NAMED_CATALOGS_FIELD)) {
|
|
4214
|
+
for (const { key, value } of textEntries(catalogs)) {
|
|
4215
|
+
if (isMap(value)) {
|
|
4216
|
+
const label = [prefix + NAMED_CATALOGS_FIELD, key.value].join(PATH_SEPARATOR$1);
|
|
4217
|
+
maps.push({ name: key.value, label, map: value });
|
|
4218
|
+
}
|
|
4219
|
+
}
|
|
4220
|
+
}
|
|
4221
|
+
return maps;
|
|
4222
|
+
}
|
|
4223
|
+
const manifestCatalogMaps = (manifest) => [
|
|
4224
|
+
...catalogMaps(manifest),
|
|
4225
|
+
...mapsAt(manifest, WORKSPACES_FIELD).flatMap(
|
|
4226
|
+
(workspaces) => catalogMaps(workspaces, `${WORKSPACES_FIELD}${PATH_SEPARATOR$1}`)
|
|
4227
|
+
)
|
|
4228
|
+
];
|
|
4229
|
+
function entriesInUse(manifests) {
|
|
4230
|
+
const inUse = new CatalogEntries();
|
|
4231
|
+
const fields = manifests.flatMap(
|
|
4232
|
+
(manifest) => DEPENDENCY_FIELDS.flatMap((field) => mapsAt(manifest, field))
|
|
4233
|
+
);
|
|
4234
|
+
for (const dependencies of fields) {
|
|
4235
|
+
const entries = specEntries(dependencies);
|
|
4236
|
+
const names = new Set(entries.map((entry) => entry.name));
|
|
4237
|
+
for (const { name, spec } of entries) {
|
|
4238
|
+
const catalog = spec === void 0 ? void 0 : catalogOfSpec(spec.value);
|
|
4239
|
+
const to = PACKAGE_RENAMES.get(name);
|
|
4240
|
+
if (catalog !== void 0 && to !== void 0 && names.has(to)) {
|
|
4241
|
+
inUse.add(catalog, name);
|
|
4242
|
+
}
|
|
4243
|
+
}
|
|
4244
|
+
}
|
|
4245
|
+
return inUse;
|
|
4246
|
+
}
|
|
4247
|
+
function nestedTexts(node) {
|
|
4248
|
+
if (node.kind !== "map") {
|
|
4249
|
+
return [];
|
|
4250
|
+
}
|
|
4251
|
+
return textEntries(node).flatMap(
|
|
4252
|
+
({ key, value }) => value.kind === "scalar" ? [{ key: key.value, value: value.value }] : nestedTexts(value)
|
|
4253
|
+
);
|
|
4254
|
+
}
|
|
4255
|
+
function addOverrideUses(documents, inUse) {
|
|
4256
|
+
const sections = documents.flatMap(
|
|
4257
|
+
(document) => [...OVERRIDE_FIELDS, PNPM_SETTINGS_FIELD].flatMap((field) => valuesAt(document, field))
|
|
4258
|
+
);
|
|
4259
|
+
for (const { key, value } of sections.flatMap(nestedTexts)) {
|
|
4260
|
+
const catalog = catalogOfSpec(value);
|
|
4261
|
+
const name = overrideTarget(key);
|
|
4262
|
+
if (catalog !== void 0 && PACKAGE_RENAMES.has(name)) {
|
|
4263
|
+
inUse.add(catalog, name);
|
|
4264
|
+
}
|
|
4265
|
+
}
|
|
4266
|
+
}
|
|
4267
|
+
function planCatalogs({
|
|
4268
|
+
manifests,
|
|
4269
|
+
catalogFiles,
|
|
4270
|
+
isWorkspaceRoot
|
|
4271
|
+
}) {
|
|
4272
|
+
const inUse = entriesInUse(manifests);
|
|
4273
|
+
addOverrideUses([...manifests, ...catalogFiles], inUse);
|
|
4274
|
+
const kept = new CatalogEntries();
|
|
4275
|
+
const defined = new CatalogEntries();
|
|
4276
|
+
const catalogs = [
|
|
4277
|
+
...catalogFiles.flatMap((file) => catalogMaps(file)),
|
|
4278
|
+
...manifests.flatMap(manifestCatalogMaps)
|
|
4279
|
+
];
|
|
4280
|
+
for (const { name: catalog, map } of catalogs) {
|
|
4281
|
+
const entries = specEntries(map);
|
|
4282
|
+
const names = new Set(entries.map((entry) => entry.name));
|
|
4283
|
+
for (const { name, spec } of entries) {
|
|
4284
|
+
defined.add(catalog, name);
|
|
4285
|
+
const to = PACKAGE_RENAMES.get(name);
|
|
4286
|
+
const stays = spec === void 0 || inUse.has(catalog, name);
|
|
4287
|
+
if (to !== void 0 && !names.has(to) && stays) {
|
|
4288
|
+
kept.add(catalog, name);
|
|
4289
|
+
}
|
|
4290
|
+
}
|
|
4291
|
+
}
|
|
4292
|
+
return { inUse, kept, defined, isWorkspaceRoot };
|
|
4293
|
+
}
|
|
4294
|
+
|
|
4295
|
+
const PNPM_OVERRIDES = "overrides";
|
|
4296
|
+
function isSuccessorAlias(key, value) {
|
|
4297
|
+
const successor = PACKAGE_RENAMES.get(overrideTarget(key));
|
|
4298
|
+
return value.kind === "scalar" && value.value.startsWith(NPM_SPECIFIER_PREFIX) && packageReference(value.value).name === successor;
|
|
4299
|
+
}
|
|
4300
|
+
function overriddenOldPackages(node) {
|
|
4301
|
+
const names = node.kind === "map" ? textEntries(node).flatMap(
|
|
4302
|
+
({ key, value }) => isSuccessorAlias(key.value, value) ? [] : [overrideTarget(key.value), ...overriddenOldPackages(value)]
|
|
4303
|
+
) : documentStrings([node]).map((string) => packageReference(string.value).name);
|
|
4304
|
+
return [...new Set(names.filter((name) => PACKAGE_RENAMES.has(name)))];
|
|
4305
|
+
}
|
|
4306
|
+
function aliasedIn(node) {
|
|
4307
|
+
if (node.kind !== "map") {
|
|
4308
|
+
return [];
|
|
4309
|
+
}
|
|
4310
|
+
return textEntries(node).flatMap(
|
|
4311
|
+
({ key, value }) => isSuccessorAlias(key.value, value) ? [overrideTarget(key.value)] : aliasedIn(value)
|
|
4312
|
+
);
|
|
4313
|
+
}
|
|
4314
|
+
function successorAliasedPackages(root) {
|
|
4315
|
+
const fields = [...OVERRIDE_FIELDS].flatMap((field) => mapsAt(root, field));
|
|
4316
|
+
const pnpm = mapsAt(root, PNPM_SETTINGS_FIELD).flatMap((map) => mapsAt(map, PNPM_OVERRIDES));
|
|
4317
|
+
return [...new Set([...fields, ...pnpm].flatMap(aliasedIn))];
|
|
4318
|
+
}
|
|
4319
|
+
function aliasedPackagesFor(aliases, filePath) {
|
|
4320
|
+
const applying = aliases.filter(({ path }) => isAtOrAbove(path, filePath));
|
|
4321
|
+
return new Set(applying.flatMap(({ names }) => [...names]));
|
|
4322
|
+
}
|
|
4323
|
+
|
|
3726
4324
|
function oldPackagesNamedBy(node) {
|
|
3727
4325
|
const values = documentStrings([node]).map((string) => packageReference(string.value).name);
|
|
3728
4326
|
const names = [...nestedKeys(node).map(overrideTarget), ...values];
|
|
@@ -3735,7 +4333,8 @@ function reportSettingSections(settings, file, findings) {
|
|
|
3735
4333
|
}
|
|
3736
4334
|
const field = `${file.prefix}${key.value}`;
|
|
3737
4335
|
const isOverride = file.overrideSections.has(key.value);
|
|
3738
|
-
|
|
4336
|
+
const names = isOverride ? overriddenOldPackages(value) : oldPackagesNamedBy(value);
|
|
4337
|
+
for (const name of names) {
|
|
3739
4338
|
findings.manualSteps.push(
|
|
3740
4339
|
isOverride ? { kind: "override-names-package", field, name } : { kind: "setting-names-package", field, name }
|
|
3741
4340
|
);
|
|
@@ -3806,7 +4405,18 @@ function migrateBrowserField(manifest, findings) {
|
|
|
3806
4405
|
}
|
|
3807
4406
|
}
|
|
3808
4407
|
}
|
|
4408
|
+
function reportOldPackagePaths(node, prefix, findings) {
|
|
4409
|
+
for (const value of documentStrings([node])) {
|
|
4410
|
+
const name = oldPackageInNodeModules(value.value);
|
|
4411
|
+
const to = name === void 0 ? void 0 : PACKAGE_RENAMES.get(name);
|
|
4412
|
+
if (name !== void 0 && to !== void 0) {
|
|
4413
|
+
const location = [...prefix, ...value.path].join(PATH_SEPARATOR);
|
|
4414
|
+
findings.manualSteps.push({ kind: "old-package-path", location, path: value.value, to });
|
|
4415
|
+
}
|
|
4416
|
+
}
|
|
4417
|
+
}
|
|
3809
4418
|
|
|
4419
|
+
const TYPES_VERSIONS_FIELD = "typesVersions";
|
|
3810
4420
|
function migrateDependencyFields(manifest, target, findings) {
|
|
3811
4421
|
for (const field of DEPENDENCY_FIELDS) {
|
|
3812
4422
|
for (const dependencies of mapsAt(manifest, field)) {
|
|
@@ -3852,7 +4462,7 @@ const PNPM_SETTINGS = {
|
|
|
3852
4462
|
};
|
|
3853
4463
|
function reportSettings(manifest, findings) {
|
|
3854
4464
|
for (const field of OVERRIDE_FIELDS) {
|
|
3855
|
-
for (const name of valuesAt(manifest, field).flatMap(
|
|
4465
|
+
for (const name of valuesAt(manifest, field).flatMap(overriddenOldPackages)) {
|
|
3856
4466
|
findings.manualSteps.push({ kind: "override-names-package", field, name });
|
|
3857
4467
|
}
|
|
3858
4468
|
}
|
|
@@ -3860,10 +4470,10 @@ function reportSettings(manifest, findings) {
|
|
|
3860
4470
|
reportSettingSections(settings, PNPM_SETTINGS, findings);
|
|
3861
4471
|
}
|
|
3862
4472
|
}
|
|
3863
|
-
function reportOldPeers(manifest, findings) {
|
|
4473
|
+
function reportOldPeers(manifest, aliased, findings) {
|
|
3864
4474
|
const dependencies = new Set(declaredNames(manifest));
|
|
3865
4475
|
for (const [dependent, { peer, range }] of OLD_PEER_DEPENDENTS) {
|
|
3866
|
-
if (dependencies.has(dependent)) {
|
|
4476
|
+
if (dependencies.has(dependent) && !aliased.has(peer)) {
|
|
3867
4477
|
findings.manualSteps.push({ kind: "old-peer-needed", dependent, peer, range });
|
|
3868
4478
|
}
|
|
3869
4479
|
}
|
|
@@ -3875,11 +4485,14 @@ function migrateManifestMap(manifest, target, findings) {
|
|
|
3875
4485
|
migrateCatalogs$1(manifest, target, findings);
|
|
3876
4486
|
migrateSubpathImports(manifest, findings);
|
|
3877
4487
|
migrateBrowserField(manifest, findings);
|
|
4488
|
+
for (const versions of valuesAt(manifest, TYPES_VERSIONS_FIELD)) {
|
|
4489
|
+
reportOldPackagePaths(versions, [TYPES_VERSIONS_FIELD], findings);
|
|
4490
|
+
}
|
|
3878
4491
|
reportSettings(manifest, findings);
|
|
3879
4492
|
for (const jest of valuesAt(manifest, JEST_FIELD)) {
|
|
3880
4493
|
findings.manualSteps.push(...jestConfigSteps(jest, [JEST_FIELD]));
|
|
3881
4494
|
}
|
|
3882
|
-
reportOldPeers(manifest, findings);
|
|
4495
|
+
reportOldPeers(manifest, target.aliased ?? /* @__PURE__ */ new Set(), findings);
|
|
3883
4496
|
}
|
|
3884
4497
|
function migratePackageManifest(text, read, target) {
|
|
3885
4498
|
if (read.kind === "unreadable") {
|
|
@@ -3914,6 +4527,73 @@ function oldPackagePatchSteps(fileName) {
|
|
|
3914
4527
|
return name === void 0 || to === void 0 ? [] : [{ kind: "old-package-patch", name, to }];
|
|
3915
4528
|
}
|
|
3916
4529
|
|
|
4530
|
+
const STEP_SHELL_KEY = "shell";
|
|
4531
|
+
const DEFAULT_SHELL_PATH = ["defaults", "run", STEP_SHELL_KEY];
|
|
4532
|
+
const COMMAND_LINE_SHELLS = /* @__PURE__ */ new Set([
|
|
4533
|
+
...["sh", "bash", "dash", "ash", "zsh", "ksh"],
|
|
4534
|
+
...["pwsh", "powershell", "cmd"],
|
|
4535
|
+
...["msys2", "wsl-bash"]
|
|
4536
|
+
]);
|
|
4537
|
+
const ENV_PROGRAM = "env";
|
|
4538
|
+
const ENV_OPTIONS_WITH_VALUE = /* @__PURE__ */ new Set(["-u", "--unset", "-C", "--chdir"]);
|
|
4539
|
+
const OPTION_START = "-";
|
|
4540
|
+
const ASSIGNMENT = "=";
|
|
4541
|
+
const PATH_SEPARATOR_RE = /[/\\]/;
|
|
4542
|
+
const WINDOWS_EXECUTABLE_RE = /\.exe$/i;
|
|
4543
|
+
const WHITESPACE_RE = /\s+/;
|
|
4544
|
+
const programName = (word) => (word.split(PATH_SEPARATOR_RE).at(-1) ?? "").replace(WINDOWS_EXECUTABLE_RE, "");
|
|
4545
|
+
function envPrefixLength(words) {
|
|
4546
|
+
let index = 0;
|
|
4547
|
+
while (index < words.length) {
|
|
4548
|
+
const word = words[index] ?? "";
|
|
4549
|
+
if (ENV_OPTIONS_WITH_VALUE.has(word)) {
|
|
4550
|
+
index += 2;
|
|
4551
|
+
} else if (word.startsWith(OPTION_START) || word.includes(ASSIGNMENT)) {
|
|
4552
|
+
index += 1;
|
|
4553
|
+
} else {
|
|
4554
|
+
break;
|
|
4555
|
+
}
|
|
4556
|
+
}
|
|
4557
|
+
return index;
|
|
4558
|
+
}
|
|
4559
|
+
function shellProgram(shell) {
|
|
4560
|
+
const words = shell.trim().split(WHITESPACE_RE);
|
|
4561
|
+
const first = programName(words[0] ?? "");
|
|
4562
|
+
if (first !== ENV_PROGRAM) {
|
|
4563
|
+
return first;
|
|
4564
|
+
}
|
|
4565
|
+
const rest = words.slice(1);
|
|
4566
|
+
return programName(rest[envPrefixLength(rest)] ?? "");
|
|
4567
|
+
}
|
|
4568
|
+
const endsWith = (path, keys) => keys.every((key, index) => path[path.length - keys.length + index] === key);
|
|
4569
|
+
const isDefaultShell = (value) => endsWith(value.path, DEFAULT_SHELL_PATH);
|
|
4570
|
+
function scopeOf(value) {
|
|
4571
|
+
const keys = isDefaultShell(value) ? DEFAULT_SHELL_PATH.length : 1;
|
|
4572
|
+
return JSON.stringify(value.path.slice(0, -keys));
|
|
4573
|
+
}
|
|
4574
|
+
function stepShells(strings) {
|
|
4575
|
+
const shells = strings.filter((value) => value.path.at(-1) === STEP_SHELL_KEY);
|
|
4576
|
+
const isOwnShell = (value) => !isDefaultShell(value);
|
|
4577
|
+
const ordered = [...shells.filter(isDefaultShell), ...shells.filter(isOwnShell)];
|
|
4578
|
+
const byScope = new Map(ordered.map((value) => [scopeOf(value), value.value]));
|
|
4579
|
+
return (value) => {
|
|
4580
|
+
for (let depth = value.path.length - 1; depth >= 0; depth -= 1) {
|
|
4581
|
+
const shell = byScope.get(JSON.stringify(value.path.slice(0, depth)));
|
|
4582
|
+
if (shell !== void 0) {
|
|
4583
|
+
return COMMAND_LINE_SHELLS.has(shellProgram(shell)) ? void 0 : shell;
|
|
4584
|
+
}
|
|
4585
|
+
}
|
|
4586
|
+
return void 0;
|
|
4587
|
+
};
|
|
4588
|
+
}
|
|
4589
|
+
function otherShellFindings(values, shellOf, locate) {
|
|
4590
|
+
const manualSteps = values.flatMap((value) => {
|
|
4591
|
+
const shell = shellOf(value);
|
|
4592
|
+
return shell === void 0 || !namesOriginalPackage(value.value) ? [] : [{ kind: "script-not-shell", location: locate(value.start), shell }];
|
|
4593
|
+
});
|
|
4594
|
+
return { edits: [], changes: [], manualSteps };
|
|
4595
|
+
}
|
|
4596
|
+
|
|
3917
4597
|
const YAML_COMMAND_KEYS = /* @__PURE__ */ new Set([
|
|
3918
4598
|
"run",
|
|
3919
4599
|
"script",
|
|
@@ -4017,9 +4697,10 @@ function appliedFindings(text, found) {
|
|
|
4017
4697
|
};
|
|
4018
4698
|
}
|
|
4019
4699
|
function migrateYamlCommands(text, file, strings, keys = YAML_COMMAND_KEYS) {
|
|
4020
|
-
const values = valuesOf(strings, keys);
|
|
4021
4700
|
const lineOf = lineLocator(text);
|
|
4022
4701
|
const locate = (offset) => `${file}:${lineOf(offset)}`;
|
|
4702
|
+
const shellOf = stepShells(strings);
|
|
4703
|
+
const values = valuesOf(strings, keys).filter((value) => shellOf(value) === void 0);
|
|
4023
4704
|
const commandValues = new Set(values.filter((value) => !isExecFormItem(value)));
|
|
4024
4705
|
const shellValues = strings.filter(
|
|
4025
4706
|
(value) => commandValues.has(value) || isEnvironmentValue(value)
|
|
@@ -4027,7 +4708,8 @@ function migrateYamlCommands(text, file, strings, keys = YAML_COMMAND_KEYS) {
|
|
|
4027
4708
|
const variables = environmentVariables(text, strings);
|
|
4028
4709
|
return appliedFindings(text, [
|
|
4029
4710
|
...shellValues.map((value) => valueFindings(text, value, locate, variables)),
|
|
4030
|
-
commandWordFindings(execFormCommands(text, values.filter(isExecFormItem)), locate)
|
|
4711
|
+
commandWordFindings(execFormCommands(text, values.filter(isExecFormItem)), locate),
|
|
4712
|
+
otherShellFindings(valuesOf(strings, keys), shellOf, locate)
|
|
4031
4713
|
]);
|
|
4032
4714
|
}
|
|
4033
4715
|
function migrateYamlPathCommands(text, strings, patterns) {
|
|
@@ -4115,16 +4797,6 @@ const COMPILER_OPTIONS_FIELD = "compilerOptions";
|
|
|
4115
4797
|
const PATHS_FIELD = "paths";
|
|
4116
4798
|
const TYPES_FIELD = "types";
|
|
4117
4799
|
const FIELD_SEPARATOR = ".";
|
|
4118
|
-
function reportOldPackagePaths(config, findings) {
|
|
4119
|
-
for (const value of documentStrings([config])) {
|
|
4120
|
-
const name = oldPackageInNodeModules(value.value);
|
|
4121
|
-
const to = name === void 0 ? void 0 : PACKAGE_RENAMES.get(name);
|
|
4122
|
-
if (name !== void 0 && to !== void 0) {
|
|
4123
|
-
const location = value.path.join(FIELD_SEPARATOR);
|
|
4124
|
-
findings.manualSteps.push({ kind: "old-package-path", location, path: value.value, to });
|
|
4125
|
-
}
|
|
4126
|
-
}
|
|
4127
|
-
}
|
|
4128
4800
|
function migrateCompilerOptions(options, findings) {
|
|
4129
4801
|
for (const paths of mapsAt(options, PATHS_FIELD)) {
|
|
4130
4802
|
const field = [COMPILER_OPTIONS_FIELD, PATHS_FIELD].join(FIELD_SEPARATOR);
|
|
@@ -4146,7 +4818,7 @@ function migrateTsconfig(text, read) {
|
|
|
4146
4818
|
for (const options of mapsAt(config, COMPILER_OPTIONS_FIELD)) {
|
|
4147
4819
|
migrateCompilerOptions(options, findings);
|
|
4148
4820
|
}
|
|
4149
|
-
reportOldPackagePaths(config, findings);
|
|
4821
|
+
reportOldPackagePaths(config, [], findings);
|
|
4150
4822
|
}
|
|
4151
4823
|
const { edits, changes, manualSteps } = findings;
|
|
4152
4824
|
return { text: applyTextEdits(text, edits), changes, manualSteps };
|
|
@@ -4215,7 +4887,7 @@ const SHELL_EXTENSIONS = /* @__PURE__ */ new Set([".sh", ".bash", ".zsh"]);
|
|
|
4215
4887
|
const MAKEFILE_EXTENSION = ".mk";
|
|
4216
4888
|
const YAML_EXTENSIONS = /* @__PURE__ */ new Set([".yml", ".yaml"]);
|
|
4217
4889
|
const MAKEFILE_NAMES = /* @__PURE__ */ new Set(["Makefile", "makefile", "GNUmakefile"]);
|
|
4218
|
-
const
|
|
4890
|
+
const JUSTFILE_NAMES = /* @__PURE__ */ new Set(["justfile", "Justfile", ".justfile"]);
|
|
4219
4891
|
const DOCKERFILE_NAMES = /* @__PURE__ */ new Set(["Dockerfile", "Containerfile"]);
|
|
4220
4892
|
const HUSKY_FOLDER = ".husky/";
|
|
4221
4893
|
const HUSKY_INTERNALS = ".husky/_/";
|
|
@@ -4289,10 +4961,11 @@ function joinedNames(sets) {
|
|
|
4289
4961
|
}
|
|
4290
4962
|
function withNamedImportMaps(declarations, importMaps) {
|
|
4291
4963
|
const mapNames = new Map(declarations.map(({ path, names }) => [path, names]));
|
|
4292
|
-
return declarations.filter(({ path }) => !importMaps.has(path)).map((
|
|
4964
|
+
return declarations.filter(({ path }) => !importMaps.has(path)).map((declaration) => {
|
|
4965
|
+
const { path, names } = declaration;
|
|
4293
4966
|
const maps = [...importMaps].filter(([, configs]) => configs.includes(path));
|
|
4294
4967
|
const named = maps.flatMap(([map]) => mapNames.has(map) ? [mapNames.get(map)] : []);
|
|
4295
|
-
return {
|
|
4968
|
+
return { ...declaration, names: joinedNames([names, ...named]) };
|
|
4296
4969
|
});
|
|
4297
4970
|
}
|
|
4298
4971
|
|
|
@@ -4300,8 +4973,9 @@ const isHuskyHook = (path) => (path.startsWith(HUSKY_FOLDER) || path.includes(`/
|
|
|
4300
4973
|
const isDependabotConfig = (path) => [...DEPENDABOT_FILES].some((file) => path === file || path.endsWith(`/${file}`));
|
|
4301
4974
|
function migrateSource(text, path, context) {
|
|
4302
4975
|
const strings = context.scanner.scan(text, path);
|
|
4976
|
+
const kept = localPackagesFor(context.manifests, path);
|
|
4303
4977
|
const migrated = chain(
|
|
4304
|
-
migrateModuleSpecifiers(text, strings, context.version),
|
|
4978
|
+
migrateModuleSpecifiers(text, strings, context.version, kept),
|
|
4305
4979
|
(renamed) => context.rewriter.rewrite(renamed, path)
|
|
4306
4980
|
);
|
|
4307
4981
|
const imports = importedSpecifiers(text, strings);
|
|
@@ -4353,18 +5027,24 @@ const COMMAND_CONFIG_KINDS = [
|
|
|
4353
5027
|
)
|
|
4354
5028
|
}
|
|
4355
5029
|
];
|
|
5030
|
+
const yamlCommandsStep = (path, isPart) => (text, read) => isPart || read.kind === "read" && isApiDescription(read.documents) ? unchanged(text) : stringsStep((current, strings) => migrateYamlCommands(current, path, strings))(text, read);
|
|
5031
|
+
const manifestTarget = ({ version, catalogs, aliases }, path) => ({
|
|
5032
|
+
version,
|
|
5033
|
+
catalogs,
|
|
5034
|
+
aliased: aliasedPackagesFor(aliases, path)
|
|
5035
|
+
});
|
|
4356
5036
|
const FILE_KINDS = [
|
|
4357
5037
|
{
|
|
4358
5038
|
matches: (path) => baseName(path) === MANIFEST_FILE,
|
|
4359
|
-
migrate: jsonConfig((
|
|
4360
|
-
(text, read) => migratePackageManifest(text, read,
|
|
5039
|
+
migrate: jsonConfig((context, path) => [
|
|
5040
|
+
(text, read) => migratePackageManifest(text, read, manifestTarget(context, path)),
|
|
4361
5041
|
jsonCommandsStep(MANIFEST_COMMAND_PATHS)
|
|
4362
5042
|
])
|
|
4363
5043
|
},
|
|
4364
5044
|
{
|
|
4365
5045
|
matches: (path) => YAML_MANIFEST_FILES.has(baseName(path)),
|
|
4366
|
-
migrate: yamlConfig((
|
|
4367
|
-
(text, read) => migratePackageManifest(text, read,
|
|
5046
|
+
migrate: yamlConfig((context, path) => [
|
|
5047
|
+
(text, read) => migratePackageManifest(text, read, manifestTarget(context, path)),
|
|
4368
5048
|
yamlPathCommands(MANIFEST_COMMAND_PATHS)
|
|
4369
5049
|
])
|
|
4370
5050
|
},
|
|
@@ -4424,8 +5104,8 @@ const FILE_KINDS = [
|
|
|
4424
5104
|
{
|
|
4425
5105
|
matches: (path) => YAML_EXTENSIONS.has(extensionOf(path)),
|
|
4426
5106
|
migrate: whenNamed(
|
|
4427
|
-
yamlConfig((
|
|
4428
|
-
|
|
5107
|
+
yamlConfig((context, path) => [
|
|
5108
|
+
yamlCommandsStep(path, context.apiDescriptionParts.has(path))
|
|
4429
5109
|
])
|
|
4430
5110
|
)
|
|
4431
5111
|
},
|
|
@@ -4438,7 +5118,11 @@ const FILE_KINDS = [
|
|
|
4438
5118
|
migrate: whenNamed((text, path) => migrateMakefile(text, path))
|
|
4439
5119
|
},
|
|
4440
5120
|
{
|
|
4441
|
-
matches: (path) =>
|
|
5121
|
+
matches: (path) => JUSTFILE_NAMES.has(baseName(path)),
|
|
5122
|
+
migrate: whenNamed((text, path) => migrateJustfile(text, path))
|
|
5123
|
+
},
|
|
5124
|
+
{
|
|
5125
|
+
matches: (path) => SHELL_EXTENSIONS.has(extensionOf(path)) || isHuskyHook(path),
|
|
4442
5126
|
migrate: whenNamed((text, path) => migrateCommandLines(text, path))
|
|
4443
5127
|
}
|
|
4444
5128
|
];
|
|
@@ -4452,6 +5136,58 @@ function fileMigrationFor(path, namedImportMaps = NO_NAMED_IMPORT_MAPS) {
|
|
|
4452
5136
|
return FILE_KINDS.find((kind) => kind.matches(path))?.migrate;
|
|
4453
5137
|
}
|
|
4454
5138
|
|
|
5139
|
+
const NO_API_DESCRIPTION_PARTS = /* @__PURE__ */ new Set();
|
|
5140
|
+
const JSON_EXTENSION = ".json";
|
|
5141
|
+
const isYaml = (path) => YAML_EXTENSIONS.has(extensionOf(path));
|
|
5142
|
+
const isDescriptionFormat = (path) => isYaml(path) || extensionOf(path) === JSON_EXTENSION;
|
|
5143
|
+
async function textOf(path, files) {
|
|
5144
|
+
const read = await files.read(path);
|
|
5145
|
+
return read.kind === "read" ? read.text : void 0;
|
|
5146
|
+
}
|
|
5147
|
+
function documentsOf(path, text, readers) {
|
|
5148
|
+
const parsed = (isYaml(path) ? readers.yaml : readers.json).read(text);
|
|
5149
|
+
return parsed.kind === "read" ? [...parsed.documents] : void 0;
|
|
5150
|
+
}
|
|
5151
|
+
async function hasNamingYaml(paths, files) {
|
|
5152
|
+
for (const path of paths.filter(isYaml)) {
|
|
5153
|
+
const text = await textOf(path, files);
|
|
5154
|
+
if (text !== void 0 && namesOriginalPackage(text)) {
|
|
5155
|
+
return true;
|
|
5156
|
+
}
|
|
5157
|
+
}
|
|
5158
|
+
return false;
|
|
5159
|
+
}
|
|
5160
|
+
async function descriptionRoots(paths, { files, readers }) {
|
|
5161
|
+
const roots = /* @__PURE__ */ new Map();
|
|
5162
|
+
for (const path of paths.filter(isDescriptionFormat)) {
|
|
5163
|
+
const text = await textOf(path, files);
|
|
5164
|
+
const documents = text !== void 0 && mayBeApiDescription(text) ? documentsOf(path, text, readers) : void 0;
|
|
5165
|
+
if (documents !== void 0 && isApiDescription(documents)) {
|
|
5166
|
+
roots.set(path, documents);
|
|
5167
|
+
}
|
|
5168
|
+
}
|
|
5169
|
+
return roots;
|
|
5170
|
+
}
|
|
5171
|
+
async function apiDescriptionParts(paths, dependencies) {
|
|
5172
|
+
if (!await hasNamingYaml(paths, dependencies.files)) {
|
|
5173
|
+
return NO_API_DESCRIPTION_PARTS;
|
|
5174
|
+
}
|
|
5175
|
+
const listed = new Set(paths.filter(isDescriptionFormat));
|
|
5176
|
+
const roots = await descriptionRoots(paths, dependencies);
|
|
5177
|
+
const parts = /* @__PURE__ */ new Set();
|
|
5178
|
+
const pending = [...roots].flatMap(([path, documents]) => referencedFiles(path, documents));
|
|
5179
|
+
for (let path = pending.pop(); path !== void 0; path = pending.pop()) {
|
|
5180
|
+
if (!listed.has(path) || roots.has(path) || parts.has(path)) {
|
|
5181
|
+
continue;
|
|
5182
|
+
}
|
|
5183
|
+
parts.add(path);
|
|
5184
|
+
const text = await textOf(path, dependencies.files);
|
|
5185
|
+
const documents = text === void 0 ? void 0 : documentsOf(path, text, dependencies.readers);
|
|
5186
|
+
pending.push(...documents === void 0 ? [] : referencedFiles(path, documents));
|
|
5187
|
+
}
|
|
5188
|
+
return parts;
|
|
5189
|
+
}
|
|
5190
|
+
|
|
4455
5191
|
const readJson = (text, readers) => readers.json.read(text);
|
|
4456
5192
|
const readYaml = (text, readers) => readers.yaml.read(text);
|
|
4457
5193
|
function planSourceOf(path, namedImportMaps) {
|
|
@@ -4472,27 +5208,6 @@ function planSourceOf(path, namedImportMaps) {
|
|
|
4472
5208
|
return isCatalogFile ? { role: "catalogs", read: readYaml } : void 0;
|
|
4473
5209
|
}
|
|
4474
5210
|
|
|
4475
|
-
async function planFile(path, dependencies, target) {
|
|
4476
|
-
const migrate = fileMigrationFor(path, target.importMaps);
|
|
4477
|
-
if (migrate === void 0) {
|
|
4478
|
-
return { kind: "not-migrated" };
|
|
4479
|
-
}
|
|
4480
|
-
const read = await dependencies.files.read(path);
|
|
4481
|
-
if (read.kind === "skipped") {
|
|
4482
|
-
return read;
|
|
4483
|
-
}
|
|
4484
|
-
const { rewriter, scanner, readers } = dependencies;
|
|
4485
|
-
const { version, catalogs, manifests } = target;
|
|
4486
|
-
const context = { version, catalogs, manifests, rewriter, scanner, readers };
|
|
4487
|
-
const migration = migrate(read.text, path, context);
|
|
4488
|
-
const isChanged = migration.text !== read.text;
|
|
4489
|
-
const { changes, manualSteps } = migration;
|
|
4490
|
-
if (isChanged || manualSteps.length > 0) {
|
|
4491
|
-
dependencies.logger.info("file_migrated", { path, isChanged, changes, manualSteps });
|
|
4492
|
-
}
|
|
4493
|
-
const report = { path, isChanged, changes, manualSteps };
|
|
4494
|
-
return { kind: "planned", file: { report, text: isChanged ? migration.text : void 0 } };
|
|
4495
|
-
}
|
|
4496
5211
|
async function readForPlan(path, source, dependencies) {
|
|
4497
5212
|
const read = await dependencies.files.read(path);
|
|
4498
5213
|
if (read.kind !== "read") {
|
|
@@ -4516,9 +5231,22 @@ function marksWorkspaceRoot(path, roots) {
|
|
|
4516
5231
|
return manifests.some((manifest) => valuesAt(manifest, WORKSPACES_FIELD).length > 0);
|
|
4517
5232
|
}
|
|
4518
5233
|
const DECLARED_NAMES = { manifest: declaredNames, "import-map": importMapNames, catalogs: void 0 };
|
|
5234
|
+
function declarationsOf(path, role, roots) {
|
|
5235
|
+
const names = DECLARED_NAMES[role];
|
|
5236
|
+
if (names === void 0) {
|
|
5237
|
+
return [];
|
|
5238
|
+
}
|
|
5239
|
+
const local = role === "manifest" ? (roots ?? []).flatMap(localPackageNames) : [];
|
|
5240
|
+
return [{ path, names: roots && new Set(roots.flatMap(names)), localPackages: new Set(local) }];
|
|
5241
|
+
}
|
|
5242
|
+
function aliasesOf(path, roots) {
|
|
5243
|
+
const names = (roots ?? []).flatMap(successorAliasedPackages);
|
|
5244
|
+
return names.length === 0 ? [] : [{ path, names: new Set(names) }];
|
|
5245
|
+
}
|
|
4519
5246
|
async function planProjectTarget(paths, dependencies, version) {
|
|
4520
5247
|
const documents = { manifest: [], catalogs: [] };
|
|
4521
5248
|
const manifests = [];
|
|
5249
|
+
const aliases = [];
|
|
4522
5250
|
let isWorkspaceRoot = false;
|
|
4523
5251
|
const importMaps = await namedImportMaps(paths, dependencies.files, dependencies.readers);
|
|
4524
5252
|
for (const path of paths) {
|
|
@@ -4531,17 +5259,45 @@ async function planProjectTarget(paths, dependencies, version) {
|
|
|
4531
5259
|
if (namesOriginal && source.role !== "import-map") {
|
|
4532
5260
|
documents[source.role].push(...roots ?? []);
|
|
4533
5261
|
}
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
manifests.push({ path, names: roots && new Set(roots.flatMap(names)) });
|
|
4537
|
-
}
|
|
5262
|
+
manifests.push(...declarationsOf(path, source.role, roots));
|
|
5263
|
+
aliases.push(...aliasesOf(path, roots));
|
|
4538
5264
|
}
|
|
4539
5265
|
const catalogs = planCatalogs({
|
|
4540
5266
|
manifests: documents.manifest,
|
|
4541
5267
|
catalogFiles: documents.catalogs,
|
|
4542
5268
|
isWorkspaceRoot
|
|
4543
5269
|
});
|
|
4544
|
-
|
|
5270
|
+
const declarations = withNamedImportMaps(manifests, importMaps);
|
|
5271
|
+
const parts = await apiDescriptionParts(paths, dependencies);
|
|
5272
|
+
return {
|
|
5273
|
+
...{ version, catalogs, manifests: declarations, aliases, importMaps },
|
|
5274
|
+
apiDescriptionParts: parts
|
|
5275
|
+
};
|
|
5276
|
+
}
|
|
5277
|
+
|
|
5278
|
+
async function planFile(path, dependencies, target) {
|
|
5279
|
+
const migrate = fileMigrationFor(path, target.importMaps);
|
|
5280
|
+
if (migrate === void 0) {
|
|
5281
|
+
return { kind: "not-migrated" };
|
|
5282
|
+
}
|
|
5283
|
+
const read = await dependencies.files.read(path);
|
|
5284
|
+
if (read.kind === "skipped") {
|
|
5285
|
+
return read;
|
|
5286
|
+
}
|
|
5287
|
+
const { rewriter, scanner, readers } = dependencies;
|
|
5288
|
+
const { version, catalogs, manifests, aliases, apiDescriptionParts } = target;
|
|
5289
|
+
const context = {
|
|
5290
|
+
...{ version, catalogs, manifests, aliases, apiDescriptionParts },
|
|
5291
|
+
...{ rewriter, scanner, readers }
|
|
5292
|
+
};
|
|
5293
|
+
const migration = migrate(read.text, path, context);
|
|
5294
|
+
const isChanged = migration.text !== read.text;
|
|
5295
|
+
const { changes, manualSteps } = migration;
|
|
5296
|
+
if (isChanged || manualSteps.length > 0) {
|
|
5297
|
+
dependencies.logger.info("file_migrated", { path, isChanged, changes, manualSteps });
|
|
5298
|
+
}
|
|
5299
|
+
const report = { path, isChanged, changes, manualSteps };
|
|
5300
|
+
return { kind: "planned", file: { report, text: isChanged ? migration.text : void 0 } };
|
|
4545
5301
|
}
|
|
4546
5302
|
async function planProject(paths, dependencies, version) {
|
|
4547
5303
|
const files = [];
|
|
@@ -4621,8 +5377,9 @@ function terminalSafeText(text) {
|
|
|
4621
5377
|
const PINNED_NOTE = "change it to openapi-typesafe@<version>";
|
|
4622
5378
|
const OLD_FILE_NOTE$1 = "is a file of openapi-typescript, which is no longer installed: run openapi-typesafe instead";
|
|
4623
5379
|
const FLAGS_IN_VARIABLE_NOTE = "holds old flags of the generator and may serve other commands, so it was kept: rename";
|
|
4624
|
-
const NOT_ONLY_GENERATOR_NOTE = "
|
|
5380
|
+
const NOT_ONLY_GENERATOR_NOTE = "may run openapi-typescript or another program (set elsewhere in the file, in another step or outside it), so the flags after it were kept; where it runs the generator, rename";
|
|
4625
5381
|
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";
|
|
5382
|
+
const SCRIPT_NOT_SHELL_NOTE = "so the tool does not read it as commands: migrate the old package names in it by hand";
|
|
4626
5383
|
const COMMAND_STRING_NOTE = "a string runs openapi-typescript, so it was kept; change it to";
|
|
4627
5384
|
function pinnedPackageMessage(step) {
|
|
4628
5385
|
const successor = PACKAGE_RENAMES.get(step.name) ?? step.name;
|
|
@@ -4642,6 +5399,7 @@ const COMMAND_STEP_KINDS = /* @__PURE__ */ new Set([
|
|
|
4642
5399
|
"pinned-package",
|
|
4643
5400
|
"old-package-file",
|
|
4644
5401
|
"old-name-in-command",
|
|
5402
|
+
"script-not-shell",
|
|
4645
5403
|
"command-string"
|
|
4646
5404
|
]);
|
|
4647
5405
|
const isCommandStep = (step) => COMMAND_STEP_KINDS.has(step.kind);
|
|
@@ -4659,6 +5417,8 @@ function commandStepMessage(step) {
|
|
|
4659
5417
|
return `${step.location}: ${step.path} ${OLD_FILE_NOTE$1}`;
|
|
4660
5418
|
case "old-name-in-command":
|
|
4661
5419
|
return `${step.location}: "${step.word}" ${OLD_NAME_IN_COMMAND_NOTE}`;
|
|
5420
|
+
case "script-not-shell":
|
|
5421
|
+
return `${step.location}: the step runs with shell: ${step.shell}, ${SCRIPT_NOT_SHELL_NOTE}`;
|
|
4662
5422
|
case "command-string":
|
|
4663
5423
|
return `line ${step.line}: ${COMMAND_STRING_NOTE} "${step.to}"`;
|
|
4664
5424
|
default:
|
|
@@ -4732,10 +5492,12 @@ const PATCH_NOTE = "check whether the fix is still needed, then make the patch a
|
|
|
4732
5492
|
const PATTERN_NOTE = "is a pattern that names";
|
|
4733
5493
|
const PATTERN_FIX_NOTE = "where it means the package, make it match";
|
|
4734
5494
|
const SETTING_NOTE = "remove the setting if it no longer applies, or make it name";
|
|
5495
|
+
const LOCAL_PACKAGE_NOTE = "points at a local package, not the npm package, so it and the imports of it were kept: if that package is a copy of the original, move it to";
|
|
4735
5496
|
const DEEP_TARGET_NOTE = "points at a file inside the package; check that it exists";
|
|
4736
5497
|
const OLD_PATH_NOTE = "is a path into node_modules of an old package, which is no longer installed:";
|
|
4737
5498
|
const OLD_PATH_FIX_NOTE = "point it at the files of";
|
|
4738
5499
|
const renamed = (name) => PACKAGE_RENAMES.get(name) ?? name;
|
|
5500
|
+
const localPackageMessage = (step) => `${step.field}: ${step.name} "${step.spec}" ${LOCAL_PACKAGE_NOTE} ${renamed(step.name)}`;
|
|
4739
5501
|
function oldPeerMessage(step) {
|
|
4740
5502
|
const { dependent, peer, range } = step;
|
|
4741
5503
|
const successor = PACKAGE_RENAMES.get(peer) ?? peer;
|
|
@@ -4779,6 +5541,8 @@ function packageStepMessage(step) {
|
|
|
4779
5541
|
return `${step.name} is a peer dependency: ${PEER_NOTE}`;
|
|
4780
5542
|
case "spec-kept":
|
|
4781
5543
|
return `${step.name} kept the spec "${step.spec}": point it at an openapi-typesafe version`;
|
|
5544
|
+
case "local-package":
|
|
5545
|
+
return localPackageMessage(step);
|
|
4782
5546
|
case "override-names-package":
|
|
4783
5547
|
return `"${step.field}" names ${step.name}: update or remove that override`;
|
|
4784
5548
|
case "setting-names-package":
|
|
@@ -4817,6 +5581,7 @@ function manualStepMessage(step) {
|
|
|
4817
5581
|
return catalogStepMessage(step);
|
|
4818
5582
|
case "peer-dependency-renamed":
|
|
4819
5583
|
case "spec-kept":
|
|
5584
|
+
case "local-package":
|
|
4820
5585
|
case "override-names-package":
|
|
4821
5586
|
case "setting-names-package":
|
|
4822
5587
|
case "pattern-names-package":
|
|
@@ -5107,8 +5872,8 @@ const createGit = (root) => createGitFileList({
|
|
|
5107
5872
|
const dependencies = {
|
|
5108
5873
|
version: readVersion(),
|
|
5109
5874
|
cwd: process.cwd(),
|
|
5110
|
-
writeStdout: (
|
|
5111
|
-
writeStderr: (
|
|
5875
|
+
writeStdout: createPipeSafeWriter(process.stdout),
|
|
5876
|
+
writeStderr: createPipeSafeWriter(process.stderr),
|
|
5112
5877
|
inspectRoot: inspectProjectRoot,
|
|
5113
5878
|
createFiles: (root, logger) => createNodeProjectFiles(root, { git: createGit(root), logger }),
|
|
5114
5879
|
createLogger,
|