@ethlete/query 6.0.0-next.3 → 6.0.0-next.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 +12 -0
- package/fesm2022/ethlete-query.mjs +38 -5
- package/fesm2022/ethlete-query.mjs.map +1 -1
- package/generators/migrate-to-query-v3/cleanup-migration.js +242 -0
- package/generators/migrate-to-query-v3/legacy-prepare-migration.js +773 -0
- package/generators/migrate-to-query-v3/legacy-query-creator-migration.js +589 -0
- package/generators/migrate-to-query-v3/migration.js +16 -2928
- package/generators/migrate-to-query-v3/query-client-migration.js +477 -0
- package/generators/migrate-to-query-v3/report.js +136 -0
- package/generators/migrate-to-query-v3/shared.js +97 -0
- package/package.json +1 -1
- package/types/ethlete-query.d.ts +26 -1
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { visitNotIgnoredFiles } from '@nx/devkit';
|
|
2
|
+
import * as ts from 'typescript';
|
|
3
|
+
import { createSourceFile, getLineNumberFromPosition } from './shared.js';
|
|
4
|
+
export const removeDevtoolsUsage = (tree) => {
|
|
5
|
+
const updatedFiles = [];
|
|
6
|
+
visitNotIgnoredFiles(tree, '', (filePath) => {
|
|
7
|
+
if (!filePath.endsWith('.ts') && !filePath.endsWith('.html')) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
const content = tree.read(filePath, 'utf-8');
|
|
11
|
+
if (!content) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (filePath.endsWith('.ts')) {
|
|
15
|
+
if (!content.includes('provideQueryClientForDevtools') && !content.includes('QueryDevtoolsComponent')) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const withoutProviders = removeProvideQueryClientForDevtools(content);
|
|
19
|
+
const nextContent = removeQueryDevtoolsComponent(withoutProviders);
|
|
20
|
+
if (nextContent !== content) {
|
|
21
|
+
tree.write(filePath, nextContent);
|
|
22
|
+
updatedFiles.push(filePath);
|
|
23
|
+
}
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (!content.includes('et-query-devtools')) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const nextContent = removeDevtoolsFromHtml(content);
|
|
30
|
+
if (nextContent !== content) {
|
|
31
|
+
tree.write(filePath, nextContent);
|
|
32
|
+
updatedFiles.push(filePath);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
if (updatedFiles.length > 0) {
|
|
36
|
+
console.log('\n✅ Removed legacy query devtools usage in:');
|
|
37
|
+
updatedFiles.forEach((filePath) => console.log(` - ${filePath}`));
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
export const replaceAnyQueryWithLegacy = (tree) => {
|
|
41
|
+
const updatedFiles = [];
|
|
42
|
+
visitNotIgnoredFiles(tree, '', (filePath) => {
|
|
43
|
+
if (!filePath.endsWith('.ts') || filePath.endsWith('.spec.ts')) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const content = tree.read(filePath, 'utf-8');
|
|
47
|
+
if (!content) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const nextContent = replaceAnyQueryInFile(content);
|
|
51
|
+
if (nextContent !== content) {
|
|
52
|
+
tree.write(filePath, nextContent);
|
|
53
|
+
updatedFiles.push(filePath);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
if (updatedFiles.length > 0) {
|
|
57
|
+
console.log(`\n✅ Replaced legacy AnyV2Query aliases in ${updatedFiles.length} files`);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
export const migrateEmptyPrepareCalls = (tree) => {
|
|
61
|
+
const updatedFiles = [];
|
|
62
|
+
visitNotIgnoredFiles(tree, '', (filePath) => {
|
|
63
|
+
if (!filePath.endsWith('.ts') || filePath.endsWith('.spec.ts')) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const content = tree.read(filePath, 'utf-8');
|
|
67
|
+
if (!content || !content.includes('.prepare()')) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const nextContent = transformEmptyPrepareCalls(content);
|
|
71
|
+
if (nextContent !== content) {
|
|
72
|
+
tree.write(filePath, nextContent);
|
|
73
|
+
updatedFiles.push(filePath);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
if (updatedFiles.length > 0) {
|
|
77
|
+
console.log(`\n✅ Migrated empty .prepare() calls in ${updatedFiles.length} files`);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const removeProvideQueryClientForDevtools = (content) => {
|
|
81
|
+
return content
|
|
82
|
+
.replace(/,?\s*provideQueryClientForDevtools\([^)]*\)/g, '')
|
|
83
|
+
.replace(/\[\s*,/g, '[')
|
|
84
|
+
.replace(/,\s*\]/g, ']')
|
|
85
|
+
.replace(/\n\s*\n\s*\n/g, '\n\n');
|
|
86
|
+
};
|
|
87
|
+
const removeQueryDevtoolsComponent = (content) => {
|
|
88
|
+
const withoutImportsArray = removeQueryDevtoolsImportsFromMetadata(content);
|
|
89
|
+
return removeDevtoolsImports(withoutImportsArray);
|
|
90
|
+
};
|
|
91
|
+
const removeQueryDevtoolsImportsFromMetadata = (content) => {
|
|
92
|
+
const sourceFile = createSourceFile(content);
|
|
93
|
+
const replacements = [];
|
|
94
|
+
const visit = (node) => {
|
|
95
|
+
if (ts.isPropertyAssignment(node) &&
|
|
96
|
+
ts.isIdentifier(node.name) &&
|
|
97
|
+
node.name.text === 'imports' &&
|
|
98
|
+
ts.isArrayLiteralExpression(node.initializer)) {
|
|
99
|
+
const nextElements = node.initializer.elements.filter((element) => {
|
|
100
|
+
return !(ts.isIdentifier(element) && element.text === 'QueryDevtoolsComponent');
|
|
101
|
+
});
|
|
102
|
+
if (nextElements.length === node.initializer.elements.length) {
|
|
103
|
+
ts.forEachChild(node, visit);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const replacement = `imports: [${nextElements.map((element) => element.getText(sourceFile)).join(', ')}]`;
|
|
107
|
+
replacements.push({
|
|
108
|
+
start: node.getStart(sourceFile),
|
|
109
|
+
end: node.getEnd(),
|
|
110
|
+
replacement,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
ts.forEachChild(node, visit);
|
|
114
|
+
};
|
|
115
|
+
visit(sourceFile);
|
|
116
|
+
let result = content;
|
|
117
|
+
replacements.sort((left, right) => right.start - left.start);
|
|
118
|
+
replacements.forEach(({ start, end, replacement }) => {
|
|
119
|
+
result = result.slice(0, start) + replacement + result.slice(end);
|
|
120
|
+
});
|
|
121
|
+
return result;
|
|
122
|
+
};
|
|
123
|
+
const removeDevtoolsImports = (content) => {
|
|
124
|
+
const sourceFile = createSourceFile(content);
|
|
125
|
+
let importNode;
|
|
126
|
+
ts.forEachChild(sourceFile, (node) => {
|
|
127
|
+
if (ts.isImportDeclaration(node) &&
|
|
128
|
+
ts.isStringLiteral(node.moduleSpecifier) &&
|
|
129
|
+
node.moduleSpecifier.text === '@ethlete/query') {
|
|
130
|
+
importNode = node;
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
if (!importNode?.importClause?.namedBindings || !ts.isNamedImports(importNode.importClause.namedBindings)) {
|
|
134
|
+
return content;
|
|
135
|
+
}
|
|
136
|
+
const nextElements = importNode.importClause.namedBindings.elements.filter((element) => {
|
|
137
|
+
return element.name.text !== 'QueryDevtoolsComponent' && element.name.text !== 'provideQueryClientForDevtools';
|
|
138
|
+
});
|
|
139
|
+
if (nextElements.length === importNode.importClause.namedBindings.elements.length) {
|
|
140
|
+
return content;
|
|
141
|
+
}
|
|
142
|
+
if (nextElements.length === 0) {
|
|
143
|
+
const nextLineEnd = content[importNode.getEnd()] === '\n' ? importNode.getEnd() + 1 : importNode.getEnd();
|
|
144
|
+
return content.slice(0, importNode.getStart(sourceFile)) + content.slice(nextLineEnd);
|
|
145
|
+
}
|
|
146
|
+
const nextImport = `import { ${nextElements.map((element) => element.getText(sourceFile)).join(', ')} } from '@ethlete/query';`;
|
|
147
|
+
return content.slice(0, importNode.getStart(sourceFile)) + nextImport + content.slice(importNode.getEnd());
|
|
148
|
+
};
|
|
149
|
+
const removeDevtoolsFromHtml = (content) => {
|
|
150
|
+
return content
|
|
151
|
+
.replace(/<et-query-devtools\s*\/>/g, '')
|
|
152
|
+
.replace(/<et-query-devtools[^>]*>[\s\S]*?<\/et-query-devtools>/g, '')
|
|
153
|
+
.replace(/\n\s*\n\s*\n/g, '\n\n');
|
|
154
|
+
};
|
|
155
|
+
const replaceAnyQueryInFile = (content) => {
|
|
156
|
+
const sourceFile = createSourceFile(content);
|
|
157
|
+
const replacements = [];
|
|
158
|
+
const visit = (node) => {
|
|
159
|
+
if (ts.isIdentifier(node)) {
|
|
160
|
+
if (node.text === 'AnyV2Query') {
|
|
161
|
+
replacements.push({
|
|
162
|
+
start: node.getStart(sourceFile),
|
|
163
|
+
end: node.getEnd(),
|
|
164
|
+
replacement: 'AnyLegacyQuery',
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
if (node.text === 'AnyV2QueryCreator') {
|
|
168
|
+
replacements.push({
|
|
169
|
+
start: node.getStart(sourceFile),
|
|
170
|
+
end: node.getEnd(),
|
|
171
|
+
replacement: 'AnyLegacyQueryCreator',
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
ts.forEachChild(node, visit);
|
|
176
|
+
};
|
|
177
|
+
visit(sourceFile);
|
|
178
|
+
let result = content;
|
|
179
|
+
replacements.sort((left, right) => right.start - left.start);
|
|
180
|
+
replacements.forEach(({ start, end, replacement }) => {
|
|
181
|
+
result = result.slice(0, start) + replacement + result.slice(end);
|
|
182
|
+
});
|
|
183
|
+
return removeAnyQueryFromImports(result);
|
|
184
|
+
};
|
|
185
|
+
const removeAnyQueryFromImports = (content) => {
|
|
186
|
+
const sourceFile = createSourceFile(content);
|
|
187
|
+
let importNode;
|
|
188
|
+
ts.forEachChild(sourceFile, (node) => {
|
|
189
|
+
if (ts.isImportDeclaration(node) &&
|
|
190
|
+
ts.isStringLiteral(node.moduleSpecifier) &&
|
|
191
|
+
node.moduleSpecifier.text === '@ethlete/query') {
|
|
192
|
+
importNode = node;
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
if (!importNode?.importClause?.namedBindings || !ts.isNamedImports(importNode.importClause.namedBindings)) {
|
|
196
|
+
return content;
|
|
197
|
+
}
|
|
198
|
+
const nextElements = importNode.importClause.namedBindings.elements.filter((element) => {
|
|
199
|
+
return element.name.text !== 'AnyV2Query' && element.name.text !== 'AnyV2QueryCreator';
|
|
200
|
+
});
|
|
201
|
+
const names = nextElements.map((element) => element.getText(sourceFile));
|
|
202
|
+
if (!names.includes('AnyLegacyQuery')) {
|
|
203
|
+
names.push('AnyLegacyQuery');
|
|
204
|
+
}
|
|
205
|
+
if (!names.includes('AnyLegacyQueryCreator')) {
|
|
206
|
+
names.push('AnyLegacyQueryCreator');
|
|
207
|
+
}
|
|
208
|
+
const nextImport = `import { ${names.sort().join(', ')} } from '@ethlete/query';`;
|
|
209
|
+
return content.slice(0, importNode.getStart(sourceFile)) + nextImport + content.slice(importNode.getEnd());
|
|
210
|
+
};
|
|
211
|
+
const transformEmptyPrepareCalls = (content) => {
|
|
212
|
+
const sourceFile = createSourceFile(content);
|
|
213
|
+
const replacements = [];
|
|
214
|
+
const visit = (node) => {
|
|
215
|
+
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression)) {
|
|
216
|
+
const propertyAccess = node.expression;
|
|
217
|
+
if (ts.isIdentifier(propertyAccess.name) &&
|
|
218
|
+
propertyAccess.name.text === 'prepare' &&
|
|
219
|
+
node.arguments.length === 0) {
|
|
220
|
+
const callText = content.slice(node.getStart(sourceFile), node.getEnd());
|
|
221
|
+
replacements.push({
|
|
222
|
+
start: node.getStart(sourceFile),
|
|
223
|
+
end: node.getEnd(),
|
|
224
|
+
replacement: callText.replace(/\.prepare\(\)/, '.prepare({})'),
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
ts.forEachChild(node, visit);
|
|
229
|
+
};
|
|
230
|
+
visit(sourceFile);
|
|
231
|
+
let result = content;
|
|
232
|
+
replacements.sort((left, right) => right.start - left.start);
|
|
233
|
+
replacements.forEach(({ start, end, replacement }) => {
|
|
234
|
+
result = result.slice(0, start) + replacement + result.slice(end);
|
|
235
|
+
});
|
|
236
|
+
return result;
|
|
237
|
+
};
|
|
238
|
+
export const describeTemplateLine = (content, position, suffix) => {
|
|
239
|
+
const lineNumber = getLineNumberFromPosition(content, position);
|
|
240
|
+
return `${lineNumber} (${suffix})`;
|
|
241
|
+
};
|
|
242
|
+
//# sourceMappingURL=cleanup-migration.js.map
|