uql-codemod 0.39.2 → 0.41.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/bin.js +0 -0
- package/dist/transform.js +68 -2
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
File without changes
|
package/dist/transform.js
CHANGED
|
@@ -23,7 +23,10 @@ const REMOVED_DECORATORS = new Map([
|
|
|
23
23
|
* same reason as the decorators: what replaces each is decided at its call site.
|
|
24
24
|
*/
|
|
25
25
|
const REMOVED_EXPORTS = new Map([
|
|
26
|
-
[
|
|
26
|
+
[
|
|
27
|
+
'setQuerierPool',
|
|
28
|
+
'pass the pool where it is used: `createFetchHandler({ pool, include })`, `querierMiddleware({ pool, include })`',
|
|
29
|
+
],
|
|
27
30
|
['getQuerierPool', 'take the pool from the module that builds it, or from Nest DI'],
|
|
28
31
|
['getQuerier', 'use `pool.withQuerier(...)` / `pool.transaction(...)`, which release the connection'],
|
|
29
32
|
['QueryWhereFieldMap', 'use `QueryWhere`'],
|
|
@@ -285,7 +288,8 @@ function foreignKeyColumn(property, column, relation, checker) {
|
|
|
285
288
|
}
|
|
286
289
|
const indent = ' '.repeat(property.getSourceFile().getLineAndCharacterOfPosition(property.getStart()).character);
|
|
287
290
|
const type = keyTypeSource(key, property, checker);
|
|
288
|
-
|
|
291
|
+
// `| null`, as on every column the codemod touches: a foreign key holds one like any other.
|
|
292
|
+
return inserted(property, `@Field({ references: () => ${target} }) ${column}?: ${type} | null;\n${indent}`);
|
|
289
293
|
}
|
|
290
294
|
/** The key's type as written where that is in scope, the same file, or as the checker spells it out. */
|
|
291
295
|
function keyTypeSource(key, at, checker) {
|
|
@@ -377,6 +381,7 @@ function rewriteEntityOptions(options, owner, ctx) {
|
|
|
377
381
|
}
|
|
378
382
|
for (const field of objectProperties(fields)) {
|
|
379
383
|
renameSqlOption(optionsOf(field.initializer), 'virtual', 'computed', field, owner, ctx);
|
|
384
|
+
admitNullOnDefined(field, owner, ctx);
|
|
380
385
|
}
|
|
381
386
|
for (const filter of objectProperties(propertyValue(options, 'filters'))) {
|
|
382
387
|
renameOption(optionsOf(filter.initializer), 'condition', 'where', filter, ctx);
|
|
@@ -669,6 +674,9 @@ function rewriteProperty(node, ctx) {
|
|
|
669
674
|
}
|
|
670
675
|
const options = decoratorOptions(decorator);
|
|
671
676
|
if (FIELD_DECORATORS.has(name)) {
|
|
677
|
+
if (name === 'Field') {
|
|
678
|
+
admitNull(options, node, ctx);
|
|
679
|
+
}
|
|
672
680
|
addFieldType(decorator, node, ctx);
|
|
673
681
|
// Options it cannot read may still hold `virtual`, so they are reported where they mention it.
|
|
674
682
|
if (options.kind === 'opaque' && /\bvirtual\b/.test(decorator.getText())) {
|
|
@@ -692,6 +700,64 @@ function rewriteProperty(node, ctx) {
|
|
|
692
700
|
}
|
|
693
701
|
unwrapRelationAlias(node, ctx);
|
|
694
702
|
}
|
|
703
|
+
/**
|
|
704
|
+
* A column holds `null` unless `nullable: false` says otherwise, and a read hydrates one, so the property
|
|
705
|
+
* says so too. A key is NOT NULL on every engine, and a relation aggregate is typed by the aggregate,
|
|
706
|
+
* which declares its own `null` or none, so neither is touched.
|
|
707
|
+
*/
|
|
708
|
+
function admitNull(options, node, ctx) {
|
|
709
|
+
// Options it cannot read may state `nullable` themselves, and appending to the property would then
|
|
710
|
+
// contradict the column. `addFieldType` already reports the same options, so this adds no second note.
|
|
711
|
+
if (options.kind === 'opaque') {
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
if (declaresNotNull(options) ||
|
|
715
|
+
findProperty(options, 'isId') ||
|
|
716
|
+
(findProperty(options, 'computed') && !findProperty(options, 'type'))) {
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
if (!node.type) {
|
|
720
|
+
ctx.notes.push(`${ctx.describe(node)}: declare '${propertyKey(node.name)}' as a type that admits 'null', which the column holds`);
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
723
|
+
if (admitsNull(node.type)) {
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
ctx.edits.push(appended(node.type, ' | null'));
|
|
727
|
+
}
|
|
728
|
+
/**
|
|
729
|
+
* The same null rule where `defineEntity` names the field: the property is on the class the call takes,
|
|
730
|
+
* so the declaration is found there rather than under a decorator.
|
|
731
|
+
*/
|
|
732
|
+
function admitNullOnDefined(field, owner, ctx) {
|
|
733
|
+
if (!ts.isPropertyAssignment(field)) {
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
const key = propertyKey(field.name);
|
|
737
|
+
const declaration = key
|
|
738
|
+
? instanceTypeOf(owner.entity, ctx.checker)
|
|
739
|
+
.getProperty(key)
|
|
740
|
+
?.declarations?.find((it) => ts.isPropertyDeclaration(it))
|
|
741
|
+
: undefined;
|
|
742
|
+
if (declaration?.type) {
|
|
743
|
+
admitNull(optionsOf(field.initializer), declaration, ctx);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
/** Whether the options say the column refuses `null`; `nullable: true` is the default said out loud. */
|
|
747
|
+
function declaresNotNull(options) {
|
|
748
|
+
const nullable = findProperty(options, 'nullable');
|
|
749
|
+
return !!nullable && ts.isPropertyAssignment(nullable) && nullable.initializer.kind === ts.SyntaxKind.FalseKeyword;
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Whether a written type already admits `null`, wherever it sits in the union. In a type position `null`
|
|
753
|
+
* parses as a literal type rather than a keyword, which is why the kind is read off `literal`.
|
|
754
|
+
*/
|
|
755
|
+
function admitsNull(type) {
|
|
756
|
+
if (ts.isLiteralTypeNode(type)) {
|
|
757
|
+
return type.literal.kind === ts.SyntaxKind.NullKeyword;
|
|
758
|
+
}
|
|
759
|
+
return ts.isUnionTypeNode(type) && type.types.some(admitsNull);
|
|
760
|
+
}
|
|
695
761
|
/** Names a decorator that no longer exists, wherever it appears. */
|
|
696
762
|
function reportRemovedDecorators(node, ctx) {
|
|
697
763
|
for (const decorator of decoratorsOf(node)) {
|