@trackunit/react-components 3.12.4-alpha-07efa4379b2.0 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs.js +104 -959
- package/index.esm.js +102 -952
- package/migrations/assets/react-router-components/package.json +23 -0
- package/migrations/entry.js.map +1 -0
- package/migrations/utils/jsx-utils.js.map +1 -0
- package/migrations/utils/move-named-imports.js +409 -0
- package/migrations/utils/move-named-imports.js.map +1 -0
- package/migrations/utils/package-json-utils.js +73 -0
- package/migrations/utils/package-json-utils.js.map +1 -0
- package/migrations/v2-0-0/breadcrumb-remove-deprecated-props.js.map +1 -0
- package/migrations/v2-0-0/cardheader-onclickclose-to-actions.js.map +1 -0
- package/migrations/v2-0-0/iconbutton-add-required-name.js.map +1 -0
- package/migrations/v2-0-0/kpi-tooltiplabel-to-wrapper.js.map +1 -0
- package/migrations/v2-0-0/notice-tooltiplabel-to-wrapper.js.map +1 -0
- package/migrations/v2-0-0/pagination-add-required-titles.js.map +1 -0
- package/migrations/v2-0-0/tag-add-removetaglabel.js.map +1 -0
- package/migrations/v2-0-0/togglegroup-remove-item-style.js.map +1 -0
- package/migrations/v3-0-0/copyabletext-to-text-copybutton.js.map +1 -0
- package/migrations/v3-0-0/menulist-rename-to-menucontent.js.map +1 -0
- package/migrations/v4-0-0/move-to-router-components.js +71 -0
- package/migrations/v4-0-0/move-to-router-components.js.map +1 -0
- package/migrations.json +5 -0
- package/package.json +6 -7
- package/src/components/ExternalLink/ExternalLink.d.ts +2 -2
- package/src/index.d.ts +0 -4
- package/translation.cjs.js +0 -1
- package/translation.esm.js +0 -1
- package/translation10.cjs.js +0 -1
- package/translation10.esm.js +0 -1
- package/translation11.cjs.js +0 -1
- package/translation11.esm.js +0 -1
- package/translation12.cjs.js +0 -1
- package/translation12.esm.js +0 -1
- package/translation13.cjs.js +0 -1
- package/translation13.esm.js +0 -1
- package/translation14.cjs.js +0 -1
- package/translation14.esm.js +0 -1
- package/translation15.cjs.js +0 -1
- package/translation15.esm.js +0 -1
- package/translation16.cjs.js +0 -1
- package/translation16.esm.js +0 -1
- package/translation17.cjs.js +0 -1
- package/translation17.esm.js +0 -1
- package/translation2.cjs.js +0 -1
- package/translation2.esm.js +0 -1
- package/translation3.cjs.js +0 -1
- package/translation3.esm.js +0 -1
- package/translation4.cjs.js +0 -1
- package/translation4.esm.js +0 -1
- package/translation5.cjs.js +0 -1
- package/translation5.esm.js +0 -1
- package/translation6.cjs.js +0 -1
- package/translation6.esm.js +0 -1
- package/translation7.cjs.js +0 -1
- package/translation7.esm.js +0 -1
- package/translation8.cjs.js +0 -1
- package/translation8.esm.js +0 -1
- package/translation9.cjs.js +0 -1
- package/translation9.esm.js +0 -1
- package/src/components/Breadcrumb/Breadcrumb.d.ts +0 -39
- package/src/components/Breadcrumb/Breadcrumb.variant.d.ts +0 -45
- package/src/components/Breadcrumb/BreadcrumbContainer.d.ts +0 -8
- package/src/components/Breadcrumb/BreadcrumbForLargeScreen.d.ts +0 -6
- package/src/components/Breadcrumb/BreadcrumbForMediumScreen.d.ts +0 -6
- package/src/components/Breadcrumb/BreadcrumbForSmallScreen.d.ts +0 -6
- package/src/components/Breadcrumb/BreadcrumbItem.d.ts +0 -6
- package/src/components/Breadcrumb/utils/types.d.ts +0 -28
- package/src/components/Breadcrumb/utils/useBreadcrumbItemsToRender.d.ts +0 -6
- package/src/hooks/persistence/hashFragment.d.ts +0 -70
- package/src/hooks/persistence/readPrimitiveSearchParam.d.ts +0 -8
- package/src/hooks/persistence/urlIdentity.d.ts +0 -64
- package/src/hooks/persistence/usePersistedState.d.ts +0 -117
- package/src/hooks/persistence/useSearchParamSync.d.ts +0 -17
- package/src/hooks/persistence/useUrlParamSync.d.ts +0 -71
- package/src/hooks/useCursorUrlSync.d.ts +0 -23
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@trackunit/react-router-components",
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"repository": "https://github.com/Trackunit/manager",
|
|
5
|
+
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=24.x"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@trackunit/css-class-variance-utilities": "2.6.7",
|
|
11
|
+
"@trackunit/i18n-library-translation": "2.12.6",
|
|
12
|
+
"@trackunit/react-components": "4.0.1",
|
|
13
|
+
"@trackunit/react-drawer": "2.14.9",
|
|
14
|
+
"@trackunit/shared-utils": "1.22.7",
|
|
15
|
+
"dequal": "^2.0.3",
|
|
16
|
+
"zod": "^3.25.76"
|
|
17
|
+
},
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"@tanstack/react-router": "^1.114.29",
|
|
20
|
+
"react": "^19.0.0"
|
|
21
|
+
},
|
|
22
|
+
"migrations": "./migrations.json"
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.js","sourceRoot":"","sources":["../../../../../libs/react/components/migrations/entry.ts"],"names":[],"mappings":"","sourcesContent":["// Migration entry point for @nx/js:tsc build target.\n// Migrations are registered in ../migrations.json and resolved by NX at runtime.\nexport {};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsx-utils.js","sourceRoot":"","sources":["../../../../../../libs/react/components/migrations/utils/jsx-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { logger, type Tree, visitNotIgnoredFiles } from \"@nx/devkit\";\nimport * as ts from \"typescript\";\n\nconst TSX_EXTENSIONS = [\".tsx\", \".jsx\"] as const;\nconst TS_EXTENSIONS = [\".ts\", \".tsx\", \".jsx\"] as const;\n\nconst isTsxFile = (filePath: string): boolean => TSX_EXTENSIONS.some(ext => filePath.endsWith(ext));\nconst isTsFile = (filePath: string): boolean => TS_EXTENSIONS.some(ext => filePath.endsWith(ext));\n\nconst isUnderNodeModules = (filePath: string): boolean =>\n filePath.includes(\"/node_modules/\") || filePath.startsWith(\"node_modules/\");\n\nconst isUnderDist = (filePath: string): boolean =>\n filePath.includes(\"/dist/\") || filePath.startsWith(\"dist/\") || filePath.includes(\"/.nx/\");\n\n/**\n * Visits every `.tsx`/`.jsx` file under the workspace root and invokes the\n * callback with the file path and its current contents. Files that don't\n * include the marker substring are skipped, which makes large workspaces\n * cheap to scan.\n */\nexport const visitTsxFiles = (\n tree: Tree,\n marker: string,\n callback: (filePath: string, content: string) => string | null | undefined\n): number => {\n let touched = 0;\n visitNotIgnoredFiles(tree, \"/\", filePath => {\n if (!isTsxFile(filePath)) return;\n if (isUnderNodeModules(filePath) || isUnderDist(filePath)) return;\n const content = tree.read(filePath, \"utf-8\");\n if (content === null) return;\n if (!content.includes(marker)) return;\n const updated = callback(filePath, content);\n if (updated !== null && updated !== undefined && updated !== content) {\n tree.write(filePath, updated);\n touched += 1;\n }\n });\n return touched;\n};\n\n/**\n * Same as {@link visitTsxFiles} but also includes plain `.ts` files. Use this\n * when the codemod also rewrites non-JSX files such as helpers or hooks.\n */\nexport const visitTsFiles = (\n tree: Tree,\n marker: string,\n callback: (filePath: string, content: string) => string | null | undefined\n): number => {\n let touched = 0;\n visitNotIgnoredFiles(tree, \"/\", filePath => {\n if (!isTsFile(filePath)) return;\n if (isUnderNodeModules(filePath) || isUnderDist(filePath)) return;\n const content = tree.read(filePath, \"utf-8\");\n if (content === null) return;\n if (!content.includes(marker)) return;\n const updated = callback(filePath, content);\n if (updated !== null && updated !== undefined && updated !== content) {\n tree.write(filePath, updated);\n touched += 1;\n }\n });\n return touched;\n};\n\n/**\n * Mapping of imported component aliases to their original names for a given\n * package. For `import { IconButton as Btn } from \"@trackunit/react-components\"`\n * this returns `{ Btn: \"IconButton\" }`.\n *\n * Returns `null` when the file imports nothing from the package, which lets\n * callers short-circuit before parsing JSX.\n */\nexport const getImportedAliases = (sourceFile: ts.SourceFile, packageName: string): Record<string, string> | null => {\n const result: Record<string, string> = {};\n let found = false;\n\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const moduleSpecifier = stmt.moduleSpecifier;\n if (!ts.isStringLiteral(moduleSpecifier)) continue;\n if (moduleSpecifier.text !== packageName) continue;\n\n const namedBindings = stmt.importClause?.namedBindings;\n if (namedBindings === undefined || !ts.isNamedImports(namedBindings)) continue;\n\n for (const element of namedBindings.elements) {\n const localName = element.name.text;\n const importedName = element.propertyName?.text ?? localName;\n result[localName] = importedName;\n found = true;\n }\n }\n\n return found ? result : null;\n};\n\n/**\n * Returns the local alias used in this file for `originalName` when imported\n * from `packageName`, or `null` if the component is not imported.\n */\nexport const getLocalAliasFor = (\n sourceFile: ts.SourceFile,\n packageName: string,\n originalName: string\n): string | null => {\n const aliases = getImportedAliases(sourceFile, packageName);\n if (aliases === null) return null;\n for (const [local, original] of Object.entries(aliases)) {\n if (original === originalName) return local;\n }\n return null;\n};\n\nexport type JsxElementMatch = {\n /** The opening JSX element (the one carrying the attributes). */\n openingElement: ts.JsxOpeningElement | ts.JsxSelfClosingElement;\n /** The full element including children, or the self-closing element. */\n element: ts.JsxElement | ts.JsxSelfClosingElement;\n};\n\n/**\n * Finds every JSX element whose tag name resolves to one of `tagNames`\n * (typically the local aliases returned by {@link getImportedAliases}).\n *\n * The result intentionally includes both opening and full elements so callers\n * can manipulate attributes (via `openingElement`) or wrap/replace the whole\n * element (via `element`).\n */\nexport const findJsxElements = (\n sourceFile: ts.SourceFile,\n tagNames: ReadonlyArray<string>\n): ReadonlyArray<JsxElementMatch> => {\n const matches: Array<JsxElementMatch> = [];\n const tagSet = new Set(tagNames);\n\n const visit = (node: ts.Node): void => {\n if (ts.isJsxSelfClosingElement(node)) {\n if (ts.isIdentifier(node.tagName) && tagSet.has(node.tagName.text)) {\n matches.push({ openingElement: node, element: node });\n }\n } else if (ts.isJsxElement(node)) {\n const opening = node.openingElement;\n if (ts.isIdentifier(opening.tagName) && tagSet.has(opening.tagName.text)) {\n matches.push({ openingElement: opening, element: node });\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return matches;\n};\n\n/**\n * Looks up a named JSX attribute on the opening element. Returns `null` when\n * the attribute is missing or part of a spread attribute (which we cannot\n * statically inspect).\n */\nexport const findJsxAttribute = (\n openingElement: ts.JsxOpeningElement | ts.JsxSelfClosingElement,\n attributeName: string\n): ts.JsxAttribute | null => {\n for (const attr of openingElement.attributes.properties) {\n if (!ts.isJsxAttribute(attr)) continue;\n if (!ts.isIdentifier(attr.name)) continue;\n if (attr.name.text === attributeName) return attr;\n }\n return null;\n};\n\n/**\n * `true` when the element forwards a spread expression such as `{...rest}`,\n * which means we can't be sure which attributes are actually set.\n */\nexport const hasSpreadAttribute = (openingElement: ts.JsxOpeningElement | ts.JsxSelfClosingElement): boolean => {\n return openingElement.attributes.properties.some(prop => ts.isJsxSpreadAttribute(prop));\n};\n\n/**\n * Parses the file as TSX so JSX is recognised. We do not need a full program\n * here; tsquery's `ast` helper produces a script-kind source file which loses\n * JSX context, so we go through `createSourceFile` directly.\n */\nexport const parseTsx = (content: string, fileName = \"file.tsx\"): ts.SourceFile =>\n ts.createSourceFile(fileName, content, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);\n\n/**\n * Helper for codemods to log a one-line summary at the end of a run. Migration\n * runners aggregate logs per migration, so this keeps output focused.\n */\nexport const logSummary = (migrationName: string, touched: number, manualReviewNeeded?: number): void => {\n if (touched === 0) {\n logger.info(` ${migrationName}: no files changed`);\n return;\n }\n const reviewSuffix =\n manualReviewNeeded !== undefined && manualReviewNeeded > 0\n ? ` (${manualReviewNeeded} location(s) need manual review)`\n : \"\";\n logger.info(` ${migrationName}: updated ${touched} file(s)${reviewSuffix}`);\n};\n\n/**\n * Inserts an attribute string immediately after the tag name (so the new\n * attribute appears first). Returns the resulting source content.\n *\n * The added attribute is rendered verbatim, so callers are responsible for\n * including the leading space (e.g. ` title=\"Close\"`).\n */\nexport const insertAttributeIntoOpeningTag = (\n content: string,\n openingElement: ts.JsxOpeningElement | ts.JsxSelfClosingElement,\n attributeText: string\n): string => {\n const tagName = openingElement.tagName;\n const insertPos = tagName.getEnd();\n return `${content.slice(0, insertPos)} ${attributeText}${content.slice(insertPos)}`;\n};\n"]}
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.logManualReview = exports.moveNamedImports = void 0;
|
|
37
|
+
const devkit_1 = require("@nx/devkit");
|
|
38
|
+
const ts = __importStar(require("typescript"));
|
|
39
|
+
const jsx_utils_1 = require("./jsx-utils");
|
|
40
|
+
const MOCK_OBJECTS = new Set(["vi", "jest"]);
|
|
41
|
+
const MOCK_METHODS = new Set([
|
|
42
|
+
"mock",
|
|
43
|
+
"doMock",
|
|
44
|
+
"unmock",
|
|
45
|
+
"doUnmock",
|
|
46
|
+
"importActual",
|
|
47
|
+
"importMock",
|
|
48
|
+
"requireActual",
|
|
49
|
+
"requireMock",
|
|
50
|
+
]);
|
|
51
|
+
const toRenameMap = (names) => Array.isArray(names) ? new Map(names.map(name => [name, name])) : new Map(Object.entries(names));
|
|
52
|
+
const parseSource = (filePath, content) => ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true, filePath.endsWith(".ts") ? ts.ScriptKind.TS : ts.ScriptKind.TSX);
|
|
53
|
+
const isModule = (node, moduleName) => node !== undefined &&
|
|
54
|
+
(ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) &&
|
|
55
|
+
node.text === moduleName;
|
|
56
|
+
/** Renders `moduleName` with the quote style of an existing specifier. */
|
|
57
|
+
const quoteLike = (specifier, moduleName) => {
|
|
58
|
+
const quote = specifier.getText().startsWith("'") ? "'" : '"';
|
|
59
|
+
return `${quote}${moduleName}${quote}`;
|
|
60
|
+
};
|
|
61
|
+
const renderSpecifier = ({ imported, local, isTypeOnly }, withTypePrefix) => `${withTypePrefix && isTypeOnly ? "type " : ""}${imported === local ? imported : `${imported} as ${local}`}`;
|
|
62
|
+
const statementTerminator = (statement) => (statement.getText().endsWith(";") ? ";" : "");
|
|
63
|
+
const lineOf = (sourceFile, node) => sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
|
|
64
|
+
/** `true` when `node` is a property-like key (`a.X`, `{ X: 1 }`, `<C X="" />`) rather than a reference to a binding. */
|
|
65
|
+
const isPropertyKey = (node) => {
|
|
66
|
+
const parent = node.parent;
|
|
67
|
+
if (ts.isPropertyAccessExpression(parent) || ts.isQualifiedName(parent)) {
|
|
68
|
+
return ts.isPropertyAccessExpression(parent) ? parent.name === node : parent.right === node;
|
|
69
|
+
}
|
|
70
|
+
if (ts.isBindingElement(parent))
|
|
71
|
+
return parent.propertyName === node;
|
|
72
|
+
if (ts.isPropertyAssignment(parent) ||
|
|
73
|
+
ts.isPropertyDeclaration(parent) ||
|
|
74
|
+
ts.isPropertySignature(parent) ||
|
|
75
|
+
ts.isMethodDeclaration(parent) ||
|
|
76
|
+
ts.isMethodSignature(parent) ||
|
|
77
|
+
ts.isGetAccessorDeclaration(parent) ||
|
|
78
|
+
ts.isSetAccessorDeclaration(parent) ||
|
|
79
|
+
ts.isEnumMember(parent) ||
|
|
80
|
+
ts.isJsxAttribute(parent)) {
|
|
81
|
+
return parent.name === node;
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
84
|
+
};
|
|
85
|
+
/** `true` when `node` declares a new binding (variable, parameter, function, class, type...). */
|
|
86
|
+
const isBindingDeclaration = (node) => {
|
|
87
|
+
const parent = node.parent;
|
|
88
|
+
if (ts.isBindingElement(parent))
|
|
89
|
+
return parent.name === node;
|
|
90
|
+
if (ts.isVariableDeclaration(parent) ||
|
|
91
|
+
ts.isParameter(parent) ||
|
|
92
|
+
ts.isFunctionDeclaration(parent) ||
|
|
93
|
+
ts.isFunctionExpression(parent) ||
|
|
94
|
+
ts.isClassDeclaration(parent) ||
|
|
95
|
+
ts.isClassExpression(parent) ||
|
|
96
|
+
ts.isInterfaceDeclaration(parent) ||
|
|
97
|
+
ts.isTypeAliasDeclaration(parent) ||
|
|
98
|
+
ts.isEnumDeclaration(parent) ||
|
|
99
|
+
ts.isTypeParameterDeclaration(parent) ||
|
|
100
|
+
ts.isImportSpecifier(parent) ||
|
|
101
|
+
ts.isImportClause(parent) ||
|
|
102
|
+
ts.isNamespaceImport(parent) ||
|
|
103
|
+
ts.isImportEqualsDeclaration(parent)) {
|
|
104
|
+
return parent.name === node;
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
};
|
|
108
|
+
/** Import and re-export statements are rewritten as a whole, so their identifiers are never edited one by one. */
|
|
109
|
+
const isInsideModuleStatement = (node) => ts.findAncestor(node, ancestor => ts.isImportDeclaration(ancestor) || (ts.isExportDeclaration(ancestor) && ancestor.moduleSpecifier !== undefined)) !== undefined;
|
|
110
|
+
const collectIdentifiers = (sourceFile) => {
|
|
111
|
+
const identifiers = [];
|
|
112
|
+
const visit = (node) => {
|
|
113
|
+
if (ts.isIdentifier(node))
|
|
114
|
+
identifiers.push(node);
|
|
115
|
+
ts.forEachChild(node, visit);
|
|
116
|
+
};
|
|
117
|
+
visit(sourceFile);
|
|
118
|
+
return identifiers;
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* Edits that rename every reference to the local binding `oldName` to
|
|
122
|
+
* `newName`, or `null` when that can't be done safely (the new name is
|
|
123
|
+
* already used in the file, or `oldName` is redeclared and might be shadowed).
|
|
124
|
+
*/
|
|
125
|
+
const renameReferenceEdits = (sourceFile, identifiers, oldName, newName) => {
|
|
126
|
+
if (identifiers.some(id => id.text === newName))
|
|
127
|
+
return null;
|
|
128
|
+
const outside = identifiers.filter(id => id.text === oldName && !isInsideModuleStatement(id));
|
|
129
|
+
if (outside.some(isBindingDeclaration))
|
|
130
|
+
return null;
|
|
131
|
+
const edits = [];
|
|
132
|
+
for (const id of outside) {
|
|
133
|
+
if (isPropertyKey(id))
|
|
134
|
+
continue;
|
|
135
|
+
const start = id.getStart(sourceFile);
|
|
136
|
+
const end = id.getEnd();
|
|
137
|
+
const parent = id.parent;
|
|
138
|
+
if (ts.isShorthandPropertyAssignment(parent)) {
|
|
139
|
+
edits.push({ start, end, text: `${oldName}: ${newName}` });
|
|
140
|
+
}
|
|
141
|
+
else if (ts.isExportSpecifier(parent)) {
|
|
142
|
+
if (parent.propertyName === undefined)
|
|
143
|
+
edits.push({ start, end, text: `${newName} as ${oldName}` });
|
|
144
|
+
else if (parent.propertyName === id)
|
|
145
|
+
edits.push({ start, end, text: newName });
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
edits.push({ start, end, text: newName });
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return edits;
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* Usages of `fromModule` the codemod can't rewrite statically. They are only
|
|
155
|
+
* reported when the file references a moved name at all, so e.g. a
|
|
156
|
+
* `vi.mock(fromModule, ...)` in a spec that never touches a moved name is not
|
|
157
|
+
* noise. `export *` is always reported: the moved names silently drop out of it.
|
|
158
|
+
*/
|
|
159
|
+
const findManualReviewItems = (sourceFile, identifiers, fromModule, toModule, renames) => {
|
|
160
|
+
const items = [];
|
|
161
|
+
const file = sourceFile.fileName;
|
|
162
|
+
const mentionsMovedName = identifiers.some(id => renames.has(id.text)) || sourceFile.text.split(/["'`]/).some(chunk => renames.has(chunk));
|
|
163
|
+
const movedList = [...renames.keys()].join(", ");
|
|
164
|
+
const hint = `moved names (${movedList}) now come from "${toModule}"`;
|
|
165
|
+
const report = (node, what) => {
|
|
166
|
+
items.push({ file, line: lineOf(sourceFile, node), reason: `${what} of "${fromModule}"; ${hint}` });
|
|
167
|
+
};
|
|
168
|
+
const visit = (node) => {
|
|
169
|
+
if (ts.isImportDeclaration(node) && isModule(node.moduleSpecifier, fromModule)) {
|
|
170
|
+
const bindings = node.importClause?.namedBindings;
|
|
171
|
+
if (bindings !== undefined && ts.isNamespaceImport(bindings) && mentionsMovedName) {
|
|
172
|
+
report(node, `namespace import \`* as ${bindings.name.text}\``);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
else if (ts.isExportDeclaration(node) && isModule(node.moduleSpecifier, fromModule)) {
|
|
176
|
+
if (node.exportClause === undefined)
|
|
177
|
+
report(node, "`export *`");
|
|
178
|
+
else if (ts.isNamespaceExport(node.exportClause))
|
|
179
|
+
report(node, "`export * as`");
|
|
180
|
+
}
|
|
181
|
+
else if (ts.isImportEqualsDeclaration(node) && mentionsMovedName) {
|
|
182
|
+
const reference = node.moduleReference;
|
|
183
|
+
if (ts.isExternalModuleReference(reference) && isModule(reference.expression, fromModule)) {
|
|
184
|
+
report(node, "`import = require()`");
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
else if (ts.isImportTypeNode(node) && mentionsMovedName) {
|
|
188
|
+
const argument = node.argument;
|
|
189
|
+
if (ts.isLiteralTypeNode(argument) && isModule(argument.literal, fromModule))
|
|
190
|
+
report(node, "`import()` type");
|
|
191
|
+
}
|
|
192
|
+
else if (ts.isCallExpression(node) && mentionsMovedName && isModule(node.arguments[0], fromModule)) {
|
|
193
|
+
const callee = node.expression;
|
|
194
|
+
if (callee.kind === ts.SyntaxKind.ImportKeyword) {
|
|
195
|
+
report(node, "dynamic import()");
|
|
196
|
+
}
|
|
197
|
+
else if (ts.isIdentifier(callee) && callee.text === "require") {
|
|
198
|
+
report(node, "require()");
|
|
199
|
+
}
|
|
200
|
+
else if (ts.isPropertyAccessExpression(callee) &&
|
|
201
|
+
ts.isIdentifier(callee.expression) &&
|
|
202
|
+
MOCK_OBJECTS.has(callee.expression.text) &&
|
|
203
|
+
MOCK_METHODS.has(callee.name.text)) {
|
|
204
|
+
report(node, `${callee.expression.text}.${callee.name.text}()`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
ts.forEachChild(node, visit);
|
|
208
|
+
};
|
|
209
|
+
visit(sourceFile);
|
|
210
|
+
return items;
|
|
211
|
+
};
|
|
212
|
+
const findTargetImport = (sourceFile, toModule, typeOnly) => {
|
|
213
|
+
for (const statement of sourceFile.statements) {
|
|
214
|
+
if (!ts.isImportDeclaration(statement) || !isModule(statement.moduleSpecifier, toModule))
|
|
215
|
+
continue;
|
|
216
|
+
const clause = statement.importClause;
|
|
217
|
+
if (clause === undefined || clause.isTypeOnly !== typeOnly)
|
|
218
|
+
continue;
|
|
219
|
+
const bindings = clause.namedBindings;
|
|
220
|
+
if (bindings === undefined || !ts.isNamedImports(bindings))
|
|
221
|
+
continue;
|
|
222
|
+
return { statement, elements: bindings.elements, additions: [] };
|
|
223
|
+
}
|
|
224
|
+
return null;
|
|
225
|
+
};
|
|
226
|
+
const specifierKey = ({ imported, local }) => `${imported} as ${local}`;
|
|
227
|
+
const specifierOf = (element, parentTypeOnly) => ({
|
|
228
|
+
imported: (element.propertyName ?? element.name).text,
|
|
229
|
+
local: element.name.text,
|
|
230
|
+
isTypeOnly: parentTypeOnly || element.isTypeOnly,
|
|
231
|
+
});
|
|
232
|
+
const rewriteFile = (filePath, content, { fromModule, toModule }, renames) => {
|
|
233
|
+
const sourceFile = parseSource(filePath, content);
|
|
234
|
+
const identifiers = collectIdentifiers(sourceFile);
|
|
235
|
+
const manualReview = findManualReviewItems(sourceFile, identifiers, fromModule, toModule, renames);
|
|
236
|
+
const edits = [];
|
|
237
|
+
const valueTarget = findTargetImport(sourceFile, toModule, false);
|
|
238
|
+
const typeTarget = findTargetImport(sourceFile, toModule, true);
|
|
239
|
+
const targetFor = (spec) => {
|
|
240
|
+
if (!spec.isTypeOnly)
|
|
241
|
+
return valueTarget;
|
|
242
|
+
return typeTarget ?? valueTarget;
|
|
243
|
+
};
|
|
244
|
+
const replaceStatement = (statement, kept, added) => {
|
|
245
|
+
const parts = [...(kept === null ? [] : [kept]), ...added];
|
|
246
|
+
const start = statement.getStart(sourceFile);
|
|
247
|
+
let end = statement.getEnd();
|
|
248
|
+
if (parts.length === 0) {
|
|
249
|
+
if (content.startsWith("\r\n", end))
|
|
250
|
+
end += 2;
|
|
251
|
+
else if (content.startsWith("\n", end))
|
|
252
|
+
end += 1;
|
|
253
|
+
const leading = content.slice(statement.getFullStart(), start);
|
|
254
|
+
if (leading.includes("eslint-disable")) {
|
|
255
|
+
manualReview.push({
|
|
256
|
+
file: filePath,
|
|
257
|
+
line: lineOf(sourceFile, statement),
|
|
258
|
+
reason: `removed import of "${fromModule}" had an eslint-disable comment, which now applies to the next line`,
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
edits.push({ start, end, text: parts.join("\n") });
|
|
263
|
+
};
|
|
264
|
+
const createdImports = new Map();
|
|
265
|
+
const deferredImports = [];
|
|
266
|
+
for (const statement of sourceFile.statements) {
|
|
267
|
+
if (ts.isImportDeclaration(statement) && isModule(statement.moduleSpecifier, fromModule)) {
|
|
268
|
+
const clause = statement.importClause;
|
|
269
|
+
const bindings = clause?.namedBindings;
|
|
270
|
+
if (clause === undefined || bindings === undefined || !ts.isNamedImports(bindings))
|
|
271
|
+
continue;
|
|
272
|
+
const moved = bindings.elements.filter(element => renames.has((element.propertyName ?? element.name).text));
|
|
273
|
+
if (moved.length === 0)
|
|
274
|
+
continue;
|
|
275
|
+
const kept = bindings.elements.filter(element => !moved.includes(element));
|
|
276
|
+
const createdKind = clause.isTypeOnly;
|
|
277
|
+
const addCreated = (spec) => {
|
|
278
|
+
const created = createdImports.get(createdKind) ?? { anchor: statement, specs: [] };
|
|
279
|
+
createdImports.set(createdKind, created);
|
|
280
|
+
if (!created.specs.some(existing => specifierKey(existing) === specifierKey(spec)))
|
|
281
|
+
created.specs.push(spec);
|
|
282
|
+
};
|
|
283
|
+
for (const element of moved) {
|
|
284
|
+
const original = specifierOf(element, clause.isTypeOnly);
|
|
285
|
+
const newName = renames.get(original.imported) ?? original.imported;
|
|
286
|
+
let local = original.local;
|
|
287
|
+
if (newName !== original.imported && original.local === original.imported) {
|
|
288
|
+
const renameEdits = renameReferenceEdits(sourceFile, identifiers, original.local, newName);
|
|
289
|
+
if (renameEdits !== null) {
|
|
290
|
+
edits.push(...renameEdits);
|
|
291
|
+
local = newName;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const spec = { imported: newName, local, isTypeOnly: original.isTypeOnly };
|
|
295
|
+
const target = targetFor(spec);
|
|
296
|
+
if (target === null) {
|
|
297
|
+
addCreated(spec);
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
const existing = new Set([
|
|
301
|
+
...target.elements.map(e => specifierKey(specifierOf(e, false))),
|
|
302
|
+
...target.additions.map(specifierKey),
|
|
303
|
+
]);
|
|
304
|
+
if (!existing.has(specifierKey(spec)))
|
|
305
|
+
target.additions.push(spec);
|
|
306
|
+
}
|
|
307
|
+
const terminator = statementTerminator(statement);
|
|
308
|
+
const defaultName = clause.name?.text;
|
|
309
|
+
const keptText = kept.length === 0 && defaultName === undefined
|
|
310
|
+
? null
|
|
311
|
+
: `import ${clause.isTypeOnly ? "type " : ""}${[
|
|
312
|
+
...(defaultName === undefined ? [] : [defaultName]),
|
|
313
|
+
...(kept.length === 0 ? [] : [`{ ${kept.map(e => e.getText(sourceFile)).join(", ")} }`]),
|
|
314
|
+
].join(", ")} from ${statement.moduleSpecifier.getText(sourceFile)}${terminator}`;
|
|
315
|
+
deferredImports.push({ statement, keptText });
|
|
316
|
+
}
|
|
317
|
+
else if (ts.isExportDeclaration(statement) &&
|
|
318
|
+
isModule(statement.moduleSpecifier, fromModule) &&
|
|
319
|
+
statement.moduleSpecifier !== undefined &&
|
|
320
|
+
statement.exportClause !== undefined &&
|
|
321
|
+
ts.isNamedExports(statement.exportClause)) {
|
|
322
|
+
const elements = statement.exportClause.elements;
|
|
323
|
+
const moved = elements.filter(element => renames.has((element.propertyName ?? element.name).text));
|
|
324
|
+
if (moved.length === 0)
|
|
325
|
+
continue;
|
|
326
|
+
const kept = elements.filter(element => !moved.includes(element));
|
|
327
|
+
const typePrefix = statement.isTypeOnly ? "type " : "";
|
|
328
|
+
const terminator = statementTerminator(statement);
|
|
329
|
+
const specs = moved.map(element => {
|
|
330
|
+
const imported = (element.propertyName ?? element.name).text;
|
|
331
|
+
return renderSpecifier({ imported: renames.get(imported) ?? imported, local: element.name.text, isTypeOnly: element.isTypeOnly }, true);
|
|
332
|
+
});
|
|
333
|
+
replaceStatement(statement, kept.length === 0
|
|
334
|
+
? null
|
|
335
|
+
: `export ${typePrefix}{ ${kept.map(e => e.getText(sourceFile)).join(", ")} } from ${statement.moduleSpecifier.getText(sourceFile)}${terminator}`, [
|
|
336
|
+
`export ${typePrefix}{ ${specs.join(", ")} } from ${quoteLike(statement.moduleSpecifier, toModule)}${terminator}`,
|
|
337
|
+
]);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
for (const { statement, keptText } of deferredImports) {
|
|
341
|
+
const createdText = [...createdImports.entries()]
|
|
342
|
+
.filter(([, created]) => created.anchor === statement)
|
|
343
|
+
.map(([typeOnly, created]) => `import ${typeOnly ? "type " : ""}{ ${created.specs
|
|
344
|
+
.map(spec => renderSpecifier(spec, !typeOnly))
|
|
345
|
+
.join(", ")} } from ${quoteLike(statement.moduleSpecifier, toModule)}${statementTerminator(statement)}`);
|
|
346
|
+
replaceStatement(statement, keptText, createdText);
|
|
347
|
+
}
|
|
348
|
+
for (const target of [valueTarget, typeTarget]) {
|
|
349
|
+
if (target === null || target.additions.length === 0)
|
|
350
|
+
continue;
|
|
351
|
+
const typeOnly = target.statement.importClause?.isTypeOnly === true;
|
|
352
|
+
const bindings = target.statement.importClause?.namedBindings;
|
|
353
|
+
if (bindings === undefined)
|
|
354
|
+
continue;
|
|
355
|
+
const merged = [
|
|
356
|
+
...target.elements.map(e => e.getText(sourceFile)),
|
|
357
|
+
...target.additions.map(spec => renderSpecifier(spec, !typeOnly)),
|
|
358
|
+
];
|
|
359
|
+
edits.push({ start: bindings.getStart(sourceFile), end: bindings.getEnd(), text: `{ ${merged.join(", ")} }` });
|
|
360
|
+
}
|
|
361
|
+
if (edits.length === 0)
|
|
362
|
+
return { content, manualReview };
|
|
363
|
+
edits.sort((a, b) => b.start - a.start);
|
|
364
|
+
let updated = content;
|
|
365
|
+
for (const { start, end, text } of edits) {
|
|
366
|
+
updated = updated.slice(0, start) + text + updated.slice(end);
|
|
367
|
+
}
|
|
368
|
+
return { content: updated, manualReview };
|
|
369
|
+
};
|
|
370
|
+
/**
|
|
371
|
+
* Moves named imports and named re-exports of `names` from `fromModule` to
|
|
372
|
+
* `toModule` across every `.ts`/`.tsx`/`.jsx` file in the tree.
|
|
373
|
+
*
|
|
374
|
+
* - Mixed imports are split; names that didn't move stay on `fromModule`.
|
|
375
|
+
* - Aliases (`as`), `import type` and inline `type` modifiers are preserved.
|
|
376
|
+
* - Moved names are merged into an existing named import of `toModule`, or
|
|
377
|
+
* else into one new import per kind (value / `import type`).
|
|
378
|
+
* - With a rename record, an unaliased import has its references renamed too;
|
|
379
|
+
* when that isn't safe (name clash or shadowing) it is imported as
|
|
380
|
+
* `{ NewName as OldName }` instead. Re-exports keep their public name.
|
|
381
|
+
* - Namespace imports, `export *`, dynamic `import()`, `require()` and
|
|
382
|
+
* `vi`/`jest` mocks of `fromModule` are left untouched and returned in
|
|
383
|
+
* `manualReview`, never skipped silently.
|
|
384
|
+
*
|
|
385
|
+
* Synchronous and format-free, so it can run inside a `run-migrations`
|
|
386
|
+
* migration; callers format changed files themselves (e.g. `formatFiles`).
|
|
387
|
+
*/
|
|
388
|
+
const moveNamedImports = (tree, options) => {
|
|
389
|
+
const renames = toRenameMap(options.names);
|
|
390
|
+
const changedFiles = [];
|
|
391
|
+
const manualReview = [];
|
|
392
|
+
(0, jsx_utils_1.visitTsFiles)(tree, options.fromModule, (filePath, content) => {
|
|
393
|
+
const result = rewriteFile(filePath, content, options, renames);
|
|
394
|
+
manualReview.push(...result.manualReview);
|
|
395
|
+
if (result.content !== content)
|
|
396
|
+
changedFiles.push(filePath);
|
|
397
|
+
return result.content;
|
|
398
|
+
});
|
|
399
|
+
return { changedFiles, manualReview };
|
|
400
|
+
};
|
|
401
|
+
exports.moveNamedImports = moveNamedImports;
|
|
402
|
+
/** Logs each manual-review item as a warning, prefixed with the migration name. */
|
|
403
|
+
const logManualReview = (migrationName, items) => {
|
|
404
|
+
for (const { file, line, reason } of items) {
|
|
405
|
+
devkit_1.logger.warn(` ${migrationName}: manual review needed at ${file}:${line} - ${reason}`);
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
exports.logManualReview = logManualReview;
|
|
409
|
+
//# sourceMappingURL=move-named-imports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"move-named-imports.js","sourceRoot":"","sources":["../../../../../../libs/react/components/migrations/utils/move-named-imports.ts"],"names":[],"mappings":"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","sourcesContent":["import { logger, type Tree } from \"@nx/devkit\";\nimport * as ts from \"typescript\";\nimport { visitTsFiles } from \"./jsx-utils\";\n\n/**\n * Names to move. A list keeps every name; a record maps each old exported\n * name to its new exported name in the target module.\n */\nexport type MovedNames = ReadonlyArray<string> | Readonly<Record<string, string>>;\n\nexport type MoveNamedImportsOptions = {\n /** Module the names are imported from today, e.g. `@trackunit/ui-connected-components`. */\n readonly fromModule: string;\n /** Module that exports the names now, e.g. `@trackunit/react-router-components`. */\n readonly toModule: string;\n readonly names: MovedNames;\n};\n\nexport type ManualReviewItem = {\n readonly file: string;\n /** 1-based line of the usage. */\n readonly line: number;\n readonly reason: string;\n};\n\nexport type MoveNamedImportsResult = {\n readonly changedFiles: ReadonlyArray<string>;\n /** Usages the codemod could not rewrite safely. They are left as-is and must be fixed by hand. */\n readonly manualReview: ReadonlyArray<ManualReviewItem>;\n};\n\ntype Edit = { start: number; end: number; text: string };\n\n/** A moved specifier as it should be written against the target module. */\ntype MovedSpecifier = {\n /** Exported name in the target module. */\n readonly imported: string;\n /** Local binding (imports) or public name (re-exports). */\n readonly local: string;\n /** `true` for an inline `type` modifier, or any specifier of an `import type` / `export type`. */\n readonly isTypeOnly: boolean;\n};\n\nconst MOCK_OBJECTS: ReadonlySet<string> = new Set([\"vi\", \"jest\"]);\nconst MOCK_METHODS: ReadonlySet<string> = new Set([\n \"mock\",\n \"doMock\",\n \"unmock\",\n \"doUnmock\",\n \"importActual\",\n \"importMock\",\n \"requireActual\",\n \"requireMock\",\n]);\n\nconst toRenameMap = (names: MovedNames): ReadonlyMap<string, string> =>\n Array.isArray(names) ? new Map(names.map(name => [name, name])) : new Map(Object.entries(names));\n\nconst parseSource = (filePath: string, content: string): ts.SourceFile =>\n ts.createSourceFile(\n filePath,\n content,\n ts.ScriptTarget.Latest,\n true,\n filePath.endsWith(\".ts\") ? ts.ScriptKind.TS : ts.ScriptKind.TSX\n );\n\nconst isModule = (node: ts.Expression | undefined, moduleName: string): boolean =>\n node !== undefined &&\n (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) &&\n node.text === moduleName;\n\n/** Renders `moduleName` with the quote style of an existing specifier. */\nconst quoteLike = (specifier: ts.Expression, moduleName: string): string => {\n const quote = specifier.getText().startsWith(\"'\") ? \"'\" : '\"';\n return `${quote}${moduleName}${quote}`;\n};\n\nconst renderSpecifier = ({ imported, local, isTypeOnly }: MovedSpecifier, withTypePrefix: boolean): string =>\n `${withTypePrefix && isTypeOnly ? \"type \" : \"\"}${imported === local ? imported : `${imported} as ${local}`}`;\n\nconst statementTerminator = (statement: ts.Statement): string => (statement.getText().endsWith(\";\") ? \";\" : \"\");\n\nconst lineOf = (sourceFile: ts.SourceFile, node: ts.Node): number =>\n sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;\n\n/** `true` when `node` is a property-like key (`a.X`, `{ X: 1 }`, `<C X=\"\" />`) rather than a reference to a binding. */\nconst isPropertyKey = (node: ts.Identifier): boolean => {\n const parent = node.parent;\n if (ts.isPropertyAccessExpression(parent) || ts.isQualifiedName(parent)) {\n return ts.isPropertyAccessExpression(parent) ? parent.name === node : parent.right === node;\n }\n if (ts.isBindingElement(parent)) return parent.propertyName === node;\n if (\n ts.isPropertyAssignment(parent) ||\n ts.isPropertyDeclaration(parent) ||\n ts.isPropertySignature(parent) ||\n ts.isMethodDeclaration(parent) ||\n ts.isMethodSignature(parent) ||\n ts.isGetAccessorDeclaration(parent) ||\n ts.isSetAccessorDeclaration(parent) ||\n ts.isEnumMember(parent) ||\n ts.isJsxAttribute(parent)\n ) {\n return parent.name === node;\n }\n return false;\n};\n\n/** `true` when `node` declares a new binding (variable, parameter, function, class, type...). */\nconst isBindingDeclaration = (node: ts.Identifier): boolean => {\n const parent = node.parent;\n if (ts.isBindingElement(parent)) return parent.name === node;\n if (\n ts.isVariableDeclaration(parent) ||\n ts.isParameter(parent) ||\n ts.isFunctionDeclaration(parent) ||\n ts.isFunctionExpression(parent) ||\n ts.isClassDeclaration(parent) ||\n ts.isClassExpression(parent) ||\n ts.isInterfaceDeclaration(parent) ||\n ts.isTypeAliasDeclaration(parent) ||\n ts.isEnumDeclaration(parent) ||\n ts.isTypeParameterDeclaration(parent) ||\n ts.isImportSpecifier(parent) ||\n ts.isImportClause(parent) ||\n ts.isNamespaceImport(parent) ||\n ts.isImportEqualsDeclaration(parent)\n ) {\n return parent.name === node;\n }\n return false;\n};\n\n/** Import and re-export statements are rewritten as a whole, so their identifiers are never edited one by one. */\nconst isInsideModuleStatement = (node: ts.Node): boolean =>\n ts.findAncestor(\n node,\n ancestor =>\n ts.isImportDeclaration(ancestor) || (ts.isExportDeclaration(ancestor) && ancestor.moduleSpecifier !== undefined)\n ) !== undefined;\n\nconst collectIdentifiers = (sourceFile: ts.SourceFile): ReadonlyArray<ts.Identifier> => {\n const identifiers: Array<ts.Identifier> = [];\n const visit = (node: ts.Node): void => {\n if (ts.isIdentifier(node)) identifiers.push(node);\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n return identifiers;\n};\n\n/**\n * Edits that rename every reference to the local binding `oldName` to\n * `newName`, or `null` when that can't be done safely (the new name is\n * already used in the file, or `oldName` is redeclared and might be shadowed).\n */\nconst renameReferenceEdits = (\n sourceFile: ts.SourceFile,\n identifiers: ReadonlyArray<ts.Identifier>,\n oldName: string,\n newName: string\n): Array<Edit> | null => {\n if (identifiers.some(id => id.text === newName)) return null;\n const outside = identifiers.filter(id => id.text === oldName && !isInsideModuleStatement(id));\n if (outside.some(isBindingDeclaration)) return null;\n\n const edits: Array<Edit> = [];\n for (const id of outside) {\n if (isPropertyKey(id)) continue;\n const start = id.getStart(sourceFile);\n const end = id.getEnd();\n const parent = id.parent;\n if (ts.isShorthandPropertyAssignment(parent)) {\n edits.push({ start, end, text: `${oldName}: ${newName}` });\n } else if (ts.isExportSpecifier(parent)) {\n if (parent.propertyName === undefined) edits.push({ start, end, text: `${newName} as ${oldName}` });\n else if (parent.propertyName === id) edits.push({ start, end, text: newName });\n } else {\n edits.push({ start, end, text: newName });\n }\n }\n return edits;\n};\n\n/**\n * Usages of `fromModule` the codemod can't rewrite statically. They are only\n * reported when the file references a moved name at all, so e.g. a\n * `vi.mock(fromModule, ...)` in a spec that never touches a moved name is not\n * noise. `export *` is always reported: the moved names silently drop out of it.\n */\nconst findManualReviewItems = (\n sourceFile: ts.SourceFile,\n identifiers: ReadonlyArray<ts.Identifier>,\n fromModule: string,\n toModule: string,\n renames: ReadonlyMap<string, string>\n): Array<ManualReviewItem> => {\n const items: Array<ManualReviewItem> = [];\n const file = sourceFile.fileName;\n const mentionsMovedName =\n identifiers.some(id => renames.has(id.text)) || sourceFile.text.split(/[\"'`]/).some(chunk => renames.has(chunk));\n const movedList = [...renames.keys()].join(\", \");\n const hint = `moved names (${movedList}) now come from \"${toModule}\"`;\n\n const report = (node: ts.Node, what: string): void => {\n items.push({ file, line: lineOf(sourceFile, node), reason: `${what} of \"${fromModule}\"; ${hint}` });\n };\n\n const visit = (node: ts.Node): void => {\n if (ts.isImportDeclaration(node) && isModule(node.moduleSpecifier, fromModule)) {\n const bindings = node.importClause?.namedBindings;\n if (bindings !== undefined && ts.isNamespaceImport(bindings) && mentionsMovedName) {\n report(node, `namespace import \\`* as ${bindings.name.text}\\``);\n }\n } else if (ts.isExportDeclaration(node) && isModule(node.moduleSpecifier, fromModule)) {\n if (node.exportClause === undefined) report(node, \"`export *`\");\n else if (ts.isNamespaceExport(node.exportClause)) report(node, \"`export * as`\");\n } else if (ts.isImportEqualsDeclaration(node) && mentionsMovedName) {\n const reference = node.moduleReference;\n if (ts.isExternalModuleReference(reference) && isModule(reference.expression, fromModule)) {\n report(node, \"`import = require()`\");\n }\n } else if (ts.isImportTypeNode(node) && mentionsMovedName) {\n const argument = node.argument;\n if (ts.isLiteralTypeNode(argument) && isModule(argument.literal, fromModule)) report(node, \"`import()` type\");\n } else if (ts.isCallExpression(node) && mentionsMovedName && isModule(node.arguments[0], fromModule)) {\n const callee = node.expression;\n if (callee.kind === ts.SyntaxKind.ImportKeyword) {\n report(node, \"dynamic import()\");\n } else if (ts.isIdentifier(callee) && callee.text === \"require\") {\n report(node, \"require()\");\n } else if (\n ts.isPropertyAccessExpression(callee) &&\n ts.isIdentifier(callee.expression) &&\n MOCK_OBJECTS.has(callee.expression.text) &&\n MOCK_METHODS.has(callee.name.text)\n ) {\n report(node, `${callee.expression.text}.${callee.name.text}()`);\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n return items;\n};\n\ntype TargetImport = {\n readonly statement: ts.ImportDeclaration;\n readonly elements: ts.NodeArray<ts.ImportSpecifier>;\n readonly additions: Array<MovedSpecifier>;\n};\n\nconst findTargetImport = (sourceFile: ts.SourceFile, toModule: string, typeOnly: boolean): TargetImport | null => {\n for (const statement of sourceFile.statements) {\n if (!ts.isImportDeclaration(statement) || !isModule(statement.moduleSpecifier, toModule)) continue;\n const clause = statement.importClause;\n if (clause === undefined || clause.isTypeOnly !== typeOnly) continue;\n const bindings = clause.namedBindings;\n if (bindings === undefined || !ts.isNamedImports(bindings)) continue;\n return { statement, elements: bindings.elements, additions: [] };\n }\n return null;\n};\n\nconst specifierKey = ({ imported, local }: MovedSpecifier): string => `${imported} as ${local}`;\n\nconst specifierOf = (element: ts.ImportSpecifier, parentTypeOnly: boolean): MovedSpecifier => ({\n imported: (element.propertyName ?? element.name).text,\n local: element.name.text,\n isTypeOnly: parentTypeOnly || element.isTypeOnly,\n});\n\nconst rewriteFile = (\n filePath: string,\n content: string,\n { fromModule, toModule }: MoveNamedImportsOptions,\n renames: ReadonlyMap<string, string>\n): { content: string; manualReview: Array<ManualReviewItem> } => {\n const sourceFile = parseSource(filePath, content);\n const identifiers = collectIdentifiers(sourceFile);\n const manualReview = findManualReviewItems(sourceFile, identifiers, fromModule, toModule, renames);\n\n const edits: Array<Edit> = [];\n const valueTarget = findTargetImport(sourceFile, toModule, false);\n const typeTarget = findTargetImport(sourceFile, toModule, true);\n\n const targetFor = (spec: MovedSpecifier): TargetImport | null => {\n if (!spec.isTypeOnly) return valueTarget;\n return typeTarget ?? valueTarget;\n };\n\n const replaceStatement = (statement: ts.Statement, kept: string | null, added: ReadonlyArray<string>): void => {\n const parts = [...(kept === null ? [] : [kept]), ...added];\n const start = statement.getStart(sourceFile);\n let end = statement.getEnd();\n if (parts.length === 0) {\n if (content.startsWith(\"\\r\\n\", end)) end += 2;\n else if (content.startsWith(\"\\n\", end)) end += 1;\n const leading = content.slice(statement.getFullStart(), start);\n if (leading.includes(\"eslint-disable\")) {\n manualReview.push({\n file: filePath,\n line: lineOf(sourceFile, statement),\n reason: `removed import of \"${fromModule}\" had an eslint-disable comment, which now applies to the next line`,\n });\n }\n }\n edits.push({ start, end, text: parts.join(\"\\n\") });\n };\n\n /**\n * Moved names with no existing target import, keyed by whether they came\n * from an `import type`. Each kind is written as one new import at the\n * first statement that needed it, so several old imports never become\n * several imports of `toModule`.\n */\n type CreatedImport = { readonly anchor: ts.ImportDeclaration; readonly specs: Array<MovedSpecifier> };\n const createdImports = new Map<boolean, CreatedImport>();\n const deferredImports: Array<{ statement: ts.ImportDeclaration; keptText: string | null }> = [];\n\n for (const statement of sourceFile.statements) {\n if (ts.isImportDeclaration(statement) && isModule(statement.moduleSpecifier, fromModule)) {\n const clause = statement.importClause;\n const bindings = clause?.namedBindings;\n if (clause === undefined || bindings === undefined || !ts.isNamedImports(bindings)) continue;\n const moved = bindings.elements.filter(element => renames.has((element.propertyName ?? element.name).text));\n if (moved.length === 0) continue;\n\n const kept = bindings.elements.filter(element => !moved.includes(element));\n const createdKind = clause.isTypeOnly;\n const addCreated = (spec: MovedSpecifier): void => {\n const created = createdImports.get(createdKind) ?? { anchor: statement, specs: [] };\n createdImports.set(createdKind, created);\n if (!created.specs.some(existing => specifierKey(existing) === specifierKey(spec))) created.specs.push(spec);\n };\n for (const element of moved) {\n const original = specifierOf(element, clause.isTypeOnly);\n const newName = renames.get(original.imported) ?? original.imported;\n let local = original.local;\n if (newName !== original.imported && original.local === original.imported) {\n const renameEdits = renameReferenceEdits(sourceFile, identifiers, original.local, newName);\n if (renameEdits !== null) {\n edits.push(...renameEdits);\n local = newName;\n }\n }\n const spec: MovedSpecifier = { imported: newName, local, isTypeOnly: original.isTypeOnly };\n const target = targetFor(spec);\n if (target === null) {\n addCreated(spec);\n continue;\n }\n const existing = new Set([\n ...target.elements.map(e => specifierKey(specifierOf(e, false))),\n ...target.additions.map(specifierKey),\n ]);\n if (!existing.has(specifierKey(spec))) target.additions.push(spec);\n }\n\n const terminator = statementTerminator(statement);\n const defaultName = clause.name?.text;\n const keptText =\n kept.length === 0 && defaultName === undefined\n ? null\n : `import ${clause.isTypeOnly ? \"type \" : \"\"}${[\n ...(defaultName === undefined ? [] : [defaultName]),\n ...(kept.length === 0 ? [] : [`{ ${kept.map(e => e.getText(sourceFile)).join(\", \")} }`]),\n ].join(\", \")} from ${statement.moduleSpecifier.getText(sourceFile)}${terminator}`;\n deferredImports.push({ statement, keptText });\n } else if (\n ts.isExportDeclaration(statement) &&\n isModule(statement.moduleSpecifier, fromModule) &&\n statement.moduleSpecifier !== undefined &&\n statement.exportClause !== undefined &&\n ts.isNamedExports(statement.exportClause)\n ) {\n const elements = statement.exportClause.elements;\n const moved = elements.filter(element => renames.has((element.propertyName ?? element.name).text));\n if (moved.length === 0) continue;\n const kept = elements.filter(element => !moved.includes(element));\n const typePrefix = statement.isTypeOnly ? \"type \" : \"\";\n const terminator = statementTerminator(statement);\n const specs = moved.map(element => {\n const imported = (element.propertyName ?? element.name).text;\n return renderSpecifier(\n { imported: renames.get(imported) ?? imported, local: element.name.text, isTypeOnly: element.isTypeOnly },\n true\n );\n });\n replaceStatement(\n statement,\n kept.length === 0\n ? null\n : `export ${typePrefix}{ ${kept.map(e => e.getText(sourceFile)).join(\", \")} } from ${statement.moduleSpecifier.getText(sourceFile)}${terminator}`,\n [\n `export ${typePrefix}{ ${specs.join(\", \")} } from ${quoteLike(statement.moduleSpecifier, toModule)}${terminator}`,\n ]\n );\n }\n }\n\n for (const { statement, keptText } of deferredImports) {\n const createdText = [...createdImports.entries()]\n .filter(([, created]) => created.anchor === statement)\n .map(\n ([typeOnly, created]) =>\n `import ${typeOnly ? \"type \" : \"\"}{ ${created.specs\n .map(spec => renderSpecifier(spec, !typeOnly))\n .join(\", \")} } from ${quoteLike(statement.moduleSpecifier, toModule)}${statementTerminator(statement)}`\n );\n replaceStatement(statement, keptText, createdText);\n }\n\n for (const target of [valueTarget, typeTarget]) {\n if (target === null || target.additions.length === 0) continue;\n const typeOnly = target.statement.importClause?.isTypeOnly === true;\n const bindings = target.statement.importClause?.namedBindings;\n if (bindings === undefined) continue;\n const merged = [\n ...target.elements.map(e => e.getText(sourceFile)),\n ...target.additions.map(spec => renderSpecifier(spec, !typeOnly)),\n ];\n edits.push({ start: bindings.getStart(sourceFile), end: bindings.getEnd(), text: `{ ${merged.join(\", \")} }` });\n }\n\n if (edits.length === 0) return { content, manualReview };\n edits.sort((a, b) => b.start - a.start);\n let updated = content;\n for (const { start, end, text } of edits) {\n updated = updated.slice(0, start) + text + updated.slice(end);\n }\n return { content: updated, manualReview };\n};\n\n/**\n * Moves named imports and named re-exports of `names` from `fromModule` to\n * `toModule` across every `.ts`/`.tsx`/`.jsx` file in the tree.\n *\n * - Mixed imports are split; names that didn't move stay on `fromModule`.\n * - Aliases (`as`), `import type` and inline `type` modifiers are preserved.\n * - Moved names are merged into an existing named import of `toModule`, or\n * else into one new import per kind (value / `import type`).\n * - With a rename record, an unaliased import has its references renamed too;\n * when that isn't safe (name clash or shadowing) it is imported as\n * `{ NewName as OldName }` instead. Re-exports keep their public name.\n * - Namespace imports, `export *`, dynamic `import()`, `require()` and\n * `vi`/`jest` mocks of `fromModule` are left untouched and returned in\n * `manualReview`, never skipped silently.\n *\n * Synchronous and format-free, so it can run inside a `run-migrations`\n * migration; callers format changed files themselves (e.g. `formatFiles`).\n */\nexport const moveNamedImports = (tree: Tree, options: MoveNamedImportsOptions): MoveNamedImportsResult => {\n const renames = toRenameMap(options.names);\n const changedFiles: Array<string> = [];\n const manualReview: Array<ManualReviewItem> = [];\n\n visitTsFiles(tree, options.fromModule, (filePath, content) => {\n const result = rewriteFile(filePath, content, options, renames);\n manualReview.push(...result.manualReview);\n if (result.content !== content) changedFiles.push(filePath);\n return result.content;\n });\n\n return { changedFiles, manualReview };\n};\n\n/** Logs each manual-review item as a warning, prefixed with the migration name. */\nexport const logManualReview = (migrationName: string, items: ReadonlyArray<ManualReviewItem>): void => {\n for (const { file, line, reason } of items) {\n logger.warn(` ${migrationName}: manual review needed at ${file}:${line} - ${reason}`);\n }\n};\n"]}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readCompanionVersion = exports.findPackageJsonsDeclaring = exports.ensureDependency = void 0;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
/** Root package name of the manager monorepo, where `@trackunit/*` versions are owned by CI. */
|
|
7
|
+
const MANAGER_WORKSPACE_PACKAGE_NAME = "@trackunit/manager";
|
|
8
|
+
/**
|
|
9
|
+
* Adds `packageName@range` to a package.json unless it is already declared
|
|
10
|
+
* in `dependencies` or `devDependencies` (an existing entry is never
|
|
11
|
+
* changed). Does nothing in the manager monorepo itself. Doesn't install;
|
|
12
|
+
* the consumer has to re-install afterwards.
|
|
13
|
+
*/
|
|
14
|
+
const ensureDependency = (tree, options) => {
|
|
15
|
+
const { packageName, range, besidePackage, packageJsonPath = "package.json" } = options;
|
|
16
|
+
if (!tree.exists(packageJsonPath))
|
|
17
|
+
return "no-package-json";
|
|
18
|
+
const packageJson = (0, devkit_1.readJson)(tree, packageJsonPath);
|
|
19
|
+
if (packageJson.name === MANAGER_WORKSPACE_PACKAGE_NAME)
|
|
20
|
+
return "manager-workspace";
|
|
21
|
+
if (packageJson.dependencies?.[packageName] !== undefined ||
|
|
22
|
+
packageJson.devDependencies?.[packageName] !== undefined) {
|
|
23
|
+
return "already-present";
|
|
24
|
+
}
|
|
25
|
+
const asDevDependency = besidePackage !== undefined &&
|
|
26
|
+
packageJson.dependencies?.[besidePackage] === undefined &&
|
|
27
|
+
packageJson.devDependencies?.[besidePackage] !== undefined;
|
|
28
|
+
const entry = { [packageName]: range };
|
|
29
|
+
(0, devkit_1.addDependenciesToPackageJson)(tree, asDevDependency ? {} : entry, asDevDependency ? entry : {}, packageJsonPath, true);
|
|
30
|
+
return "added";
|
|
31
|
+
};
|
|
32
|
+
exports.ensureDependency = ensureDependency;
|
|
33
|
+
/**
|
|
34
|
+
* Every package.json except the root one (and anything under
|
|
35
|
+
* `node_modules`) that declares `packageName` as a dependency, devDependency
|
|
36
|
+
* or peerDependency.
|
|
37
|
+
*/
|
|
38
|
+
const findPackageJsonsDeclaring = (tree, packageName) => {
|
|
39
|
+
const found = [];
|
|
40
|
+
(0, devkit_1.visitNotIgnoredFiles)(tree, "/", filePath => {
|
|
41
|
+
if (filePath === "package.json" || !filePath.endsWith("/package.json"))
|
|
42
|
+
return;
|
|
43
|
+
if (filePath.startsWith("node_modules/") || filePath.includes("/node_modules/"))
|
|
44
|
+
return;
|
|
45
|
+
const packageJson = (0, devkit_1.readJson)(tree, filePath);
|
|
46
|
+
if (packageJson.dependencies?.[packageName] !== undefined ||
|
|
47
|
+
packageJson.devDependencies?.[packageName] !== undefined ||
|
|
48
|
+
packageJson.peerDependencies?.[packageName] !== undefined) {
|
|
49
|
+
found.push(filePath);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
return found;
|
|
53
|
+
};
|
|
54
|
+
exports.findPackageJsonsDeclaring = findPackageJsonsDeclaring;
|
|
55
|
+
/**
|
|
56
|
+
* Version of a companion package, read from the first of `candidatePaths`
|
|
57
|
+
* (absolute file-system paths, not tree paths) that is the package.json of
|
|
58
|
+
* `packageName`. Throws when none is, so a migration fails and stays pending
|
|
59
|
+
* instead of writing a wrong range.
|
|
60
|
+
*/
|
|
61
|
+
const readCompanionVersion = (packageName, candidatePaths) => {
|
|
62
|
+
for (const candidatePath of candidatePaths) {
|
|
63
|
+
if (!(0, node_fs_1.existsSync)(candidatePath))
|
|
64
|
+
continue;
|
|
65
|
+
const packageJson = JSON.parse((0, node_fs_1.readFileSync)(candidatePath, "utf-8"));
|
|
66
|
+
if (packageJson.name === packageName && typeof packageJson.version === "string" && packageJson.version !== "") {
|
|
67
|
+
return packageJson.version;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
throw new Error(`Could not find the version of ${packageName}. Looked in: ${candidatePaths.join(", ")}`);
|
|
71
|
+
};
|
|
72
|
+
exports.readCompanionVersion = readCompanionVersion;
|
|
73
|
+
//# sourceMappingURL=package-json-utils.js.map
|