@ethlete/core 5.0.0-next.60 → 5.0.0-next.62
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 +75 -0
- package/fesm2022/ethlete-core.mjs +972 -597
- package/fesm2022/ethlete-core.mjs.map +1 -1
- package/generators/generators.json +10 -0
- package/generators/migrate-create-destroy/create-destroy.js +317 -0
- package/generators/migrate-create-destroy/migration.js +46 -0
- package/generators/migrate-create-destroy/schema.json +26 -0
- package/generators/migrate-legacy-color-themes/legacy-color-themes.js +123 -0
- package/generators/migrate-legacy-color-themes/migration.js +93 -0
- package/generators/migrate-legacy-color-themes/schema.json +26 -0
- package/generators/migrate-to-v5/apply-replacements.js +14 -0
- package/generators/migrate-to-v5/color-naming.js +11 -57
- package/generators/migrate-to-v5/create-provider.js +56 -44
- package/generators/migrate-to-v5/migration-files.js +13 -0
- package/generators/migrate-to-v5/migration.js +31 -27
- package/generators/migrate-to-v5/removed-exports.js +101 -33
- package/generators/migrate-to-v5/router-state-service.js +118 -350
- package/generators/migrate-to-v5/schema.json +12 -0
- package/generators/migrate-to-v5/service-classes.js +108 -0
- package/generators/migrate-to-v5/viewport-service.js +195 -443
- package/generators/tailwind-4-color-theme/generator.js +71 -85
- package/migrations/legacy-color-themes.md +38 -0
- package/migrations/seo-directive-removed.md +2 -1
- package/migrations.json +15 -0
- package/package.json +11 -11
- package/types/ethlete-core.d.ts +300 -202
|
@@ -4,6 +4,18 @@
|
|
|
4
4
|
"title": "Migrate to Core v5",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"properties": {
|
|
7
|
+
"projects": {
|
|
8
|
+
"type": "array",
|
|
9
|
+
"items": { "type": "string" },
|
|
10
|
+
"description": "Nx projects to migrate. Defaults to every project in the workspace.",
|
|
11
|
+
"alias": "project"
|
|
12
|
+
},
|
|
13
|
+
"include": {
|
|
14
|
+
"type": "array",
|
|
15
|
+
"items": { "type": "string" },
|
|
16
|
+
"description": "Path prefixes to migrate, relative to the workspace root (e.g. 'apps/web'). Unioned with `projects`. Defaults to the whole workspace.",
|
|
17
|
+
"alias": "includePath"
|
|
18
|
+
},
|
|
7
19
|
"skipFormat": {
|
|
8
20
|
"type": "boolean",
|
|
9
21
|
"description": "Skip formatting files after migration",
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import * as ts from 'typescript';
|
|
2
|
+
import { applyReplacements } from './apply-replacements.js';
|
|
3
|
+
export function getServiceImport(sourceFile, importedName) {
|
|
4
|
+
for (const statement of sourceFile.statements) {
|
|
5
|
+
if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier))
|
|
6
|
+
continue;
|
|
7
|
+
const bindings = statement.importClause?.namedBindings;
|
|
8
|
+
if (!bindings || !ts.isNamedImports(bindings))
|
|
9
|
+
continue;
|
|
10
|
+
const element = bindings.elements.find((el) => (el.propertyName?.text ?? el.name.text) === importedName);
|
|
11
|
+
if (element)
|
|
12
|
+
return { localName: element.name.text, packageName: statement.moduleSpecifier.text };
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
export function collectClasses(sourceFile) {
|
|
17
|
+
const classes = [];
|
|
18
|
+
const visit = (node) => {
|
|
19
|
+
if (ts.isClassDeclaration(node))
|
|
20
|
+
classes.push(node);
|
|
21
|
+
ts.forEachChild(node, visit);
|
|
22
|
+
};
|
|
23
|
+
visit(sourceFile);
|
|
24
|
+
return classes;
|
|
25
|
+
}
|
|
26
|
+
export function isServiceProperty(member, serviceName) {
|
|
27
|
+
const initializer = member.initializer;
|
|
28
|
+
const injectsService = !!initializer &&
|
|
29
|
+
ts.isCallExpression(initializer) &&
|
|
30
|
+
ts.isIdentifier(initializer.expression) &&
|
|
31
|
+
initializer.expression.text === 'inject' &&
|
|
32
|
+
!!initializer.arguments[0] &&
|
|
33
|
+
ts.isIdentifier(initializer.arguments[0]) &&
|
|
34
|
+
initializer.arguments[0].text === serviceName;
|
|
35
|
+
return injectsService || isServiceType(member.type, serviceName);
|
|
36
|
+
}
|
|
37
|
+
export function isServiceParameter(param, serviceName) {
|
|
38
|
+
return ts.isIdentifier(param.name) && isServiceType(param.type, serviceName);
|
|
39
|
+
}
|
|
40
|
+
export function findServiceClasses(sourceFile, serviceName) {
|
|
41
|
+
return collectClasses(sourceFile).flatMap((classNode, index) => {
|
|
42
|
+
const fields = classNode.members.flatMap((member) => {
|
|
43
|
+
if (ts.isPropertyDeclaration(member) && ts.isIdentifier(member.name) && isServiceProperty(member, serviceName)) {
|
|
44
|
+
return [member.name.text];
|
|
45
|
+
}
|
|
46
|
+
if (ts.isConstructorDeclaration(member)) {
|
|
47
|
+
return member.parameters
|
|
48
|
+
.filter((param) => isServiceParameter(param, serviceName))
|
|
49
|
+
.map((param) => param.name.text);
|
|
50
|
+
}
|
|
51
|
+
return [];
|
|
52
|
+
});
|
|
53
|
+
return fields.length > 0 ? [{ index, fields }] : [];
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
export function applyReplacementsInClass(content, sourceFile, classNode, replacements) {
|
|
57
|
+
const start = classNode.getStart(sourceFile);
|
|
58
|
+
const end = classNode.getEnd();
|
|
59
|
+
return content.slice(0, start) + applyReplacements(content.slice(start, end), replacements) + content.slice(end);
|
|
60
|
+
}
|
|
61
|
+
export function removeServiceImport(sourceFile, content, importedName) {
|
|
62
|
+
for (const statement of sourceFile.statements) {
|
|
63
|
+
if (!ts.isImportDeclaration(statement))
|
|
64
|
+
continue;
|
|
65
|
+
const bindings = statement.importClause?.namedBindings;
|
|
66
|
+
if (!bindings || !ts.isNamedImports(bindings))
|
|
67
|
+
continue;
|
|
68
|
+
const elements = bindings.elements;
|
|
69
|
+
const index = elements.findIndex((el) => (el.propertyName?.text ?? el.name.text) === importedName);
|
|
70
|
+
if (index === -1)
|
|
71
|
+
continue;
|
|
72
|
+
if (elements.length === 1) {
|
|
73
|
+
const defaultImport = statement.importClause.name;
|
|
74
|
+
if (defaultImport)
|
|
75
|
+
return content.slice(0, defaultImport.getEnd()) + content.slice(bindings.getEnd());
|
|
76
|
+
let lineEnd = statement.getEnd();
|
|
77
|
+
while (lineEnd < content.length && content[lineEnd] !== '\n')
|
|
78
|
+
lineEnd++;
|
|
79
|
+
if (content[lineEnd] === '\n')
|
|
80
|
+
lineEnd++;
|
|
81
|
+
return content.slice(0, statement.getStart(sourceFile)) + content.slice(lineEnd);
|
|
82
|
+
}
|
|
83
|
+
const element = elements[index];
|
|
84
|
+
const next = elements[index + 1];
|
|
85
|
+
const previous = elements[index - 1];
|
|
86
|
+
const [start, end] = next
|
|
87
|
+
? [element.getStart(sourceFile), next.getStart(sourceFile)]
|
|
88
|
+
: [previous.getEnd(), element.getEnd()];
|
|
89
|
+
return content.slice(0, start) + content.slice(end);
|
|
90
|
+
}
|
|
91
|
+
return content;
|
|
92
|
+
}
|
|
93
|
+
function isServiceType(type, serviceName) {
|
|
94
|
+
return !!type && ts.isTypeReferenceNode(type) && ts.isIdentifier(type.typeName) && type.typeName.text === serviceName;
|
|
95
|
+
}
|
|
96
|
+
export function isServiceStillUsed(sourceFile, serviceName, serviceClasses) {
|
|
97
|
+
const classes = collectClasses(sourceFile);
|
|
98
|
+
const referencesField = serviceClasses.some(({ index, fields }) => containsIdentifier(classes[index], fields));
|
|
99
|
+
const referencesService = sourceFile.statements.some((statement) => !ts.isImportDeclaration(statement) && containsIdentifier(statement, [serviceName]));
|
|
100
|
+
return referencesField || referencesService;
|
|
101
|
+
}
|
|
102
|
+
function containsIdentifier(node, names) {
|
|
103
|
+
if (!node)
|
|
104
|
+
return false;
|
|
105
|
+
if (ts.isIdentifier(node) && names.includes(node.text))
|
|
106
|
+
return true;
|
|
107
|
+
return !!ts.forEachChild(node, (child) => containsIdentifier(child, names) || undefined);
|
|
108
|
+
}
|