uql-codemod 0.42.0 → 0.44.0
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/dist/transform.js +53 -16
- package/package.json +1 -1
package/dist/transform.js
CHANGED
|
@@ -29,6 +29,7 @@ const REMOVED_EXPORTS = new Map([
|
|
|
29
29
|
],
|
|
30
30
|
['getQuerierPool', 'take the pool from the module that builds it, or from Nest DI'],
|
|
31
31
|
['getQuerier', 'use `pool.withQuerier(...)` / `pool.transaction(...)`, which release the connection'],
|
|
32
|
+
['ClientQuerierPool', "construct the `HttpQuerier` where it is used, `new HttpQuerier('/api')`"],
|
|
32
33
|
['QueryWhereFieldMap', 'use `QueryWhere`'],
|
|
33
34
|
['QueryStreamProjected', 'use `QueryProjected`'],
|
|
34
35
|
['RelationMappedBy', "a 'mappedBy' is `(keys: KeyMap<E>) => Key<E>` now"],
|
|
@@ -446,6 +447,37 @@ const BUILDER_INDEX_METHODS = new Map([
|
|
|
446
447
|
['addIndex', 1],
|
|
447
448
|
['createIndex', 2],
|
|
448
449
|
]);
|
|
450
|
+
/** The migration builder's `expr` helpers whose value an entity imports under the same name. */
|
|
451
|
+
const EXPR_VALUES = new Set(['currentDate', 'currentTime', 'uuid', 'uuidv7']);
|
|
452
|
+
/**
|
|
453
|
+
* Rewrites the migration builder's `expr.<helper>()` default as the value or `raw` an entity declares, or reports
|
|
454
|
+
* one with no rewrite. Called only where the file imports `expr` from uql, so a variable of its own is left alone.
|
|
455
|
+
*/
|
|
456
|
+
function rewriteExprCall(call, ctx) {
|
|
457
|
+
const callee = call.expression;
|
|
458
|
+
if (!ts.isPropertyAccessExpression(callee) ||
|
|
459
|
+
!ts.isIdentifier(callee.expression) ||
|
|
460
|
+
callee.expression.text !== 'expr') {
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
const helper = callee.name.text;
|
|
464
|
+
// The one renamed: an entity's clock is `currentTimestamp`.
|
|
465
|
+
const value = helper === 'now' ? 'currentTimestamp' : EXPR_VALUES.has(helper) ? helper : undefined;
|
|
466
|
+
const [sql] = call.arguments;
|
|
467
|
+
if (value) {
|
|
468
|
+
ctx.edits.push(replaced(call, value));
|
|
469
|
+
ctx.imports.set(value, `the expr.${helper}()`);
|
|
470
|
+
}
|
|
471
|
+
else if (helper === 'raw' && sql && ts.isStringLiteralLike(sql)) {
|
|
472
|
+
ctx.edits.push(replaced(call, rawTag(sql.text)));
|
|
473
|
+
ctx.imports.set('raw', 'the raw`...`');
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
ctx.unresolved.push(`${ctx.describe(call)}: expr.${helper}() is gone: declare the column with m.raw(...), or use a stamp on the entity`);
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
ctx.rewritten.expr += 1;
|
|
480
|
+
}
|
|
449
481
|
/** Rewrites the `where` of the migration builder's `t.index()`, `t.unique()`, `t.addIndex()` and `m.createIndex()`. */
|
|
450
482
|
function rewriteBuilderCall(call, ctx) {
|
|
451
483
|
const at = ts.isPropertyAccessExpression(call.expression)
|
|
@@ -555,13 +587,7 @@ function unwrapRelationAlias(node, ctx) {
|
|
|
555
587
|
declared.typeName.text === 'Relation' &&
|
|
556
588
|
declared.typeArguments?.length === 1) {
|
|
557
589
|
ctx.edits.push(replaced(declared, declared.typeArguments[0].getText()));
|
|
558
|
-
ctx.
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
/** Counts `Relation<T>` wherever it appears, including the places this codemod does not rewrite. */
|
|
562
|
-
function countRelationAlias(node, ctx) {
|
|
563
|
-
if (ts.isTypeReferenceNode(node) && ts.isIdentifier(node.typeName) && node.typeName.text === 'Relation') {
|
|
564
|
-
ctx.relationAlias.seen += 1;
|
|
590
|
+
ctx.rewritten.Relation += 1;
|
|
565
591
|
}
|
|
566
592
|
}
|
|
567
593
|
/** Removes a statement together with the rest of its line, so nothing is left blank behind it. */
|
|
@@ -572,17 +598,25 @@ function removeStatement(node) {
|
|
|
572
598
|
return { start: node.getStart(), end: nextLineStart ?? node.getEnd(), text: '' };
|
|
573
599
|
}
|
|
574
600
|
/**
|
|
575
|
-
* Names `uql-orm` no longer exports and that the codemod does remove:
|
|
576
|
-
* every
|
|
601
|
+
* Names `uql-orm` no longer exports and that the codemod does remove: `Relation` once every usage was
|
|
602
|
+
* unwrapped, and `expr` once every default was rewritten. A removed *decorator* keeps its import on purpose (see
|
|
577
603
|
* {@link REMOVED_DECORATORS}).
|
|
578
604
|
*/
|
|
579
605
|
function deadImportNames(source, ctx) {
|
|
580
|
-
const
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
606
|
+
const imported = uqlImports(source, true);
|
|
607
|
+
// Every use of the name the file imports, the places no rewrite reaches included.
|
|
608
|
+
const uses = (name) => {
|
|
609
|
+
const element = imported.find((specifier) => importedName(specifier) === name);
|
|
610
|
+
return element ? usesOf(source, element.name, ctx.checker).length : 0;
|
|
611
|
+
};
|
|
612
|
+
const { rewritten } = ctx;
|
|
613
|
+
const relations = uses('Relation');
|
|
614
|
+
if (relations > rewritten.Relation) {
|
|
615
|
+
ctx.unresolved.push(`${source.fileName}: ${relations - rewritten.Relation} 'Relation<T>' reference(s) are somewhere this codemod ` +
|
|
616
|
+
'does not rewrite; unwrap them and drop the import by hand');
|
|
584
617
|
}
|
|
585
|
-
|
|
618
|
+
const names = ['Relation', 'expr'];
|
|
619
|
+
return new Set(names.filter((name) => rewritten[name] > 0 && rewritten[name] === uses(name)));
|
|
586
620
|
}
|
|
587
621
|
/**
|
|
588
622
|
* Removes `import 'reflect-metadata'`, since the polyfill only ever fed `design:type`, and each `dead` name
|
|
@@ -1036,16 +1070,16 @@ export function transformFile(source, checker) {
|
|
|
1036
1070
|
unresolved: [],
|
|
1037
1071
|
notes: [],
|
|
1038
1072
|
imports: new Map(),
|
|
1039
|
-
|
|
1073
|
+
rewritten: { Relation: 0, expr: 0 },
|
|
1040
1074
|
describe: (node) => `${source.fileName}:${lineOf(node) + 1}`,
|
|
1041
1075
|
};
|
|
1042
1076
|
const lineOf = (node) => source.getLineAndCharacterOfPosition(node.getStart()).line;
|
|
1043
1077
|
const rewritesRaw = uqlImports(source).some((element) => importedName(element) === 'raw');
|
|
1044
1078
|
// The builder's methods are known by name alone, so they are read only in a file that imports uql-orm.
|
|
1045
1079
|
const importsUql = uqlImportDeclarations(source, true).length > 0;
|
|
1080
|
+
const importsExpr = uqlImports(source, true).some((element) => importedName(element) === 'expr');
|
|
1046
1081
|
const visit = (node) => {
|
|
1047
1082
|
reportRemovedDecorators(node, ctx);
|
|
1048
|
-
countRelationAlias(node, ctx);
|
|
1049
1083
|
if (rewritesRaw) {
|
|
1050
1084
|
rewriteRawCall(node, ctx, source);
|
|
1051
1085
|
}
|
|
@@ -1061,6 +1095,9 @@ export function transformFile(source, checker) {
|
|
|
1061
1095
|
if (importsUql) {
|
|
1062
1096
|
rewriteBuilderCall(node, ctx);
|
|
1063
1097
|
}
|
|
1098
|
+
if (importsExpr) {
|
|
1099
|
+
rewriteExprCall(node, ctx);
|
|
1100
|
+
}
|
|
1064
1101
|
}
|
|
1065
1102
|
if (ts.isPropertyAssignment(node)) {
|
|
1066
1103
|
rewriteStatementKeys(node, ctx);
|