@dudousxd/nestjs-codegen 0.23.0 → 0.25.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/CHANGELOG.md +34 -0
- package/dist/cli/main.cjs +49 -9
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.js +49 -9
- package/dist/cli/main.js.map +1 -1
- package/dist/extension/index.d.cts +1 -1
- package/dist/extension/index.d.ts +1 -1
- package/dist/{index-BsptKWwz.d.cts → index-Ce3YnfwS.d.cts} +19 -0
- package/dist/{index-BsptKWwz.d.ts → index-Ce3YnfwS.d.ts} +19 -0
- package/dist/index.cjs +49 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +49 -9
- package/dist/index.js.map +1 -1
- package/dist/nest/index.cjs +49 -9
- package/dist/nest/index.cjs.map +1 -1
- package/dist/nest/index.d.cts +1 -1
- package/dist/nest/index.d.ts +1 -1
- package/dist/nest/index.js +49 -9
- package/dist/nest/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { m as ApiClientLayer, n as ApiHeaderContribution, o as ApiModuleDeps, C as CodegenExtension, p as EmittedFile, E as ExtensionContext, L as LeafModel, q as RequestModel, s as RequestShape, t as defineExtension, u as requestShape } from '../index-
|
|
1
|
+
export { m as ApiClientLayer, n as ApiHeaderContribution, o as ApiModuleDeps, C as CodegenExtension, p as EmittedFile, E as ExtensionContext, L as LeafModel, q as RequestModel, s as RequestShape, t as defineExtension, u as requestShape } from '../index-Ce3YnfwS.cjs';
|
|
2
2
|
import 'ts-morph';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { m as ApiClientLayer, n as ApiHeaderContribution, o as ApiModuleDeps, C as CodegenExtension, p as EmittedFile, E as ExtensionContext, L as LeafModel, q as RequestModel, s as RequestShape, t as defineExtension, u as requestShape } from '../index-
|
|
1
|
+
export { m as ApiClientLayer, n as ApiHeaderContribution, o as ApiModuleDeps, C as CodegenExtension, p as EmittedFile, E as ExtensionContext, L as LeafModel, q as RequestModel, s as RequestShape, t as defineExtension, u as requestShape } from '../index-Ce3YnfwS.js';
|
|
2
2
|
import 'ts-morph';
|
|
@@ -430,7 +430,26 @@ type FieldTypeKind = 'string' | 'number' | 'boolean' | 'date' | 'json' | 'unknow
|
|
|
430
430
|
interface FilterFieldType {
|
|
431
431
|
/** Field name, e.g. 'age' or 'tasks.id' (dot-notation for relations). */
|
|
432
432
|
name: string;
|
|
433
|
+
/**
|
|
434
|
+
* What the COLUMN is — the semantics an operator set is derived from. A DATE
|
|
435
|
+
* column is `date` here even when its value arrives as a string.
|
|
436
|
+
*/
|
|
433
437
|
kind: FieldTypeKind;
|
|
438
|
+
/**
|
|
439
|
+
* What the VALUE is, when that differs from {@link kind}.
|
|
440
|
+
*
|
|
441
|
+
* A mapped column declares two things that can both be true and disagree:
|
|
442
|
+
* `@Property({ columnType: 'date', type: DateType }) x?: Opt<string>` is a
|
|
443
|
+
* DATE column whose JS value is `'YYYY-MM-DD'`. Collapsing them loses one or
|
|
444
|
+
* the other — answer `string` and the field stops accepting the ordering and
|
|
445
|
+
* range operators the column supports; answer `date` and the emitted type
|
|
446
|
+
* promises a `Date` the value never holds, which a type-preserving wire
|
|
447
|
+
* format like superjson then contradicts at runtime.
|
|
448
|
+
*
|
|
449
|
+
* So the two travel separately: `kind` gates operators, this types the value.
|
|
450
|
+
* Absent when they agree, which is the overwhelming majority of columns.
|
|
451
|
+
*/
|
|
452
|
+
valueKind?: FieldTypeKind;
|
|
434
453
|
/** String/number-literal union members (enums), if any. */
|
|
435
454
|
enumValues?: string[];
|
|
436
455
|
/** Whether the field's TS type includes null/undefined. */
|
|
@@ -430,7 +430,26 @@ type FieldTypeKind = 'string' | 'number' | 'boolean' | 'date' | 'json' | 'unknow
|
|
|
430
430
|
interface FilterFieldType {
|
|
431
431
|
/** Field name, e.g. 'age' or 'tasks.id' (dot-notation for relations). */
|
|
432
432
|
name: string;
|
|
433
|
+
/**
|
|
434
|
+
* What the COLUMN is — the semantics an operator set is derived from. A DATE
|
|
435
|
+
* column is `date` here even when its value arrives as a string.
|
|
436
|
+
*/
|
|
433
437
|
kind: FieldTypeKind;
|
|
438
|
+
/**
|
|
439
|
+
* What the VALUE is, when that differs from {@link kind}.
|
|
440
|
+
*
|
|
441
|
+
* A mapped column declares two things that can both be true and disagree:
|
|
442
|
+
* `@Property({ columnType: 'date', type: DateType }) x?: Opt<string>` is a
|
|
443
|
+
* DATE column whose JS value is `'YYYY-MM-DD'`. Collapsing them loses one or
|
|
444
|
+
* the other — answer `string` and the field stops accepting the ordering and
|
|
445
|
+
* range operators the column supports; answer `date` and the emitted type
|
|
446
|
+
* promises a `Date` the value never holds, which a type-preserving wire
|
|
447
|
+
* format like superjson then contradicts at runtime.
|
|
448
|
+
*
|
|
449
|
+
* So the two travel separately: `kind` gates operators, this types the value.
|
|
450
|
+
* Absent when they agree, which is the overwhelming majority of columns.
|
|
451
|
+
*/
|
|
452
|
+
valueKind?: FieldTypeKind;
|
|
434
453
|
/** String/number-literal union members (enums), if any. */
|
|
435
454
|
enumValues?: string[];
|
|
436
455
|
/** Whether the field's TS type includes null/undefined. */
|
package/dist/index.cjs
CHANGED
|
@@ -1535,12 +1535,19 @@ function classifyFromColumnDecorator(prop, sourceFile, project) {
|
|
|
1535
1535
|
return { kind: "string" };
|
|
1536
1536
|
}
|
|
1537
1537
|
}
|
|
1538
|
-
const
|
|
1539
|
-
|
|
1538
|
+
for (const key of ["columnType", "type"]) {
|
|
1539
|
+
const typeProp = arg.getProperty(key);
|
|
1540
|
+
if (!typeProp || !import_ts_morph4.Node.isPropertyAssignment(typeProp)) continue;
|
|
1540
1541
|
const init = typeProp.getInitializer();
|
|
1541
|
-
if (init
|
|
1542
|
+
if (!init) continue;
|
|
1543
|
+
if (import_ts_morph4.Node.isStringLiteral(init)) {
|
|
1542
1544
|
const kind = classifyTypeKeyword(init.getLiteralValue());
|
|
1543
1545
|
if (kind) return { kind };
|
|
1546
|
+
continue;
|
|
1547
|
+
}
|
|
1548
|
+
if (import_ts_morph4.Node.isIdentifier(init)) {
|
|
1549
|
+
const kind = classifyTypeKeyword(init.getText());
|
|
1550
|
+
if (kind) return { kind };
|
|
1544
1551
|
}
|
|
1545
1552
|
}
|
|
1546
1553
|
}
|
|
@@ -1552,12 +1559,18 @@ function classifyFromColumnDecorator(prop, sourceFile, project) {
|
|
|
1552
1559
|
function classifyFieldType(prop, sourceFile, project) {
|
|
1553
1560
|
let nullable = prop.hasQuestionToken();
|
|
1554
1561
|
const typeNode = prop.getTypeNode();
|
|
1562
|
+
const fromDecorator = classifyFromColumnDecorator(prop, sourceFile, project);
|
|
1555
1563
|
if (typeNode) {
|
|
1556
1564
|
const r = classifyTypeNode(typeNode, sourceFile, project);
|
|
1557
1565
|
if (r.nullable) nullable = true;
|
|
1558
|
-
if (r.kind !== "unknown")
|
|
1566
|
+
if (r.kind !== "unknown") {
|
|
1567
|
+
const conflicts = fromDecorator !== null && fromDecorator.kind !== "unknown" && fromDecorator.kind !== r.kind;
|
|
1568
|
+
if (conflicts) {
|
|
1569
|
+
return markNullable({ ...fromDecorator, valueKind: r.kind }, nullable);
|
|
1570
|
+
}
|
|
1571
|
+
return markNullable(r, nullable);
|
|
1572
|
+
}
|
|
1559
1573
|
}
|
|
1560
|
-
const fromDecorator = classifyFromColumnDecorator(prop, sourceFile, project);
|
|
1561
1574
|
if (fromDecorator) {
|
|
1562
1575
|
return markNullable(fromDecorator, nullable || fromDecorator.nullable === true);
|
|
1563
1576
|
}
|
|
@@ -1565,6 +1578,7 @@ function classifyFieldType(prop, sourceFile, project) {
|
|
|
1565
1578
|
}
|
|
1566
1579
|
function toFilterFieldType(name, r) {
|
|
1567
1580
|
const ft = { name, kind: r.kind };
|
|
1581
|
+
if (r.valueKind && r.valueKind !== r.kind) ft.valueKind = r.valueKind;
|
|
1568
1582
|
if (r.enumValues && r.enumValues.length > 0) ft.enumValues = r.enumValues;
|
|
1569
1583
|
if (r.nullable) ft.nullable = true;
|
|
1570
1584
|
if (r.numericEnum) ft.numericEnum = true;
|
|
@@ -1671,6 +1685,32 @@ function resolveFactoryStaticClass(node) {
|
|
|
1671
1685
|
if (!import_ts_morph5.Node.isIdentifier(inner)) return void 0;
|
|
1672
1686
|
return inner.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => n !== void 0 && import_ts_morph5.Node.isClassDeclaration(n));
|
|
1673
1687
|
}
|
|
1688
|
+
function resolveBaseClass(cls) {
|
|
1689
|
+
const heritage = cls.getExtends()?.getExpression();
|
|
1690
|
+
if (!heritage) return void 0;
|
|
1691
|
+
const call = resolveHeritageCall(heritage);
|
|
1692
|
+
if (call) {
|
|
1693
|
+
const factoryDecl = resolveFactoryDeclaration(call);
|
|
1694
|
+
return factoryDecl ? resolveReturnedClass(factoryDecl) : void 0;
|
|
1695
|
+
}
|
|
1696
|
+
const expr = unwrapExpression(heritage);
|
|
1697
|
+
if (!import_ts_morph5.Node.isIdentifier(expr)) return void 0;
|
|
1698
|
+
return expr.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => n !== void 0 && import_ts_morph5.Node.isClassDeclaration(n));
|
|
1699
|
+
}
|
|
1700
|
+
function collectMethodsThroughChain(returnedClass) {
|
|
1701
|
+
const byName = /* @__PURE__ */ new Map();
|
|
1702
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1703
|
+
let current = returnedClass;
|
|
1704
|
+
while (current && !seen.has(current)) {
|
|
1705
|
+
seen.add(current);
|
|
1706
|
+
for (const method of current.getMethods()) {
|
|
1707
|
+
const name = method.getName();
|
|
1708
|
+
if (!byName.has(name)) byName.set(name, method);
|
|
1709
|
+
}
|
|
1710
|
+
current = resolveBaseClass(current);
|
|
1711
|
+
}
|
|
1712
|
+
return [...byName.values()];
|
|
1713
|
+
}
|
|
1674
1714
|
function resolveInheritedMethods(cls) {
|
|
1675
1715
|
const expr = resolveHeritageCall(cls.getExtends()?.getExpression());
|
|
1676
1716
|
if (!expr) return void 0;
|
|
@@ -1710,7 +1750,7 @@ function resolveInheritedMethods(cls) {
|
|
|
1710
1750
|
}
|
|
1711
1751
|
}
|
|
1712
1752
|
return {
|
|
1713
|
-
methods: returnedClass
|
|
1753
|
+
methods: collectMethodsThroughChain(returnedClass),
|
|
1714
1754
|
// The DECLARATION's name, not the call-site text: consumers look the factory
|
|
1715
1755
|
// back up by name inside `factoryFilePath`, which a qualified
|
|
1716
1756
|
// `tables.createTableController` would never match. For a bare identifier
|
|
@@ -3084,7 +3124,7 @@ function extractDtoRoute(args) {
|
|
|
3084
3124
|
const methodName = method.getName();
|
|
3085
3125
|
const classAs = readAsDecorator(cls, `class ${className}`);
|
|
3086
3126
|
const methodAs = readAsDecorator(method, `${className}.${methodName}`);
|
|
3087
|
-
const dtoContract = extractDtoContract(method,
|
|
3127
|
+
const dtoContract = extractDtoContract(method, method.getSourceFile(), project, mixin, cls);
|
|
3088
3128
|
const mixinResponse = mixin ? resolveInstantiatedReturnType(cls, methodName) : void 0;
|
|
3089
3129
|
return buildRoute({
|
|
3090
3130
|
className,
|
|
@@ -3370,7 +3410,7 @@ function kindToTs(kind, enumValues, numericEnum) {
|
|
|
3370
3410
|
}
|
|
3371
3411
|
function emitFieldTypesLiteral(fts) {
|
|
3372
3412
|
const entries = fts.map((f) => {
|
|
3373
|
-
let t = f.typeRef ? f.typeRef.name : kindToTs(f.kind, f.enumValues, f.numericEnum);
|
|
3413
|
+
let t = f.typeRef ? f.typeRef.name : kindToTs(f.valueKind ?? f.kind, f.enumValues, f.numericEnum);
|
|
3374
3414
|
if (f.nullable) t = `${t} | null`;
|
|
3375
3415
|
return `${JSON.stringify(f.name)}: ${t}`;
|
|
3376
3416
|
});
|
|
@@ -5377,7 +5417,7 @@ function createChainModuleRenderer(opts) {
|
|
|
5377
5417
|
}
|
|
5378
5418
|
|
|
5379
5419
|
// src/index.ts
|
|
5380
|
-
var VERSION = "0.
|
|
5420
|
+
var VERSION = "0.25.0";
|
|
5381
5421
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5382
5422
|
0 && (module.exports = {
|
|
5383
5423
|
CodegenError,
|