openapi-typesafe-migrate 1.0.0-rc.4 → 1.0.0-rc.5
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 +93 -0
- package/README.md +43 -19
- package/dist/cli/main.mjs +1494 -459
- package/dist/cli/main.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli/main.mjs
CHANGED
|
@@ -12,7 +12,7 @@ const PATH_VARIABLE = "PATH";
|
|
|
12
12
|
const GIT_NAME = "git";
|
|
13
13
|
const WINDOWS_EXECUTABLE_EXTENSION = ".exe";
|
|
14
14
|
const GIT_FOLDER = ".git";
|
|
15
|
-
const PARENT_FOLDER = "..";
|
|
15
|
+
const PARENT_FOLDER$1 = "..";
|
|
16
16
|
const PACKAGES_FOLDER = "node_modules";
|
|
17
17
|
const ABSENT_CODES = /* @__PURE__ */ new Set(["ENOENT", "ENOTDIR", "EACCES", "EPERM"]);
|
|
18
18
|
function isAbsent(error) {
|
|
@@ -35,7 +35,7 @@ function pathVariable({ environment, platform }) {
|
|
|
35
35
|
}
|
|
36
36
|
function isAtOrUnder(paths, folder, target) {
|
|
37
37
|
const path = paths.relative(folder, target);
|
|
38
|
-
return !(path === PARENT_FOLDER || path.startsWith(`${PARENT_FOLDER}${paths.sep}`)) && !paths.isAbsolute(path);
|
|
38
|
+
return !(path === PARENT_FOLDER$1 || path.startsWith(`${PARENT_FOLDER$1}${paths.sep}`)) && !paths.isAbsolute(path);
|
|
39
39
|
}
|
|
40
40
|
function isInPackagesFolder(host, path) {
|
|
41
41
|
const separator = host.platform === WINDOWS ? /[\\/]/ : posix.sep;
|
|
@@ -283,6 +283,7 @@ function createTemporaryLogPath(parent, startTime) {
|
|
|
283
283
|
|
|
284
284
|
const FILE_NAME = "document.json";
|
|
285
285
|
const QUOTE_LENGTH = 1;
|
|
286
|
+
const JSON_ESCAPE = "\\";
|
|
286
287
|
const encode = (value) => JSON.stringify(value);
|
|
287
288
|
function spanOf$1(node, file) {
|
|
288
289
|
return { start: node.getStart(file), end: node.end };
|
|
@@ -290,7 +291,8 @@ function spanOf$1(node, file) {
|
|
|
290
291
|
function convertString(node, file) {
|
|
291
292
|
const span = spanOf$1(node, file);
|
|
292
293
|
const content = { start: span.start + QUOTE_LENGTH, end: span.end - QUOTE_LENGTH };
|
|
293
|
-
|
|
294
|
+
const isEscaped = file.text.slice(content.start, content.end).includes(JSON_ESCAPE);
|
|
295
|
+
return { kind: "scalar", value: node.text, content, isFolded: false, isEscaped, encode, ...span };
|
|
294
296
|
}
|
|
295
297
|
function convertObject(node, file) {
|
|
296
298
|
const entries = node.properties.filter(ts.isPropertyAssignment).map(
|
|
@@ -608,7 +610,10 @@ function applyTextEdits(text, edits) {
|
|
|
608
610
|
return edited + text.slice(copiedUpTo);
|
|
609
611
|
}
|
|
610
612
|
|
|
611
|
-
const GENERATOR_MODULES = /* @__PURE__ */ new Set([
|
|
613
|
+
const GENERATOR_MODULES = /* @__PURE__ */ new Set([
|
|
614
|
+
"openapi-typesafe",
|
|
615
|
+
"openapi-typescript"
|
|
616
|
+
]);
|
|
612
617
|
const TYPESCRIPT_MODULES = /* @__PURE__ */ new Set(["typescript", "@typescript/typescript6"]);
|
|
613
618
|
const DEFAULT_EXPORT$1 = "default";
|
|
614
619
|
function addNamedImports(clause, isGenerator, into) {
|
|
@@ -649,16 +654,21 @@ function addConstants(statement, into) {
|
|
|
649
654
|
}
|
|
650
655
|
}
|
|
651
656
|
}
|
|
657
|
+
function addStatement(statement, into) {
|
|
658
|
+
if (ts.isImportDeclaration(statement)) {
|
|
659
|
+
addImport(statement, into);
|
|
660
|
+
} else if (ts.isVariableStatement(statement)) {
|
|
661
|
+
addConstants(statement, into);
|
|
662
|
+
} else if (ts.isFunctionDeclaration(statement) && statement.name !== void 0) {
|
|
663
|
+
into.set(statement, { kind: "function", declaration: statement });
|
|
664
|
+
} else if (ts.isTypeAliasDeclaration(statement) || ts.isInterfaceDeclaration(statement)) {
|
|
665
|
+
into.set(statement, { kind: "local-type", declaration: statement });
|
|
666
|
+
}
|
|
667
|
+
}
|
|
652
668
|
function collectBindings(file) {
|
|
653
669
|
const bindings = /* @__PURE__ */ new Map();
|
|
654
670
|
for (const statement of file.statements) {
|
|
655
|
-
|
|
656
|
-
addImport(statement, bindings);
|
|
657
|
-
} else if (ts.isVariableStatement(statement)) {
|
|
658
|
-
addConstants(statement, bindings);
|
|
659
|
-
} else if (ts.isFunctionDeclaration(statement) && statement.name !== void 0) {
|
|
660
|
-
bindings.set(statement, { kind: "function", declaration: statement });
|
|
661
|
-
}
|
|
671
|
+
addStatement(statement, bindings);
|
|
662
672
|
}
|
|
663
673
|
return bindings;
|
|
664
674
|
}
|
|
@@ -688,6 +698,16 @@ function isDeclaredName(identifier, declaration) {
|
|
|
688
698
|
const declaredName = declaration.name;
|
|
689
699
|
return declaredName === identifier || ts.findAncestor(identifier, ts.isImportDeclaration) !== void 0;
|
|
690
700
|
}
|
|
701
|
+
function addJSDocBinding(declaration, into) {
|
|
702
|
+
if (ts.isJSDocTypedefTag(declaration)) {
|
|
703
|
+
into.set(declaration, { kind: "local-type", declaration });
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
const importTag = ts.findAncestor(declaration, ts.isJSDocImportTag);
|
|
707
|
+
if (importTag !== void 0) {
|
|
708
|
+
addImport(importTag, into);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
691
711
|
function indexUses(file, bindings) {
|
|
692
712
|
const uses = /* @__PURE__ */ new Map();
|
|
693
713
|
const visit = (node) => {
|
|
@@ -718,6 +738,9 @@ class CheckedFileBindings {
|
|
|
718
738
|
declarationOf(identifier) {
|
|
719
739
|
this.#checker ??= createChecker(this.#file);
|
|
720
740
|
const declaration = symbolOf(this.#checker, identifier)?.declarations?.[0];
|
|
741
|
+
if (declaration !== void 0 && !this.#bindings.has(declaration)) {
|
|
742
|
+
addJSDocBinding(declaration, this.#bindings);
|
|
743
|
+
}
|
|
721
744
|
return declaration !== void 0 && this.#bindings.has(declaration) ? declaration : void 0;
|
|
722
745
|
}
|
|
723
746
|
bindingOf(identifier) {
|
|
@@ -740,29 +763,48 @@ function isGenerator(callee, bindings) {
|
|
|
740
763
|
}
|
|
741
764
|
return ts.isPropertyAccessExpression(callee) && callee.name.text === DEFAULT_EXPORT && ts.isIdentifier(callee.expression) && bindings.bindingOf(callee.expression)?.kind === "generator-module";
|
|
742
765
|
}
|
|
743
|
-
function
|
|
744
|
-
if (
|
|
745
|
-
return
|
|
766
|
+
function jsDocTypes(node) {
|
|
767
|
+
if ((node.flags & ts.NodeFlags.JavaScriptFile) === 0) {
|
|
768
|
+
return [];
|
|
769
|
+
}
|
|
770
|
+
return ts.getJSDocTags(node).filter((tag) => ts.isJSDocTypeTag(tag) || ts.isJSDocSatisfiesTag(tag)).map((tag) => tag.typeExpression.type);
|
|
771
|
+
}
|
|
772
|
+
function unwrapped(expression, types = []) {
|
|
773
|
+
if (ts.isParenthesizedExpression(expression)) {
|
|
774
|
+
return unwrapped(expression.expression, [...types, ...jsDocTypes(expression)]);
|
|
775
|
+
}
|
|
776
|
+
if (ts.isAsExpression(expression) || ts.isSatisfiesExpression(expression)) {
|
|
777
|
+
return unwrapped(expression.expression, [...types, expression.type]);
|
|
746
778
|
}
|
|
747
|
-
return expression;
|
|
779
|
+
return { value: expression, types };
|
|
748
780
|
}
|
|
749
781
|
const isExported$1 = (declaration) => (ts.getCombinedModifierFlags(declaration) & ts.ModifierFlags.Export) !== 0;
|
|
750
|
-
function constantOptions(name, bindings) {
|
|
782
|
+
function constantOptions(name, bindings, outerTypes) {
|
|
751
783
|
const binding = bindings.bindingOf(name);
|
|
752
784
|
const declaration = bindings.declarationOf(name);
|
|
753
|
-
const
|
|
754
|
-
if (
|
|
785
|
+
const found = binding?.kind === "constant" ? unwrapped(binding.initializer) : void 0;
|
|
786
|
+
if (found === void 0 || !ts.isObjectLiteralExpression(found.value)) {
|
|
755
787
|
return { kind: "unknown", expression: name };
|
|
756
788
|
}
|
|
757
|
-
const isOwn = bindings.usesOf(declaration).length === 1;
|
|
758
|
-
|
|
789
|
+
const isOwn = bindings.usesOf(declaration).length === 1 && !isExported$1(declaration);
|
|
790
|
+
if (!isOwn) {
|
|
791
|
+
return { kind: "shared", options: found.value };
|
|
792
|
+
}
|
|
793
|
+
const declared = declaration.type;
|
|
794
|
+
const annotations = [
|
|
795
|
+
...outerTypes,
|
|
796
|
+
...found.types,
|
|
797
|
+
...declared === void 0 ? [] : [declared],
|
|
798
|
+
...jsDocTypes(declaration)
|
|
799
|
+
];
|
|
800
|
+
return { kind: "own", options: found.value, annotations };
|
|
759
801
|
}
|
|
760
802
|
function optionsOf(argument, bindings) {
|
|
761
|
-
const value = unwrapped(argument);
|
|
803
|
+
const { value, types } = unwrapped(argument);
|
|
762
804
|
if (ts.isObjectLiteralExpression(value)) {
|
|
763
|
-
return { kind: "own", options: value };
|
|
805
|
+
return { kind: "own", options: value, annotations: types };
|
|
764
806
|
}
|
|
765
|
-
return ts.isIdentifier(value) ? constantOptions(value, bindings) : { kind: "unknown", expression: argument };
|
|
807
|
+
return ts.isIdentifier(value) ? constantOptions(value, bindings, types) : { kind: "unknown", expression: argument };
|
|
766
808
|
}
|
|
767
809
|
function generatorCalls(file, bindings) {
|
|
768
810
|
const calls = [];
|
|
@@ -778,6 +820,117 @@ function generatorCalls(file, bindings) {
|
|
|
778
820
|
return calls;
|
|
779
821
|
}
|
|
780
822
|
|
|
823
|
+
const TS_NODE_OPTIONS = "OpenAPITSOptions";
|
|
824
|
+
const IR_OPTIONS = "OpenAPITSIrOptions";
|
|
825
|
+
const TYPE_MODIFIER = "type ";
|
|
826
|
+
function importTypeName(node) {
|
|
827
|
+
const { argument, qualifier } = node;
|
|
828
|
+
const isGeneratorModule = ts.isLiteralTypeNode(argument) && ts.isStringLiteral(argument.literal) && GENERATOR_MODULES.has(argument.literal.text);
|
|
829
|
+
const isOptions = !node.isTypeOf && qualifier !== void 0 && ts.isIdentifier(qualifier) && qualifier.text === TS_NODE_OPTIONS;
|
|
830
|
+
return isGeneratorModule && isOptions ? qualifier : void 0;
|
|
831
|
+
}
|
|
832
|
+
function referencedName$1(node) {
|
|
833
|
+
if (ts.isTypeReferenceNode(node)) {
|
|
834
|
+
return node.typeName;
|
|
835
|
+
}
|
|
836
|
+
return ts.isExpressionWithTypeArguments(node) ? node.expression : void 0;
|
|
837
|
+
}
|
|
838
|
+
function qualifiedParts(name) {
|
|
839
|
+
if (ts.isQualifiedName(name)) {
|
|
840
|
+
return { left: name.left, right: name.right };
|
|
841
|
+
}
|
|
842
|
+
return ts.isPropertyAccessExpression(name) ? { left: name.expression, right: name.name } : void 0;
|
|
843
|
+
}
|
|
844
|
+
function optionsTypeName(node, bindings) {
|
|
845
|
+
if (ts.isImportTypeNode(node)) {
|
|
846
|
+
return importTypeName(node);
|
|
847
|
+
}
|
|
848
|
+
const name = referencedName$1(node);
|
|
849
|
+
if (name !== void 0 && ts.isIdentifier(name)) {
|
|
850
|
+
const binding = bindings.bindingOf(name);
|
|
851
|
+
return binding?.kind === "helper-import" && binding.name === TS_NODE_OPTIONS ? name : void 0;
|
|
852
|
+
}
|
|
853
|
+
const parts = name === void 0 ? void 0 : qualifiedParts(name);
|
|
854
|
+
if (parts === void 0 || !ts.isIdentifier(parts.left) || !ts.isIdentifier(parts.right)) {
|
|
855
|
+
return void 0;
|
|
856
|
+
}
|
|
857
|
+
const isGeneratorModule = bindings.bindingOf(parts.left)?.kind === "generator-module";
|
|
858
|
+
return isGeneratorModule && parts.right.text === TS_NODE_OPTIONS ? parts.right : void 0;
|
|
859
|
+
}
|
|
860
|
+
function localTypeOf(node, bindings) {
|
|
861
|
+
const name = referencedName$1(node);
|
|
862
|
+
const binding = name !== void 0 && ts.isIdentifier(name) ? bindings.bindingOf(name) : void 0;
|
|
863
|
+
return binding?.kind === "local-type" ? binding.declaration : void 0;
|
|
864
|
+
}
|
|
865
|
+
function mentionsOptionsType(node, bindings, seen = /* @__PURE__ */ new Set()) {
|
|
866
|
+
const local = localTypeOf(node, bindings);
|
|
867
|
+
const isNewLocal = local !== void 0 && !seen.has(local);
|
|
868
|
+
if (isNewLocal) {
|
|
869
|
+
seen.add(local);
|
|
870
|
+
}
|
|
871
|
+
const mentions = (child) => mentionsOptionsType(child, bindings, seen) || void 0;
|
|
872
|
+
return isNewLocal && mentionsOptionsType(local, bindings, seen) || optionsTypeName(node, bindings) !== void 0 || (ts.forEachChild(node, mentions) ?? false);
|
|
873
|
+
}
|
|
874
|
+
function optionsTypeReferences(annotations, bindings) {
|
|
875
|
+
const references = [];
|
|
876
|
+
for (const annotation of annotations) {
|
|
877
|
+
const target = ts.isIndexedAccessTypeNode(annotation) ? annotation.objectType : annotation;
|
|
878
|
+
const reference = optionsTypeName(target, bindings);
|
|
879
|
+
if (reference !== void 0) {
|
|
880
|
+
references.push(reference);
|
|
881
|
+
} else if (mentionsOptionsType(annotation, bindings)) {
|
|
882
|
+
return void 0;
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
return references;
|
|
886
|
+
}
|
|
887
|
+
const renamed$1 = (identifier, text) => ({
|
|
888
|
+
start: identifier.getStart(),
|
|
889
|
+
end: identifier.getEnd(),
|
|
890
|
+
text
|
|
891
|
+
});
|
|
892
|
+
function importedIrOptions(bindings) {
|
|
893
|
+
for (const [declaration, binding] of bindings.declarations) {
|
|
894
|
+
if (binding.kind === "helper-import" && binding.name === IR_OPTIONS) {
|
|
895
|
+
return declaration.name.text;
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
return void 0;
|
|
899
|
+
}
|
|
900
|
+
function importEdits$1(specifier, references, bindings) {
|
|
901
|
+
const isJavaScript = (specifier.flags & ts.NodeFlags.JavaScriptFile) !== 0;
|
|
902
|
+
const isOnlyUse = !isJavaScript && bindings.usesOf(specifier).every((use) => references.includes(use));
|
|
903
|
+
if (isOnlyUse && specifier.propertyName !== void 0) {
|
|
904
|
+
return [renamed$1(specifier.propertyName, IR_OPTIONS)];
|
|
905
|
+
}
|
|
906
|
+
const uses = references.map((reference) => renamed$1(reference, IR_OPTIONS));
|
|
907
|
+
if (isOnlyUse) {
|
|
908
|
+
return [renamed$1(specifier.name, IR_OPTIONS), ...uses];
|
|
909
|
+
}
|
|
910
|
+
const isTypeImport = specifier.parent.parent.isTypeOnly;
|
|
911
|
+
const added = `, ${isTypeImport ? "" : TYPE_MODIFIER}${IR_OPTIONS}`;
|
|
912
|
+
return [{ start: specifier.getEnd(), end: specifier.getEnd(), text: added }, ...uses];
|
|
913
|
+
}
|
|
914
|
+
function optionsTypeEdits(references, bindings) {
|
|
915
|
+
const edits = [];
|
|
916
|
+
const byImport = /* @__PURE__ */ new Map();
|
|
917
|
+
const existing = importedIrOptions(bindings);
|
|
918
|
+
for (const reference of new Set(references)) {
|
|
919
|
+
const specifier = bindings.declarationOf(reference);
|
|
920
|
+
if (specifier === void 0 || !ts.isImportSpecifier(specifier)) {
|
|
921
|
+
edits.push(renamed$1(reference, IR_OPTIONS));
|
|
922
|
+
} else if (existing !== void 0) {
|
|
923
|
+
edits.push(renamed$1(reference, existing));
|
|
924
|
+
} else {
|
|
925
|
+
byImport.set(specifier, [...byImport.get(specifier) ?? [], reference]);
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
for (const [specifier, found] of byImport) {
|
|
929
|
+
edits.push(...importEdits$1(specifier, found, bindings));
|
|
930
|
+
}
|
|
931
|
+
return edits;
|
|
932
|
+
}
|
|
933
|
+
|
|
781
934
|
const SCRIPT_KINDS = /* @__PURE__ */ new Map([
|
|
782
935
|
[".ts", ts.ScriptKind.TS],
|
|
783
936
|
[".mts", ts.ScriptKind.TS],
|
|
@@ -789,6 +942,10 @@ const SCRIPT_KINDS = /* @__PURE__ */ new Map([
|
|
|
789
942
|
[".jsx", ts.ScriptKind.JSX]
|
|
790
943
|
]);
|
|
791
944
|
const ASTRO_EXTENSION = ".astro";
|
|
945
|
+
const MDX_EXTENSION = ".mdx";
|
|
946
|
+
const MDX_ESM_START_RE = /^(?:import|export)\b/;
|
|
947
|
+
const CODE_FENCE_RE = /^ {0,3}(`{3,}|~{3,})/;
|
|
948
|
+
const MDX_KIND = ts.ScriptKind.JSX;
|
|
792
949
|
const SCRIPT_OPEN_TAG = "<script";
|
|
793
950
|
const TAG_END = ">";
|
|
794
951
|
const ASTRO_FRONTMATTER_RE = /^(\s*---\r?\n)([\s\S]*?)\r?\n---/;
|
|
@@ -849,12 +1006,87 @@ function componentRegions(text, isAstro) {
|
|
|
849
1006
|
}
|
|
850
1007
|
return regions;
|
|
851
1008
|
}
|
|
1009
|
+
function closesFence(line, fence) {
|
|
1010
|
+
const mark = CODE_FENCE_RE.exec(line)?.[1];
|
|
1011
|
+
return mark !== void 0 && mark[0] === fence[0] && mark.length >= fence.length;
|
|
1012
|
+
}
|
|
1013
|
+
function mdxRegions(text) {
|
|
1014
|
+
const regions = [];
|
|
1015
|
+
let fence;
|
|
1016
|
+
let block;
|
|
1017
|
+
let offset = 0;
|
|
1018
|
+
for (const line of text.split("\n")) {
|
|
1019
|
+
const end = offset + line.length;
|
|
1020
|
+
if (block !== void 0 && line.trim() === "") {
|
|
1021
|
+
regions.push({
|
|
1022
|
+
offset: block.start,
|
|
1023
|
+
text: text.slice(block.start, block.end),
|
|
1024
|
+
kind: MDX_KIND
|
|
1025
|
+
});
|
|
1026
|
+
block = void 0;
|
|
1027
|
+
} else if (block !== void 0) {
|
|
1028
|
+
block.end = end;
|
|
1029
|
+
} else if (fence !== void 0) {
|
|
1030
|
+
fence = closesFence(line, fence) ? void 0 : fence;
|
|
1031
|
+
} else if (MDX_ESM_START_RE.test(line)) {
|
|
1032
|
+
block = { start: offset, end };
|
|
1033
|
+
} else {
|
|
1034
|
+
fence = CODE_FENCE_RE.exec(line)?.[1];
|
|
1035
|
+
}
|
|
1036
|
+
offset = end + 1;
|
|
1037
|
+
}
|
|
1038
|
+
if (block !== void 0) {
|
|
1039
|
+
regions.push({ offset: block.start, text: text.slice(block.start, block.end), kind: MDX_KIND });
|
|
1040
|
+
}
|
|
1041
|
+
return regions;
|
|
1042
|
+
}
|
|
852
1043
|
function scriptRegions(text, path) {
|
|
853
1044
|
const kind = plainScriptKind(path);
|
|
854
1045
|
if (kind !== void 0) {
|
|
855
1046
|
return [{ offset: 0, text, kind }];
|
|
856
1047
|
}
|
|
857
|
-
|
|
1048
|
+
const extension = extensionOf$1(path);
|
|
1049
|
+
if (extension === MDX_EXTENSION) {
|
|
1050
|
+
return mdxRegions(text);
|
|
1051
|
+
}
|
|
1052
|
+
return componentRegions(text, extension === ASTRO_EXTENSION);
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
function namedFunction(name, names) {
|
|
1056
|
+
const binding = names.bindings.bindingOf(name);
|
|
1057
|
+
if (binding?.kind === "function") {
|
|
1058
|
+
return binding.declaration;
|
|
1059
|
+
}
|
|
1060
|
+
const value = binding?.kind === "constant" ? binding.initializer : void 0;
|
|
1061
|
+
return value !== void 0 && (ts.isArrowFunction(value) || ts.isFunctionExpression(value)) ? value : void 0;
|
|
1062
|
+
}
|
|
1063
|
+
function namedValue(property) {
|
|
1064
|
+
if (ts.isShorthandPropertyAssignment(property)) {
|
|
1065
|
+
return property.name;
|
|
1066
|
+
}
|
|
1067
|
+
return ts.isPropertyAssignment(property) && ts.isIdentifier(property.initializer) ? property.initializer : void 0;
|
|
1068
|
+
}
|
|
1069
|
+
function callbackFunction(property, names) {
|
|
1070
|
+
if (ts.isMethodDeclaration(property)) {
|
|
1071
|
+
return property;
|
|
1072
|
+
}
|
|
1073
|
+
const name = namedValue(property);
|
|
1074
|
+
if (name !== void 0) {
|
|
1075
|
+
return namedFunction(name, names);
|
|
1076
|
+
}
|
|
1077
|
+
const value = ts.isPropertyAssignment(property) ? property.initializer : void 0;
|
|
1078
|
+
return value !== void 0 && (ts.isArrowFunction(value) || ts.isFunctionExpression(value)) ? value : void 0;
|
|
1079
|
+
}
|
|
1080
|
+
function callbackAnnotations(property, names) {
|
|
1081
|
+
const name = namedValue(property);
|
|
1082
|
+
const declaration = name === void 0 ? void 0 : names.bindings.declarationOf(name);
|
|
1083
|
+
const type = declaration !== void 0 && ts.isVariableDeclaration(declaration) ? declaration.type : void 0;
|
|
1084
|
+
return type === void 0 ? [] : [type];
|
|
1085
|
+
}
|
|
1086
|
+
function isSharedFunction(property, names) {
|
|
1087
|
+
const name = namedValue(property);
|
|
1088
|
+
const declaration = name === void 0 ? void 0 : names.bindings.declarationOf(name);
|
|
1089
|
+
return declaration !== void 0 && names.bindings.usesOf(declaration).length > 1;
|
|
858
1090
|
}
|
|
859
1091
|
|
|
860
1092
|
const KEYWORDS = /* @__PURE__ */ new Map([
|
|
@@ -1182,40 +1414,18 @@ function removalEdits(removed, text) {
|
|
|
1182
1414
|
const TRANSFORM = "transform";
|
|
1183
1415
|
const LEGACY_ONLY_CALLBACKS = ["postTransform", "transformProperty"];
|
|
1184
1416
|
const IR_CALLBACKS_OPTION = "irCallbacks";
|
|
1417
|
+
const noFindings = () => ({
|
|
1418
|
+
edits: [],
|
|
1419
|
+
changes: [],
|
|
1420
|
+
manualSteps: [],
|
|
1421
|
+
typeReferences: []
|
|
1422
|
+
});
|
|
1185
1423
|
function propertyNamed(options, name) {
|
|
1186
1424
|
return options.properties.find((property) => {
|
|
1187
1425
|
const key = property.name;
|
|
1188
1426
|
return key !== void 0 && (ts.isIdentifier(key) || ts.isStringLiteral(key)) && key.text === name;
|
|
1189
1427
|
});
|
|
1190
1428
|
}
|
|
1191
|
-
function namedFunction(name, names) {
|
|
1192
|
-
const binding = names.bindings.bindingOf(name);
|
|
1193
|
-
if (binding?.kind === "function") {
|
|
1194
|
-
return binding.declaration;
|
|
1195
|
-
}
|
|
1196
|
-
const value = binding?.kind === "constant" ? binding.initializer : void 0;
|
|
1197
|
-
return value !== void 0 && (ts.isArrowFunction(value) || ts.isFunctionExpression(value)) ? value : void 0;
|
|
1198
|
-
}
|
|
1199
|
-
function callbackFunction(property, names) {
|
|
1200
|
-
if (ts.isMethodDeclaration(property)) {
|
|
1201
|
-
return property;
|
|
1202
|
-
}
|
|
1203
|
-
if (!ts.isPropertyAssignment(property)) {
|
|
1204
|
-
return void 0;
|
|
1205
|
-
}
|
|
1206
|
-
const value = property.initializer;
|
|
1207
|
-
if (ts.isIdentifier(value)) {
|
|
1208
|
-
return namedFunction(value, names);
|
|
1209
|
-
}
|
|
1210
|
-
return ts.isArrowFunction(value) || ts.isFunctionExpression(value) ? value : void 0;
|
|
1211
|
-
}
|
|
1212
|
-
function isSharedFunction(property, names) {
|
|
1213
|
-
if (!ts.isPropertyAssignment(property) || !ts.isIdentifier(property.initializer)) {
|
|
1214
|
-
return false;
|
|
1215
|
-
}
|
|
1216
|
-
const declaration = names.bindings.declarationOf(property.initializer);
|
|
1217
|
-
return declaration !== void 0 && names.bindings.usesOf(declaration).length > 1;
|
|
1218
|
-
}
|
|
1219
1429
|
function returnTypeEdits(callback, text) {
|
|
1220
1430
|
const type = callback.type;
|
|
1221
1431
|
if (type === void 0) {
|
|
@@ -1251,7 +1461,10 @@ ${before}` : `${option} `;
|
|
|
1251
1461
|
}
|
|
1252
1462
|
function keepReason(options) {
|
|
1253
1463
|
const hasOther = LEGACY_ONLY_CALLBACKS.some((name) => propertyNamed(options, name) !== void 0);
|
|
1254
|
-
|
|
1464
|
+
if (hasOther) {
|
|
1465
|
+
return "other-callbacks";
|
|
1466
|
+
}
|
|
1467
|
+
return options.properties.some(ts.isSpreadAssignment) ? "spread-options" : void 0;
|
|
1255
1468
|
}
|
|
1256
1469
|
function legacyCallbackSteps(options, text) {
|
|
1257
1470
|
return LEGACY_ONLY_CALLBACKS.flatMap((callback) => {
|
|
@@ -1259,32 +1472,39 @@ function legacyCallbackSteps(options, text) {
|
|
|
1259
1472
|
return property === void 0 ? [] : [{ kind: "legacy-callback", line: lineAt(text, property.getStart()), callback }];
|
|
1260
1473
|
});
|
|
1261
1474
|
}
|
|
1475
|
+
function transformRewrite(transform, options, names, text) {
|
|
1476
|
+
const edits = keepReason(options.options) ?? transformEdits(transform, names, text);
|
|
1477
|
+
if (typeof edits === "string") {
|
|
1478
|
+
return edits;
|
|
1479
|
+
}
|
|
1480
|
+
const annotations = [...options.annotations, ...callbackAnnotations(transform, names)];
|
|
1481
|
+
const typeReferences = optionsTypeReferences(annotations, names.bindings);
|
|
1482
|
+
return typeReferences === void 0 ? "typed-options" : { edits, typeReferences };
|
|
1483
|
+
}
|
|
1262
1484
|
function migrateOptions(options, text, names) {
|
|
1263
|
-
if (propertyNamed(options, IR_CALLBACKS_OPTION) !== void 0) {
|
|
1264
|
-
return
|
|
1485
|
+
if (propertyNamed(options.options, IR_CALLBACKS_OPTION) !== void 0) {
|
|
1486
|
+
return noFindings();
|
|
1265
1487
|
}
|
|
1266
|
-
const findings =
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
manualSteps: legacyCallbackSteps(options, text)
|
|
1270
|
-
};
|
|
1271
|
-
const transform = propertyNamed(options, TRANSFORM);
|
|
1488
|
+
const findings = noFindings();
|
|
1489
|
+
findings.manualSteps.push(...legacyCallbackSteps(options.options, text));
|
|
1490
|
+
const transform = propertyNamed(options.options, TRANSFORM);
|
|
1272
1491
|
if (transform === void 0) {
|
|
1273
1492
|
return findings;
|
|
1274
1493
|
}
|
|
1275
1494
|
const start = transform.getStart();
|
|
1276
1495
|
const line = lineAt(text, start);
|
|
1277
|
-
const result =
|
|
1496
|
+
const result = transformRewrite(transform, options, names, text);
|
|
1278
1497
|
if (typeof result === "string") {
|
|
1279
1498
|
findings.manualSteps.push({ kind: "transform-not-rewritten", line, reason: result });
|
|
1280
1499
|
return findings;
|
|
1281
1500
|
}
|
|
1282
|
-
findings.edits.push({ start, end: start, text: irCallbacksOption(text, start) }, ...result);
|
|
1501
|
+
findings.edits.push({ start, end: start, text: irCallbacksOption(text, start) }, ...result.edits);
|
|
1502
|
+
findings.typeReferences.push(...result.typeReferences);
|
|
1283
1503
|
findings.changes.push({ kind: "transform-rewritten", line });
|
|
1284
1504
|
return findings;
|
|
1285
1505
|
}
|
|
1286
1506
|
function sharedOptionsFindings(options, text) {
|
|
1287
|
-
const findings =
|
|
1507
|
+
const findings = noFindings();
|
|
1288
1508
|
if (propertyNamed(options, IR_CALLBACKS_OPTION) !== void 0) {
|
|
1289
1509
|
return findings;
|
|
1290
1510
|
}
|
|
@@ -1300,19 +1520,19 @@ function callFindings(found, text, names) {
|
|
|
1300
1520
|
const options = found.options;
|
|
1301
1521
|
switch (options?.kind) {
|
|
1302
1522
|
case void 0:
|
|
1303
|
-
return
|
|
1523
|
+
return noFindings();
|
|
1304
1524
|
case "own":
|
|
1305
|
-
return migrateOptions(options
|
|
1525
|
+
return migrateOptions(options, text, names);
|
|
1306
1526
|
case "shared":
|
|
1307
1527
|
return sharedOptionsFindings(options.options, text);
|
|
1308
1528
|
case "unknown": {
|
|
1309
1529
|
const line = lineAt(text, options.expression.getStart());
|
|
1310
|
-
return {
|
|
1530
|
+
return { ...noFindings(), manualSteps: [{ kind: "options-not-inspected", line }] };
|
|
1311
1531
|
}
|
|
1312
1532
|
}
|
|
1313
1533
|
}
|
|
1314
1534
|
function findCallFindings(file, text, names) {
|
|
1315
|
-
const all =
|
|
1535
|
+
const all = noFindings();
|
|
1316
1536
|
const seen = /* @__PURE__ */ new Set();
|
|
1317
1537
|
for (const found of generatorCalls(file, names.bindings)) {
|
|
1318
1538
|
const options = found.options?.kind === "unknown" ? void 0 : found.options?.options;
|
|
@@ -1326,12 +1546,13 @@ function findCallFindings(file, text, names) {
|
|
|
1326
1546
|
all.edits.push(...findings.edits);
|
|
1327
1547
|
all.changes.push(...findings.changes);
|
|
1328
1548
|
all.manualSteps.push(...findings.manualSteps);
|
|
1549
|
+
all.typeReferences.push(...findings.typeReferences);
|
|
1329
1550
|
}
|
|
1330
1551
|
return all;
|
|
1331
1552
|
}
|
|
1332
1553
|
function rewriteFile(file, names) {
|
|
1333
1554
|
const text = file.text;
|
|
1334
|
-
const { edits, changes, manualSteps } = findCallFindings(file, text, names);
|
|
1555
|
+
const { edits, changes, manualSteps, typeReferences } = findCallFindings(file, text, names);
|
|
1335
1556
|
const removed = unusedDeclarations(names, edits);
|
|
1336
1557
|
for (const found of removed) {
|
|
1337
1558
|
changes.push({
|
|
@@ -1340,7 +1561,8 @@ function rewriteFile(file, names) {
|
|
|
1340
1561
|
name: found.name
|
|
1341
1562
|
});
|
|
1342
1563
|
}
|
|
1343
|
-
const
|
|
1564
|
+
const typeEdits = optionsTypeEdits(typeReferences, names.bindings);
|
|
1565
|
+
const allEdits = [...edits, ...typeEdits, ...removalEdits(removed, text)];
|
|
1344
1566
|
return { text: applyTextEdits(text, allEdits), changes, manualSteps };
|
|
1345
1567
|
}
|
|
1346
1568
|
class TypescriptCallbackRewriter {
|
|
@@ -1553,6 +1775,14 @@ function scalarText(node) {
|
|
|
1553
1775
|
const isWritten = node.type === Scalar.PLAIN && node.value !== null;
|
|
1554
1776
|
return isWritten ? node.source : void 0;
|
|
1555
1777
|
}
|
|
1778
|
+
const ESCAPES = {
|
|
1779
|
+
"single-quoted-scalar": "''",
|
|
1780
|
+
"double-quoted-scalar": "\\"
|
|
1781
|
+
};
|
|
1782
|
+
function isEscaped(token) {
|
|
1783
|
+
const escapeStart = token === void 0 ? void 0 : ESCAPES[token.type];
|
|
1784
|
+
return escapeStart !== void 0 && token !== void 0 && "source" in token ? token.source.includes(escapeStart) : false;
|
|
1785
|
+
}
|
|
1556
1786
|
function convertScalar(node, isFlow) {
|
|
1557
1787
|
const span = spanOf(node);
|
|
1558
1788
|
const value = scalarText(node);
|
|
@@ -1566,6 +1796,7 @@ function convertScalar(node, isFlow) {
|
|
|
1566
1796
|
value,
|
|
1567
1797
|
content: contentRange(node.srcToken, span),
|
|
1568
1798
|
isFolded: node.type !== Scalar.BLOCK_LITERAL,
|
|
1799
|
+
isEscaped: isEscaped(node.srcToken),
|
|
1569
1800
|
encode: isReplaceable ? encoderFor(quotings, isFlow) : void 0,
|
|
1570
1801
|
...span
|
|
1571
1802
|
};
|
|
@@ -1642,7 +1873,7 @@ function catalogOfSpec(spec) {
|
|
|
1642
1873
|
if (!spec.startsWith(CATALOG_PROTOCOL)) {
|
|
1643
1874
|
return void 0;
|
|
1644
1875
|
}
|
|
1645
|
-
return spec.slice(CATALOG_PROTOCOL.length) || DEFAULT_CATALOG;
|
|
1876
|
+
return spec.slice(CATALOG_PROTOCOL.length).trim() || DEFAULT_CATALOG;
|
|
1646
1877
|
}
|
|
1647
1878
|
class CatalogEntries {
|
|
1648
1879
|
#keys = /* @__PURE__ */ new Set();
|
|
@@ -1655,7 +1886,9 @@ class CatalogEntries {
|
|
|
1655
1886
|
}
|
|
1656
1887
|
const NO_CATALOG_PLAN = {
|
|
1657
1888
|
inUse: new CatalogEntries(),
|
|
1658
|
-
kept: new CatalogEntries()
|
|
1889
|
+
kept: new CatalogEntries(),
|
|
1890
|
+
defined: new CatalogEntries(),
|
|
1891
|
+
isWorkspaceRoot: false
|
|
1659
1892
|
};
|
|
1660
1893
|
|
|
1661
1894
|
const PACKAGE_RENAMES = /* @__PURE__ */ new Map([
|
|
@@ -1687,20 +1920,31 @@ const NAME_LIST_FIELDS = ["bundleDependencies", "bundledDependencies"];
|
|
|
1687
1920
|
const CATALOG_FIELD = "catalog";
|
|
1688
1921
|
const NAMED_CATALOGS_FIELD = "catalogs";
|
|
1689
1922
|
const WORKSPACES_FIELD = "workspaces";
|
|
1690
|
-
const OVERRIDE_FIELDS = ["overrides", "resolutions"
|
|
1923
|
+
const OVERRIDE_FIELDS = ["overrides", "resolutions"];
|
|
1924
|
+
const PNPM_SETTINGS_FIELD = "pnpm";
|
|
1691
1925
|
const OLD_PEER_DEPENDENTS = /* @__PURE__ */ new Map([
|
|
1692
1926
|
["swr-openapi", { peer: "openapi-fetch", range: ">=0.15" }]
|
|
1693
1927
|
]);
|
|
1694
|
-
const PATH_SEPARATOR$
|
|
1928
|
+
const PATH_SEPARATOR$9 = "/";
|
|
1929
|
+
const QUERY_START = "?";
|
|
1695
1930
|
function renamedSpecifier(value) {
|
|
1696
|
-
const
|
|
1697
|
-
|
|
1931
|
+
const ends = [value.indexOf(PATH_SEPARATOR$9), value.indexOf(QUERY_START)].filter(
|
|
1932
|
+
(at) => at !== -1
|
|
1933
|
+
);
|
|
1934
|
+
const name = value.slice(0, ends.length === 0 ? value.length : Math.min(...ends));
|
|
1698
1935
|
const renamed = PACKAGE_RENAMES.get(name);
|
|
1699
1936
|
if (renamed === void 0) {
|
|
1700
1937
|
return void 0;
|
|
1701
1938
|
}
|
|
1702
|
-
const
|
|
1703
|
-
|
|
1939
|
+
const rest = value.slice(name.length);
|
|
1940
|
+
const subpath = rest.split(QUERY_START, 1)[0] ?? rest;
|
|
1941
|
+
return { to: `${renamed}${rest}`, isDeep: subpath !== "" && subpath !== PATH_SEPARATOR$9 };
|
|
1942
|
+
}
|
|
1943
|
+
const NODE_MODULES_FOLDER = "node_modules/";
|
|
1944
|
+
function oldPackageInNodeModules(path) {
|
|
1945
|
+
return [...PACKAGE_RENAMES.keys()].find(
|
|
1946
|
+
(name) => path.includes(`${NODE_MODULES_FOLDER}${name}${PATH_SEPARATOR$9}`)
|
|
1947
|
+
);
|
|
1704
1948
|
}
|
|
1705
1949
|
|
|
1706
1950
|
const isMap = (node) => node?.kind === "map";
|
|
@@ -1743,13 +1987,13 @@ function unreadableConfig(text, offset) {
|
|
|
1743
1987
|
}
|
|
1744
1988
|
|
|
1745
1989
|
const PARENT_SEPARATOR = ">";
|
|
1746
|
-
const PATH_SEPARATOR$
|
|
1990
|
+
const PATH_SEPARATOR$8 = "/";
|
|
1747
1991
|
const SCOPE_PREFIX$2 = "@";
|
|
1748
1992
|
function overrideTarget(key) {
|
|
1749
1993
|
const child = key.split(PARENT_SEPARATOR).at(-1) ?? key;
|
|
1750
|
-
const segments = child.split(PATH_SEPARATOR$
|
|
1994
|
+
const segments = child.split(PATH_SEPARATOR$8);
|
|
1751
1995
|
const isScoped = segments.length > 1 && segments.at(-2)?.startsWith(SCOPE_PREFIX$2) === true;
|
|
1752
|
-
const name = isScoped ? segments.slice(-2).join(PATH_SEPARATOR$
|
|
1996
|
+
const name = isScoped ? segments.slice(-2).join(PATH_SEPARATOR$8) : segments.at(-1) ?? child;
|
|
1753
1997
|
const versionAt = name.indexOf(SCOPE_PREFIX$2, 1);
|
|
1754
1998
|
return versionAt === -1 ? name : name.slice(0, versionAt);
|
|
1755
1999
|
}
|
|
@@ -1786,7 +2030,7 @@ function nestedKeys(node) {
|
|
|
1786
2030
|
return textEntries(node).flatMap(({ key, value }) => [key.value, ...nestedKeys(value)]);
|
|
1787
2031
|
}
|
|
1788
2032
|
|
|
1789
|
-
const PATH_SEPARATOR$
|
|
2033
|
+
const PATH_SEPARATOR$7 = ".";
|
|
1790
2034
|
function catalogMaps(root, prefix = "") {
|
|
1791
2035
|
const maps = mapsAt(root, CATALOG_FIELD).map((map) => ({
|
|
1792
2036
|
name: DEFAULT_CATALOG,
|
|
@@ -1796,7 +2040,7 @@ function catalogMaps(root, prefix = "") {
|
|
|
1796
2040
|
for (const catalogs of mapsAt(root, NAMED_CATALOGS_FIELD)) {
|
|
1797
2041
|
for (const { key, value } of textEntries(catalogs)) {
|
|
1798
2042
|
if (isMap(value)) {
|
|
1799
|
-
const label = [prefix + NAMED_CATALOGS_FIELD, key.value].join(PATH_SEPARATOR$
|
|
2043
|
+
const label = [prefix + NAMED_CATALOGS_FIELD, key.value].join(PATH_SEPARATOR$7);
|
|
1800
2044
|
maps.push({ name: key.value, label, map: value });
|
|
1801
2045
|
}
|
|
1802
2046
|
}
|
|
@@ -1806,7 +2050,7 @@ function catalogMaps(root, prefix = "") {
|
|
|
1806
2050
|
const manifestCatalogMaps = (manifest) => [
|
|
1807
2051
|
...catalogMaps(manifest),
|
|
1808
2052
|
...mapsAt(manifest, WORKSPACES_FIELD).flatMap(
|
|
1809
|
-
(workspaces) => catalogMaps(workspaces, `${WORKSPACES_FIELD}${PATH_SEPARATOR$
|
|
2053
|
+
(workspaces) => catalogMaps(workspaces, `${WORKSPACES_FIELD}${PATH_SEPARATOR$7}`)
|
|
1810
2054
|
)
|
|
1811
2055
|
];
|
|
1812
2056
|
function entriesInUse(manifests) {
|
|
@@ -1837,7 +2081,7 @@ function nestedTexts(node) {
|
|
|
1837
2081
|
}
|
|
1838
2082
|
function addOverrideUses(documents, inUse) {
|
|
1839
2083
|
const sections = documents.flatMap(
|
|
1840
|
-
(document) => OVERRIDE_FIELDS.flatMap((field) => valuesAt(document, field))
|
|
2084
|
+
(document) => [...OVERRIDE_FIELDS, PNPM_SETTINGS_FIELD].flatMap((field) => valuesAt(document, field))
|
|
1841
2085
|
);
|
|
1842
2086
|
for (const { key, value } of sections.flatMap(nestedTexts)) {
|
|
1843
2087
|
const catalog = catalogOfSpec(value);
|
|
@@ -1847,10 +2091,15 @@ function addOverrideUses(documents, inUse) {
|
|
|
1847
2091
|
}
|
|
1848
2092
|
}
|
|
1849
2093
|
}
|
|
1850
|
-
function planCatalogs({
|
|
2094
|
+
function planCatalogs({
|
|
2095
|
+
manifests,
|
|
2096
|
+
catalogFiles,
|
|
2097
|
+
isWorkspaceRoot
|
|
2098
|
+
}) {
|
|
1851
2099
|
const inUse = entriesInUse(manifests);
|
|
1852
2100
|
addOverrideUses([...manifests, ...catalogFiles], inUse);
|
|
1853
2101
|
const kept = new CatalogEntries();
|
|
2102
|
+
const defined = new CatalogEntries();
|
|
1854
2103
|
const catalogs = [
|
|
1855
2104
|
...catalogFiles.flatMap((file) => catalogMaps(file)),
|
|
1856
2105
|
...manifests.flatMap(manifestCatalogMaps)
|
|
@@ -1859,6 +2108,7 @@ function planCatalogs({ manifests, catalogFiles }) {
|
|
|
1859
2108
|
const entries = specEntries(map);
|
|
1860
2109
|
const names = new Set(entries.map((entry) => entry.name));
|
|
1861
2110
|
for (const { name, spec } of entries) {
|
|
2111
|
+
defined.add(catalog, name);
|
|
1862
2112
|
const to = PACKAGE_RENAMES.get(name);
|
|
1863
2113
|
const stays = spec === void 0 || inUse.has(catalog, name);
|
|
1864
2114
|
if (to !== void 0 && !names.has(to) && stays) {
|
|
@@ -1866,7 +2116,7 @@ function planCatalogs({ manifests, catalogFiles }) {
|
|
|
1866
2116
|
}
|
|
1867
2117
|
}
|
|
1868
2118
|
}
|
|
1869
|
-
return { inUse, kept };
|
|
2119
|
+
return { inUse, kept, defined, isWorkspaceRoot };
|
|
1870
2120
|
}
|
|
1871
2121
|
|
|
1872
2122
|
const NO_LONGER_INSTALLED = /* @__PURE__ */ new Map([
|
|
@@ -1875,13 +2125,13 @@ const NO_LONGER_INSTALLED = /* @__PURE__ */ new Map([
|
|
|
1875
2125
|
const ORIGINAL_NAMES = new Map(
|
|
1876
2126
|
[...PACKAGE_RENAMES].map(([original, successor]) => [successor, original])
|
|
1877
2127
|
);
|
|
1878
|
-
const PATH_SEPARATOR$
|
|
2128
|
+
const PATH_SEPARATOR$6 = "/";
|
|
1879
2129
|
function namesUninstalledPackage(text) {
|
|
1880
2130
|
return [...NO_LONGER_INSTALLED.keys()].some(
|
|
1881
2131
|
(name) => text.includes(name) || text.includes(ORIGINAL_NAMES.get(name) ?? name)
|
|
1882
2132
|
);
|
|
1883
2133
|
}
|
|
1884
|
-
const directoryOf = (path) => path.slice(0, path.lastIndexOf(PATH_SEPARATOR$
|
|
2134
|
+
const directoryOf = (path) => path.slice(0, path.lastIndexOf(PATH_SEPARATOR$6) + 1);
|
|
1885
2135
|
function declaredNames(manifest) {
|
|
1886
2136
|
return DEPENDENCY_FIELDS.flatMap((field) => mapsAt(manifest, field)).flatMap(textEntries).map(({ key }) => key.value);
|
|
1887
2137
|
}
|
|
@@ -1892,7 +2142,7 @@ function isDeclaredFor(manifests, filePath, name) {
|
|
|
1892
2142
|
return containing.length === 0 || containing.some(declares);
|
|
1893
2143
|
}
|
|
1894
2144
|
const packageOfSpecifier = (specifier) => {
|
|
1895
|
-
const slash = specifier.indexOf(PATH_SEPARATOR$
|
|
2145
|
+
const slash = specifier.indexOf(PATH_SEPARATOR$6);
|
|
1896
2146
|
return slash === -1 ? specifier : specifier.slice(0, slash);
|
|
1897
2147
|
};
|
|
1898
2148
|
function undeclaredImportSteps(imports, filePath, manifests) {
|
|
@@ -1966,11 +2216,11 @@ function migrateVersionSpec(spec, version) {
|
|
|
1966
2216
|
|
|
1967
2217
|
const NPM_PROTOCOL = "npm:";
|
|
1968
2218
|
const SCOPE_PREFIX$1 = "@";
|
|
1969
|
-
const PATH_SEPARATOR$
|
|
2219
|
+
const PATH_SEPARATOR$5 = "/";
|
|
1970
2220
|
const VERSION_SEPARATOR = "@";
|
|
1971
2221
|
function nameEnd(text) {
|
|
1972
|
-
const searchFrom = text.startsWith(SCOPE_PREFIX$1) ? text.indexOf(PATH_SEPARATOR$
|
|
1973
|
-
const ends = [VERSION_SEPARATOR, PATH_SEPARATOR$
|
|
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);
|
|
1974
2224
|
return ends.length === 0 ? text.length : Math.min(...ends);
|
|
1975
2225
|
}
|
|
1976
2226
|
function parseNpmSpec(spec) {
|
|
@@ -1978,17 +2228,21 @@ function parseNpmSpec(spec) {
|
|
|
1978
2228
|
return void 0;
|
|
1979
2229
|
}
|
|
1980
2230
|
const body = spec.slice(NPM_PROTOCOL.length);
|
|
1981
|
-
const lead = body.startsWith(PATH_SEPARATOR$
|
|
2231
|
+
const lead = body.startsWith(PATH_SEPARATOR$5) ? PATH_SEPARATOR$5 : "";
|
|
1982
2232
|
const text = body.slice(lead.length);
|
|
1983
2233
|
const end = nameEnd(text);
|
|
1984
2234
|
const name = text.slice(0, end);
|
|
1985
2235
|
if (!text.startsWith(VERSION_SEPARATOR, end)) {
|
|
1986
2236
|
return { lead, name, range: void 0, rest: text.slice(end) };
|
|
1987
2237
|
}
|
|
1988
|
-
const rangeEnd = text.indexOf(PATH_SEPARATOR$
|
|
2238
|
+
const rangeEnd = text.indexOf(PATH_SEPARATOR$5, end);
|
|
1989
2239
|
const restStart = rangeEnd === -1 ? text.length : rangeEnd;
|
|
1990
2240
|
return { lead, name, range: text.slice(end + 1, restStart), rest: text.slice(restStart) };
|
|
1991
2241
|
}
|
|
2242
|
+
function isOldPackageNpmSpec(spec) {
|
|
2243
|
+
const parsed = parseNpmSpec(spec);
|
|
2244
|
+
return parsed !== void 0 && PACKAGE_RENAMES.has(parsed.name);
|
|
2245
|
+
}
|
|
1992
2246
|
function migrateNpmSpec(spec, version) {
|
|
1993
2247
|
const parsed = parseNpmSpec(spec);
|
|
1994
2248
|
const renamed = parsed === void 0 ? void 0 : PACKAGE_RENAMES.get(parsed.name);
|
|
@@ -1996,7 +2250,7 @@ function migrateNpmSpec(spec, version) {
|
|
|
1996
2250
|
return void 0;
|
|
1997
2251
|
}
|
|
1998
2252
|
const head = `${NPM_PROTOCOL}${parsed.lead}${renamed}`;
|
|
1999
|
-
const isDeep = parsed.rest !== "" && parsed.rest !== PATH_SEPARATOR$
|
|
2253
|
+
const isDeep = parsed.rest !== "" && parsed.rest !== PATH_SEPARATOR$5;
|
|
2000
2254
|
if (parsed.range === void 0) {
|
|
2001
2255
|
return { spec: `${head}${parsed.rest}`, isReported: false, isDeep };
|
|
2002
2256
|
}
|
|
@@ -2099,7 +2353,15 @@ function catalogHold(entry, spec, { map, catalogs }) {
|
|
|
2099
2353
|
return isInUse ? { kind: "catalog-entry-in-use", catalog: map.catalog, name: entry.name } : void 0;
|
|
2100
2354
|
}
|
|
2101
2355
|
const catalog = map.kind === "dependencies" ? catalogOfSpec(spec.value) : void 0;
|
|
2102
|
-
|
|
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;
|
|
2103
2365
|
}
|
|
2104
2366
|
function migrateSpecMap(entries, context) {
|
|
2105
2367
|
const names = new Set(entries.map((entry) => entry.name));
|
|
@@ -2139,34 +2401,34 @@ function renameNames(entries, field, findings) {
|
|
|
2139
2401
|
}
|
|
2140
2402
|
}
|
|
2141
2403
|
|
|
2142
|
-
const IMPORTS_FIELD = "imports";
|
|
2404
|
+
const IMPORTS_FIELD$1 = "imports";
|
|
2143
2405
|
const SCOPES_FIELD = "scopes";
|
|
2144
|
-
const FIELD_SEPARATOR = ".";
|
|
2406
|
+
const FIELD_SEPARATOR$2 = ".";
|
|
2145
2407
|
function migrateImports(config, version, findings) {
|
|
2146
|
-
for (const imports of mapsAt(config, IMPORTS_FIELD)) {
|
|
2147
|
-
const map = { kind: "imports", field: IMPORTS_FIELD };
|
|
2408
|
+
for (const imports of mapsAt(config, IMPORTS_FIELD$1)) {
|
|
2409
|
+
const map = { kind: "imports", field: IMPORTS_FIELD$1 };
|
|
2148
2410
|
migrateSpecMap(specEntries(imports), { map, version, findings, catalogs: NO_CATALOG_PLAN });
|
|
2149
2411
|
}
|
|
2150
2412
|
for (const scopes of mapsAt(config, SCOPES_FIELD)) {
|
|
2151
2413
|
for (const { key, value } of textEntries(scopes)) {
|
|
2152
2414
|
if (isMap(value)) {
|
|
2153
|
-
const field = [SCOPES_FIELD, key.value].join(FIELD_SEPARATOR);
|
|
2415
|
+
const field = [SCOPES_FIELD, key.value].join(FIELD_SEPARATOR$2);
|
|
2154
2416
|
const map = { kind: "imports", field };
|
|
2155
2417
|
migrateSpecMap(specEntries(value), { map, version, findings, catalogs: NO_CATALOG_PLAN });
|
|
2156
2418
|
}
|
|
2157
2419
|
}
|
|
2158
2420
|
}
|
|
2159
2421
|
}
|
|
2160
|
-
const PATH_SEPARATOR$
|
|
2422
|
+
const PATH_SEPARATOR$4 = "/";
|
|
2161
2423
|
const SCOPE_PREFIX = "@";
|
|
2162
2424
|
function importMapKeys(config) {
|
|
2163
2425
|
const scoped = mapsAt(config, SCOPES_FIELD).flatMap(textEntries).flatMap(({ value }) => isMap(value) ? [value] : []);
|
|
2164
|
-
return [...mapsAt(config, IMPORTS_FIELD), ...scoped].flatMap(textEntries).map(({ key }) => key.value);
|
|
2426
|
+
return [...mapsAt(config, IMPORTS_FIELD$1), ...scoped].flatMap(textEntries).map(({ key }) => key.value);
|
|
2165
2427
|
}
|
|
2166
2428
|
function importMapNames(config) {
|
|
2167
2429
|
return importMapKeys(config).map((key) => {
|
|
2168
|
-
const parts = key.split(PATH_SEPARATOR$
|
|
2169
|
-
return key.startsWith(SCOPE_PREFIX) ? parts.slice(0, 2).join(PATH_SEPARATOR$
|
|
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;
|
|
2170
2432
|
});
|
|
2171
2433
|
}
|
|
2172
2434
|
function migrateImportMap(text, read, version) {
|
|
@@ -2223,6 +2485,32 @@ const container = (words) => ({
|
|
|
2223
2485
|
...launcher(words, NONE, CONTAINER_OPTIONS),
|
|
2224
2486
|
operands: 1
|
|
2225
2487
|
});
|
|
2488
|
+
const withOperands = (words, operands, valueOptions = NONE) => ({ ...launcher(words, NONE, valueOptions), operands });
|
|
2489
|
+
const XARGS_OPTIONS = /* @__PURE__ */ new Set([
|
|
2490
|
+
"-I",
|
|
2491
|
+
"-J",
|
|
2492
|
+
"-L",
|
|
2493
|
+
"-n",
|
|
2494
|
+
"-P",
|
|
2495
|
+
"-R",
|
|
2496
|
+
"-S",
|
|
2497
|
+
"-s",
|
|
2498
|
+
"-d",
|
|
2499
|
+
"-E",
|
|
2500
|
+
"-a",
|
|
2501
|
+
"--max-args",
|
|
2502
|
+
"--max-procs",
|
|
2503
|
+
"--max-lines",
|
|
2504
|
+
"--delimiter",
|
|
2505
|
+
"--arg-file"
|
|
2506
|
+
]);
|
|
2507
|
+
const NODE_OPTIONS = /* @__PURE__ */ new Set([
|
|
2508
|
+
"-r",
|
|
2509
|
+
"--require",
|
|
2510
|
+
"--import",
|
|
2511
|
+
"--loader",
|
|
2512
|
+
"--env-file"
|
|
2513
|
+
]);
|
|
2226
2514
|
const LAUNCHERS = [
|
|
2227
2515
|
launcher(["npm", "exec"], PACKAGE_OPTIONS),
|
|
2228
2516
|
launcher(["npm", "x"], PACKAGE_OPTIONS),
|
|
@@ -2231,19 +2519,36 @@ const LAUNCHERS = [
|
|
|
2231
2519
|
launcher(["yarn", "dlx"], PACKAGE_OPTIONS),
|
|
2232
2520
|
launcher(["yarn", "exec"]),
|
|
2233
2521
|
launcher(["bun", "x"], PACKAGE_OPTIONS),
|
|
2522
|
+
withOperands(["yarn", "workspace"], 1),
|
|
2523
|
+
launcher(["dotenvx", "run"], NONE, /* @__PURE__ */ new Set(["-f", "--env-file", "-e", "--env", "--convention"])),
|
|
2524
|
+
launcher(
|
|
2525
|
+
["doppler", "run"],
|
|
2526
|
+
NONE,
|
|
2527
|
+
/* @__PURE__ */ new Set(["-p", "--project", "-c", "--config", "--token", "--mount", "--scope"])
|
|
2528
|
+
),
|
|
2529
|
+
launcher(["nx", "exec"], NONE, /* @__PURE__ */ new Set(["--projects", "-p", "--exclude"])),
|
|
2234
2530
|
launcher(["deno", "run"], NONE, /* @__PURE__ */ new Set(["--config", "-c", "--import-map", "--location"])),
|
|
2235
2531
|
launcher(["deno", "x"]),
|
|
2236
2532
|
launcher(["npx"], PACKAGE_OPTIONS, /* @__PURE__ */ new Set(["-c", "--call"])),
|
|
2237
2533
|
launcher(["pnpx"], PACKAGE_OPTIONS),
|
|
2238
2534
|
launcher(["bunx"], PACKAGE_OPTIONS),
|
|
2535
|
+
// Like a bare `pnpm <name>`, a bare `bun <name>` runs the binary when no script has the name.
|
|
2536
|
+
launcher(["bun"], NONE, /* @__PURE__ */ new Set(["--cwd", "--filter", "-F"])),
|
|
2537
|
+
launcher(["corepack"]),
|
|
2239
2538
|
launcher(["pnpm"], NONE, PACKAGE_MANAGER_OPTIONS),
|
|
2240
2539
|
launcher(["yarn"], NONE, PACKAGE_MANAGER_OPTIONS),
|
|
2241
|
-
launcher(["node"], NONE,
|
|
2540
|
+
launcher(["node"], NONE, NODE_OPTIONS),
|
|
2541
|
+
launcher(["tsx"], NONE, NODE_OPTIONS),
|
|
2542
|
+
launcher(["ts-node"], NONE, /* @__PURE__ */ new Set([...NODE_OPTIONS, "-P", "--project", "-O", "--compiler"])),
|
|
2242
2543
|
launcher(["cross-env"]),
|
|
2243
2544
|
launcher(["dotenv"], NONE, /* @__PURE__ */ new Set(["-e", "-c", "-v"])),
|
|
2244
2545
|
launcher(["env"], NONE, /* @__PURE__ */ new Set(["-u", "--unset", "-C", "--chdir"])),
|
|
2245
|
-
launcher(["exec"]),
|
|
2546
|
+
launcher(["exec"], NONE, /* @__PURE__ */ new Set(["-a"])),
|
|
2547
|
+
launcher(["command"]),
|
|
2246
2548
|
launcher(["time"]),
|
|
2549
|
+
launcher(["nice"], NONE, /* @__PURE__ */ new Set(["-n", "--adjustment"])),
|
|
2550
|
+
withOperands(["timeout"], 1, /* @__PURE__ */ new Set(["-s", "--signal", "-k", "--kill-after"])),
|
|
2551
|
+
launcher(["xargs"], NONE, XARGS_OPTIONS),
|
|
2247
2552
|
launcher(["nohup"]),
|
|
2248
2553
|
launcher(["sudo"], NONE, /* @__PURE__ */ new Set(["-u", "-g"])),
|
|
2249
2554
|
// The shell form of Dockerfile instructions runs the rest of the line in a shell.
|
|
@@ -2263,6 +2568,9 @@ const INSTALLERS = [
|
|
|
2263
2568
|
...installers("npm", NPM_INSTALL),
|
|
2264
2569
|
...installers("pnpm", ["add", "update", "up", "remove", "rm", "uninstall", "un"]),
|
|
2265
2570
|
...installers("yarn", ["add", "upgrade", "up", "remove"]),
|
|
2571
|
+
// Yarn 1 installs global packages with `yarn global add`.
|
|
2572
|
+
{ words: ["yarn", "global", "add"] },
|
|
2573
|
+
{ words: ["yarn", "global", "remove"] },
|
|
2266
2574
|
...installers("bun", ["add", "a", "update", "remove", "rm", "install", "i"]),
|
|
2267
2575
|
...installers("deno", ["add", "install", "i", "remove", "uninstall"])
|
|
2268
2576
|
];
|
|
@@ -2270,7 +2578,7 @@ const NPM_SPECIFIER_PREFIX = "npm:";
|
|
|
2270
2578
|
|
|
2271
2579
|
const ASSIGNMENT_RE$1 = /^[A-Za-z_][A-Za-z0-9_]*=/;
|
|
2272
2580
|
const END_OF_OPTIONS = "--";
|
|
2273
|
-
const isOption = (word) => word.value.startsWith("-") && word.value.length > 1;
|
|
2581
|
+
const isOption$1 = (word) => word.value.startsWith("-") && word.value.length > 1;
|
|
2274
2582
|
function skipAssignments(words, start) {
|
|
2275
2583
|
let index = start;
|
|
2276
2584
|
while (index < words.length && ASSIGNMENT_RE$1.test(words[index].raw)) {
|
|
@@ -2290,7 +2598,7 @@ function inlineOptionPackage(word, launcher) {
|
|
|
2290
2598
|
}
|
|
2291
2599
|
function launchedProgram(words, start, launcher, packages) {
|
|
2292
2600
|
let index = start;
|
|
2293
|
-
while (index < words.length && isOption(words[index])) {
|
|
2601
|
+
while (index < words.length && isOption$1(words[index])) {
|
|
2294
2602
|
const option = words[index++];
|
|
2295
2603
|
if (option.value === END_OF_OPTIONS) {
|
|
2296
2604
|
break;
|
|
@@ -2309,7 +2617,7 @@ function launchedProgram(words, start, launcher, packages) {
|
|
|
2309
2617
|
}
|
|
2310
2618
|
return index;
|
|
2311
2619
|
}
|
|
2312
|
-
const installArguments = (words, start) => words.slice(start).filter((word) => !isOption(word)).map((word) => ({ word, value: word.value }));
|
|
2620
|
+
const installArguments = (words, start) => words.slice(start).filter((word) => !isOption$1(word)).map((word) => ({ word, value: word.value }));
|
|
2313
2621
|
function commandRoles(words) {
|
|
2314
2622
|
const packages = [];
|
|
2315
2623
|
let index = skipAssignments(words, 0);
|
|
@@ -2330,10 +2638,32 @@ function commandRoles(words) {
|
|
|
2330
2638
|
return { program: void 0, packages };
|
|
2331
2639
|
}
|
|
2332
2640
|
|
|
2333
|
-
|
|
2641
|
+
function packageReference(value) {
|
|
2642
|
+
const bare = value.startsWith(NPM_SPECIFIER_PREFIX) ? value.slice(NPM_SPECIFIER_PREFIX.length) : value;
|
|
2643
|
+
const at = bare.indexOf("@", 1);
|
|
2644
|
+
return { name: at === -1 ? bare : bare.slice(0, at), isPinned: at !== -1 };
|
|
2645
|
+
}
|
|
2646
|
+
function namesOldPackage(value) {
|
|
2647
|
+
return PACKAGE_RENAMES.has(packageReference(value).name) || oldPackageInNodeModules(value) !== void 0 || value.endsWith(`/${GENERATOR_COMMAND}`);
|
|
2648
|
+
}
|
|
2649
|
+
function unmigratedWordFindings(words, handledOffsets, locate) {
|
|
2650
|
+
return words.filter((word) => !handledOffsets.has(word.start) && namesOldPackage(word.value)).map((word) => ({
|
|
2651
|
+
offset: word.start,
|
|
2652
|
+
manualStep: { kind: "old-name-in-command", location: locate(word.start), word: word.value }
|
|
2653
|
+
}));
|
|
2654
|
+
}
|
|
2655
|
+
|
|
2656
|
+
const COMMAND_SEPARATORS = /* @__PURE__ */ new Set([
|
|
2657
|
+
";",
|
|
2658
|
+
"&",
|
|
2659
|
+
"|",
|
|
2660
|
+
"(",
|
|
2661
|
+
")",
|
|
2662
|
+
"`",
|
|
2663
|
+
"\n"
|
|
2664
|
+
]);
|
|
2334
2665
|
const WORD_BREAKS = /* @__PURE__ */ new Set([" ", " ", "\r", "<", ">"]);
|
|
2335
2666
|
const BACKSLASH$1 = "\\";
|
|
2336
|
-
const COMMENT = "#";
|
|
2337
2667
|
const DOUBLE_QUOTE_ESCAPES = /* @__PURE__ */ new Set(["$", "`", '"', BACKSLASH$1, "\n"]);
|
|
2338
2668
|
function singleQuoted(text, start) {
|
|
2339
2669
|
const close = text.indexOf("'", start + 1);
|
|
@@ -2352,8 +2682,26 @@ function doubleQuoted(text, start) {
|
|
|
2352
2682
|
return { end: Math.min(index + 1, text.length), value };
|
|
2353
2683
|
}
|
|
2354
2684
|
const isLineContinuation = (text, index) => text[index] === BACKSLASH$1 && (text[index + 1] === "\n" || text.startsWith("\r\n", index + 1));
|
|
2685
|
+
const ARITHMETIC_OPEN = "$((";
|
|
2686
|
+
const NESTING_OPEN = "(";
|
|
2687
|
+
const NESTING_CLOSE = ")";
|
|
2688
|
+
const ARITHMETIC_DEPTH = 2;
|
|
2689
|
+
function arithmeticExpansion(text, start) {
|
|
2690
|
+
let depth = ARITHMETIC_DEPTH;
|
|
2691
|
+
for (let index = start + ARITHMETIC_OPEN.length; index < text.length; index++) {
|
|
2692
|
+
depth += text[index] === NESTING_OPEN ? 1 : text[index] === NESTING_CLOSE ? -1 : 0;
|
|
2693
|
+
if (depth === 0) {
|
|
2694
|
+
return { end: index + 1, value: text.slice(start, index + 1) };
|
|
2695
|
+
}
|
|
2696
|
+
}
|
|
2697
|
+
return void 0;
|
|
2698
|
+
}
|
|
2355
2699
|
function wordPart(text, index) {
|
|
2356
2700
|
const char = text[index];
|
|
2701
|
+
const arithmetic = text.startsWith(ARITHMETIC_OPEN, index) ? arithmeticExpansion(text, index) : void 0;
|
|
2702
|
+
if (arithmetic !== void 0) {
|
|
2703
|
+
return arithmetic;
|
|
2704
|
+
}
|
|
2357
2705
|
if (char === "'") {
|
|
2358
2706
|
return singleQuoted(text, index);
|
|
2359
2707
|
}
|
|
@@ -2379,6 +2727,65 @@ function readWord(text, start) {
|
|
|
2379
2727
|
}
|
|
2380
2728
|
return { start, end: index, value, raw: text.slice(start, index) };
|
|
2381
2729
|
}
|
|
2730
|
+
|
|
2731
|
+
const HEREDOC_OPERATOR = "<<";
|
|
2732
|
+
const HERE_STRING_OPERATOR = "<<<";
|
|
2733
|
+
const STRIP_TABS = "-";
|
|
2734
|
+
const LINE_BREAK$2 = "\n";
|
|
2735
|
+
const LEADING_TABS_RE = /^\t+/;
|
|
2736
|
+
const CARRIAGE_RETURN_RE = /\r$/;
|
|
2737
|
+
function heredocAt(text, index, where) {
|
|
2738
|
+
if (text.startsWith(HERE_STRING_OPERATOR, index)) {
|
|
2739
|
+
return { end: index + HERE_STRING_OPERATOR.length };
|
|
2740
|
+
}
|
|
2741
|
+
if (!text.startsWith(HEREDOC_OPERATOR, index)) {
|
|
2742
|
+
return void 0;
|
|
2743
|
+
}
|
|
2744
|
+
let start = index + HEREDOC_OPERATOR.length;
|
|
2745
|
+
const isTabStripped = text[start] === STRIP_TABS;
|
|
2746
|
+
start += isTabStripped ? 1 : 0;
|
|
2747
|
+
while (text[start] === " " || text[start] === " ") {
|
|
2748
|
+
start++;
|
|
2749
|
+
}
|
|
2750
|
+
const word = readWord(text, start);
|
|
2751
|
+
const pending = { delimiter: word.value, isTabStripped, ...where };
|
|
2752
|
+
return word.value === "" ? void 0 : { pending, end: word.end };
|
|
2753
|
+
}
|
|
2754
|
+
function isDelimiterLine(text, lineStart, end, heredoc) {
|
|
2755
|
+
let first = lineStart;
|
|
2756
|
+
while (first < lineStart + heredoc.indent && text[first] === " ") {
|
|
2757
|
+
first++;
|
|
2758
|
+
}
|
|
2759
|
+
const line = text.slice(first, end).replace(CARRIAGE_RETURN_RE, "");
|
|
2760
|
+
const compared = heredoc.isTabStripped ? line.replace(LEADING_TABS_RE, "") : line;
|
|
2761
|
+
return compared === heredoc.delimiter;
|
|
2762
|
+
}
|
|
2763
|
+
function readBody(text, start, heredoc) {
|
|
2764
|
+
let lineStart = start;
|
|
2765
|
+
while (lineStart < text.length) {
|
|
2766
|
+
const lineEnd = text.indexOf(LINE_BREAK$2, lineStart);
|
|
2767
|
+
const end = lineEnd === -1 ? text.length : lineEnd;
|
|
2768
|
+
if (isDelimiterLine(text, lineStart, end, heredoc)) {
|
|
2769
|
+
const body = { command: heredoc.command, start, text: text.slice(start, lineStart) };
|
|
2770
|
+
return { body, end: Math.min(end + 1, text.length) };
|
|
2771
|
+
}
|
|
2772
|
+
lineStart = end + 1;
|
|
2773
|
+
}
|
|
2774
|
+
return { body: { command: heredoc.command, start, text: text.slice(start) }, end: text.length };
|
|
2775
|
+
}
|
|
2776
|
+
function readBodies(text, start, pending) {
|
|
2777
|
+
const bodies = [];
|
|
2778
|
+
let end = start;
|
|
2779
|
+
for (const heredoc of pending) {
|
|
2780
|
+
const read = readBody(text, end, heredoc);
|
|
2781
|
+
bodies.push(read.body);
|
|
2782
|
+
end = read.end;
|
|
2783
|
+
}
|
|
2784
|
+
return { bodies, end };
|
|
2785
|
+
}
|
|
2786
|
+
|
|
2787
|
+
const COMMENT = "#";
|
|
2788
|
+
const LINE_BREAK$1 = "\n";
|
|
2382
2789
|
function skipTrivia(text, index) {
|
|
2383
2790
|
const char = text[index];
|
|
2384
2791
|
if (WORD_BREAKS.has(char)) {
|
|
@@ -2393,14 +2800,31 @@ function skipTrivia(text, index) {
|
|
|
2393
2800
|
}
|
|
2394
2801
|
return index;
|
|
2395
2802
|
}
|
|
2396
|
-
|
|
2803
|
+
const PIPE = "|";
|
|
2804
|
+
function topLevelCommands(text, indent) {
|
|
2397
2805
|
const commands = [[]];
|
|
2806
|
+
const heredocs = [];
|
|
2807
|
+
const pipes = /* @__PURE__ */ new Set();
|
|
2808
|
+
let pending = [];
|
|
2398
2809
|
let index = 0;
|
|
2399
2810
|
while (index < text.length) {
|
|
2400
2811
|
const afterTrivia = skipTrivia(text, index);
|
|
2401
|
-
|
|
2812
|
+
const heredoc = heredocAt(text, index, { command: commands.length - 1, indent });
|
|
2813
|
+
if (heredoc !== void 0) {
|
|
2814
|
+
pending.push(...heredoc.pending === void 0 ? [] : [heredoc.pending]);
|
|
2815
|
+
index = heredoc.end;
|
|
2816
|
+
} else if (afterTrivia !== index) {
|
|
2402
2817
|
index = afterTrivia;
|
|
2818
|
+
} else if (text[index] === LINE_BREAK$1 && pending.length > 0) {
|
|
2819
|
+
const read = readBodies(text, index + 1, pending);
|
|
2820
|
+
heredocs.push(...read.bodies);
|
|
2821
|
+
pending = [];
|
|
2822
|
+
commands.push([]);
|
|
2823
|
+
index = read.end;
|
|
2403
2824
|
} else if (COMMAND_SEPARATORS.has(text[index])) {
|
|
2825
|
+
if (text[index] === PIPE) {
|
|
2826
|
+
pipes.add(commands.length - 1);
|
|
2827
|
+
}
|
|
2404
2828
|
commands.push([]);
|
|
2405
2829
|
index++;
|
|
2406
2830
|
} else {
|
|
@@ -2409,7 +2833,7 @@ function topLevelCommands(text) {
|
|
|
2409
2833
|
index = word.end;
|
|
2410
2834
|
}
|
|
2411
2835
|
}
|
|
2412
|
-
return commands
|
|
2836
|
+
return { commands, heredocs, pipes };
|
|
2413
2837
|
}
|
|
2414
2838
|
const COMMAND_PREFIX_WORDS = /* @__PURE__ */ new Set([
|
|
2415
2839
|
"if",
|
|
@@ -2451,29 +2875,57 @@ function nestedCommandText(word) {
|
|
|
2451
2875
|
const isOneQuotedString = QUOTES$2.has(quote) && word.raw.length > 1 && word.raw.endsWith(quote) && wordPart(word.raw, 0).end === word.raw.length;
|
|
2452
2876
|
return isOneQuotedString && NESTED_COMMAND_RE.test(word.value) ? word.raw.slice(1, -1) : void 0;
|
|
2453
2877
|
}
|
|
2878
|
+
const SHELLS$1 = /* @__PURE__ */ new Set(["sh", "bash", "dash", "ash", "zsh", "ksh"]);
|
|
2879
|
+
const DOCKER_RUN = "RUN";
|
|
2880
|
+
const PASS_THROUGH = "cat";
|
|
2881
|
+
const PATH_SEPARATOR$3 = "/";
|
|
2882
|
+
const OPTION_PREFIX$1 = "-";
|
|
2883
|
+
const programName = (command) => command[0]?.value.split(PATH_SEPARATOR$3).at(-1) ?? "";
|
|
2884
|
+
const isOption = (word) => word.value.startsWith(OPTION_PREFIX$1);
|
|
2885
|
+
const isScriptShell = (command) => SHELLS$1.has(programName(command)) && command.slice(1).every(isOption);
|
|
2886
|
+
function readsScript(command) {
|
|
2887
|
+
if (programName(command) !== DOCKER_RUN) {
|
|
2888
|
+
return isScriptShell(command);
|
|
2889
|
+
}
|
|
2890
|
+
const after = command.slice(1);
|
|
2891
|
+
const shell = after.slice(after.findIndex((word) => !isOption(word)));
|
|
2892
|
+
return after.every(isOption) || isScriptShell(shell);
|
|
2893
|
+
}
|
|
2894
|
+
const passesThrough = (command) => programName(command) === PASS_THROUGH && command.slice(1).every(isOption);
|
|
2895
|
+
function scriptsRunBy(top, index, command) {
|
|
2896
|
+
const previous = index - 1;
|
|
2897
|
+
const isPipedScript = top.pipes.has(previous) && isScriptShell(command) && passesThrough(simpleCommand(top.commands[previous] ?? []));
|
|
2898
|
+
return top.heredocs.filter(
|
|
2899
|
+
(body) => body.command === index && readsScript(command) || body.command === previous && isPipedScript
|
|
2900
|
+
);
|
|
2901
|
+
}
|
|
2454
2902
|
const shifted = (words, offset) => words.map((word) => ({ ...word, start: word.start + offset, end: word.end + offset }));
|
|
2455
|
-
function shellCommandsAt(text, offset) {
|
|
2456
|
-
return shellCommands(text).map((words) => shifted(words, offset));
|
|
2903
|
+
function shellCommandsAt(text, offset, indent = 0) {
|
|
2904
|
+
return shellCommands(text, indent).map((words) => shifted(words, offset));
|
|
2457
2905
|
}
|
|
2458
|
-
function shellCommands(text) {
|
|
2906
|
+
function shellCommands(text, indent = 0) {
|
|
2907
|
+
const top = topLevelCommands(text, indent);
|
|
2459
2908
|
const commands = [];
|
|
2460
|
-
for (const
|
|
2909
|
+
for (const [index, words] of top.commands.entries()) {
|
|
2910
|
+
const command = simpleCommand(words);
|
|
2461
2911
|
if (command.length > 0) {
|
|
2462
2912
|
commands.push(command);
|
|
2463
2913
|
}
|
|
2464
2914
|
for (const word of command) {
|
|
2465
2915
|
const inner = nestedCommandText(word);
|
|
2466
2916
|
if (inner !== void 0) {
|
|
2467
|
-
const nested = shellCommands(inner).map((
|
|
2917
|
+
const nested = shellCommands(inner).map((found) => shifted(found, word.start + 1));
|
|
2468
2918
|
commands.push(...nested);
|
|
2469
2919
|
}
|
|
2470
2920
|
}
|
|
2921
|
+
const scripts = scriptsRunBy(top, index, command);
|
|
2922
|
+
commands.push(...scripts.flatMap((body) => shellCommandsAt(body.text, body.start, indent)));
|
|
2471
2923
|
}
|
|
2472
2924
|
return commands;
|
|
2473
2925
|
}
|
|
2474
2926
|
|
|
2475
2927
|
const QUOTES$1 = /* @__PURE__ */ new Set(["'", '"']);
|
|
2476
|
-
const PATH_SEPARATOR$
|
|
2928
|
+
const PATH_SEPARATOR$2 = "/";
|
|
2477
2929
|
const BIN_FOLDER = "/.bin/";
|
|
2478
2930
|
const OLD_PACKAGE_FOLDER = `node_modules/${GENERATOR_COMMAND}/`;
|
|
2479
2931
|
function renameAtEnd(word, name, to) {
|
|
@@ -2484,11 +2936,6 @@ function renameAtEnd(word, name, to) {
|
|
|
2484
2936
|
}
|
|
2485
2937
|
return { start: word.start + at, end: word.start + at + name.length, text: to };
|
|
2486
2938
|
}
|
|
2487
|
-
function packageReference(value) {
|
|
2488
|
-
const bare = value.startsWith(NPM_SPECIFIER_PREFIX) ? value.slice(NPM_SPECIFIER_PREFIX.length) : value;
|
|
2489
|
-
const at = bare.indexOf("@", 1);
|
|
2490
|
-
return { name: at === -1 ? bare : bare.slice(0, at), isPinned: at !== -1 };
|
|
2491
|
-
}
|
|
2492
2939
|
function packageFindings(found, locate) {
|
|
2493
2940
|
const { name, isPinned } = packageReference(found.value);
|
|
2494
2941
|
const to = PACKAGE_RENAMES.get(name);
|
|
@@ -2514,7 +2961,7 @@ function programPathFindings(word, location) {
|
|
|
2514
2961
|
return edit === void 0 ? [] : [{ offset, edit, change: { kind: "command-renamed", location } }];
|
|
2515
2962
|
}
|
|
2516
2963
|
function programFindings(word, location) {
|
|
2517
|
-
if (word.value.includes(PATH_SEPARATOR$
|
|
2964
|
+
if (word.value.includes(PATH_SEPARATOR$2)) {
|
|
2518
2965
|
return programPathFindings(word, location);
|
|
2519
2966
|
}
|
|
2520
2967
|
const { name, isPinned } = packageReference(word.value);
|
|
@@ -2594,6 +3041,11 @@ function uncertainFlagSteps(program, variable, found, locate) {
|
|
|
2594
3041
|
}
|
|
2595
3042
|
function commandFindings(command, locate, variables) {
|
|
2596
3043
|
const words = withoutRecipePrefix(command);
|
|
3044
|
+
const found = knownFindings(words, locate, variables);
|
|
3045
|
+
const handled = new Set(found.map((finding) => finding.offset));
|
|
3046
|
+
return [...found, ...unmigratedWordFindings(words, handled, locate)];
|
|
3047
|
+
}
|
|
3048
|
+
function knownFindings(words, locate, variables) {
|
|
2597
3049
|
const roles = commandRoles(words);
|
|
2598
3050
|
const findings = roles.packages.flatMap((found2) => packageFindings(found2, locate));
|
|
2599
3051
|
const program = roles.program === void 0 ? void 0 : words[roles.program];
|
|
@@ -2646,6 +3098,45 @@ function migrateCommandLines(text, file) {
|
|
|
2646
3098
|
return migrateShellText(text, (offset) => `${file}:${lineOf(offset)}`);
|
|
2647
3099
|
}
|
|
2648
3100
|
|
|
3101
|
+
const ANY = "*";
|
|
3102
|
+
const nxOptionPaths = (prefix) => [
|
|
3103
|
+
[...prefix, "command"],
|
|
3104
|
+
[...prefix, "commands", ANY],
|
|
3105
|
+
[...prefix, "commands", ANY, "command"]
|
|
3106
|
+
];
|
|
3107
|
+
const nxTargetPaths = (prefix) => [
|
|
3108
|
+
[...prefix, ANY, "command"],
|
|
3109
|
+
...nxOptionPaths([...prefix, ANY, "options"]),
|
|
3110
|
+
...nxOptionPaths([...prefix, ANY, "configurations", ANY])
|
|
3111
|
+
];
|
|
3112
|
+
const lintStagedPaths = (prefix) => [
|
|
3113
|
+
[...prefix, ANY],
|
|
3114
|
+
[...prefix, ANY, ANY]
|
|
3115
|
+
];
|
|
3116
|
+
const simpleGitHooksPaths = (prefix) => [
|
|
3117
|
+
[...prefix, ANY]
|
|
3118
|
+
];
|
|
3119
|
+
const NX_PROJECT_COMMAND_PATHS = nxTargetPaths(["targets"]);
|
|
3120
|
+
const NX_WORKSPACE_COMMAND_PATHS = nxTargetPaths([
|
|
3121
|
+
"targetDefaults"
|
|
3122
|
+
]);
|
|
3123
|
+
const MANIFEST_COMMAND_PATHS = [
|
|
3124
|
+
["scripts", ANY],
|
|
3125
|
+
...simpleGitHooksPaths(["simple-git-hooks"]),
|
|
3126
|
+
...lintStagedPaths(["lint-staged"]),
|
|
3127
|
+
...nxTargetPaths(["nx", "targets"])
|
|
3128
|
+
];
|
|
3129
|
+
const LINT_STAGED_COMMAND_PATHS = lintStagedPaths([]);
|
|
3130
|
+
const SIMPLE_GIT_HOOKS_COMMAND_PATHS = simpleGitHooksPaths(
|
|
3131
|
+
[]
|
|
3132
|
+
);
|
|
3133
|
+
const DENO_TASK_PATHS = [
|
|
3134
|
+
["tasks", ANY],
|
|
3135
|
+
["tasks", ANY, "command"]
|
|
3136
|
+
];
|
|
3137
|
+
const matches = (path, pattern) => path.length === pattern.length && pattern.every((part, index) => part === ANY || part === String(path[index]));
|
|
3138
|
+
const isCommandPath = (path, patterns) => patterns.some((pattern) => matches(path, pattern));
|
|
3139
|
+
|
|
2649
3140
|
const NO_LOCATION = "";
|
|
2650
3141
|
function commandStringSteps(text, strings) {
|
|
2651
3142
|
const lineOf = lineLocator(text);
|
|
@@ -2745,7 +3236,7 @@ const OPTION_PREFIX = "-";
|
|
|
2745
3236
|
const LONG_OPTION_PREFIX = "--";
|
|
2746
3237
|
const COMMAND_OPTION = "c";
|
|
2747
3238
|
const SET_OPTION = "-o";
|
|
2748
|
-
const PATH_SEPARATOR = "/";
|
|
3239
|
+
const PATH_SEPARATOR$1 = "/";
|
|
2749
3240
|
const ARRAY_BLANK_RE = /(?:[ \t\r\n]|\\\r?\n)*/y;
|
|
2750
3241
|
const QUOTED_RE = /"(?:[^"\\\n]|\\.)*"/y;
|
|
2751
3242
|
const ITEM_SEPARATOR = ",";
|
|
@@ -2802,7 +3293,7 @@ function execForms(text) {
|
|
|
2802
3293
|
});
|
|
2803
3294
|
}
|
|
2804
3295
|
function shellScript(words) {
|
|
2805
|
-
const program = words[0]?.value.split(PATH_SEPARATOR).at(-1) ?? "";
|
|
3296
|
+
const program = words[0]?.value.split(PATH_SEPARATOR$1).at(-1) ?? "";
|
|
2806
3297
|
if (!SHELLS.has(program)) {
|
|
2807
3298
|
return void 0;
|
|
2808
3299
|
}
|
|
@@ -2895,77 +3386,251 @@ function migrateDockerfile(text, file) {
|
|
|
2895
3386
|
return { text: applyTextEdits(text, edits), changes, manualSteps: steps };
|
|
2896
3387
|
}
|
|
2897
3388
|
|
|
2898
|
-
const
|
|
2899
|
-
const
|
|
2900
|
-
const
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
for (const found of strings.filter((string) => patterns.some((p) => matches(string.path, p)))) {
|
|
2916
|
-
const migrated = migrateCommand(found.value, found.path.join("."));
|
|
2917
|
-
changes.push(...migrated.changes);
|
|
2918
|
-
manualSteps.push(...migrated.manualSteps);
|
|
2919
|
-
if (migrated.text !== found.value) {
|
|
2920
|
-
edits.push({ start: found.start, end: found.end, text: JSON.stringify(migrated.text) });
|
|
3389
|
+
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
|
+
function importMapReferences(roots) {
|
|
3395
|
+
return roots.flatMap((root) => valuesAt(root, IMPORT_MAP_FIELD)).flatMap((value) => isScalar(value) ? [value.value] : []);
|
|
3396
|
+
}
|
|
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);
|
|
2921
3406
|
}
|
|
2922
3407
|
}
|
|
2923
|
-
return
|
|
3408
|
+
return parts.join(SEPARATOR);
|
|
3409
|
+
}
|
|
3410
|
+
function importMapLocation(configPath, reference) {
|
|
3411
|
+
const isOutside = URL_SCHEME.test(reference) || reference.startsWith(SEPARATOR);
|
|
3412
|
+
const path = isOutside ? void 0 : resolvedPath(configPath, reference);
|
|
3413
|
+
return path === void 0 || path === "" ? { kind: "not-editable", reference } : { kind: "in-project", path };
|
|
3414
|
+
}
|
|
3415
|
+
const importMapLocations = (configPath, roots) => importMapReferences(roots).map((reference) => importMapLocation(configPath, reference));
|
|
3416
|
+
function importMapSteps(configPath, read) {
|
|
3417
|
+
const roots = read.kind === "read" ? read.documents.filter(isMap) : [];
|
|
3418
|
+
return importMapLocations(configPath, roots).flatMap(
|
|
3419
|
+
(location) => location.kind === "not-editable" ? [{ kind: "import-map-not-editable", reference: location.reference }] : []
|
|
3420
|
+
);
|
|
2924
3421
|
}
|
|
2925
3422
|
|
|
2926
|
-
const
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
"
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
const
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
const open = text[start + 1] ?? "";
|
|
2945
|
-
const close = CLOSING[open];
|
|
2946
|
-
if (close === void 0) {
|
|
2947
|
-
return void 0;
|
|
2948
|
-
}
|
|
2949
|
-
let depth = 0;
|
|
2950
|
-
for (let index = start + 1; index < text.length; index++) {
|
|
2951
|
-
if (text[index] === open) {
|
|
2952
|
-
depth++;
|
|
2953
|
-
} else if (text[index] === close && --depth === 0) {
|
|
2954
|
-
return index + 1;
|
|
2955
|
-
}
|
|
3423
|
+
const SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
3424
|
+
".ts",
|
|
3425
|
+
".tsx",
|
|
3426
|
+
".mts",
|
|
3427
|
+
".cts",
|
|
3428
|
+
".js",
|
|
3429
|
+
".jsx",
|
|
3430
|
+
".mjs",
|
|
3431
|
+
".cjs",
|
|
3432
|
+
".vue",
|
|
3433
|
+
".svelte",
|
|
3434
|
+
".astro",
|
|
3435
|
+
".mdx"
|
|
3436
|
+
]);
|
|
3437
|
+
function renamedValue(value, version) {
|
|
3438
|
+
const npm = migrateNpmSpec(value, version);
|
|
3439
|
+
if (npm === void 0) {
|
|
3440
|
+
return renamedSpecifier(value);
|
|
2956
3441
|
}
|
|
2957
|
-
|
|
3442
|
+
const renamed = { to: npm.spec, isDeep: npm.isDeep };
|
|
3443
|
+
return npm.isReported ? { ...renamed, keptSpec: hideUrlCredentials(value) } : renamed;
|
|
2958
3444
|
}
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
3445
|
+
const namesRenamedModule = (value) => isOldPackageNpmSpec(value) || renamedSpecifier(value) !== void 0;
|
|
3446
|
+
const TEMPLATE_SUBSTITUTION = "${";
|
|
3447
|
+
function dynamicPackage(value) {
|
|
3448
|
+
const at = value.indexOf(TEMPLATE_SUBSTITUTION);
|
|
3449
|
+
return at === -1 ? void 0 : PACKAGE_RENAMES.get(value.slice(0, at));
|
|
3450
|
+
}
|
|
3451
|
+
const byStartThenOuter = (left, right) => left.start - right.start || right.end - left.end;
|
|
3452
|
+
function distinctStrings(strings) {
|
|
3453
|
+
const distinct = [];
|
|
3454
|
+
const enclosing = [];
|
|
3455
|
+
for (const found of [...strings].sort(byStartThenOuter)) {
|
|
3456
|
+
const previous = distinct.at(-1);
|
|
3457
|
+
if (previous?.start === found.start && previous.end === found.end) {
|
|
3458
|
+
const isModuleSpecifier = previous.isModuleSpecifier || found.isModuleSpecifier;
|
|
3459
|
+
distinct[distinct.length - 1] = { ...previous, isModuleSpecifier };
|
|
3460
|
+
continue;
|
|
3461
|
+
}
|
|
3462
|
+
let outer = enclosing.at(-1);
|
|
3463
|
+
while (outer !== void 0 && outer.end <= found.start) {
|
|
3464
|
+
enclosing.pop();
|
|
3465
|
+
outer = enclosing.at(-1);
|
|
3466
|
+
}
|
|
3467
|
+
if (outer !== void 0 && found.end > outer.end) {
|
|
3468
|
+
throw new Error(
|
|
3469
|
+
`Source strings overlap at offsets ${outer.start}-${outer.end} and ${found.start}-${found.end}; the file was not changed.`
|
|
3470
|
+
);
|
|
3471
|
+
}
|
|
3472
|
+
enclosing.push(found);
|
|
3473
|
+
distinct.push(found);
|
|
3474
|
+
}
|
|
3475
|
+
return distinct;
|
|
3476
|
+
}
|
|
3477
|
+
const dynamicStep = (line, value, to) => ({
|
|
3478
|
+
kind: "dynamic-specifier",
|
|
3479
|
+
line,
|
|
3480
|
+
value,
|
|
3481
|
+
to
|
|
3482
|
+
});
|
|
3483
|
+
function unrenamedSteps(found, line, dynamic) {
|
|
3484
|
+
if (dynamic !== void 0) {
|
|
3485
|
+
return [dynamicStep(line, found.value, dynamic)];
|
|
3486
|
+
}
|
|
3487
|
+
const name = found.isModuleSpecifier ? oldPackageInNodeModules(found.value) : void 0;
|
|
3488
|
+
const to = name === void 0 ? void 0 : PACKAGE_RENAMES.get(name);
|
|
3489
|
+
return name === void 0 || to === void 0 ? [] : [{ kind: "old-package-import", line, specifier: found.value, name, to }];
|
|
3490
|
+
}
|
|
3491
|
+
function migrateModuleSpecifiers(text, strings, version) {
|
|
3492
|
+
const changes = [];
|
|
3493
|
+
const manualSteps = [];
|
|
3494
|
+
let migrated = "";
|
|
3495
|
+
let copiedUpTo = 0;
|
|
3496
|
+
const lineOf = lineLocator(text);
|
|
3497
|
+
for (const found of distinctStrings(strings)) {
|
|
3498
|
+
const renamed = renamedValue(found.value, version);
|
|
3499
|
+
const line = lineOf(found.start);
|
|
3500
|
+
const dynamic = found.isModuleSpecifier ? dynamicPackage(found.value) : void 0;
|
|
3501
|
+
if (renamed === void 0) {
|
|
3502
|
+
manualSteps.push(...unrenamedSteps(found, line, dynamic));
|
|
3503
|
+
continue;
|
|
3504
|
+
}
|
|
3505
|
+
if (!found.isModuleSpecifier || found.start < copiedUpTo) {
|
|
3506
|
+
manualSteps.push({ kind: "string-names-package", line, value: found.value, to: renamed.to });
|
|
3507
|
+
continue;
|
|
3508
|
+
}
|
|
3509
|
+
changes.push({ kind: "specifier-renamed", line, from: found.value, to: renamed.to });
|
|
3510
|
+
if (renamed.isDeep) {
|
|
3511
|
+
manualSteps.push({ kind: "deep-import", line, specifier: renamed.to });
|
|
3512
|
+
}
|
|
3513
|
+
if (renamed.keptSpec !== void 0) {
|
|
3514
|
+
manualSteps.push({ kind: "spec-kept", name: renamed.to, spec: renamed.keptSpec });
|
|
3515
|
+
}
|
|
3516
|
+
migrated += `${text.slice(copiedUpTo, found.start)}${renamed.to}`;
|
|
3517
|
+
copiedUpTo = found.end;
|
|
3518
|
+
}
|
|
3519
|
+
return { text: migrated + text.slice(copiedUpTo), changes, manualSteps };
|
|
3520
|
+
}
|
|
3521
|
+
function importedSpecifiers(text, strings) {
|
|
3522
|
+
const lineOf = lineLocator(text);
|
|
3523
|
+
return strings.filter((found) => found.isModuleSpecifier).map((found) => ({
|
|
3524
|
+
specifier: renamedSpecifier(found.value)?.to ?? found.value,
|
|
3525
|
+
line: lineOf(found.start)
|
|
3526
|
+
}));
|
|
3527
|
+
}
|
|
3528
|
+
|
|
3529
|
+
const JEST_CONFIG_RE = /^jest\.config\.(?:[cm]?[jt]s|json)$/;
|
|
3530
|
+
const JEST_FIELD = "jest";
|
|
3531
|
+
const NAME_CHARACTER_RE = /[\w-]/;
|
|
3532
|
+
const FIELD_SEPARATOR$1 = ".";
|
|
3533
|
+
const isJestConfig = (fileName) => JEST_CONFIG_RE.test(fileName);
|
|
3534
|
+
function hasWholeName(value, name) {
|
|
3535
|
+
for (let at = value.indexOf(name); at !== -1; at = value.indexOf(name, at + 1)) {
|
|
3536
|
+
const before = value[at - 1] ?? "";
|
|
3537
|
+
const after = value[at + name.length] ?? "";
|
|
3538
|
+
if (!NAME_CHARACTER_RE.test(before) && !NAME_CHARACTER_RE.test(after)) {
|
|
3539
|
+
return true;
|
|
3540
|
+
}
|
|
3541
|
+
}
|
|
3542
|
+
return false;
|
|
3543
|
+
}
|
|
3544
|
+
const oldPackagesInPattern = (value) => [...PACKAGE_RENAMES.keys()].filter((name) => hasWholeName(value, name));
|
|
3545
|
+
const patternSteps = (value, location, isNameReported) => isNameReported && namesRenamedModule(value) ? [] : oldPackagesInPattern(value).map((name) => ({
|
|
3546
|
+
kind: "pattern-names-package",
|
|
3547
|
+
location,
|
|
3548
|
+
value,
|
|
3549
|
+
name,
|
|
3550
|
+
to: PACKAGE_RENAMES.get(name) ?? name
|
|
3551
|
+
}));
|
|
3552
|
+
function jestScriptSteps(text, strings) {
|
|
3553
|
+
const lineOf = lineLocator(text);
|
|
3554
|
+
return strings.filter((string) => !string.isModuleSpecifier).flatMap((string) => patternSteps(string.value, `line ${lineOf(string.start)}`, true));
|
|
3555
|
+
}
|
|
3556
|
+
function textsAt(node, path) {
|
|
3557
|
+
switch (node.kind) {
|
|
3558
|
+
case "scalar":
|
|
3559
|
+
return [{ value: node.value, path }];
|
|
3560
|
+
case "list":
|
|
3561
|
+
return node.items.flatMap((item, index) => textsAt(item, [...path, index]));
|
|
3562
|
+
case "map":
|
|
3563
|
+
return textEntries(node).flatMap(({ key, value }) => [
|
|
3564
|
+
{ value: key.value, path },
|
|
3565
|
+
...textsAt(value, [...path, key.value])
|
|
3566
|
+
]);
|
|
3567
|
+
default:
|
|
3568
|
+
return [];
|
|
3569
|
+
}
|
|
3570
|
+
}
|
|
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
|
+
}
|
|
3587
|
+
}
|
|
3588
|
+
return { text: applyTextEdits(text, edits), changes, manualSteps };
|
|
3589
|
+
}
|
|
3590
|
+
|
|
3591
|
+
const ASSIGNMENT_RE = new RegExp(
|
|
3592
|
+
[
|
|
3593
|
+
"^(?:[^\\s:#=][^:#=\\n]*:[ \\t]*)?",
|
|
3594
|
+
"(?:(?:export|override|private)[ \\t]+)*",
|
|
3595
|
+
"([A-Za-z_][A-Za-z0-9_.-]*)",
|
|
3596
|
+
"[ \\t]*(:::=|::=|:=|\\?=|\\+=|!=|=)"
|
|
3597
|
+
].join(""),
|
|
3598
|
+
"gm"
|
|
3599
|
+
);
|
|
3600
|
+
const VARIABLE_REFERENCE_RE = /^\$(?:\(([A-Za-z_][A-Za-z0-9_.-]*)\)|\{([A-Za-z_][A-Za-z0-9_.-]*)\}|([A-Za-z_]))$/;
|
|
3601
|
+
const RECIPE_PREFIX_RE = /^[@+-]+/;
|
|
3602
|
+
const DOLLAR = "$";
|
|
3603
|
+
const CLOSING = { "(": ")", "{": "}" };
|
|
3604
|
+
const NOT_LINE_BREAK_RE = /[^\n]/g;
|
|
3605
|
+
const MASK = "_";
|
|
3606
|
+
const LINE_BREAK = "\n";
|
|
3607
|
+
const BACKSLASH = "\\";
|
|
3608
|
+
function expansionEnd(text, start) {
|
|
3609
|
+
const open = text[start + 1] ?? "";
|
|
3610
|
+
const close = CLOSING[open];
|
|
3611
|
+
if (close === void 0) {
|
|
3612
|
+
return void 0;
|
|
3613
|
+
}
|
|
3614
|
+
let depth = 0;
|
|
3615
|
+
for (let index = start + 1; index < text.length; index++) {
|
|
3616
|
+
if (text[index] === open) {
|
|
3617
|
+
depth++;
|
|
3618
|
+
} else if (text[index] === close && --depth === 0) {
|
|
3619
|
+
return index + 1;
|
|
3620
|
+
}
|
|
3621
|
+
}
|
|
3622
|
+
return void 0;
|
|
3623
|
+
}
|
|
3624
|
+
function maskExpansions(text) {
|
|
3625
|
+
const parts = [];
|
|
3626
|
+
let copiedUpTo = 0;
|
|
3627
|
+
for (let index = text.indexOf(DOLLAR); index !== -1; index = text.indexOf(DOLLAR, index + 1)) {
|
|
3628
|
+
if (text[index + 1] === DOLLAR) {
|
|
3629
|
+
index++;
|
|
3630
|
+
continue;
|
|
3631
|
+
}
|
|
3632
|
+
const end = expansionEnd(text, index);
|
|
3633
|
+
if (end !== void 0) {
|
|
2969
3634
|
parts.push(text.slice(copiedUpTo, index + 1), MASK.repeat(end - index - 1));
|
|
2970
3635
|
copiedUpTo = end;
|
|
2971
3636
|
index = end - 1;
|
|
@@ -3058,6 +3723,90 @@ function migrateMakefile(text, file) {
|
|
|
3058
3723
|
return { text: applyTextEdits(text, edits), changes, manualSteps };
|
|
3059
3724
|
}
|
|
3060
3725
|
|
|
3726
|
+
function oldPackagesNamedBy(node) {
|
|
3727
|
+
const values = documentStrings([node]).map((string) => packageReference(string.value).name);
|
|
3728
|
+
const names = [...nestedKeys(node).map(overrideTarget), ...values];
|
|
3729
|
+
return [...new Set(names.filter((name) => PACKAGE_RENAMES.has(name)))];
|
|
3730
|
+
}
|
|
3731
|
+
function reportSettingSections(settings, file, findings) {
|
|
3732
|
+
for (const { key, value } of textEntries(settings)) {
|
|
3733
|
+
if (file.migratedSections.has(key.value)) {
|
|
3734
|
+
continue;
|
|
3735
|
+
}
|
|
3736
|
+
const field = `${file.prefix}${key.value}`;
|
|
3737
|
+
const isOverride = file.overrideSections.has(key.value);
|
|
3738
|
+
for (const name of oldPackagesNamedBy(value)) {
|
|
3739
|
+
findings.manualSteps.push(
|
|
3740
|
+
isOverride ? { kind: "override-names-package", field, name } : { kind: "setting-names-package", field, name }
|
|
3741
|
+
);
|
|
3742
|
+
}
|
|
3743
|
+
}
|
|
3744
|
+
}
|
|
3745
|
+
|
|
3746
|
+
const PATH_SEPARATOR = ".";
|
|
3747
|
+
const IMPORTS_FIELD = "imports";
|
|
3748
|
+
const BROWSER_FIELD = "browser";
|
|
3749
|
+
function reportDeep(renamed, location, findings) {
|
|
3750
|
+
if (renamed.isDeep) {
|
|
3751
|
+
findings.manualSteps.push({ kind: "deep-target", location, specifier: renamed.to });
|
|
3752
|
+
}
|
|
3753
|
+
}
|
|
3754
|
+
function renameSpecifierTargets(nodes, field, findings) {
|
|
3755
|
+
for (const target of documentStrings(nodes)) {
|
|
3756
|
+
const renamed = renamedSpecifier(target.value);
|
|
3757
|
+
if (renamed === void 0) {
|
|
3758
|
+
continue;
|
|
3759
|
+
}
|
|
3760
|
+
const location = [field, ...target.path].join(PATH_SEPARATOR);
|
|
3761
|
+
if (target.encode === void 0) {
|
|
3762
|
+
findings.manualSteps.push({ kind: "entry-not-edited", field: location, name: target.value });
|
|
3763
|
+
continue;
|
|
3764
|
+
}
|
|
3765
|
+
findings.edits.push(replaceScalar({ ...target, encode: target.encode }, renamed.to));
|
|
3766
|
+
findings.changes.push({
|
|
3767
|
+
kind: "package-name-renamed",
|
|
3768
|
+
location,
|
|
3769
|
+
from: target.value,
|
|
3770
|
+
to: renamed.to
|
|
3771
|
+
});
|
|
3772
|
+
reportDeep(renamed, location, findings);
|
|
3773
|
+
}
|
|
3774
|
+
}
|
|
3775
|
+
function renameSpecifierKeys(map, field, findings) {
|
|
3776
|
+
const keys = textEntries(map).map(({ key }) => key);
|
|
3777
|
+
const names = new Set(keys.map((key) => key.value));
|
|
3778
|
+
return keys.flatMap((key) => {
|
|
3779
|
+
const renamed = renamedSpecifier(key.value);
|
|
3780
|
+
if (renamed === void 0) {
|
|
3781
|
+
return [];
|
|
3782
|
+
}
|
|
3783
|
+
if (key.encode === void 0) {
|
|
3784
|
+
findings.manualSteps.push({ kind: "entry-not-edited", field, name: key.value });
|
|
3785
|
+
return [];
|
|
3786
|
+
}
|
|
3787
|
+
const { to } = renamed;
|
|
3788
|
+
if (!isFree({ from: key.value, to, field, names }, findings)) {
|
|
3789
|
+
return [];
|
|
3790
|
+
}
|
|
3791
|
+
findings.edits.push(replaceScalar({ ...key, encode: key.encode }, to));
|
|
3792
|
+
findings.changes.push({ kind: "package-name-renamed", location: field, from: key.value, to });
|
|
3793
|
+
return [{ location: `${field}${PATH_SEPARATOR}${key.value}`, renamed }];
|
|
3794
|
+
});
|
|
3795
|
+
}
|
|
3796
|
+
function migrateSubpathImports(manifest, findings) {
|
|
3797
|
+
renameSpecifierTargets(valuesAt(manifest, IMPORTS_FIELD), IMPORTS_FIELD, findings);
|
|
3798
|
+
}
|
|
3799
|
+
function migrateBrowserField(manifest, findings) {
|
|
3800
|
+
for (const browser of valuesAt(manifest, BROWSER_FIELD).filter(isMap)) {
|
|
3801
|
+
for (const { location, renamed } of renameSpecifierKeys(browser, BROWSER_FIELD, findings)) {
|
|
3802
|
+
reportDeep(renamed, location, findings);
|
|
3803
|
+
}
|
|
3804
|
+
for (const { key, value } of textEntries(browser)) {
|
|
3805
|
+
renameSpecifierTargets([value], `${BROWSER_FIELD}${PATH_SEPARATOR}${key.value}`, findings);
|
|
3806
|
+
}
|
|
3807
|
+
}
|
|
3808
|
+
}
|
|
3809
|
+
|
|
3061
3810
|
function migrateDependencyFields(manifest, target, findings) {
|
|
3062
3811
|
for (const field of DEPENDENCY_FIELDS) {
|
|
3063
3812
|
for (const dependencies of mapsAt(manifest, field)) {
|
|
@@ -3096,13 +3845,20 @@ function migrateCatalogs$1(manifest, target, findings) {
|
|
|
3096
3845
|
migrateSpecMap(specEntries(map), context);
|
|
3097
3846
|
}
|
|
3098
3847
|
}
|
|
3099
|
-
|
|
3848
|
+
const PNPM_SETTINGS = {
|
|
3849
|
+
migratedSections: /* @__PURE__ */ new Set(),
|
|
3850
|
+
overrideSections: /* @__PURE__ */ new Set(["overrides", "patchedDependencies"]),
|
|
3851
|
+
prefix: `${PNPM_SETTINGS_FIELD}.`
|
|
3852
|
+
};
|
|
3853
|
+
function reportSettings(manifest, findings) {
|
|
3100
3854
|
for (const field of OVERRIDE_FIELDS) {
|
|
3101
|
-
const
|
|
3102
|
-
for (const name of overriddenPackages(keys)) {
|
|
3855
|
+
for (const name of valuesAt(manifest, field).flatMap(oldPackagesNamedBy)) {
|
|
3103
3856
|
findings.manualSteps.push({ kind: "override-names-package", field, name });
|
|
3104
3857
|
}
|
|
3105
3858
|
}
|
|
3859
|
+
for (const settings of mapsAt(manifest, PNPM_SETTINGS_FIELD)) {
|
|
3860
|
+
reportSettingSections(settings, PNPM_SETTINGS, findings);
|
|
3861
|
+
}
|
|
3106
3862
|
}
|
|
3107
3863
|
function reportOldPeers(manifest, findings) {
|
|
3108
3864
|
const dependencies = new Set(declaredNames(manifest));
|
|
@@ -3117,7 +3873,12 @@ function migrateManifestMap(manifest, target, findings) {
|
|
|
3117
3873
|
migrateNameKeys(manifest, findings);
|
|
3118
3874
|
migrateNameLists(manifest, findings);
|
|
3119
3875
|
migrateCatalogs$1(manifest, target, findings);
|
|
3120
|
-
|
|
3876
|
+
migrateSubpathImports(manifest, findings);
|
|
3877
|
+
migrateBrowserField(manifest, findings);
|
|
3878
|
+
reportSettings(manifest, findings);
|
|
3879
|
+
for (const jest of valuesAt(manifest, JEST_FIELD)) {
|
|
3880
|
+
findings.manualSteps.push(...jestConfigSteps(jest, [JEST_FIELD]));
|
|
3881
|
+
}
|
|
3121
3882
|
reportOldPeers(manifest, findings);
|
|
3122
3883
|
}
|
|
3123
3884
|
function migratePackageManifest(text, read, target) {
|
|
@@ -3135,134 +3896,22 @@ function unreadManifest(text) {
|
|
|
3135
3896
|
return namesOriginalPackage(text) ? { ...unchanged(text), manualSteps: [{ kind: "manifest-not-read" }] } : unchanged(text);
|
|
3136
3897
|
}
|
|
3137
3898
|
|
|
3138
|
-
const
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
".jsx",
|
|
3145
|
-
".mjs",
|
|
3146
|
-
".cjs",
|
|
3147
|
-
".vue",
|
|
3148
|
-
".svelte",
|
|
3149
|
-
".astro"
|
|
3150
|
-
]);
|
|
3151
|
-
function renamedValue(value, version) {
|
|
3152
|
-
const npm = migrateNpmSpec(value, version);
|
|
3153
|
-
if (npm === void 0) {
|
|
3154
|
-
return renamedSpecifier(value);
|
|
3155
|
-
}
|
|
3156
|
-
const renamed = { to: npm.spec, isDeep: npm.isDeep };
|
|
3157
|
-
return npm.isReported ? { ...renamed, keptSpec: hideUrlCredentials(value) } : renamed;
|
|
3158
|
-
}
|
|
3159
|
-
const TEMPLATE_SUBSTITUTION = "${";
|
|
3160
|
-
function dynamicPackage(value) {
|
|
3161
|
-
const at = value.indexOf(TEMPLATE_SUBSTITUTION);
|
|
3162
|
-
return at === -1 ? void 0 : PACKAGE_RENAMES.get(value.slice(0, at));
|
|
3163
|
-
}
|
|
3164
|
-
const byStartThenOuter = (left, right) => left.start - right.start || right.end - left.end;
|
|
3165
|
-
function distinctStrings(strings) {
|
|
3166
|
-
const distinct = [];
|
|
3167
|
-
const enclosing = [];
|
|
3168
|
-
for (const found of [...strings].sort(byStartThenOuter)) {
|
|
3169
|
-
const previous = distinct.at(-1);
|
|
3170
|
-
if (previous?.start === found.start && previous.end === found.end) {
|
|
3171
|
-
const isModuleSpecifier = previous.isModuleSpecifier || found.isModuleSpecifier;
|
|
3172
|
-
distinct[distinct.length - 1] = { ...previous, isModuleSpecifier };
|
|
3173
|
-
continue;
|
|
3174
|
-
}
|
|
3175
|
-
let outer = enclosing.at(-1);
|
|
3176
|
-
while (outer !== void 0 && outer.end <= found.start) {
|
|
3177
|
-
enclosing.pop();
|
|
3178
|
-
outer = enclosing.at(-1);
|
|
3179
|
-
}
|
|
3180
|
-
if (outer !== void 0 && found.end > outer.end) {
|
|
3181
|
-
throw new Error(
|
|
3182
|
-
`Source strings overlap at offsets ${outer.start}-${outer.end} and ${found.start}-${found.end}; the file was not changed.`
|
|
3183
|
-
);
|
|
3184
|
-
}
|
|
3185
|
-
enclosing.push(found);
|
|
3186
|
-
distinct.push(found);
|
|
3187
|
-
}
|
|
3188
|
-
return distinct;
|
|
3189
|
-
}
|
|
3190
|
-
const dynamicStep = (line, value, to) => ({
|
|
3191
|
-
kind: "dynamic-specifier",
|
|
3192
|
-
line,
|
|
3193
|
-
value,
|
|
3194
|
-
to
|
|
3195
|
-
});
|
|
3196
|
-
function migrateModuleSpecifiers(text, strings, version) {
|
|
3197
|
-
const changes = [];
|
|
3198
|
-
const manualSteps = [];
|
|
3199
|
-
let migrated = "";
|
|
3200
|
-
let copiedUpTo = 0;
|
|
3201
|
-
const lineOf = lineLocator(text);
|
|
3202
|
-
for (const found of distinctStrings(strings)) {
|
|
3203
|
-
const renamed = renamedValue(found.value, version);
|
|
3204
|
-
const line = lineOf(found.start);
|
|
3205
|
-
const dynamic = found.isModuleSpecifier ? dynamicPackage(found.value) : void 0;
|
|
3206
|
-
if (renamed === void 0) {
|
|
3207
|
-
manualSteps.push(...dynamic === void 0 ? [] : [dynamicStep(line, found.value, dynamic)]);
|
|
3208
|
-
continue;
|
|
3209
|
-
}
|
|
3210
|
-
if (!found.isModuleSpecifier || found.start < copiedUpTo) {
|
|
3211
|
-
manualSteps.push({ kind: "string-names-package", line, value: found.value, to: renamed.to });
|
|
3212
|
-
continue;
|
|
3213
|
-
}
|
|
3214
|
-
changes.push({ kind: "specifier-renamed", line, from: found.value, to: renamed.to });
|
|
3215
|
-
if (renamed.isDeep) {
|
|
3216
|
-
manualSteps.push({ kind: "deep-import", line, specifier: renamed.to });
|
|
3217
|
-
}
|
|
3218
|
-
if (renamed.keptSpec !== void 0) {
|
|
3219
|
-
manualSteps.push({ kind: "spec-kept", name: renamed.to, spec: renamed.keptSpec });
|
|
3220
|
-
}
|
|
3221
|
-
migrated += `${text.slice(copiedUpTo, found.start)}${renamed.to}`;
|
|
3222
|
-
copiedUpTo = found.end;
|
|
3223
|
-
}
|
|
3224
|
-
return { text: migrated + text.slice(copiedUpTo), changes, manualSteps };
|
|
3225
|
-
}
|
|
3226
|
-
function importedSpecifiers(text, strings) {
|
|
3227
|
-
const lineOf = lineLocator(text);
|
|
3228
|
-
return strings.filter((found) => found.isModuleSpecifier).map((found) => ({
|
|
3229
|
-
specifier: renamedSpecifier(found.value)?.to ?? found.value,
|
|
3230
|
-
line: lineOf(found.start)
|
|
3231
|
-
}));
|
|
3232
|
-
}
|
|
3233
|
-
|
|
3234
|
-
const PNPM_WORKSPACE_FILE = {
|
|
3235
|
-
reportedSections: /* @__PURE__ */ new Set(["overrides", "patchedDependencies"])
|
|
3236
|
-
};
|
|
3237
|
-
const YARNRC_FILE = { reportedSections: /* @__PURE__ */ new Set() };
|
|
3238
|
-
function migrateCatalogs(workspace, target, findings) {
|
|
3239
|
-
for (const { name, label, map } of catalogMaps(workspace)) {
|
|
3240
|
-
const context = {
|
|
3241
|
-
...target,
|
|
3242
|
-
map: { kind: "catalog", catalog: label, name },
|
|
3243
|
-
findings
|
|
3244
|
-
};
|
|
3245
|
-
migrateSpecMap(specEntries(map), context);
|
|
3246
|
-
}
|
|
3247
|
-
}
|
|
3248
|
-
function reportSections(workspace, file, findings) {
|
|
3249
|
-
for (const field of file.reportedSections) {
|
|
3250
|
-
for (const name of overriddenPackages(valuesAt(workspace, field).flatMap(nestedKeys))) {
|
|
3251
|
-
findings.manualSteps.push({ kind: "override-names-package", field, name });
|
|
3252
|
-
}
|
|
3899
|
+
const PATCH_EXTENSION = ".patch";
|
|
3900
|
+
const NESTED_SEPARATOR = "++";
|
|
3901
|
+
const NAME_ENDS = ["+", "@", "-npm-"];
|
|
3902
|
+
function patchedOldPackage(fileName) {
|
|
3903
|
+
if (!fileName.endsWith(PATCH_EXTENSION)) {
|
|
3904
|
+
return void 0;
|
|
3253
3905
|
}
|
|
3906
|
+
const innermost = fileName.split(NESTED_SEPARATOR).at(-1) ?? fileName;
|
|
3907
|
+
return [...PACKAGE_RENAMES.keys()].find(
|
|
3908
|
+
(name) => NAME_ENDS.some((end) => innermost.startsWith(`${name}${end}`))
|
|
3909
|
+
);
|
|
3254
3910
|
}
|
|
3255
|
-
function
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
}
|
|
3259
|
-
const findings = newFindings();
|
|
3260
|
-
for (const workspace of read.documents.filter(isMap)) {
|
|
3261
|
-
migrateCatalogs(workspace, target, findings);
|
|
3262
|
-
reportSections(workspace, file, findings);
|
|
3263
|
-
}
|
|
3264
|
-
const { edits, changes, manualSteps } = findings;
|
|
3265
|
-
return { text: applyTextEdits(text, edits), changes, manualSteps };
|
|
3911
|
+
function oldPackagePatchSteps(fileName) {
|
|
3912
|
+
const name = patchedOldPackage(fileName);
|
|
3913
|
+
const to = name === void 0 ? void 0 : PACKAGE_RENAMES.get(name);
|
|
3914
|
+
return name === void 0 || to === void 0 ? [] : [{ kind: "old-package-patch", name, to }];
|
|
3266
3915
|
}
|
|
3267
3916
|
|
|
3268
3917
|
const YAML_COMMAND_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -3279,11 +3928,24 @@ const YAML_COMMAND_KEYS = /* @__PURE__ */ new Set([
|
|
|
3279
3928
|
"commands",
|
|
3280
3929
|
"entrypoint"
|
|
3281
3930
|
]);
|
|
3931
|
+
const TASKFILE_COMMAND_KEYS = /* @__PURE__ */ new Set([
|
|
3932
|
+
...YAML_COMMAND_KEYS,
|
|
3933
|
+
"cmds",
|
|
3934
|
+
"cmd",
|
|
3935
|
+
"defer",
|
|
3936
|
+
"sh",
|
|
3937
|
+
"preconditions",
|
|
3938
|
+
"status"
|
|
3939
|
+
]);
|
|
3940
|
+
|
|
3282
3941
|
const ENVIRONMENT_KEYS = /* @__PURE__ */ new Set(["env"]);
|
|
3283
3942
|
const isEnvironmentValue = (value) => value.path.length >= 2 && ENVIRONMENT_KEYS.has(String(value.path.at(-2)));
|
|
3284
3943
|
function environmentVariables(text, strings) {
|
|
3285
3944
|
return shellVariables(
|
|
3286
|
-
strings.filter(isEnvironmentValue).map((value) => ({
|
|
3945
|
+
strings.filter(isEnvironmentValue).map((value) => ({
|
|
3946
|
+
name: String(value.path.at(-1)),
|
|
3947
|
+
value: value.isEscaped ? value.value : shellText(text, value)
|
|
3948
|
+
}))
|
|
3287
3949
|
);
|
|
3288
3950
|
}
|
|
3289
3951
|
const DEPENDABOT_NAME_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -3299,6 +3961,12 @@ function shellText(text, value) {
|
|
|
3299
3961
|
const unfolded = value.isFolded ? slice.replace(FOLDED_LINE_BREAK_RE, " ") : slice;
|
|
3300
3962
|
return unfolded.replace(ENV_EXPRESSION_RE, asShellVariable);
|
|
3301
3963
|
}
|
|
3964
|
+
const LEADING_SPACES_RE = /^ */;
|
|
3965
|
+
function blockIndent(shell) {
|
|
3966
|
+
const lines = shell.split("\n").slice(1).filter((line) => line.trim() !== "");
|
|
3967
|
+
const indents = lines.map((line) => LEADING_SPACES_RE.exec(line)?.[0].length ?? 0);
|
|
3968
|
+
return indents.length === 0 ? 0 : Math.min(...indents);
|
|
3969
|
+
}
|
|
3302
3970
|
const valuesOf = (strings, keys) => strings.filter((string) => keys.has(ownerKey(string.path) ?? ""));
|
|
3303
3971
|
const EXEC_FORM_KEYS = /* @__PURE__ */ new Set(["command", "entrypoint"]);
|
|
3304
3972
|
const isExecFormItem = (value) => typeof value.path.at(-1) === "number" && EXEC_FORM_KEYS.has(String(value.path.at(-2)));
|
|
@@ -3319,9 +3987,21 @@ function execFormCommands(text, items) {
|
|
|
3319
3987
|
}
|
|
3320
3988
|
return commands;
|
|
3321
3989
|
}
|
|
3990
|
+
function escapedValueFindings(value, encode, locate, variables) {
|
|
3991
|
+
const commands = shellCommands(value.value);
|
|
3992
|
+
const found = commandWordFindings(commands, () => locate(value.start), variables);
|
|
3993
|
+
const migrated = applyTextEdits(value.value, found.edits);
|
|
3994
|
+
const isChanged = migrated !== value.value;
|
|
3995
|
+
const edits = isChanged ? [{ start: value.start, end: value.end, text: encode(migrated) }] : [];
|
|
3996
|
+
return { ...found, edits };
|
|
3997
|
+
}
|
|
3322
3998
|
function valueFindings(text, value, locate, variables) {
|
|
3999
|
+
if (value.isEscaped && value.encode !== void 0) {
|
|
4000
|
+
return escapedValueFindings(value, value.encode, locate, variables);
|
|
4001
|
+
}
|
|
3323
4002
|
const { start } = value.content;
|
|
3324
|
-
const
|
|
4003
|
+
const shell = shellText(text, value);
|
|
4004
|
+
const commands = shellCommands(shell, blockIndent(shell));
|
|
3325
4005
|
const found = commandWordFindings(commands, (offset) => locate(start + offset), variables);
|
|
3326
4006
|
return { ...found, edits: shiftedEdits(found.edits, start) };
|
|
3327
4007
|
}
|
|
@@ -3336,8 +4016,8 @@ function appliedFindings(text, found) {
|
|
|
3336
4016
|
manualSteps: found.flatMap((findings) => findings.manualSteps)
|
|
3337
4017
|
};
|
|
3338
4018
|
}
|
|
3339
|
-
function migrateYamlCommands(text, file, strings) {
|
|
3340
|
-
const values = valuesOf(strings,
|
|
4019
|
+
function migrateYamlCommands(text, file, strings, keys = YAML_COMMAND_KEYS) {
|
|
4020
|
+
const values = valuesOf(strings, keys);
|
|
3341
4021
|
const lineOf = lineLocator(text);
|
|
3342
4022
|
const locate = (offset) => `${file}:${lineOf(offset)}`;
|
|
3343
4023
|
const commandValues = new Set(values.filter((value) => !isExecFormItem(value)));
|
|
@@ -3350,31 +4030,186 @@ function migrateYamlCommands(text, file, strings) {
|
|
|
3350
4030
|
commandWordFindings(execFormCommands(text, values.filter(isExecFormItem)), locate)
|
|
3351
4031
|
]);
|
|
3352
4032
|
}
|
|
3353
|
-
|
|
3354
|
-
const
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
4033
|
+
function migrateYamlPathCommands(text, strings, patterns) {
|
|
4034
|
+
const commands = strings.filter((string) => isCommandPath(string.path, patterns));
|
|
4035
|
+
return appliedFindings(
|
|
4036
|
+
text,
|
|
4037
|
+
commands.map((command) => valueFindings(text, command, () => command.path.join(".")))
|
|
4038
|
+
);
|
|
4039
|
+
}
|
|
4040
|
+
function migrateDependabotConfig(text, file, strings) {
|
|
4041
|
+
const changes = [];
|
|
4042
|
+
const edits = [];
|
|
4043
|
+
const lineOf = lineLocator(text);
|
|
4044
|
+
for (const value of valuesOf(strings, DEPENDABOT_NAME_KEYS)) {
|
|
4045
|
+
const from = value.value;
|
|
4046
|
+
const to = PACKAGE_RENAMES.get(from);
|
|
4047
|
+
if (to !== void 0) {
|
|
4048
|
+
const { start, end } = value.content;
|
|
4049
|
+
const location = `${file}:${lineOf(start)}`;
|
|
4050
|
+
changes.push({ kind: "package-name-renamed", location, from, to });
|
|
4051
|
+
edits.push({ start, end, text: to });
|
|
4052
|
+
}
|
|
4053
|
+
}
|
|
4054
|
+
return { text: applyTextEdits(text, edits), changes, manualSteps: [] };
|
|
4055
|
+
}
|
|
4056
|
+
|
|
4057
|
+
const ENTRY_KEY = "entry";
|
|
4058
|
+
const ARGS_KEY = "args";
|
|
4059
|
+
const DEPENDENCIES_KEY = "additional_dependencies";
|
|
4060
|
+
const hookOf = (path) => path.slice(0, -1).join(".");
|
|
4061
|
+
function listsByHook(strings, key) {
|
|
4062
|
+
const lists = /* @__PURE__ */ new Map();
|
|
4063
|
+
for (const item of strings) {
|
|
4064
|
+
if (item.path.at(-2) === key) {
|
|
4065
|
+
const hook = item.path.slice(0, -2).join(".");
|
|
4066
|
+
lists.set(hook, [...lists.get(hook) ?? [], item]);
|
|
4067
|
+
}
|
|
4068
|
+
}
|
|
4069
|
+
return lists;
|
|
4070
|
+
}
|
|
4071
|
+
function entryWords(text, entry) {
|
|
4072
|
+
const { start } = entry.content;
|
|
4073
|
+
return shellCommands(shellText(text, entry)).flat().map((word) => ({ ...word, start: word.start + start, end: word.end + start }));
|
|
4074
|
+
}
|
|
4075
|
+
const itemWord = (text, item) => {
|
|
4076
|
+
const { start, end } = item.content;
|
|
4077
|
+
return { start, end, value: item.value, raw: text.slice(start, end) };
|
|
4078
|
+
};
|
|
4079
|
+
function hookCommands(text, strings) {
|
|
4080
|
+
const args = listsByHook(strings, ARGS_KEY);
|
|
4081
|
+
return strings.filter((string) => string.path.at(-1) === ENTRY_KEY).map((entry) => [
|
|
4082
|
+
...entryWords(text, entry),
|
|
4083
|
+
...(args.get(hookOf(entry.path)) ?? []).map((item) => itemWord(text, item))
|
|
4084
|
+
]);
|
|
4085
|
+
}
|
|
4086
|
+
function dependencyFindings(strings, locate) {
|
|
4087
|
+
const found = {
|
|
4088
|
+
edits: [],
|
|
4089
|
+
changes: [],
|
|
4090
|
+
manualSteps: []
|
|
4091
|
+
};
|
|
4092
|
+
for (const item of [...listsByHook(strings, DEPENDENCIES_KEY).values()].flat()) {
|
|
4093
|
+
const { name, isPinned } = packageReference(item.value);
|
|
4094
|
+
const to = PACKAGE_RENAMES.get(name);
|
|
4095
|
+
const location = locate(item.content.start);
|
|
4096
|
+
if (to !== void 0 && isPinned) {
|
|
4097
|
+
found.manualSteps.push({ kind: "pinned-package", location, name });
|
|
4098
|
+
} else if (to !== void 0) {
|
|
4099
|
+
found.edits.push({ start: item.content.start, end: item.content.end, text: to });
|
|
4100
|
+
found.changes.push({ kind: "package-name-renamed", location, from: name, to });
|
|
4101
|
+
}
|
|
4102
|
+
}
|
|
4103
|
+
return found;
|
|
4104
|
+
}
|
|
4105
|
+
function migratePreCommitHooks(text, file, strings) {
|
|
4106
|
+
const lineOf = lineLocator(text);
|
|
4107
|
+
const locate = (offset) => `${file}:${lineOf(offset)}`;
|
|
4108
|
+
return appliedFindings(text, [
|
|
4109
|
+
commandWordFindings(hookCommands(text, strings), locate),
|
|
4110
|
+
dependencyFindings(strings, locate)
|
|
4111
|
+
]);
|
|
4112
|
+
}
|
|
4113
|
+
|
|
4114
|
+
const COMPILER_OPTIONS_FIELD = "compilerOptions";
|
|
4115
|
+
const PATHS_FIELD = "paths";
|
|
4116
|
+
const TYPES_FIELD = "types";
|
|
4117
|
+
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
|
+
function migrateCompilerOptions(options, findings) {
|
|
4129
|
+
for (const paths of mapsAt(options, PATHS_FIELD)) {
|
|
4130
|
+
const field = [COMPILER_OPTIONS_FIELD, PATHS_FIELD].join(FIELD_SEPARATOR);
|
|
4131
|
+
renameSpecifierKeys(paths, field, findings);
|
|
4132
|
+
}
|
|
4133
|
+
for (const types of valuesAt(options, TYPES_FIELD)) {
|
|
4134
|
+
if (types.kind === "list") {
|
|
4135
|
+
const field = [COMPILER_OPTIONS_FIELD, TYPES_FIELD].join(FIELD_SEPARATOR);
|
|
4136
|
+
renameNames(itemEntries(types), field, findings);
|
|
4137
|
+
}
|
|
4138
|
+
}
|
|
4139
|
+
}
|
|
4140
|
+
function migrateTsconfig(text, read) {
|
|
4141
|
+
if (read.kind === "unreadable") {
|
|
4142
|
+
return unreadableConfig(text, read.offset);
|
|
4143
|
+
}
|
|
4144
|
+
const findings = newFindings();
|
|
4145
|
+
for (const config of read.documents.filter(isMap)) {
|
|
4146
|
+
for (const options of mapsAt(config, COMPILER_OPTIONS_FIELD)) {
|
|
4147
|
+
migrateCompilerOptions(options, findings);
|
|
4148
|
+
}
|
|
4149
|
+
reportOldPackagePaths(config, findings);
|
|
4150
|
+
}
|
|
4151
|
+
const { edits, changes, manualSteps } = findings;
|
|
4152
|
+
return { text: applyTextEdits(text, edits), changes, manualSteps };
|
|
4153
|
+
}
|
|
4154
|
+
|
|
4155
|
+
const CATALOG_SECTIONS = [CATALOG_FIELD, NAMED_CATALOGS_FIELD];
|
|
4156
|
+
const PNPM_WORKSPACE_FILE = {
|
|
4157
|
+
migratedSections: /* @__PURE__ */ new Set([...CATALOG_SECTIONS, "packages"]),
|
|
4158
|
+
overrideSections: /* @__PURE__ */ new Set(["overrides", "patchedDependencies"]),
|
|
4159
|
+
prefix: ""
|
|
4160
|
+
};
|
|
4161
|
+
const YARNRC_FILE = {
|
|
4162
|
+
migratedSections: new Set(CATALOG_SECTIONS),
|
|
4163
|
+
overrideSections: /* @__PURE__ */ new Set(),
|
|
4164
|
+
prefix: ""
|
|
4165
|
+
};
|
|
4166
|
+
function migrateCatalogs(workspace, target, findings) {
|
|
4167
|
+
for (const { name, label, map } of catalogMaps(workspace)) {
|
|
4168
|
+
const context = {
|
|
4169
|
+
...target,
|
|
4170
|
+
map: { kind: "catalog", catalog: label, name },
|
|
4171
|
+
findings
|
|
4172
|
+
};
|
|
4173
|
+
migrateSpecMap(specEntries(map), context);
|
|
4174
|
+
}
|
|
4175
|
+
}
|
|
4176
|
+
function migrateWorkspaceCatalogs(text, read, target, file) {
|
|
4177
|
+
if (read.kind === "unreadable") {
|
|
4178
|
+
return unreadableConfig(text, read.offset);
|
|
4179
|
+
}
|
|
4180
|
+
const findings = newFindings();
|
|
4181
|
+
for (const workspace of read.documents.filter(isMap)) {
|
|
4182
|
+
migrateCatalogs(workspace, target, findings);
|
|
4183
|
+
reportSettingSections(workspace, file, findings);
|
|
4184
|
+
}
|
|
4185
|
+
const { edits, changes, manualSteps } = findings;
|
|
4186
|
+
return { text: applyTextEdits(text, edits), changes, manualSteps };
|
|
4187
|
+
}
|
|
4188
|
+
|
|
4189
|
+
const withSteps = (migration, steps) => ({
|
|
4190
|
+
...migration,
|
|
4191
|
+
manualSteps: [...migration.manualSteps, ...steps]
|
|
4192
|
+
});
|
|
4193
|
+
function chain(first, next) {
|
|
4194
|
+
const second = next(first.text);
|
|
4195
|
+
const changes = [...first.changes, ...second.changes];
|
|
4196
|
+
const manualSteps = [...first.manualSteps, ...second.manualSteps];
|
|
4197
|
+
return { text: second.text, changes, manualSteps };
|
|
3361
4198
|
}
|
|
3362
|
-
function
|
|
3363
|
-
const
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
for (const value of valuesOf(strings, DEPENDABOT_NAME_KEYS)) {
|
|
3367
|
-
const from = value.value;
|
|
3368
|
-
const to = PACKAGE_RENAMES.get(from);
|
|
3369
|
-
if (to !== void 0) {
|
|
3370
|
-
const { start, end } = value.content;
|
|
3371
|
-
const location = `${file}:${lineOf(start)}`;
|
|
3372
|
-
changes.push({ kind: "package-name-renamed", location, from, to });
|
|
3373
|
-
edits.push({ start, end, text: to });
|
|
3374
|
-
}
|
|
4199
|
+
function migrateConfig(text, read, steps) {
|
|
4200
|
+
const first = read(text);
|
|
4201
|
+
if (first.kind === "unreadable") {
|
|
4202
|
+
return unreadableConfig(text, first.offset);
|
|
3375
4203
|
}
|
|
3376
|
-
return
|
|
4204
|
+
return steps.reduce(
|
|
4205
|
+
(done, step) => chain(done, (current) => step(current, current === text ? first : read(current))),
|
|
4206
|
+
unchanged(text)
|
|
4207
|
+
);
|
|
3377
4208
|
}
|
|
4209
|
+
const stringsStep = (migrate) => (text, read) => read.kind === "unreadable" ? unreadableConfig(text, read.offset) : migrate(text, documentStrings(read.documents));
|
|
4210
|
+
const jsonConfig = (steps) => (text, path, context) => migrateConfig(text, (current) => context.readers.json.read(current), steps(context, path));
|
|
4211
|
+
const yamlConfig = (steps) => (text, path, context) => migrateConfig(text, (current) => context.readers.yaml.read(current), steps(context, path));
|
|
4212
|
+
const whenNamed = (migrate) => (text, path, context) => namesOriginalPackage(text) ? migrate(text, path, context) : unchanged(text);
|
|
3378
4213
|
|
|
3379
4214
|
const SHELL_EXTENSIONS = /* @__PURE__ */ new Set([".sh", ".bash", ".zsh"]);
|
|
3380
4215
|
const MAKEFILE_EXTENSION = ".mk";
|
|
@@ -3385,6 +4220,28 @@ const DOCKERFILE_NAMES = /* @__PURE__ */ new Set(["Dockerfile", "Containerfile"]
|
|
|
3385
4220
|
const HUSKY_FOLDER = ".husky/";
|
|
3386
4221
|
const HUSKY_INTERNALS = ".husky/_/";
|
|
3387
4222
|
const NX_PROJECT_FILE = "project.json";
|
|
4223
|
+
const NX_WORKSPACE_FILE = "nx.json";
|
|
4224
|
+
const JEST_JSON_CONFIG_FILE = "jest.config.json";
|
|
4225
|
+
const TASKFILE_NAMES = new Set(
|
|
4226
|
+
["Taskfile", "taskfile", "Taskfile.dist", "taskfile.dist"].flatMap((name) => [
|
|
4227
|
+
`${name}.yml`,
|
|
4228
|
+
`${name}.yaml`
|
|
4229
|
+
])
|
|
4230
|
+
);
|
|
4231
|
+
const PRE_COMMIT_FILES = /* @__PURE__ */ new Set([
|
|
4232
|
+
".pre-commit-config.yaml",
|
|
4233
|
+
".pre-commit-config.yml"
|
|
4234
|
+
]);
|
|
4235
|
+
const LINT_STAGED_YAML_FILES = /* @__PURE__ */ new Set([
|
|
4236
|
+
".lintstagedrc",
|
|
4237
|
+
".lintstagedrc.yaml",
|
|
4238
|
+
".lintstagedrc.yml"
|
|
4239
|
+
]);
|
|
4240
|
+
const LINT_STAGED_JSON_FILE = ".lintstagedrc.json";
|
|
4241
|
+
const SIMPLE_GIT_HOOKS_FILES = /* @__PURE__ */ new Set([
|
|
4242
|
+
".simple-git-hooks.json",
|
|
4243
|
+
"simple-git-hooks.json"
|
|
4244
|
+
]);
|
|
3388
4245
|
const DENO_CONFIG_FILES = /* @__PURE__ */ new Set(["deno.json", "deno.jsonc"]);
|
|
3389
4246
|
const IMPORT_MAP_FILE = "import_map.json";
|
|
3390
4247
|
const DEPENDABOT_FILES = /* @__PURE__ */ new Set([
|
|
@@ -3396,6 +4253,7 @@ const YARNRC_FILE_NAME = ".yarnrc.yml";
|
|
|
3396
4253
|
const YAML_MANIFEST_FILES = /* @__PURE__ */ new Set(["package.yaml", "package.yml"]);
|
|
3397
4254
|
const JSON5_MANIFEST_FILE = "package.json5";
|
|
3398
4255
|
const MANIFEST_FILE = "package.json";
|
|
4256
|
+
const PROJECT_CONFIG_NAME = /^[jt]sconfig(\.[^/]+)?\.json$/;
|
|
3399
4257
|
const LOCK_FILES = /* @__PURE__ */ new Set(["pnpm-lock.yaml", "yarn.lock", "bun.lock"]);
|
|
3400
4258
|
function baseName(path) {
|
|
3401
4259
|
return path.slice(path.lastIndexOf("/") + 1);
|
|
@@ -3406,12 +4264,40 @@ function extensionOf(path) {
|
|
|
3406
4264
|
return dot <= 0 ? "" : name.slice(dot);
|
|
3407
4265
|
}
|
|
3408
4266
|
|
|
4267
|
+
const NO_NAMED_IMPORT_MAPS = /* @__PURE__ */ new Map();
|
|
4268
|
+
async function importMapsOf(path, files, readers) {
|
|
4269
|
+
const read = await files.read(path);
|
|
4270
|
+
const parsed = read.kind === "read" ? readers.json.read(read.text) : void 0;
|
|
4271
|
+
if (parsed?.kind !== "read") {
|
|
4272
|
+
return [];
|
|
4273
|
+
}
|
|
4274
|
+
return importMapLocations(path, parsed.documents.filter(isMap)).flatMap(
|
|
4275
|
+
(location) => location.kind === "in-project" ? [location.path] : []
|
|
4276
|
+
);
|
|
4277
|
+
}
|
|
4278
|
+
async function namedImportMaps(paths, files, readers) {
|
|
4279
|
+
const named = /* @__PURE__ */ new Map();
|
|
4280
|
+
for (const path of paths.filter((candidate) => DENO_CONFIG_FILES.has(baseName(candidate)))) {
|
|
4281
|
+
for (const map of await importMapsOf(path, files, readers)) {
|
|
4282
|
+
named.set(map, [...named.get(map) ?? [], path]);
|
|
4283
|
+
}
|
|
4284
|
+
}
|
|
4285
|
+
return named;
|
|
4286
|
+
}
|
|
4287
|
+
function joinedNames(sets) {
|
|
4288
|
+
return sets.some((names) => names === void 0) ? void 0 : new Set(sets.flatMap((names) => [...names ?? []]));
|
|
4289
|
+
}
|
|
4290
|
+
function withNamedImportMaps(declarations, importMaps) {
|
|
4291
|
+
const mapNames = new Map(declarations.map(({ path, names }) => [path, names]));
|
|
4292
|
+
return declarations.filter(({ path }) => !importMaps.has(path)).map(({ path, names }) => {
|
|
4293
|
+
const maps = [...importMaps].filter(([, configs]) => configs.includes(path));
|
|
4294
|
+
const named = maps.flatMap(([map]) => mapNames.has(map) ? [mapNames.get(map)] : []);
|
|
4295
|
+
return { path, names: joinedNames([names, ...named]) };
|
|
4296
|
+
});
|
|
4297
|
+
}
|
|
4298
|
+
|
|
3409
4299
|
const isHuskyHook = (path) => (path.startsWith(HUSKY_FOLDER) || path.includes(`/${HUSKY_FOLDER}`)) && !path.includes(HUSKY_INTERNALS);
|
|
3410
4300
|
const isDependabotConfig = (path) => [...DEPENDABOT_FILES].some((file) => path === file || path.endsWith(`/${file}`));
|
|
3411
|
-
const withSteps = (migration, steps) => ({
|
|
3412
|
-
...migration,
|
|
3413
|
-
manualSteps: [...migration.manualSteps, ...steps]
|
|
3414
|
-
});
|
|
3415
4301
|
function migrateSource(text, path, context) {
|
|
3416
4302
|
const strings = context.scanner.scan(text, path);
|
|
3417
4303
|
const migrated = chain(
|
|
@@ -3420,42 +4306,66 @@ function migrateSource(text, path, context) {
|
|
|
3420
4306
|
);
|
|
3421
4307
|
const imports = importedSpecifiers(text, strings);
|
|
3422
4308
|
const undeclared = undeclaredImportSteps(imports, path, context.manifests);
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
function chain(first, next) {
|
|
3426
|
-
const second = next(first.text);
|
|
3427
|
-
const changes = [...first.changes, ...second.changes];
|
|
3428
|
-
const manualSteps = [...first.manualSteps, ...second.manualSteps];
|
|
3429
|
-
return { text: second.text, changes, manualSteps };
|
|
3430
|
-
}
|
|
3431
|
-
function migrateConfig(text, read, steps) {
|
|
3432
|
-
const first = read(text);
|
|
3433
|
-
if (first.kind === "unreadable") {
|
|
3434
|
-
return unreadableConfig(text, first.offset);
|
|
3435
|
-
}
|
|
3436
|
-
return steps.reduce(
|
|
3437
|
-
(done, step) => chain(done, (current) => step(current, current === text ? first : read(current))),
|
|
3438
|
-
unchanged(text)
|
|
3439
|
-
);
|
|
4309
|
+
const patterns = isJestConfig(baseName(path)) ? jestScriptSteps(text, strings) : [];
|
|
4310
|
+
return withSteps(migrated, [...commandStringSteps(text, strings), ...undeclared, ...patterns]);
|
|
3440
4311
|
}
|
|
3441
|
-
const stringsStep = (migrate) => (text, read) => read.kind === "unreadable" ? unreadableConfig(text, read.offset) : migrate(text, documentStrings(read.documents));
|
|
3442
4312
|
const jsonCommandsStep = (patterns) => stringsStep((text, strings) => migrateJsonCommands(text, strings, patterns));
|
|
3443
|
-
const
|
|
3444
|
-
const
|
|
3445
|
-
const
|
|
4313
|
+
const importMapStep = (version) => (text, read) => migrateImportMap(text, read, version);
|
|
4314
|
+
const importMapFile = jsonConfig(({ version }) => [importMapStep(version)]);
|
|
4315
|
+
const yamlPathCommands = (patterns) => stringsStep((text, strings) => migrateYamlPathCommands(text, strings, patterns));
|
|
4316
|
+
const COMMAND_CONFIG_KINDS = [
|
|
4317
|
+
{
|
|
4318
|
+
matches: (path) => baseName(path) === NX_PROJECT_FILE,
|
|
4319
|
+
migrate: jsonConfig(() => [jsonCommandsStep(NX_PROJECT_COMMAND_PATHS)])
|
|
4320
|
+
},
|
|
4321
|
+
{
|
|
4322
|
+
matches: (path) => baseName(path) === NX_WORKSPACE_FILE,
|
|
4323
|
+
migrate: jsonConfig(() => [jsonCommandsStep(NX_WORKSPACE_COMMAND_PATHS)])
|
|
4324
|
+
},
|
|
4325
|
+
{
|
|
4326
|
+
matches: (path) => baseName(path) === LINT_STAGED_JSON_FILE,
|
|
4327
|
+
migrate: jsonConfig(() => [jsonCommandsStep(LINT_STAGED_COMMAND_PATHS)])
|
|
4328
|
+
},
|
|
4329
|
+
{
|
|
4330
|
+
matches: (path) => LINT_STAGED_YAML_FILES.has(baseName(path)),
|
|
4331
|
+
migrate: whenNamed(yamlConfig(() => [yamlPathCommands(LINT_STAGED_COMMAND_PATHS)]))
|
|
4332
|
+
},
|
|
4333
|
+
{
|
|
4334
|
+
matches: (path) => SIMPLE_GIT_HOOKS_FILES.has(baseName(path)),
|
|
4335
|
+
migrate: jsonConfig(() => [jsonCommandsStep(SIMPLE_GIT_HOOKS_COMMAND_PATHS)])
|
|
4336
|
+
},
|
|
4337
|
+
{
|
|
4338
|
+
matches: (path) => TASKFILE_NAMES.has(baseName(path)),
|
|
4339
|
+
migrate: whenNamed(
|
|
4340
|
+
yamlConfig((_context, path) => [
|
|
4341
|
+
stringsStep(
|
|
4342
|
+
(text, strings) => migrateYamlCommands(text, path, strings, TASKFILE_COMMAND_KEYS)
|
|
4343
|
+
)
|
|
4344
|
+
])
|
|
4345
|
+
)
|
|
4346
|
+
},
|
|
4347
|
+
{
|
|
4348
|
+
matches: (path) => PRE_COMMIT_FILES.has(baseName(path)),
|
|
4349
|
+
migrate: whenNamed(
|
|
4350
|
+
yamlConfig((_context, path) => [
|
|
4351
|
+
stringsStep((text, strings) => migratePreCommitHooks(text, path, strings))
|
|
4352
|
+
])
|
|
4353
|
+
)
|
|
4354
|
+
}
|
|
4355
|
+
];
|
|
3446
4356
|
const FILE_KINDS = [
|
|
3447
4357
|
{
|
|
3448
4358
|
matches: (path) => baseName(path) === MANIFEST_FILE,
|
|
3449
4359
|
migrate: jsonConfig(({ version, catalogs }) => [
|
|
3450
4360
|
(text, read) => migratePackageManifest(text, read, { version, catalogs }),
|
|
3451
|
-
jsonCommandsStep(
|
|
4361
|
+
jsonCommandsStep(MANIFEST_COMMAND_PATHS)
|
|
3452
4362
|
])
|
|
3453
4363
|
},
|
|
3454
4364
|
{
|
|
3455
4365
|
matches: (path) => YAML_MANIFEST_FILES.has(baseName(path)),
|
|
3456
4366
|
migrate: yamlConfig(({ version, catalogs }) => [
|
|
3457
4367
|
(text, read) => migratePackageManifest(text, read, { version, catalogs }),
|
|
3458
|
-
|
|
4368
|
+
yamlPathCommands(MANIFEST_COMMAND_PATHS)
|
|
3459
4369
|
])
|
|
3460
4370
|
},
|
|
3461
4371
|
{
|
|
@@ -3475,23 +4385,33 @@ const FILE_KINDS = [
|
|
|
3475
4385
|
])
|
|
3476
4386
|
},
|
|
3477
4387
|
{
|
|
3478
|
-
matches: (path) =>
|
|
3479
|
-
migrate:
|
|
4388
|
+
matches: (path) => baseName(path) === JEST_JSON_CONFIG_FILE,
|
|
4389
|
+
migrate: jsonConfig(() => [(text, read) => withSteps(unchanged(text), jestJsonSteps(read))])
|
|
3480
4390
|
},
|
|
3481
4391
|
{
|
|
3482
|
-
matches: (path) => baseName(path)
|
|
3483
|
-
migrate:
|
|
4392
|
+
matches: (path) => patchedOldPackage(baseName(path)) !== void 0,
|
|
4393
|
+
migrate: (text, path) => withSteps(unchanged(text), oldPackagePatchSteps(baseName(path)))
|
|
4394
|
+
},
|
|
4395
|
+
{
|
|
4396
|
+
matches: (path) => SOURCE_EXTENSIONS.has(extensionOf(path)),
|
|
4397
|
+
migrate: migrateSource
|
|
3484
4398
|
},
|
|
4399
|
+
...COMMAND_CONFIG_KINDS,
|
|
3485
4400
|
{
|
|
3486
4401
|
matches: (path) => DENO_CONFIG_FILES.has(baseName(path)),
|
|
3487
|
-
migrate: jsonConfig(({ version }) => [
|
|
3488
|
-
(
|
|
4402
|
+
migrate: jsonConfig(({ version }, path) => [
|
|
4403
|
+
importMapStep(version),
|
|
4404
|
+
(text, read) => withSteps(unchanged(text), importMapSteps(path, read)),
|
|
3489
4405
|
jsonCommandsStep(DENO_TASK_PATHS)
|
|
3490
4406
|
])
|
|
3491
4407
|
},
|
|
3492
4408
|
{
|
|
3493
4409
|
matches: (path) => baseName(path) === IMPORT_MAP_FILE,
|
|
3494
|
-
migrate:
|
|
4410
|
+
migrate: importMapFile
|
|
4411
|
+
},
|
|
4412
|
+
{
|
|
4413
|
+
matches: (path) => PROJECT_CONFIG_NAME.test(baseName(path)),
|
|
4414
|
+
migrate: whenNamed(jsonConfig(() => [migrateTsconfig]))
|
|
3495
4415
|
},
|
|
3496
4416
|
{
|
|
3497
4417
|
matches: isDependabotConfig,
|
|
@@ -3522,23 +4442,26 @@ const FILE_KINDS = [
|
|
|
3522
4442
|
migrate: whenNamed((text, path) => migrateCommandLines(text, path))
|
|
3523
4443
|
}
|
|
3524
4444
|
];
|
|
3525
|
-
function fileMigrationFor(path) {
|
|
4445
|
+
function fileMigrationFor(path, namedImportMaps = NO_NAMED_IMPORT_MAPS) {
|
|
3526
4446
|
if (LOCK_FILES.has(baseName(path))) {
|
|
3527
4447
|
return void 0;
|
|
3528
4448
|
}
|
|
4449
|
+
if (namedImportMaps.has(path)) {
|
|
4450
|
+
return importMapFile;
|
|
4451
|
+
}
|
|
3529
4452
|
return FILE_KINDS.find((kind) => kind.matches(path))?.migrate;
|
|
3530
4453
|
}
|
|
3531
4454
|
|
|
3532
4455
|
const readJson = (text, readers) => readers.json.read(text);
|
|
3533
4456
|
const readYaml = (text, readers) => readers.yaml.read(text);
|
|
3534
|
-
function planSourceOf(path) {
|
|
4457
|
+
function planSourceOf(path, namedImportMaps) {
|
|
3535
4458
|
const name = baseName(path);
|
|
4459
|
+
if (namedImportMaps.has(path) || DENO_CONFIG_FILES.has(name) || name === IMPORT_MAP_FILE) {
|
|
4460
|
+
return { role: "import-map", read: readJson };
|
|
4461
|
+
}
|
|
3536
4462
|
if (name === MANIFEST_FILE) {
|
|
3537
4463
|
return { role: "manifest", read: readJson };
|
|
3538
4464
|
}
|
|
3539
|
-
if (DENO_CONFIG_FILES.has(name) || name === IMPORT_MAP_FILE) {
|
|
3540
|
-
return { role: "import-map", read: readJson };
|
|
3541
|
-
}
|
|
3542
4465
|
if (YAML_MANIFEST_FILES.has(name)) {
|
|
3543
4466
|
return { role: "manifest", read: readYaml };
|
|
3544
4467
|
}
|
|
@@ -3550,7 +4473,7 @@ function planSourceOf(path) {
|
|
|
3550
4473
|
}
|
|
3551
4474
|
|
|
3552
4475
|
async function planFile(path, dependencies, target) {
|
|
3553
|
-
const migrate = fileMigrationFor(path);
|
|
4476
|
+
const migrate = fileMigrationFor(path, target.importMaps);
|
|
3554
4477
|
if (migrate === void 0) {
|
|
3555
4478
|
return { kind: "not-migrated" };
|
|
3556
4479
|
}
|
|
@@ -3559,7 +4482,8 @@ async function planFile(path, dependencies, target) {
|
|
|
3559
4482
|
return read;
|
|
3560
4483
|
}
|
|
3561
4484
|
const { rewriter, scanner, readers } = dependencies;
|
|
3562
|
-
const
|
|
4485
|
+
const { version, catalogs, manifests } = target;
|
|
4486
|
+
const context = { version, catalogs, manifests, rewriter, scanner, readers };
|
|
3563
4487
|
const migration = migrate(read.text, path, context);
|
|
3564
4488
|
const isChanged = migration.text !== read.text;
|
|
3565
4489
|
const { changes, manualSteps } = migration;
|
|
@@ -3575,23 +4499,35 @@ async function readForPlan(path, source, dependencies) {
|
|
|
3575
4499
|
return { namesOriginal: false, roots: void 0 };
|
|
3576
4500
|
}
|
|
3577
4501
|
const namesOriginal = namesOriginalPackage(read.text);
|
|
3578
|
-
|
|
4502
|
+
const isNeeded = namesOriginal || namesUninstalledPackage(read.text) || path === MANIFEST_FILE;
|
|
4503
|
+
if (!isNeeded) {
|
|
3579
4504
|
return { namesOriginal, roots: [] };
|
|
3580
4505
|
}
|
|
3581
4506
|
const parsed = source.read?.(read.text, dependencies.readers);
|
|
3582
4507
|
const roots = parsed?.kind === "read" ? parsed.documents.filter(isMap) : void 0;
|
|
3583
4508
|
return { namesOriginal, roots };
|
|
3584
4509
|
}
|
|
4510
|
+
const ROOT_WORKSPACE_FILES = /* @__PURE__ */ new Set([WORKSPACE_FILE, YARNRC_FILE_NAME]);
|
|
4511
|
+
function marksWorkspaceRoot(path, roots) {
|
|
4512
|
+
if (ROOT_WORKSPACE_FILES.has(path)) {
|
|
4513
|
+
return true;
|
|
4514
|
+
}
|
|
4515
|
+
const manifests = path === MANIFEST_FILE ? roots ?? [] : [];
|
|
4516
|
+
return manifests.some((manifest) => valuesAt(manifest, WORKSPACES_FIELD).length > 0);
|
|
4517
|
+
}
|
|
3585
4518
|
const DECLARED_NAMES = { manifest: declaredNames, "import-map": importMapNames, catalogs: void 0 };
|
|
3586
4519
|
async function planProjectTarget(paths, dependencies, version) {
|
|
3587
4520
|
const documents = { manifest: [], catalogs: [] };
|
|
3588
4521
|
const manifests = [];
|
|
4522
|
+
let isWorkspaceRoot = false;
|
|
4523
|
+
const importMaps = await namedImportMaps(paths, dependencies.files, dependencies.readers);
|
|
3589
4524
|
for (const path of paths) {
|
|
3590
|
-
const source = planSourceOf(path);
|
|
4525
|
+
const source = planSourceOf(path, importMaps);
|
|
3591
4526
|
if (source === void 0) {
|
|
3592
4527
|
continue;
|
|
3593
4528
|
}
|
|
3594
4529
|
const { namesOriginal, roots } = await readForPlan(path, source, dependencies);
|
|
4530
|
+
isWorkspaceRoot ||= marksWorkspaceRoot(path, roots);
|
|
3595
4531
|
if (namesOriginal && source.role !== "import-map") {
|
|
3596
4532
|
documents[source.role].push(...roots ?? []);
|
|
3597
4533
|
}
|
|
@@ -3602,9 +4538,10 @@ async function planProjectTarget(paths, dependencies, version) {
|
|
|
3602
4538
|
}
|
|
3603
4539
|
const catalogs = planCatalogs({
|
|
3604
4540
|
manifests: documents.manifest,
|
|
3605
|
-
catalogFiles: documents.catalogs
|
|
4541
|
+
catalogFiles: documents.catalogs,
|
|
4542
|
+
isWorkspaceRoot
|
|
3606
4543
|
});
|
|
3607
|
-
return { version, catalogs, manifests };
|
|
4544
|
+
return { version, catalogs, manifests: withNamedImportMaps(manifests, importMaps), importMaps };
|
|
3608
4545
|
}
|
|
3609
4546
|
async function planProject(paths, dependencies, version) {
|
|
3610
4547
|
const files = [];
|
|
@@ -3654,39 +4591,39 @@ async function migrateProject(dependencies, input) {
|
|
|
3654
4591
|
return { files: plan.files.map((file) => file.report), skipped, write };
|
|
3655
4592
|
}
|
|
3656
4593
|
|
|
3657
|
-
const
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
};
|
|
3666
|
-
const
|
|
4594
|
+
const CONTROL_RANGES = [
|
|
4595
|
+
[0, 8],
|
|
4596
|
+
[10, 31],
|
|
4597
|
+
[127, 159],
|
|
4598
|
+
[8232, 8233],
|
|
4599
|
+
[8234, 8238],
|
|
4600
|
+
[8294, 8297]
|
|
4601
|
+
];
|
|
4602
|
+
const SHORT_ESCAPES = { "\n": "\\n", "\r": "\\r" };
|
|
4603
|
+
const HEX_DIGITS = 4;
|
|
4604
|
+
const HEX_RADIX = 16;
|
|
4605
|
+
function isControl(codePoint) {
|
|
4606
|
+
return CONTROL_RANGES.some(([first, last]) => codePoint >= first && codePoint <= last);
|
|
4607
|
+
}
|
|
4608
|
+
function escapeOf(character, codePoint) {
|
|
4609
|
+
const hex = codePoint.toString(HEX_RADIX).padStart(HEX_DIGITS, "0");
|
|
4610
|
+
return SHORT_ESCAPES[character] ?? `\\u${hex}`;
|
|
4611
|
+
}
|
|
4612
|
+
function terminalSafeText(text) {
|
|
4613
|
+
let shown = "";
|
|
4614
|
+
for (const character of text) {
|
|
4615
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
4616
|
+
shown += isControl(codePoint) ? escapeOf(character, codePoint) : character;
|
|
4617
|
+
}
|
|
4618
|
+
return shown;
|
|
4619
|
+
}
|
|
4620
|
+
|
|
3667
4621
|
const PINNED_NOTE = "change it to openapi-typesafe@<version>";
|
|
3668
|
-
const OLD_FILE_NOTE = "is a file of openapi-typescript, which is no longer installed: run openapi-typesafe instead";
|
|
4622
|
+
const OLD_FILE_NOTE$1 = "is a file of openapi-typescript, which is no longer installed: run openapi-typesafe instead";
|
|
3669
4623
|
const FLAGS_IN_VARIABLE_NOTE = "holds old flags of the generator and may serve other commands, so it was kept: rename";
|
|
3670
4624
|
const NOT_ONLY_GENERATOR_NOTE = "runs openapi-typescript in some of its definitions in this file and another program in others, so the flags after it were kept; where it runs the generator, rename";
|
|
4625
|
+
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";
|
|
3671
4626
|
const COMMAND_STRING_NOTE = "a string runs openapi-typescript, so it was kept; change it to";
|
|
3672
|
-
const OPTIONS_NOTE = `the options of openapiTS() are not an object written in this file: check them for transform, postTransform and transformProperty. See ${IR_CALLBACKS_GUIDE}`;
|
|
3673
|
-
const MANIFEST_NOT_READ_NOTE = "is a JSON5 manifest, which the tool does not read: rename the packages and the generator command by hand, or write it as package.json and run the tool again";
|
|
3674
|
-
const DEEP_IMPORT_NOTE = "imports a file inside the package; check that it exists";
|
|
3675
|
-
const DYNAMIC_NOTE = "builds its module name at run time from an old package name, so it was kept; rename it to";
|
|
3676
|
-
const STRING_NOTE = "is a string, not a module specifier, so it was kept";
|
|
3677
|
-
const STRING_FIX_NOTE = "if it names the package, change it to";
|
|
3678
|
-
const KEPT_NOTE = `it works, with a deprecation warning. See ${IR_CALLBACKS_GUIDE}`;
|
|
3679
|
-
const LEGACY_CALLBACK_NOTE = `receives TypeScript nodes (deprecated). See ${IR_CALLBACKS_GUIDE}`;
|
|
3680
|
-
const HELPER_TYPES_ENTRY = "openapi-typesafe-fetch/helpers";
|
|
3681
|
-
function packageNotDeclaredMessage(step) {
|
|
3682
|
-
const { line, name, installers } = step;
|
|
3683
|
-
return `line ${line}: no package.json or Deno import map at or above this file lists ${name}; ${installers.join(" and ")} installed it, the openapi-typesafe packages do not: add it to the dependencies, or import the types from ${HELPER_TYPES_ENTRY}`;
|
|
3684
|
-
}
|
|
3685
|
-
function oldPeerMessage(step) {
|
|
3686
|
-
const { dependent, peer, range } = step;
|
|
3687
|
-
const successor = PACKAGE_RENAMES.get(peer) ?? peer;
|
|
3688
|
-
return `${dependent} takes its client type from ${peer}@${range}, its peer dependency: alias ${peer} to ${successor} with overrides or resolutions, or passing it the ${successor} client fails to type-check. See ${OPENAPI_FETCH_ALIAS_GUIDE}`;
|
|
3689
|
-
}
|
|
3690
4627
|
function pinnedPackageMessage(step) {
|
|
3691
4628
|
const successor = PACKAGE_RENAMES.get(step.name) ?? step.name;
|
|
3692
4629
|
return `${step.location} names a pinned ${step.name}@<version>: change it to ${successor}@<version>`;
|
|
@@ -3704,6 +4641,7 @@ const COMMAND_STEP_KINDS = /* @__PURE__ */ new Set([
|
|
|
3704
4641
|
"variable-not-only-generator",
|
|
3705
4642
|
"pinned-package",
|
|
3706
4643
|
"old-package-file",
|
|
4644
|
+
"old-name-in-command",
|
|
3707
4645
|
"command-string"
|
|
3708
4646
|
]);
|
|
3709
4647
|
const isCommandStep = (step) => COMMAND_STEP_KINDS.has(step.kind);
|
|
@@ -3718,47 +4656,141 @@ function commandStepMessage(step) {
|
|
|
3718
4656
|
case "pinned-package":
|
|
3719
4657
|
return pinnedPackageMessage(step);
|
|
3720
4658
|
case "old-package-file":
|
|
3721
|
-
return `${step.location}: ${step.path} ${OLD_FILE_NOTE}`;
|
|
4659
|
+
return `${step.location}: ${step.path} ${OLD_FILE_NOTE$1}`;
|
|
4660
|
+
case "old-name-in-command":
|
|
4661
|
+
return `${step.location}: "${step.word}" ${OLD_NAME_IN_COMMAND_NOTE}`;
|
|
3722
4662
|
case "command-string":
|
|
3723
4663
|
return `line ${step.line}: ${COMMAND_STRING_NOTE} "${step.to}"`;
|
|
3724
4664
|
default:
|
|
3725
4665
|
return assertNever(step);
|
|
3726
4666
|
}
|
|
3727
4667
|
}
|
|
4668
|
+
|
|
4669
|
+
const IR_CALLBACKS_GUIDE = "https://github.com/openapi-typesafe/openapi-typesafe/blob/main/docs/node.md#ir-callbacks";
|
|
4670
|
+
const KEEP_REASONS = {
|
|
4671
|
+
"other-callbacks": "postTransform or transformProperty are set too, and they need TypeScript nodes",
|
|
4672
|
+
"not-a-function": "it is not an inline function or a function of this file",
|
|
4673
|
+
"shared-function": "the function it names is used elsewhere too",
|
|
4674
|
+
"shared-options": "its options object is used elsewhere too",
|
|
4675
|
+
"unknown-return": "a return value is not a plain ts.factory type",
|
|
4676
|
+
"typed-options": "its options are declared with a type built from OpenAPITSOptions, which the tool cannot change to OpenAPITSIrOptions",
|
|
4677
|
+
"spread-options": "its options take keys from another object (`...base`), whose callbacks and type the tool cannot see"
|
|
4678
|
+
};
|
|
4679
|
+
const OPTIONS_NOTE = `the options of openapiTS() are not an object written in this file: check them for transform, postTransform and transformProperty. See ${IR_CALLBACKS_GUIDE}`;
|
|
4680
|
+
const DEEP_IMPORT_NOTE = "imports a file inside the package; check that it exists";
|
|
4681
|
+
const OLD_FILE_NOTE = "imports a file from node_modules of";
|
|
4682
|
+
const OLD_FILE_FIX_NOTE = "which is no longer installed: import from";
|
|
4683
|
+
const DYNAMIC_NOTE = "builds its module name at run time from an old package name, so it was kept; rename it to";
|
|
4684
|
+
const STRING_NOTE = "is a string, not a module specifier, so it was kept";
|
|
4685
|
+
const STRING_FIX_NOTE = "if it names the package, change it to";
|
|
4686
|
+
const KEPT_NOTE = `it works, with a deprecation warning. See ${IR_CALLBACKS_GUIDE}`;
|
|
4687
|
+
const LEGACY_CALLBACK_NOTE = `receives TypeScript nodes (deprecated). See ${IR_CALLBACKS_GUIDE}`;
|
|
4688
|
+
const HELPER_TYPES_ENTRY = "openapi-typesafe-fetch/helpers";
|
|
4689
|
+
function packageNotDeclaredMessage(step) {
|
|
4690
|
+
const { line, name, installers } = step;
|
|
4691
|
+
return `line ${line}: no package.json or Deno import map at or above this file lists ${name}; ${installers.join(" and ")} installed it, the openapi-typesafe packages do not: add it to the dependencies, or import the types from ${HELPER_TYPES_ENTRY}`;
|
|
4692
|
+
}
|
|
4693
|
+
const SOURCE_STEP_KINDS = /* @__PURE__ */ new Set([
|
|
4694
|
+
"options-not-inspected",
|
|
4695
|
+
"deep-import",
|
|
4696
|
+
"old-package-import",
|
|
4697
|
+
"dynamic-specifier",
|
|
4698
|
+
"string-names-package",
|
|
4699
|
+
"transform-not-rewritten",
|
|
4700
|
+
"legacy-callback",
|
|
4701
|
+
"package-not-declared"
|
|
4702
|
+
]);
|
|
4703
|
+
const isSourceStep = (step) => SOURCE_STEP_KINDS.has(step.kind);
|
|
4704
|
+
function sourceStepMessage(step) {
|
|
4705
|
+
switch (step.kind) {
|
|
4706
|
+
case "options-not-inspected":
|
|
4707
|
+
return `line ${step.line}: ${OPTIONS_NOTE}`;
|
|
4708
|
+
case "deep-import":
|
|
4709
|
+
return `line ${step.line}: "${step.specifier}" ${DEEP_IMPORT_NOTE}`;
|
|
4710
|
+
case "old-package-import":
|
|
4711
|
+
return `line ${step.line}: "${step.specifier}" ${OLD_FILE_NOTE} ${step.name}, ${OLD_FILE_FIX_NOTE} ${step.to}`;
|
|
4712
|
+
case "dynamic-specifier":
|
|
4713
|
+
return `line ${step.line}: \`${step.value}\` ${DYNAMIC_NOTE} ${step.to}`;
|
|
4714
|
+
case "string-names-package":
|
|
4715
|
+
return `line ${step.line}: "${step.value}" ${STRING_NOTE}; ${STRING_FIX_NOTE} "${step.to}"`;
|
|
4716
|
+
case "transform-not-rewritten":
|
|
4717
|
+
return `line ${step.line}: transform kept (${KEEP_REASONS[step.reason]}); ${KEPT_NOTE}`;
|
|
4718
|
+
case "legacy-callback":
|
|
4719
|
+
return `line ${step.line}: ${step.callback} ${LEGACY_CALLBACK_NOTE}`;
|
|
4720
|
+
case "package-not-declared":
|
|
4721
|
+
return packageNotDeclaredMessage(step);
|
|
4722
|
+
default:
|
|
4723
|
+
return assertNever(step);
|
|
4724
|
+
}
|
|
4725
|
+
}
|
|
4726
|
+
|
|
4727
|
+
const OPENAPI_FETCH_ALIAS_GUIDE = "https://github.com/openapi-typesafe/openapi-typesafe/blob/main/docs/fetch/index.md#libraries-built-on-openapi-fetch";
|
|
4728
|
+
const PEER_NOTE = "users of this package must switch too (a breaking change for them)";
|
|
4729
|
+
const MANIFEST_NOT_READ_NOTE = "is a JSON5 manifest, which the tool does not read: rename the packages and the generator command by hand, or write it as package.json and run the tool again";
|
|
4730
|
+
const IMPORT_MAP_NOTE = "is a URL or a file outside the project folder, so it was not migrated: rename the old packages in it by hand";
|
|
4731
|
+
const PATCH_NOTE = "check whether the fix is still needed, then make the patch again or delete it";
|
|
4732
|
+
const PATTERN_NOTE = "is a pattern that names";
|
|
4733
|
+
const PATTERN_FIX_NOTE = "where it means the package, make it match";
|
|
4734
|
+
const SETTING_NOTE = "remove the setting if it no longer applies, or make it name";
|
|
4735
|
+
const DEEP_TARGET_NOTE = "points at a file inside the package; check that it exists";
|
|
4736
|
+
const OLD_PATH_NOTE = "is a path into node_modules of an old package, which is no longer installed:";
|
|
4737
|
+
const OLD_PATH_FIX_NOTE = "point it at the files of";
|
|
4738
|
+
const renamed = (name) => PACKAGE_RENAMES.get(name) ?? name;
|
|
4739
|
+
function oldPeerMessage(step) {
|
|
4740
|
+
const { dependent, peer, range } = step;
|
|
4741
|
+
const successor = PACKAGE_RENAMES.get(peer) ?? peer;
|
|
4742
|
+
return `${dependent} takes its client type from ${peer}@${range}, its peer dependency: alias ${peer} to ${successor} with overrides or resolutions, or passing it the ${successor} client fails to type-check. See ${OPENAPI_FETCH_ALIAS_GUIDE}`;
|
|
4743
|
+
}
|
|
3728
4744
|
function uneditedStepMessage(step) {
|
|
3729
4745
|
switch (step.kind) {
|
|
3730
4746
|
case "config-unreadable":
|
|
3731
4747
|
return step.position === void 0 ? "nests too deep to be read; migrate it by hand" : `cannot be parsed at line ${step.position.line}, column ${step.position.column}; migrate it by hand`;
|
|
3732
4748
|
case "manifest-not-read":
|
|
3733
4749
|
return MANIFEST_NOT_READ_NOTE;
|
|
4750
|
+
case "import-map-not-editable":
|
|
4751
|
+
return `importMap "${step.reference}" ${IMPORT_MAP_NOTE}`;
|
|
4752
|
+
case "old-package-patch":
|
|
4753
|
+
return `patches the code of ${step.name}, which ${step.to} does not share: ${PATCH_NOTE}`;
|
|
3734
4754
|
case "entry-not-edited":
|
|
3735
4755
|
return `${step.field}: ${step.name} has a value the tool does not read; rename it by hand`;
|
|
3736
4756
|
case "name-collision":
|
|
3737
4757
|
return `${step.field} has both ${step.from} and ${step.to}, so ${step.from} was kept: remove one of them`;
|
|
4758
|
+
default:
|
|
4759
|
+
return assertNever(step);
|
|
4760
|
+
}
|
|
4761
|
+
}
|
|
4762
|
+
function catalogStepMessage(step) {
|
|
4763
|
+
switch (step.kind) {
|
|
3738
4764
|
case "catalog-reference-kept":
|
|
3739
4765
|
return `${step.field}: ${step.name} was kept, because catalog "${step.catalog}" keeps ${step.name}: rename the entry and the dependency together`;
|
|
4766
|
+
case "catalog-entry-outside":
|
|
4767
|
+
return `${step.field}: ${step.name} was kept, because no catalog of this project has its "${step.catalog}" entry; a catalog above the root (pnpm-workspace.yaml, .yarnrc.yml or the workspace package.json) may hold it: rename the entry and the dependency together`;
|
|
4768
|
+
case "catalog-entry-missing":
|
|
4769
|
+
return `${step.field}: ${step.name} was kept, because no catalog of the workspace has its "${step.catalog}" entry: add the entry, or give the dependency a version`;
|
|
3740
4770
|
case "catalog-entry-in-use":
|
|
3741
4771
|
return `${step.catalog}: ${step.name} was kept, because a dependency or an override still names it: rename the entry and what names it together`;
|
|
3742
4772
|
default:
|
|
3743
4773
|
return assertNever(step);
|
|
3744
4774
|
}
|
|
3745
4775
|
}
|
|
3746
|
-
function
|
|
4776
|
+
function packageStepMessage(step) {
|
|
3747
4777
|
switch (step.kind) {
|
|
3748
|
-
case "
|
|
3749
|
-
return
|
|
3750
|
-
case "
|
|
3751
|
-
return
|
|
3752
|
-
case "
|
|
3753
|
-
return `
|
|
3754
|
-
case "
|
|
3755
|
-
return `
|
|
3756
|
-
case "
|
|
3757
|
-
return
|
|
3758
|
-
case "
|
|
3759
|
-
return
|
|
3760
|
-
case "package-
|
|
3761
|
-
return
|
|
4778
|
+
case "peer-dependency-renamed":
|
|
4779
|
+
return `${step.name} is a peer dependency: ${PEER_NOTE}`;
|
|
4780
|
+
case "spec-kept":
|
|
4781
|
+
return `${step.name} kept the spec "${step.spec}": point it at an openapi-typesafe version`;
|
|
4782
|
+
case "override-names-package":
|
|
4783
|
+
return `"${step.field}" names ${step.name}: update or remove that override`;
|
|
4784
|
+
case "setting-names-package":
|
|
4785
|
+
return `"${step.field}" names ${step.name}: ${SETTING_NOTE} ${renamed(step.name)}`;
|
|
4786
|
+
case "pattern-names-package":
|
|
4787
|
+
return `${step.location}: "${step.value}" ${PATTERN_NOTE} ${step.name}: ${PATTERN_FIX_NOTE} ${step.to}`;
|
|
4788
|
+
case "deep-target":
|
|
4789
|
+
return `${step.location}: "${step.specifier}" ${DEEP_TARGET_NOTE}`;
|
|
4790
|
+
case "old-package-path":
|
|
4791
|
+
return `${step.location}: "${step.path}" ${OLD_PATH_NOTE} ${OLD_PATH_FIX_NOTE} ${step.to}`;
|
|
4792
|
+
case "old-peer-needed":
|
|
4793
|
+
return oldPeerMessage(step);
|
|
3762
4794
|
default:
|
|
3763
4795
|
return assertNever(step);
|
|
3764
4796
|
}
|
|
@@ -3767,30 +4799,31 @@ function manualStepMessage(step) {
|
|
|
3767
4799
|
if (isCommandStep(step)) {
|
|
3768
4800
|
return commandStepMessage(step);
|
|
3769
4801
|
}
|
|
4802
|
+
if (isSourceStep(step)) {
|
|
4803
|
+
return sourceStepMessage(step);
|
|
4804
|
+
}
|
|
3770
4805
|
switch (step.kind) {
|
|
3771
4806
|
case "config-unreadable":
|
|
3772
4807
|
case "manifest-not-read":
|
|
4808
|
+
case "import-map-not-editable":
|
|
4809
|
+
case "old-package-patch":
|
|
3773
4810
|
case "entry-not-edited":
|
|
3774
4811
|
case "name-collision":
|
|
4812
|
+
return uneditedStepMessage(step);
|
|
3775
4813
|
case "catalog-reference-kept":
|
|
4814
|
+
case "catalog-entry-outside":
|
|
4815
|
+
case "catalog-entry-missing":
|
|
3776
4816
|
case "catalog-entry-in-use":
|
|
3777
|
-
return
|
|
4817
|
+
return catalogStepMessage(step);
|
|
3778
4818
|
case "peer-dependency-renamed":
|
|
3779
|
-
return `${step.name} is a peer dependency: ${PEER_NOTE}`;
|
|
3780
4819
|
case "spec-kept":
|
|
3781
|
-
return `${step.name} kept the spec "${step.spec}": point it at an openapi-typesafe version`;
|
|
3782
4820
|
case "override-names-package":
|
|
3783
|
-
|
|
3784
|
-
case "
|
|
3785
|
-
case "deep-
|
|
3786
|
-
case "
|
|
3787
|
-
case "string-names-package":
|
|
3788
|
-
case "transform-not-rewritten":
|
|
3789
|
-
case "legacy-callback":
|
|
3790
|
-
case "package-not-declared":
|
|
3791
|
-
return sourceStepMessage(step);
|
|
4821
|
+
case "setting-names-package":
|
|
4822
|
+
case "pattern-names-package":
|
|
4823
|
+
case "deep-target":
|
|
4824
|
+
case "old-package-path":
|
|
3792
4825
|
case "old-peer-needed":
|
|
3793
|
-
return
|
|
4826
|
+
return packageStepMessage(step);
|
|
3794
4827
|
default:
|
|
3795
4828
|
return assertNever(step);
|
|
3796
4829
|
}
|
|
@@ -3905,12 +4938,15 @@ function writeSection(write) {
|
|
|
3905
4938
|
return assertNever(write);
|
|
3906
4939
|
}
|
|
3907
4940
|
}
|
|
4941
|
+
function printed(lines) {
|
|
4942
|
+
return `${lines.map(terminalSafeText).join("\n")}
|
|
4943
|
+
`;
|
|
4944
|
+
}
|
|
3908
4945
|
function renderReport(migration) {
|
|
3909
4946
|
const reports = migration.files;
|
|
3910
4947
|
const skipped = skippedSection(migration.skipped);
|
|
3911
4948
|
if (reports.length === 0) {
|
|
3912
|
-
return
|
|
3913
|
-
`;
|
|
4949
|
+
return printed([...skipped, NOTHING_FOUND]);
|
|
3914
4950
|
}
|
|
3915
4951
|
const lines = [
|
|
3916
4952
|
...changesSection(reports),
|
|
@@ -3921,8 +4957,7 @@ function renderReport(migration) {
|
|
|
3921
4957
|
"",
|
|
3922
4958
|
...writeSection(migration.write)
|
|
3923
4959
|
];
|
|
3924
|
-
return
|
|
3925
|
-
`;
|
|
4960
|
+
return printed(lines);
|
|
3926
4961
|
}
|
|
3927
4962
|
|
|
3928
4963
|
const OPTIONS = {
|
|
@@ -4028,7 +5063,7 @@ async function runMigration(request, dependencies) {
|
|
|
4028
5063
|
} catch (error) {
|
|
4029
5064
|
const message = errorMessage(error);
|
|
4030
5065
|
logger.warn("migration_failed", { root, message });
|
|
4031
|
-
dependencies.writeStderr(`${message}
|
|
5066
|
+
dependencies.writeStderr(`${terminalSafeText(message)}
|
|
4032
5067
|
`);
|
|
4033
5068
|
return EXIT_CODES.failure;
|
|
4034
5069
|
} finally {
|