@ethlete/core 5.0.0-next.60 ā 5.0.0-next.61
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 +28 -0
- package/fesm2022/ethlete-core.mjs +269 -203
- package/fesm2022/ethlete-core.mjs.map +1 -1
- 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 +7 -27
- 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/package.json +1 -1
- package/types/ethlete-core.d.ts +41 -34
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const IDENTIFIER_CHAR = /[\w$]/;
|
|
2
|
+
export function applyReplacements(content, replacements) {
|
|
3
|
+
return [...replacements]
|
|
4
|
+
.sort(([a], [b]) => b.length - a.length)
|
|
5
|
+
.reduce((result, [original, replacement]) => result.replace(snippetPattern(original), () => replacement), content);
|
|
6
|
+
}
|
|
7
|
+
function snippetPattern(snippet) {
|
|
8
|
+
const start = IDENTIFIER_CHAR.test(snippet.charAt(0)) ? '(?<![\\w$])' : '';
|
|
9
|
+
const end = IDENTIFIER_CHAR.test(snippet.charAt(snippet.length - 1)) ? '(?![\\w$])' : '';
|
|
10
|
+
return new RegExp(`${start}${escapeRegExp(snippet)}${end}`, 'g');
|
|
11
|
+
}
|
|
12
|
+
function escapeRegExp(value) {
|
|
13
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
14
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { collectFiles } from './migration-files.js';
|
|
2
2
|
/**
|
|
3
3
|
* Symbol renames in TypeScript files (imports + usage).
|
|
4
4
|
*/
|
|
@@ -45,71 +45,25 @@ const HOST_DIRECTIVE_REPLACEMENTS = [
|
|
|
45
45
|
["'etProvideTheme: theme'", "'etProvideColor: color'"],
|
|
46
46
|
['"etProvideTheme: theme"', '"etProvideColor: color"'],
|
|
47
47
|
];
|
|
48
|
-
export default async function migrateColorNaming(tree) {
|
|
49
|
-
logger.log('\nš Migrating theme ā color naming...\n');
|
|
50
|
-
const tsFiles = [];
|
|
51
|
-
const htmlFiles = [];
|
|
52
|
-
const cssFiles = [];
|
|
53
|
-
findFiles('.', tree, tsFiles, htmlFiles, cssFiles);
|
|
48
|
+
export default async function migrateColorNaming(tree, scope) {
|
|
54
49
|
let filesModified = 0;
|
|
55
|
-
for (const filePath of
|
|
56
|
-
const wasModified =
|
|
57
|
-
|
|
50
|
+
for (const filePath of collectFiles(tree, scope, ['.ts', '.html', '.css', '.scss'])) {
|
|
51
|
+
const wasModified = filePath.endsWith('.ts')
|
|
52
|
+
? migrateTypeScriptFile(tree, filePath)
|
|
53
|
+
: filePath.endsWith('.html')
|
|
54
|
+
? migrateTemplateFile(tree, filePath)
|
|
55
|
+
: migrateCssFile(tree, filePath);
|
|
56
|
+
if (wasModified)
|
|
58
57
|
filesModified++;
|
|
59
|
-
logger.log(` ā ${filePath}`);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
for (const filePath of htmlFiles) {
|
|
63
|
-
const wasModified = migrateTemplateFile(tree, filePath);
|
|
64
|
-
if (wasModified) {
|
|
65
|
-
filesModified++;
|
|
66
|
-
logger.log(` ā ${filePath}`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
for (const filePath of cssFiles) {
|
|
70
|
-
const wasModified = migrateCssFile(tree, filePath);
|
|
71
|
-
if (wasModified) {
|
|
72
|
-
filesModified++;
|
|
73
|
-
logger.log(` ā ${filePath}`);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
if (filesModified > 0) {
|
|
77
|
-
logger.log(`\nā
Successfully migrated color naming in ${filesModified} file(s)\n`);
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
logger.log('\nā¹ļø No files needed migration\n');
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
function findFiles(dir, tree, tsFiles, htmlFiles, cssFiles) {
|
|
84
|
-
const children = tree.children(dir);
|
|
85
|
-
for (const child of children) {
|
|
86
|
-
const path = dir === '.' ? child : `${dir}/${child}`;
|
|
87
|
-
if (tree.isFile(path)) {
|
|
88
|
-
if (path.includes('node_modules'))
|
|
89
|
-
continue;
|
|
90
|
-
if (path.endsWith('.ts')) {
|
|
91
|
-
tsFiles.push(path);
|
|
92
|
-
}
|
|
93
|
-
else if (path.endsWith('.html')) {
|
|
94
|
-
htmlFiles.push(path);
|
|
95
|
-
}
|
|
96
|
-
else if (path.endsWith('.css') || path.endsWith('.scss')) {
|
|
97
|
-
cssFiles.push(path);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
if (child === 'node_modules')
|
|
102
|
-
continue;
|
|
103
|
-
findFiles(path, tree, tsFiles, htmlFiles, cssFiles);
|
|
104
|
-
}
|
|
105
58
|
}
|
|
59
|
+
return { filesChanged: filesModified, review: [] };
|
|
106
60
|
}
|
|
107
61
|
function migrateTypeScriptFile(tree, filePath) {
|
|
108
62
|
let content = tree.read(filePath, 'utf-8');
|
|
109
63
|
if (!content)
|
|
110
64
|
return false;
|
|
111
65
|
const original = content;
|
|
112
|
-
if (!/from\s+['"]@ethlete\/(?:core|cdk)['"]/.test(content))
|
|
66
|
+
if (!/from\s+['"]@ethlete\/(?:core|cdk|theming)['"]/.test(content))
|
|
113
67
|
return false;
|
|
114
68
|
// Rename symbols
|
|
115
69
|
for (const [oldName, newName] of Object.entries(TS_SYMBOL_RENAMES)) {
|
|
@@ -1,40 +1,65 @@
|
|
|
1
|
-
import { logger } from '@nx/devkit';
|
|
2
1
|
import * as ts from 'typescript';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
// Recursively find all TypeScript files
|
|
7
|
-
function findTsFiles(dir) {
|
|
8
|
-
const children = tree.children(dir);
|
|
9
|
-
for (const child of children) {
|
|
10
|
-
const path = dir === '.' ? child : `${dir}/${child}`;
|
|
11
|
-
if (tree.isFile(path)) {
|
|
12
|
-
if (path.endsWith('.ts') && !path.includes('node_modules')) {
|
|
13
|
-
tsFiles.push(path);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
if (child === 'node_modules')
|
|
18
|
-
continue;
|
|
19
|
-
findTsFiles(path);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
findTsFiles('.');
|
|
2
|
+
import { collectFiles } from './migration-files.js';
|
|
3
|
+
export default async function migrateCreateProvider(tree, scope) {
|
|
4
|
+
const review = [];
|
|
24
5
|
let filesModified = 0;
|
|
25
|
-
for (const filePath of
|
|
26
|
-
const
|
|
27
|
-
|
|
6
|
+
for (const filePath of collectFiles(tree, scope, ['.ts'])) {
|
|
7
|
+
const reexportsModified = migrateCreateProviderReexports(tree, filePath, review);
|
|
8
|
+
const wasModified = migrateCreateProviderInFile(tree, filePath) || reexportsModified;
|
|
9
|
+
if (wasModified)
|
|
28
10
|
filesModified++;
|
|
29
|
-
logger.log(` ā ${filePath}`);
|
|
30
|
-
}
|
|
31
11
|
}
|
|
32
|
-
|
|
33
|
-
|
|
12
|
+
return { filesChanged: filesModified, review };
|
|
13
|
+
}
|
|
14
|
+
function migrateCreateProviderReexports(tree, filePath, review) {
|
|
15
|
+
const content = tree.read(filePath, 'utf-8');
|
|
16
|
+
if (!content || !content.includes('createProvider'))
|
|
17
|
+
return false;
|
|
18
|
+
const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
|
|
19
|
+
const edits = [];
|
|
20
|
+
for (const statement of sourceFile.statements) {
|
|
21
|
+
if (!ts.isImportDeclaration(statement) && !ts.isExportDeclaration(statement))
|
|
22
|
+
continue;
|
|
23
|
+
if (!statement.moduleSpecifier || !ts.isStringLiteral(statement.moduleSpecifier))
|
|
24
|
+
continue;
|
|
25
|
+
if (statement.moduleSpecifier.text !== '@ethlete/cdk')
|
|
26
|
+
continue;
|
|
27
|
+
if (ts.isImportDeclaration(statement)) {
|
|
28
|
+
const bindings = statement.importClause?.namedBindings;
|
|
29
|
+
if (bindings && ts.isNamespaceImport(bindings) && content.includes(`${bindings.name.text}.createProvider`)) {
|
|
30
|
+
review.push(`${filePath}: ${bindings.name.text}.createProvider is used through a namespace import of @ethlete/cdk. Switch it to createProvider from @ethlete/core manually.`);
|
|
31
|
+
}
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const clause = statement.exportClause;
|
|
35
|
+
if (!clause) {
|
|
36
|
+
review.push(`${filePath}: "export * from '@ethlete/cdk'" may re-export createProvider. Re-export it from @ethlete/core manually.`);
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (ts.isNamespaceExport(clause))
|
|
40
|
+
continue;
|
|
41
|
+
const isCreateProvider = (element) => (element.propertyName?.text ?? element.name.text) === 'createProvider';
|
|
42
|
+
const moved = clause.elements.filter(isCreateProvider);
|
|
43
|
+
if (moved.length === 0)
|
|
44
|
+
continue;
|
|
45
|
+
const rest = clause.elements.filter((element) => !isCreateProvider(element));
|
|
46
|
+
const typeOnly = statement.isTypeOnly ? 'type ' : '';
|
|
47
|
+
const lines = [
|
|
48
|
+
...(rest.length > 0
|
|
49
|
+
? [`export ${typeOnly}{ ${rest.map((el) => el.getText(sourceFile)).join(', ')} } from '@ethlete/cdk';`]
|
|
50
|
+
: []),
|
|
51
|
+
`export ${typeOnly}{ ${moved.map((el) => el.getText(sourceFile)).join(', ')} } from '@ethlete/core';`,
|
|
52
|
+
];
|
|
53
|
+
edits.push({ start: statement.getStart(sourceFile), end: statement.getEnd(), text: lines.join('\n') });
|
|
34
54
|
}
|
|
35
|
-
|
|
36
|
-
|
|
55
|
+
if (edits.length === 0)
|
|
56
|
+
return false;
|
|
57
|
+
let updatedContent = content;
|
|
58
|
+
for (const edit of edits.reverse()) {
|
|
59
|
+
updatedContent = updatedContent.slice(0, edit.start) + edit.text + updatedContent.slice(edit.end);
|
|
37
60
|
}
|
|
61
|
+
tree.write(filePath, updatedContent);
|
|
62
|
+
return true;
|
|
38
63
|
}
|
|
39
64
|
function migrateCreateProviderInFile(tree, filePath) {
|
|
40
65
|
const content = tree.read(filePath, 'utf-8');
|
|
@@ -44,7 +69,6 @@ function migrateCreateProviderInFile(tree, filePath) {
|
|
|
44
69
|
let cdkImport;
|
|
45
70
|
let hasCreateProviderInCdk = false;
|
|
46
71
|
let createProviderImport = 'createProvider';
|
|
47
|
-
// Find relevant imports
|
|
48
72
|
for (const statement of sourceFile.statements) {
|
|
49
73
|
if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier)) {
|
|
50
74
|
const modulePath = statement.moduleSpecifier.text;
|
|
@@ -58,18 +82,15 @@ function migrateCreateProviderInFile(tree, filePath) {
|
|
|
58
82
|
}
|
|
59
83
|
}
|
|
60
84
|
}
|
|
61
|
-
// If createProvider is not imported from @ethlete/cdk, nothing to do
|
|
62
85
|
if (!hasCreateProviderInCdk)
|
|
63
86
|
return false;
|
|
64
87
|
let updatedContent = content;
|
|
65
|
-
// Remove createProvider from @ethlete/cdk import
|
|
66
88
|
if (cdkImport && cdkImport.importClause?.namedBindings && ts.isNamedImports(cdkImport.importClause.namedBindings)) {
|
|
67
89
|
const namedBindings = cdkImport.importClause.namedBindings;
|
|
68
90
|
const otherImports = namedBindings.elements.filter((element) => (element.propertyName?.text ?? element.name.text) !== 'createProvider');
|
|
69
91
|
const importStart = cdkImport.getStart(sourceFile);
|
|
70
92
|
const importEnd = cdkImport.getEnd();
|
|
71
93
|
if (otherImports.length === 0) {
|
|
72
|
-
// Remove entire import line including newline
|
|
73
94
|
let lineStart = importStart;
|
|
74
95
|
while (lineStart > 0 && content[lineStart - 1] !== '\n') {
|
|
75
96
|
lineStart--;
|
|
@@ -84,15 +105,12 @@ function migrateCreateProviderInFile(tree, filePath) {
|
|
|
84
105
|
updatedContent = content.slice(0, lineStart) + content.slice(lineEnd);
|
|
85
106
|
}
|
|
86
107
|
else {
|
|
87
|
-
// Keep other imports
|
|
88
108
|
const newImports = otherImports.map((el) => el.getText(sourceFile)).join(', ');
|
|
89
109
|
const newImportText = `import { ${newImports} } from '@ethlete/cdk';`;
|
|
90
110
|
updatedContent = content.slice(0, importStart) + newImportText + content.slice(importEnd);
|
|
91
111
|
}
|
|
92
112
|
}
|
|
93
|
-
// Re-parse after first modification
|
|
94
113
|
const intermediateSourceFile = ts.createSourceFile(filePath, updatedContent, ts.ScriptTarget.Latest, true);
|
|
95
|
-
// Find @ethlete/core import in the updated content
|
|
96
114
|
let updatedCoreImport;
|
|
97
115
|
for (const statement of intermediateSourceFile.statements) {
|
|
98
116
|
if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier)) {
|
|
@@ -102,11 +120,9 @@ function migrateCreateProviderInFile(tree, filePath) {
|
|
|
102
120
|
}
|
|
103
121
|
}
|
|
104
122
|
}
|
|
105
|
-
// Add createProvider to @ethlete/core import
|
|
106
123
|
if (updatedCoreImport?.importClause?.namedBindings &&
|
|
107
124
|
ts.isNamedImports(updatedCoreImport.importClause.namedBindings)) {
|
|
108
125
|
const namedBindings = updatedCoreImport.importClause.namedBindings;
|
|
109
|
-
// Check if createProvider already exists
|
|
110
126
|
const hasCreateProvider = namedBindings.elements.some((element) => (element.propertyName?.text ?? element.name.text) === 'createProvider');
|
|
111
127
|
if (!hasCreateProvider) {
|
|
112
128
|
const importStart = updatedCoreImport.getStart(intermediateSourceFile);
|
|
@@ -118,10 +134,8 @@ function migrateCreateProviderInFile(tree, filePath) {
|
|
|
118
134
|
}
|
|
119
135
|
}
|
|
120
136
|
else {
|
|
121
|
-
// Add new import from @ethlete/core at the top
|
|
122
137
|
const firstImportIndex = updatedContent.indexOf('import');
|
|
123
138
|
if (firstImportIndex !== -1) {
|
|
124
|
-
// Add after other imports
|
|
125
139
|
let insertPosition;
|
|
126
140
|
let lastImportEnd = firstImportIndex;
|
|
127
141
|
for (const statement of intermediateSourceFile.statements) {
|
|
@@ -133,7 +147,6 @@ function migrateCreateProviderInFile(tree, filePath) {
|
|
|
133
147
|
}
|
|
134
148
|
}
|
|
135
149
|
insertPosition = lastImportEnd;
|
|
136
|
-
// Find end of line
|
|
137
150
|
while (insertPosition < updatedContent.length && updatedContent[insertPosition] !== '\n') {
|
|
138
151
|
insertPosition++;
|
|
139
152
|
}
|
|
@@ -146,7 +159,6 @@ function migrateCreateProviderInFile(tree, filePath) {
|
|
|
146
159
|
updatedContent.slice(insertPosition);
|
|
147
160
|
}
|
|
148
161
|
else {
|
|
149
|
-
// No imports, add at the beginning
|
|
150
162
|
updatedContent = `import { ${createProviderImport} } from '@ethlete/core';\n\n` + updatedContent;
|
|
151
163
|
}
|
|
152
164
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createMigrationScope } from '../migrate-provider-shape/migration-scope.js';
|
|
2
|
+
const SKIPPED_DIRECTORIES = new Set(['node_modules', 'dist', '.git', '.angular', '.nx']);
|
|
3
|
+
export const collectFiles = (tree, scope, extensions) => {
|
|
4
|
+
const files = [];
|
|
5
|
+
(scope ?? createMigrationScope(tree, {})).visit(tree, (filePath) => {
|
|
6
|
+
if (filePath.split('/').some((segment) => SKIPPED_DIRECTORIES.has(segment)))
|
|
7
|
+
return;
|
|
8
|
+
if (!extensions.some((extension) => filePath.endsWith(extension)))
|
|
9
|
+
return;
|
|
10
|
+
files.push(filePath);
|
|
11
|
+
});
|
|
12
|
+
return files;
|
|
13
|
+
};
|
|
@@ -1,38 +1,42 @@
|
|
|
1
|
-
import { formatFiles } from '@nx/devkit';
|
|
1
|
+
import { formatFiles, logger } from '@nx/devkit';
|
|
2
|
+
import { createMigrationScope, } from '../migrate-provider-shape/migration-scope.js';
|
|
2
3
|
import migrateColorNaming from './color-naming.js';
|
|
3
4
|
import migrateCreateProvider from './create-provider.js';
|
|
4
5
|
import reportRemovedExports from './removed-exports.js';
|
|
5
6
|
import migrateRouterStateService from './router-state-service.js';
|
|
6
7
|
import migrateViewportService from './viewport-service.js';
|
|
7
8
|
export default async function migrate(tree, schema) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (schema.reportRemovedExports !== false) {
|
|
29
|
-
console.log(' ⢠Reporting removed exports...');
|
|
30
|
-
await reportRemovedExports(tree);
|
|
9
|
+
const scope = createMigrationScope(tree, schema);
|
|
10
|
+
logger.info('\nš Starting core v5 migration...');
|
|
11
|
+
logger.info(` Scope: ${scope.describe()}`);
|
|
12
|
+
const transforms = [
|
|
13
|
+
{ label: 'ViewportService', enabled: schema.migrateViewportService !== false, run: migrateViewportService },
|
|
14
|
+
{ label: 'createProvider', enabled: schema.migrateCreateProvider !== false, run: migrateCreateProvider },
|
|
15
|
+
{
|
|
16
|
+
label: 'RouterStateService',
|
|
17
|
+
enabled: schema.migrateRouterStateService !== false,
|
|
18
|
+
run: migrateRouterStateService,
|
|
19
|
+
},
|
|
20
|
+
{ label: 'Theme ā color naming', enabled: schema.migrateColorNaming !== false, run: migrateColorNaming },
|
|
21
|
+
{ label: 'Removed exports', enabled: schema.reportRemovedExports !== false, run: reportRemovedExports },
|
|
22
|
+
];
|
|
23
|
+
const reports = [];
|
|
24
|
+
for (const transform of transforms) {
|
|
25
|
+
if (!transform.enabled)
|
|
26
|
+
continue;
|
|
27
|
+
logger.info(` ⢠${transform.label}...`);
|
|
28
|
+
reports.push([transform.label, await transform.run(tree, scope)]);
|
|
31
29
|
}
|
|
32
30
|
if (!schema.skipFormat) {
|
|
33
|
-
console.log(' ⢠Formatting files...');
|
|
34
31
|
await formatFiles(tree);
|
|
35
32
|
}
|
|
36
|
-
|
|
33
|
+
logger.info('\nSummary:');
|
|
34
|
+
for (const [label, report] of reports) {
|
|
35
|
+
const review = report.review.length > 0 ? `, ${report.review.length} to review manually` : '';
|
|
36
|
+
logger.info(` ⢠${label}: ${report.filesChanged} file(s) changed${review}`);
|
|
37
|
+
for (const message of report.review) {
|
|
38
|
+
logger.warn(` ā ${message}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
logger.info('\nā
Migration completed. Review the diff before committing.');
|
|
37
42
|
}
|
|
38
|
-
//#endregion
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
|
+
import { collectFiles } from './migration-files.js';
|
|
2
3
|
const REMOVED_EXPORTS = new Map([
|
|
3
4
|
...['Memo', 'MemoConfig', 'MemoResolver', 'MapLike'].map((name) => [name, 'the @Memo decorator']),
|
|
4
5
|
...[
|
|
@@ -31,34 +32,13 @@ const REMOVED_EXPORTS = new Map([
|
|
|
31
32
|
].map((name) => [name, 'the props module']),
|
|
32
33
|
]);
|
|
33
34
|
const ET_PROPS_ATTRIBUTE = /\betProps\b/;
|
|
34
|
-
export default async function reportRemovedExports(tree) {
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
continue;
|
|
40
|
-
const path = dir === '.' ? child : `${dir}/${child}`;
|
|
41
|
-
if (!tree.isFile(path)) {
|
|
42
|
-
walkFiles(path);
|
|
43
|
-
continue;
|
|
44
|
-
}
|
|
45
|
-
const messages = path.endsWith('.ts')
|
|
46
|
-
? findRemovedImports(tree, path)
|
|
47
|
-
: path.endsWith('.html')
|
|
48
|
-
? findEtPropsUsage(tree, path)
|
|
49
|
-
: [];
|
|
50
|
-
if (messages.length > 0)
|
|
51
|
-
findings.set(path, messages);
|
|
52
|
-
}
|
|
35
|
+
export default async function reportRemovedExports(tree, scope) {
|
|
36
|
+
const review = [];
|
|
37
|
+
for (const filePath of collectFiles(tree, scope, ['.ts', '.html'])) {
|
|
38
|
+
const messages = filePath.endsWith('.ts') ? findRemovedImports(tree, filePath) : findEtPropsUsage(tree, filePath);
|
|
39
|
+
review.push(...messages.map((message) => `${filePath}: ${message}`));
|
|
53
40
|
}
|
|
54
|
-
|
|
55
|
-
if (findings.size === 0)
|
|
56
|
-
return;
|
|
57
|
-
console.log('\nā ļø Manual migration required for the following files:');
|
|
58
|
-
findings.forEach((messages, file) => {
|
|
59
|
-
console.log(`\nš ${file}:`);
|
|
60
|
-
messages.forEach((message) => console.log(` - ${message}`));
|
|
61
|
-
});
|
|
41
|
+
return { filesChanged: 0, review };
|
|
62
42
|
}
|
|
63
43
|
function findRemovedImports(tree, filePath) {
|
|
64
44
|
const content = tree.read(filePath, 'utf-8');
|