@dudousxd/nestjs-codegen 0.17.1 → 0.17.2
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 +22 -0
- package/dist/cli/main.cjs +196 -172
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.js +190 -166
- package/dist/cli/main.js.map +1 -1
- package/dist/index.cjs +196 -172
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +190 -166
- package/dist/index.js.map +1 -1
- package/dist/nest/index.cjs +196 -172
- package/dist/nest/index.cjs.map +1 -1
- package/dist/nest/index.js +190 -166
- package/dist/nest/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @dudousxd/nestjs-codegen
|
|
2
2
|
|
|
3
|
+
## 0.17.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- fcf816e: Resolve `@ApplyFilter(<Table>.filter)` on overridden mixin routes.
|
|
8
|
+
|
|
9
|
+
A controller that extends a factory-produced base and overrides one of its
|
|
10
|
+
routes has to re-declare `@ApplyFilter`, and the only handle on the filter the
|
|
11
|
+
factory generated internally is the static it hands back — a property access,
|
|
12
|
+
not an importable identifier. Discovery accepted identifiers only, so it skipped
|
|
13
|
+
the decorator entirely.
|
|
14
|
+
|
|
15
|
+
The failure was silent and total rather than partial: the route emitted with
|
|
16
|
+
`body: never` and `filterFields: never`, dropping the typed filter builder from
|
|
17
|
+
exactly the routes that took the override escape hatch, while `tsc` and codegen
|
|
18
|
+
both stayed green. It only surfaced downstream, as a client call that could no
|
|
19
|
+
longer be typed.
|
|
20
|
+
|
|
21
|
+
Such a property access is now resolved through the factory — const → factory
|
|
22
|
+
call → returned class → static property → the class declared in the factory
|
|
23
|
+
body.
|
|
24
|
+
|
|
3
25
|
## 0.17.1
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
package/dist/cli/main.cjs
CHANGED
|
@@ -2475,7 +2475,7 @@ var import_fast_glob3 = __toESM(require("fast-glob"), 1);
|
|
|
2475
2475
|
var import_ts_morph10 = require("ts-morph");
|
|
2476
2476
|
|
|
2477
2477
|
// src/discovery/dto-type-resolver.ts
|
|
2478
|
-
var
|
|
2478
|
+
var import_ts_morph8 = require("ts-morph");
|
|
2479
2479
|
|
|
2480
2480
|
// src/discovery/dto-to-ir.ts
|
|
2481
2481
|
var import_ts_morph4 = require("ts-morph");
|
|
@@ -3231,7 +3231,7 @@ function inSchemaFromDecorator(decorator) {
|
|
|
3231
3231
|
}
|
|
3232
3232
|
|
|
3233
3233
|
// src/discovery/filter-for.ts
|
|
3234
|
-
var
|
|
3234
|
+
var import_ts_morph7 = require("ts-morph");
|
|
3235
3235
|
|
|
3236
3236
|
// src/discovery/filter-field-types.ts
|
|
3237
3237
|
var import_ts_morph5 = require("ts-morph");
|
|
@@ -3450,6 +3450,123 @@ function toFilterFieldType(name, r) {
|
|
|
3450
3450
|
return ft;
|
|
3451
3451
|
}
|
|
3452
3452
|
|
|
3453
|
+
// src/discovery/heritage.ts
|
|
3454
|
+
var import_ts_morph6 = require("ts-morph");
|
|
3455
|
+
function resolveHeritageCall(node) {
|
|
3456
|
+
if (!node) return void 0;
|
|
3457
|
+
const expr = unwrapExpression(node);
|
|
3458
|
+
if (import_ts_morph6.Node.isCallExpression(expr)) return expr;
|
|
3459
|
+
if (!import_ts_morph6.Node.isIdentifier(expr)) return void 0;
|
|
3460
|
+
const decl = expr.getDefinitions().map((d) => d.getDeclarationNode()).find(
|
|
3461
|
+
(n) => n !== void 0 && import_ts_morph6.Node.isVariableDeclaration(n)
|
|
3462
|
+
);
|
|
3463
|
+
const init = decl?.getInitializer();
|
|
3464
|
+
if (!init) return void 0;
|
|
3465
|
+
const unwrapped = unwrapExpression(init);
|
|
3466
|
+
return import_ts_morph6.Node.isCallExpression(unwrapped) ? unwrapped : void 0;
|
|
3467
|
+
}
|
|
3468
|
+
function unwrapExpression(node) {
|
|
3469
|
+
let current = node;
|
|
3470
|
+
while (import_ts_morph6.Node.isAsExpression(current) || import_ts_morph6.Node.isSatisfiesExpression(current) || import_ts_morph6.Node.isParenthesizedExpression(current) || import_ts_morph6.Node.isTypeAssertion(current)) {
|
|
3471
|
+
current = current.getExpression();
|
|
3472
|
+
}
|
|
3473
|
+
return current;
|
|
3474
|
+
}
|
|
3475
|
+
function resolveReturnedClass(factoryDecl) {
|
|
3476
|
+
const body = factoryDecl.getBody();
|
|
3477
|
+
if (!body) return void 0;
|
|
3478
|
+
const returns = body.getDescendants().filter((n) => import_ts_morph6.Node.isReturnStatement(n));
|
|
3479
|
+
for (const ret of returns) {
|
|
3480
|
+
const expr = ret.getExpression();
|
|
3481
|
+
if (!expr) continue;
|
|
3482
|
+
const inner = unwrapExpression(expr);
|
|
3483
|
+
if (import_ts_morph6.Node.isClassExpression(inner)) {
|
|
3484
|
+
return inner;
|
|
3485
|
+
}
|
|
3486
|
+
if (import_ts_morph6.Node.isIdentifier(inner)) {
|
|
3487
|
+
const name = inner.getText();
|
|
3488
|
+
const decl = body.getDescendants().find((n) => import_ts_morph6.Node.isClassDeclaration(n) && n.getName() === name);
|
|
3489
|
+
if (decl) return decl;
|
|
3490
|
+
}
|
|
3491
|
+
}
|
|
3492
|
+
return void 0;
|
|
3493
|
+
}
|
|
3494
|
+
function resolveFactoryDeclaration(call) {
|
|
3495
|
+
const callee = call.getExpression();
|
|
3496
|
+
if (!import_ts_morph6.Node.isIdentifier(callee)) return void 0;
|
|
3497
|
+
return callee.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => import_ts_morph6.Node.isFunctionDeclaration(n));
|
|
3498
|
+
}
|
|
3499
|
+
function resolveFactoryStaticClass(node) {
|
|
3500
|
+
if (!import_ts_morph6.Node.isPropertyAccessExpression(node)) return void 0;
|
|
3501
|
+
const call = resolveHeritageCall(node.getExpression());
|
|
3502
|
+
if (!call) return void 0;
|
|
3503
|
+
const factoryDecl = resolveFactoryDeclaration(call);
|
|
3504
|
+
if (!factoryDecl) return void 0;
|
|
3505
|
+
const returnedClass = resolveReturnedClass(factoryDecl);
|
|
3506
|
+
if (!returnedClass) return void 0;
|
|
3507
|
+
const staticProp = returnedClass.getStaticProperties().find((p) => p.getName() === node.getName());
|
|
3508
|
+
if (!staticProp || !import_ts_morph6.Node.isPropertyDeclaration(staticProp)) return void 0;
|
|
3509
|
+
const init = staticProp.getInitializer();
|
|
3510
|
+
if (!init) return void 0;
|
|
3511
|
+
const inner = unwrapExpression(init);
|
|
3512
|
+
if (import_ts_morph6.Node.isClassExpression(inner)) return inner;
|
|
3513
|
+
if (!import_ts_morph6.Node.isIdentifier(inner)) return void 0;
|
|
3514
|
+
return inner.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => n !== void 0 && import_ts_morph6.Node.isClassDeclaration(n));
|
|
3515
|
+
}
|
|
3516
|
+
function resolveInheritedMethods(cls) {
|
|
3517
|
+
const expr = resolveHeritageCall(cls.getExtends()?.getExpression());
|
|
3518
|
+
if (!expr) return void 0;
|
|
3519
|
+
const callee = expr.getExpression();
|
|
3520
|
+
if (!import_ts_morph6.Node.isIdentifier(callee)) return void 0;
|
|
3521
|
+
const factoryDecl = resolveFactoryDeclaration(expr);
|
|
3522
|
+
if (!factoryDecl) return void 0;
|
|
3523
|
+
const returnedClass = resolveReturnedClass(factoryDecl);
|
|
3524
|
+
if (!returnedClass) return void 0;
|
|
3525
|
+
const classArgs = [];
|
|
3526
|
+
for (const arg of expr.getArguments()) {
|
|
3527
|
+
if (!import_ts_morph6.Node.isIdentifier(arg)) continue;
|
|
3528
|
+
const decl = arg.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => import_ts_morph6.Node.isClassDeclaration(n));
|
|
3529
|
+
if (decl) {
|
|
3530
|
+
classArgs.push({
|
|
3531
|
+
name: decl.getName() ?? arg.getText(),
|
|
3532
|
+
filePath: decl.getSourceFile().getFilePath()
|
|
3533
|
+
});
|
|
3534
|
+
}
|
|
3535
|
+
}
|
|
3536
|
+
return {
|
|
3537
|
+
methods: returnedClass.getMethods(),
|
|
3538
|
+
factoryName: callee.getText(),
|
|
3539
|
+
factoryFilePath: factoryDecl.getSourceFile().getFilePath(),
|
|
3540
|
+
classArgs
|
|
3541
|
+
};
|
|
3542
|
+
}
|
|
3543
|
+
var mixinTypeProject;
|
|
3544
|
+
function getMixinTypeProject() {
|
|
3545
|
+
mixinTypeProject ??= new import_ts_morph6.Project({
|
|
3546
|
+
skipAddingFilesFromTsConfig: true,
|
|
3547
|
+
compilerOptions: { strict: true }
|
|
3548
|
+
});
|
|
3549
|
+
return mixinTypeProject;
|
|
3550
|
+
}
|
|
3551
|
+
function clearMixinTypeProject() {
|
|
3552
|
+
mixinTypeProject = void 0;
|
|
3553
|
+
}
|
|
3554
|
+
function resolveInstantiatedReturnType(cls, methodName) {
|
|
3555
|
+
const filePath = cls.getSourceFile().getFilePath();
|
|
3556
|
+
const className = cls.getName();
|
|
3557
|
+
if (!className) return void 0;
|
|
3558
|
+
const project = getMixinTypeProject();
|
|
3559
|
+
const sourceFile = project.getSourceFile(filePath) ?? project.addSourceFileAtPathIfExists(filePath);
|
|
3560
|
+
const typedCls = sourceFile?.getClass(className);
|
|
3561
|
+
if (!typedCls) return void 0;
|
|
3562
|
+
const prop = typedCls.getType().getProperty(methodName);
|
|
3563
|
+
if (!prop) return void 0;
|
|
3564
|
+
const returnType = prop.getTypeAtLocation(typedCls).getCallSignatures()[0]?.getReturnType();
|
|
3565
|
+
if (!returnType) return void 0;
|
|
3566
|
+
const unwrapped = returnType.getSymbol()?.getName() === "Promise" ? returnType.getTypeArguments()[0] ?? returnType : returnType;
|
|
3567
|
+
return unwrapped.getText(typedCls);
|
|
3568
|
+
}
|
|
3569
|
+
|
|
3453
3570
|
// src/discovery/filter-for.ts
|
|
3454
3571
|
function resolveMixinEntityClass(mixin, project) {
|
|
3455
3572
|
const entityArg = mixin?.classArgs[0];
|
|
@@ -3458,7 +3575,7 @@ function resolveMixinEntityClass(mixin, project) {
|
|
|
3458
3575
|
return file?.getClass(entityArg.name);
|
|
3459
3576
|
}
|
|
3460
3577
|
function classifyFilterForHint(typeInit) {
|
|
3461
|
-
if (
|
|
3578
|
+
if (import_ts_morph7.Node.isStringLiteral(typeInit)) {
|
|
3462
3579
|
switch (typeInit.getLiteralValue()) {
|
|
3463
3580
|
case "string":
|
|
3464
3581
|
return { kind: "string" };
|
|
@@ -3472,10 +3589,10 @@ function classifyFilterForHint(typeInit) {
|
|
|
3472
3589
|
return null;
|
|
3473
3590
|
}
|
|
3474
3591
|
}
|
|
3475
|
-
if (
|
|
3592
|
+
if (import_ts_morph7.Node.isArrayLiteralExpression(typeInit)) {
|
|
3476
3593
|
const values = [];
|
|
3477
3594
|
for (const el of typeInit.getElements()) {
|
|
3478
|
-
if (!
|
|
3595
|
+
if (!import_ts_morph7.Node.isStringLiteral(el)) return null;
|
|
3479
3596
|
values.push(el.getLiteralValue());
|
|
3480
3597
|
}
|
|
3481
3598
|
if (values.length === 0) return null;
|
|
@@ -3510,11 +3627,11 @@ function extractFilterForHints(classDecl, project) {
|
|
|
3510
3627
|
if (!filterForDec) continue;
|
|
3511
3628
|
const args = filterForDec.getArguments();
|
|
3512
3629
|
const keyArg = args[0];
|
|
3513
|
-
const inputKey = keyArg &&
|
|
3630
|
+
const inputKey = keyArg && import_ts_morph7.Node.isStringLiteral(keyArg) ? keyArg.getLiteralValue() : method.getName();
|
|
3514
3631
|
const optsArg = args[1];
|
|
3515
|
-
if (optsArg &&
|
|
3632
|
+
if (optsArg && import_ts_morph7.Node.isObjectLiteralExpression(optsArg)) {
|
|
3516
3633
|
const typeProp = optsArg.getProperty("type");
|
|
3517
|
-
if (typeProp &&
|
|
3634
|
+
if (typeProp && import_ts_morph7.Node.isPropertyAssignment(typeProp)) {
|
|
3518
3635
|
const typeInit = typeProp.getInitializer();
|
|
3519
3636
|
if (typeInit) {
|
|
3520
3637
|
const classified = classifyFilterForHint(typeInit);
|
|
@@ -3539,21 +3656,23 @@ function extractApplyFilterInfo(method, sourceFile, project, mixin) {
|
|
|
3539
3656
|
const args = filterDecorator.getArguments();
|
|
3540
3657
|
if (args.length === 0) continue;
|
|
3541
3658
|
const filterClassArg = args[0];
|
|
3542
|
-
if (!filterClassArg
|
|
3659
|
+
if (!filterClassArg) continue;
|
|
3660
|
+
const factoryStaticClass = resolveFactoryStaticClass(filterClassArg);
|
|
3661
|
+
if (!factoryStaticClass && !import_ts_morph7.Node.isIdentifier(filterClassArg)) continue;
|
|
3543
3662
|
let source = "query";
|
|
3544
3663
|
const optionsArg = args[1];
|
|
3545
|
-
if (optionsArg &&
|
|
3664
|
+
if (optionsArg && import_ts_morph7.Node.isObjectLiteralExpression(optionsArg)) {
|
|
3546
3665
|
const sourceProp = optionsArg.getProperty("source");
|
|
3547
|
-
if (sourceProp &&
|
|
3666
|
+
if (sourceProp && import_ts_morph7.Node.isPropertyAssignment(sourceProp)) {
|
|
3548
3667
|
const init = sourceProp.getInitializer();
|
|
3549
|
-
if (init &&
|
|
3668
|
+
if (init && import_ts_morph7.Node.isStringLiteral(init) && init.getLiteralValue() === "body") {
|
|
3550
3669
|
source = "body";
|
|
3551
3670
|
}
|
|
3552
3671
|
}
|
|
3553
3672
|
}
|
|
3554
3673
|
const filterClassName = filterClassArg.getText();
|
|
3555
|
-
const resolved = findType(filterClassName, declFile, project);
|
|
3556
|
-
const classDecl = resolved?.kind === "class" ? resolved.decl : resolveLocalClassDeclaration(filterClassArg);
|
|
3674
|
+
const resolved = factoryStaticClass ? void 0 : findType(filterClassName, declFile, project);
|
|
3675
|
+
const classDecl = factoryStaticClass ?? (resolved?.kind === "class" ? resolved.decl : resolveLocalClassDeclaration(filterClassArg));
|
|
3557
3676
|
if (classDecl) {
|
|
3558
3677
|
let fieldTypes = extractClassPropertyTypes(classDecl, project);
|
|
3559
3678
|
if (fieldTypes.length === 0) {
|
|
@@ -3609,22 +3728,22 @@ function resolveRelationEntity(prop, sourceFile, project) {
|
|
|
3609
3728
|
const args = dec.getArguments();
|
|
3610
3729
|
if (args.length === 0) continue;
|
|
3611
3730
|
const arg = args[0];
|
|
3612
|
-
if (
|
|
3731
|
+
if (import_ts_morph7.Node.isObjectLiteralExpression(arg)) {
|
|
3613
3732
|
const entityProp = arg.getProperty("entity");
|
|
3614
|
-
if (entityProp &&
|
|
3733
|
+
if (entityProp && import_ts_morph7.Node.isPropertyAssignment(entityProp)) {
|
|
3615
3734
|
const init = entityProp.getInitializer();
|
|
3616
|
-
if (init &&
|
|
3735
|
+
if (init && import_ts_morph7.Node.isArrowFunction(init)) {
|
|
3617
3736
|
const body = init.getBody();
|
|
3618
|
-
if (
|
|
3737
|
+
if (import_ts_morph7.Node.isIdentifier(body)) {
|
|
3619
3738
|
const resolved = findType(body.getText(), prop.getSourceFile(), project);
|
|
3620
3739
|
if (resolved?.kind === "class") return resolved.decl;
|
|
3621
3740
|
}
|
|
3622
3741
|
}
|
|
3623
3742
|
}
|
|
3624
3743
|
}
|
|
3625
|
-
if (
|
|
3744
|
+
if (import_ts_morph7.Node.isArrowFunction(arg)) {
|
|
3626
3745
|
const body = arg.getBody();
|
|
3627
|
-
if (
|
|
3746
|
+
if (import_ts_morph7.Node.isIdentifier(body)) {
|
|
3628
3747
|
const resolved = findType(body.getText(), prop.getSourceFile(), project);
|
|
3629
3748
|
if (resolved?.kind === "class") return resolved.decl;
|
|
3630
3749
|
}
|
|
@@ -3643,15 +3762,15 @@ function extractClassPropertyTypes(classDecl, project) {
|
|
|
3643
3762
|
return fields;
|
|
3644
3763
|
}
|
|
3645
3764
|
function resolveLocalClassDeclaration(identifier) {
|
|
3646
|
-
if (!
|
|
3647
|
-
return identifier.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => n !== void 0 &&
|
|
3765
|
+
if (!import_ts_morph7.Node.isIdentifier(identifier)) return void 0;
|
|
3766
|
+
return identifier.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => n !== void 0 && import_ts_morph7.Node.isClassDeclaration(n));
|
|
3648
3767
|
}
|
|
3649
3768
|
function resolveDeclaredEntity(optionsArg, filterClass, project) {
|
|
3650
|
-
if (!
|
|
3769
|
+
if (!import_ts_morph7.Node.isObjectLiteralExpression(optionsArg)) return void 0;
|
|
3651
3770
|
const entityProp = optionsArg.getProperty("entity");
|
|
3652
|
-
if (!entityProp || !
|
|
3771
|
+
if (!entityProp || !import_ts_morph7.Node.isPropertyAssignment(entityProp)) return void 0;
|
|
3653
3772
|
const entityInit = entityProp.getInitializer();
|
|
3654
|
-
if (!entityInit || !
|
|
3773
|
+
if (!entityInit || !import_ts_morph7.Node.isIdentifier(entityInit)) return void 0;
|
|
3655
3774
|
const resolved = findType(entityInit.getText(), filterClass.getSourceFile(), project);
|
|
3656
3775
|
if (!resolved || resolved.kind !== "class") return void 0;
|
|
3657
3776
|
return resolved.decl;
|
|
@@ -3662,7 +3781,7 @@ function extractFilterableEntityFields(filterClass, project, entityOverride) {
|
|
|
3662
3781
|
const args = filterableDecorator.getArguments();
|
|
3663
3782
|
if (args.length === 0) return [];
|
|
3664
3783
|
const optionsArg = args[0];
|
|
3665
|
-
if (!
|
|
3784
|
+
if (!import_ts_morph7.Node.isObjectLiteralExpression(optionsArg)) return [];
|
|
3666
3785
|
const entityDecl = entityOverride ?? resolveDeclaredEntity(optionsArg, filterClass, project);
|
|
3667
3786
|
if (!entityDecl) return [];
|
|
3668
3787
|
const fields = collectEntityFields(
|
|
@@ -3675,17 +3794,17 @@ function extractFilterableEntityFields(filterClass, project, entityOverride) {
|
|
|
3675
3794
|
const relationsDecorator = filterClass.getDecorators().find((d) => d.getName() === "Relations");
|
|
3676
3795
|
if (relationsDecorator) {
|
|
3677
3796
|
const relArgs = relationsDecorator.getArguments();
|
|
3678
|
-
if (relArgs.length > 0 &&
|
|
3797
|
+
if (relArgs.length > 0 && import_ts_morph7.Node.isObjectLiteralExpression(relArgs[0])) {
|
|
3679
3798
|
for (const relProp of relArgs[0].getProperties()) {
|
|
3680
|
-
if (!
|
|
3799
|
+
if (!import_ts_morph7.Node.isPropertyAssignment(relProp)) continue;
|
|
3681
3800
|
const relInit = relProp.getInitializer();
|
|
3682
|
-
if (!relInit || !
|
|
3801
|
+
if (!relInit || !import_ts_morph7.Node.isObjectLiteralExpression(relInit)) continue;
|
|
3683
3802
|
const keysProp = relInit.getProperty("keys");
|
|
3684
|
-
if (!keysProp || !
|
|
3803
|
+
if (!keysProp || !import_ts_morph7.Node.isPropertyAssignment(keysProp)) continue;
|
|
3685
3804
|
const keysInit = keysProp.getInitializer();
|
|
3686
|
-
if (!keysInit || !
|
|
3805
|
+
if (!keysInit || !import_ts_morph7.Node.isArrayLiteralExpression(keysInit)) continue;
|
|
3687
3806
|
for (const el of keysInit.getElements()) {
|
|
3688
|
-
if (
|
|
3807
|
+
if (import_ts_morph7.Node.isStringLiteral(el)) {
|
|
3689
3808
|
fields.push(toFilterFieldType(el.getLiteralValue(), { kind: "unknown" }));
|
|
3690
3809
|
}
|
|
3691
3810
|
}
|
|
@@ -3726,22 +3845,22 @@ var PASSTHROUGH_UTILITY = /* @__PURE__ */ new Set([
|
|
|
3726
3845
|
]);
|
|
3727
3846
|
function resolveTypeNodeToString(typeNode, sourceFile, project, depth, subst = /* @__PURE__ */ new Map()) {
|
|
3728
3847
|
if (depth <= 0) return "unknown";
|
|
3729
|
-
if (
|
|
3848
|
+
if (import_ts_morph8.Node.isArrayTypeNode(typeNode)) {
|
|
3730
3849
|
const elementType = typeNode.getElementTypeNode();
|
|
3731
3850
|
return `Array<${resolveTypeNodeToString(elementType, sourceFile, project, depth, subst)}>`;
|
|
3732
3851
|
}
|
|
3733
|
-
if (
|
|
3852
|
+
if (import_ts_morph8.Node.isUnionTypeNode(typeNode)) {
|
|
3734
3853
|
return typeNode.getTypeNodes().map((t) => resolveTypeNodeToString(t, sourceFile, project, depth, subst)).join(" | ");
|
|
3735
3854
|
}
|
|
3736
|
-
if (
|
|
3855
|
+
if (import_ts_morph8.Node.isIntersectionTypeNode(typeNode)) {
|
|
3737
3856
|
return typeNode.getTypeNodes().map((t) => resolveTypeNodeToString(t, sourceFile, project, depth, subst)).join(" & ");
|
|
3738
3857
|
}
|
|
3739
|
-
if (
|
|
3858
|
+
if (import_ts_morph8.Node.isParenthesizedTypeNode(typeNode)) {
|
|
3740
3859
|
return `(${resolveTypeNodeToString(typeNode.getTypeNode(), sourceFile, project, depth, subst)})`;
|
|
3741
3860
|
}
|
|
3742
|
-
if (
|
|
3861
|
+
if (import_ts_morph8.Node.isTypeReference(typeNode)) {
|
|
3743
3862
|
const typeName = typeNode.getTypeName();
|
|
3744
|
-
const name =
|
|
3863
|
+
const name = import_ts_morph8.Node.isIdentifier(typeName) ? typeName.getText() : typeNode.getText();
|
|
3745
3864
|
const bound = subst.get(name);
|
|
3746
3865
|
if (bound !== void 0) return bound;
|
|
3747
3866
|
if (name === "string" || name === "number" || name === "boolean") return name;
|
|
@@ -3764,10 +3883,10 @@ function resolveTypeNodeToString(typeNode, sourceFile, project, depth, subst = /
|
|
|
3764
3883
|
dbg("unresolvable type:", name, "in", sourceFile.getFilePath());
|
|
3765
3884
|
return "unknown";
|
|
3766
3885
|
}
|
|
3767
|
-
if (
|
|
3886
|
+
if (import_ts_morph8.Node.isTypeLiteral(typeNode)) {
|
|
3768
3887
|
const members = [];
|
|
3769
3888
|
for (const member of typeNode.getMembers()) {
|
|
3770
|
-
if (
|
|
3889
|
+
if (import_ts_morph8.Node.isPropertySignature(member)) {
|
|
3771
3890
|
const memberTypeNode = member.getTypeNode();
|
|
3772
3891
|
const memberType = memberTypeNode ? resolveTypeNodeToString(memberTypeNode, sourceFile, project, depth, subst) : "unknown";
|
|
3773
3892
|
members.push(`${member.getName()}${member.hasQuestionToken() ? "?" : ""}: ${memberType}`);
|
|
@@ -3778,11 +3897,11 @@ function resolveTypeNodeToString(typeNode, sourceFile, project, depth, subst = /
|
|
|
3778
3897
|
return members.length > 0 ? `{ ${members.join("; ")} }` : "{}";
|
|
3779
3898
|
}
|
|
3780
3899
|
const kind = typeNode.getKind();
|
|
3781
|
-
if (kind ===
|
|
3782
|
-
if (kind ===
|
|
3783
|
-
if (kind ===
|
|
3784
|
-
if (kind ===
|
|
3785
|
-
if (kind ===
|
|
3900
|
+
if (kind === import_ts_morph8.SyntaxKind.StringKeyword) return "string";
|
|
3901
|
+
if (kind === import_ts_morph8.SyntaxKind.NumberKeyword) return "number";
|
|
3902
|
+
if (kind === import_ts_morph8.SyntaxKind.BooleanKeyword) return "boolean";
|
|
3903
|
+
if (kind === import_ts_morph8.SyntaxKind.UnknownKeyword) return "unknown";
|
|
3904
|
+
if (kind === import_ts_morph8.SyntaxKind.AnyKeyword) return "unknown";
|
|
3786
3905
|
return typeNode.getText();
|
|
3787
3906
|
}
|
|
3788
3907
|
function unwrapFirstTypeArg(typeNode, sourceFile, project, depth, mode, subst = /* @__PURE__ */ new Map()) {
|
|
@@ -3867,7 +3986,7 @@ function extractQueryType(method, sourceFile, project) {
|
|
|
3867
3986
|
if (!queryDecorator) continue;
|
|
3868
3987
|
const queryArgs = queryDecorator.getArguments();
|
|
3869
3988
|
const nameArg = queryArgs[0];
|
|
3870
|
-
if (!nameArg || !
|
|
3989
|
+
if (!nameArg || !import_ts_morph8.Node.isStringLiteral(nameArg)) continue;
|
|
3871
3990
|
const queryName = nameArg.getLiteralValue();
|
|
3872
3991
|
const typeNode = param.getTypeNode();
|
|
3873
3992
|
const queryType = typeNode ? resolveTypeNodeToString(typeNode, sourceFile, project, 3) : "string";
|
|
@@ -3878,8 +3997,8 @@ function extractQueryType(method, sourceFile, project) {
|
|
|
3878
3997
|
function isParamOptional(param) {
|
|
3879
3998
|
if (param.hasQuestionToken() || param.hasInitializer()) return true;
|
|
3880
3999
|
const typeNode = param.getTypeNode();
|
|
3881
|
-
if (typeNode &&
|
|
3882
|
-
return typeNode.getTypeNodes().some((t) => t.getKind() ===
|
|
4000
|
+
if (typeNode && import_ts_morph8.Node.isUnionTypeNode(typeNode)) {
|
|
4001
|
+
return typeNode.getTypeNodes().some((t) => t.getKind() === import_ts_morph8.SyntaxKind.UndefinedKeyword);
|
|
3883
4002
|
}
|
|
3884
4003
|
return false;
|
|
3885
4004
|
}
|
|
@@ -3891,7 +4010,7 @@ function extractParamsType(method, sourceFile, project) {
|
|
|
3891
4010
|
const paramArgs = paramDecorator.getArguments();
|
|
3892
4011
|
if (paramArgs.length === 0) continue;
|
|
3893
4012
|
const nameArg = paramArgs[0];
|
|
3894
|
-
if (!
|
|
4013
|
+
if (!import_ts_morph8.Node.isStringLiteral(nameArg)) continue;
|
|
3895
4014
|
const paramName = nameArg.getLiteralValue();
|
|
3896
4015
|
const typeNode = param.getTypeNode();
|
|
3897
4016
|
const paramType = typeNode ? resolveTypeNodeToString(typeNode, sourceFile, project, 3) : "string";
|
|
@@ -3912,28 +4031,28 @@ function extractUploadedFiles(method) {
|
|
|
3912
4031
|
for (const decorator of method.getDecorators()) {
|
|
3913
4032
|
if (decorator.getName() !== "UseInterceptors") continue;
|
|
3914
4033
|
for (const arg of decorator.getArguments()) {
|
|
3915
|
-
if (!
|
|
4034
|
+
if (!import_ts_morph8.Node.isCallExpression(arg)) continue;
|
|
3916
4035
|
const interceptor = arg.getExpression().getText();
|
|
3917
4036
|
const callArgs = arg.getArguments();
|
|
3918
4037
|
const firstArg2 = callArgs[0];
|
|
3919
4038
|
if (interceptor === "FileInterceptor") {
|
|
3920
|
-
if (firstArg2 &&
|
|
4039
|
+
if (firstArg2 && import_ts_morph8.Node.isStringLiteral(firstArg2)) {
|
|
3921
4040
|
entries.push(`${firstArg2.getLiteralValue()}: ${FILE}`);
|
|
3922
4041
|
multipart = true;
|
|
3923
4042
|
}
|
|
3924
4043
|
} else if (interceptor === "FilesInterceptor") {
|
|
3925
|
-
if (firstArg2 &&
|
|
4044
|
+
if (firstArg2 && import_ts_morph8.Node.isStringLiteral(firstArg2)) {
|
|
3926
4045
|
entries.push(`${firstArg2.getLiteralValue()}: Array<${FILE}>`);
|
|
3927
4046
|
multipart = true;
|
|
3928
4047
|
}
|
|
3929
4048
|
} else if (interceptor === "FileFieldsInterceptor") {
|
|
3930
|
-
if (firstArg2 &&
|
|
4049
|
+
if (firstArg2 && import_ts_morph8.Node.isArrayLiteralExpression(firstArg2)) {
|
|
3931
4050
|
for (const el of firstArg2.getElements()) {
|
|
3932
|
-
if (!
|
|
4051
|
+
if (!import_ts_morph8.Node.isObjectLiteralExpression(el)) continue;
|
|
3933
4052
|
const nameProp = el.getProperty("name");
|
|
3934
|
-
if (nameProp &&
|
|
4053
|
+
if (nameProp && import_ts_morph8.Node.isPropertyAssignment(nameProp)) {
|
|
3935
4054
|
const init = nameProp.getInitializer();
|
|
3936
|
-
if (init &&
|
|
4055
|
+
if (init && import_ts_morph8.Node.isStringLiteral(init)) {
|
|
3937
4056
|
entries.push(`${init.getLiteralValue()}: Array<${FILE}>`);
|
|
3938
4057
|
}
|
|
3939
4058
|
}
|
|
@@ -3953,13 +4072,13 @@ function extractResponseType(method, sourceFile, project) {
|
|
|
3953
4072
|
if (apiResponseDecorator) {
|
|
3954
4073
|
const args = apiResponseDecorator.getArguments();
|
|
3955
4074
|
const optsArg = args[0];
|
|
3956
|
-
if (optsArg &&
|
|
4075
|
+
if (optsArg && import_ts_morph8.Node.isObjectLiteralExpression(optsArg)) {
|
|
3957
4076
|
for (const prop of optsArg.getProperties()) {
|
|
3958
|
-
if (!
|
|
4077
|
+
if (!import_ts_morph8.Node.isPropertyAssignment(prop)) continue;
|
|
3959
4078
|
if (prop.getName() !== "type") continue;
|
|
3960
4079
|
const val = prop.getInitializer();
|
|
3961
4080
|
if (!val) continue;
|
|
3962
|
-
if (
|
|
4081
|
+
if (import_ts_morph8.Node.isArrayLiteralExpression(val)) {
|
|
3963
4082
|
const elements = val.getElements();
|
|
3964
4083
|
const firstEl = elements[0];
|
|
3965
4084
|
if (elements.length > 0 && firstEl !== void 0) {
|
|
@@ -3980,24 +4099,24 @@ function extractResponseType(method, sourceFile, project) {
|
|
|
3980
4099
|
}
|
|
3981
4100
|
function apiResponseStatus(decorator) {
|
|
3982
4101
|
const optsArg = decorator.getArguments()[0];
|
|
3983
|
-
if (!optsArg || !
|
|
4102
|
+
if (!optsArg || !import_ts_morph8.Node.isObjectLiteralExpression(optsArg)) return null;
|
|
3984
4103
|
for (const prop of optsArg.getProperties()) {
|
|
3985
|
-
if (!
|
|
4104
|
+
if (!import_ts_morph8.Node.isPropertyAssignment(prop)) continue;
|
|
3986
4105
|
if (prop.getName() !== "status") continue;
|
|
3987
4106
|
const val = prop.getInitializer();
|
|
3988
|
-
if (val &&
|
|
4107
|
+
if (val && import_ts_morph8.Node.isNumericLiteral(val)) return Number(val.getLiteralValue());
|
|
3989
4108
|
}
|
|
3990
4109
|
return null;
|
|
3991
4110
|
}
|
|
3992
4111
|
function apiResponseTypeNode(decorator) {
|
|
3993
4112
|
const optsArg = decorator.getArguments()[0];
|
|
3994
|
-
if (!optsArg || !
|
|
4113
|
+
if (!optsArg || !import_ts_morph8.Node.isObjectLiteralExpression(optsArg)) return null;
|
|
3995
4114
|
for (const prop of optsArg.getProperties()) {
|
|
3996
|
-
if (!
|
|
4115
|
+
if (!import_ts_morph8.Node.isPropertyAssignment(prop)) continue;
|
|
3997
4116
|
if (prop.getName() !== "type") continue;
|
|
3998
4117
|
const val = prop.getInitializer();
|
|
3999
4118
|
if (!val) return null;
|
|
4000
|
-
if (
|
|
4119
|
+
if (import_ts_morph8.Node.isArrayLiteralExpression(val)) {
|
|
4001
4120
|
const first = val.getElements()[0];
|
|
4002
4121
|
return first ? { node: first, isArray: true } : null;
|
|
4003
4122
|
}
|
|
@@ -4015,7 +4134,7 @@ function extractErrorType(method, sourceFile, project) {
|
|
|
4015
4134
|
const inner = resolveIdentifierToClassType(typeInfo.node, sourceFile, project, 3);
|
|
4016
4135
|
const type = typeInfo.isArray ? `Array<${inner}>` : inner;
|
|
4017
4136
|
let ref = null;
|
|
4018
|
-
if (
|
|
4137
|
+
if (import_ts_morph8.Node.isIdentifier(typeInfo.node)) {
|
|
4019
4138
|
const name = typeInfo.node.getText();
|
|
4020
4139
|
const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
|
|
4021
4140
|
if (localDecl?.isExported()) {
|
|
@@ -4032,7 +4151,7 @@ function extractErrorType(method, sourceFile, project) {
|
|
|
4032
4151
|
return null;
|
|
4033
4152
|
}
|
|
4034
4153
|
function resolveIdentifierToClassType(node, sourceFile, project, depth) {
|
|
4035
|
-
if (!
|
|
4154
|
+
if (!import_ts_morph8.Node.isIdentifier(node)) return "unknown";
|
|
4036
4155
|
const name = node.getText();
|
|
4037
4156
|
const resolved = findType(name, sourceFile, project);
|
|
4038
4157
|
if (resolved) {
|
|
@@ -4052,9 +4171,9 @@ var STREAM_ENVELOPES = /* @__PURE__ */ new Set(["MessageEvent", "MessageEventLik
|
|
|
4052
4171
|
var BINARY_RESPONSE_TYPES = /* @__PURE__ */ new Set(["StreamableFile", "Buffer"]);
|
|
4053
4172
|
function detectBinaryResponse(method) {
|
|
4054
4173
|
const node = unwrapNamedContainer(method.getReturnTypeNode(), /* @__PURE__ */ new Set(["Promise"]));
|
|
4055
|
-
if (!node || !
|
|
4174
|
+
if (!node || !import_ts_morph8.Node.isTypeReference(node)) return false;
|
|
4056
4175
|
const typeName = node.getTypeName();
|
|
4057
|
-
const name =
|
|
4176
|
+
const name = import_ts_morph8.Node.isIdentifier(typeName) ? typeName.getText() : "";
|
|
4058
4177
|
return BINARY_RESPONSE_TYPES.has(name);
|
|
4059
4178
|
}
|
|
4060
4179
|
function detectStreamElement(method) {
|
|
@@ -4069,9 +4188,9 @@ function detectStreamElement(method) {
|
|
|
4069
4188
|
return null;
|
|
4070
4189
|
}
|
|
4071
4190
|
function streamContainerElement(node) {
|
|
4072
|
-
if (!node || !
|
|
4191
|
+
if (!node || !import_ts_morph8.Node.isTypeReference(node)) return null;
|
|
4073
4192
|
const typeName = node.getTypeName();
|
|
4074
|
-
const name =
|
|
4193
|
+
const name = import_ts_morph8.Node.isIdentifier(typeName) ? typeName.getText() : "";
|
|
4075
4194
|
if (STREAM_CONTAINERS.has(name) || STREAM_CONTAINERS_GENERATOR.has(name)) {
|
|
4076
4195
|
return node.getTypeArguments()[0] ?? null;
|
|
4077
4196
|
}
|
|
@@ -4081,9 +4200,9 @@ function hasAsQueryDecorator(method) {
|
|
|
4081
4200
|
return method.getDecorators().some((d) => d.getName() === "AsQuery");
|
|
4082
4201
|
}
|
|
4083
4202
|
function unwrapNamedContainer(node, names) {
|
|
4084
|
-
if (!node || !
|
|
4203
|
+
if (!node || !import_ts_morph8.Node.isTypeReference(node)) return node;
|
|
4085
4204
|
const typeName = node.getTypeName();
|
|
4086
|
-
const name =
|
|
4205
|
+
const name = import_ts_morph8.Node.isIdentifier(typeName) ? typeName.getText() : "";
|
|
4087
4206
|
if (names.has(name)) {
|
|
4088
4207
|
return node.getTypeArguments()[0] ?? node;
|
|
4089
4208
|
}
|
|
@@ -4129,11 +4248,11 @@ function extractDtoContract(method, sourceFile, project, mixin) {
|
|
|
4129
4248
|
if (apiResp) {
|
|
4130
4249
|
const args = apiResp.getArguments();
|
|
4131
4250
|
const optsArg = args[0];
|
|
4132
|
-
if (optsArg &&
|
|
4251
|
+
if (optsArg && import_ts_morph8.Node.isObjectLiteralExpression(optsArg)) {
|
|
4133
4252
|
for (const prop of optsArg.getProperties()) {
|
|
4134
|
-
if (
|
|
4253
|
+
if (import_ts_morph8.Node.isPropertyAssignment(prop) && prop.getName() === "type") {
|
|
4135
4254
|
const val = prop.getInitializer();
|
|
4136
|
-
if (val &&
|
|
4255
|
+
if (val && import_ts_morph8.Node.isIdentifier(val)) {
|
|
4137
4256
|
const name = val.getText();
|
|
4138
4257
|
const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
|
|
4139
4258
|
if (localDecl?.isExported()) {
|
|
@@ -4201,101 +4320,6 @@ function resolveParamClass(method, decoratorName, sourceFile, project) {
|
|
|
4201
4320
|
return null;
|
|
4202
4321
|
}
|
|
4203
4322
|
|
|
4204
|
-
// src/discovery/heritage.ts
|
|
4205
|
-
var import_ts_morph8 = require("ts-morph");
|
|
4206
|
-
function resolveHeritageCall(node) {
|
|
4207
|
-
if (!node) return void 0;
|
|
4208
|
-
const expr = unwrapExpression(node);
|
|
4209
|
-
if (import_ts_morph8.Node.isCallExpression(expr)) return expr;
|
|
4210
|
-
if (!import_ts_morph8.Node.isIdentifier(expr)) return void 0;
|
|
4211
|
-
const decl = expr.getDefinitions().map((d) => d.getDeclarationNode()).find(
|
|
4212
|
-
(n) => n !== void 0 && import_ts_morph8.Node.isVariableDeclaration(n)
|
|
4213
|
-
);
|
|
4214
|
-
const init = decl?.getInitializer();
|
|
4215
|
-
if (!init) return void 0;
|
|
4216
|
-
const unwrapped = unwrapExpression(init);
|
|
4217
|
-
return import_ts_morph8.Node.isCallExpression(unwrapped) ? unwrapped : void 0;
|
|
4218
|
-
}
|
|
4219
|
-
function unwrapExpression(node) {
|
|
4220
|
-
let current = node;
|
|
4221
|
-
while (import_ts_morph8.Node.isAsExpression(current) || import_ts_morph8.Node.isSatisfiesExpression(current) || import_ts_morph8.Node.isParenthesizedExpression(current) || import_ts_morph8.Node.isTypeAssertion(current)) {
|
|
4222
|
-
current = current.getExpression();
|
|
4223
|
-
}
|
|
4224
|
-
return current;
|
|
4225
|
-
}
|
|
4226
|
-
function resolveReturnedClass(factoryDecl) {
|
|
4227
|
-
const body = factoryDecl.getBody();
|
|
4228
|
-
if (!body) return void 0;
|
|
4229
|
-
const returns = body.getDescendants().filter((n) => import_ts_morph8.Node.isReturnStatement(n));
|
|
4230
|
-
for (const ret of returns) {
|
|
4231
|
-
const expr = ret.getExpression();
|
|
4232
|
-
if (!expr) continue;
|
|
4233
|
-
const inner = unwrapExpression(expr);
|
|
4234
|
-
if (import_ts_morph8.Node.isClassExpression(inner)) {
|
|
4235
|
-
return inner;
|
|
4236
|
-
}
|
|
4237
|
-
if (import_ts_morph8.Node.isIdentifier(inner)) {
|
|
4238
|
-
const name = inner.getText();
|
|
4239
|
-
const decl = body.getDescendants().find((n) => import_ts_morph8.Node.isClassDeclaration(n) && n.getName() === name);
|
|
4240
|
-
if (decl) return decl;
|
|
4241
|
-
}
|
|
4242
|
-
}
|
|
4243
|
-
return void 0;
|
|
4244
|
-
}
|
|
4245
|
-
function resolveInheritedMethods(cls) {
|
|
4246
|
-
const expr = resolveHeritageCall(cls.getExtends()?.getExpression());
|
|
4247
|
-
if (!expr) return void 0;
|
|
4248
|
-
const callee = expr.getExpression();
|
|
4249
|
-
if (!import_ts_morph8.Node.isIdentifier(callee)) return void 0;
|
|
4250
|
-
const factoryDecl = callee.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => import_ts_morph8.Node.isFunctionDeclaration(n));
|
|
4251
|
-
if (!factoryDecl) return void 0;
|
|
4252
|
-
const returnedClass = resolveReturnedClass(factoryDecl);
|
|
4253
|
-
if (!returnedClass) return void 0;
|
|
4254
|
-
const classArgs = [];
|
|
4255
|
-
for (const arg of expr.getArguments()) {
|
|
4256
|
-
if (!import_ts_morph8.Node.isIdentifier(arg)) continue;
|
|
4257
|
-
const decl = arg.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => import_ts_morph8.Node.isClassDeclaration(n));
|
|
4258
|
-
if (decl) {
|
|
4259
|
-
classArgs.push({
|
|
4260
|
-
name: decl.getName() ?? arg.getText(),
|
|
4261
|
-
filePath: decl.getSourceFile().getFilePath()
|
|
4262
|
-
});
|
|
4263
|
-
}
|
|
4264
|
-
}
|
|
4265
|
-
return {
|
|
4266
|
-
methods: returnedClass.getMethods(),
|
|
4267
|
-
factoryName: callee.getText(),
|
|
4268
|
-
factoryFilePath: factoryDecl.getSourceFile().getFilePath(),
|
|
4269
|
-
classArgs
|
|
4270
|
-
};
|
|
4271
|
-
}
|
|
4272
|
-
var mixinTypeProject;
|
|
4273
|
-
function getMixinTypeProject() {
|
|
4274
|
-
mixinTypeProject ??= new import_ts_morph8.Project({
|
|
4275
|
-
skipAddingFilesFromTsConfig: true,
|
|
4276
|
-
compilerOptions: { strict: true }
|
|
4277
|
-
});
|
|
4278
|
-
return mixinTypeProject;
|
|
4279
|
-
}
|
|
4280
|
-
function clearMixinTypeProject() {
|
|
4281
|
-
mixinTypeProject = void 0;
|
|
4282
|
-
}
|
|
4283
|
-
function resolveInstantiatedReturnType(cls, methodName) {
|
|
4284
|
-
const filePath = cls.getSourceFile().getFilePath();
|
|
4285
|
-
const className = cls.getName();
|
|
4286
|
-
if (!className) return void 0;
|
|
4287
|
-
const project = getMixinTypeProject();
|
|
4288
|
-
const sourceFile = project.getSourceFile(filePath) ?? project.addSourceFileAtPathIfExists(filePath);
|
|
4289
|
-
const typedCls = sourceFile?.getClass(className);
|
|
4290
|
-
if (!typedCls) return void 0;
|
|
4291
|
-
const prop = typedCls.getType().getProperty(methodName);
|
|
4292
|
-
if (!prop) return void 0;
|
|
4293
|
-
const returnType = prop.getTypeAtLocation(typedCls).getCallSignatures()[0]?.getReturnType();
|
|
4294
|
-
if (!returnType) return void 0;
|
|
4295
|
-
const unwrapped = returnType.getSymbol()?.getName() === "Promise" ? returnType.getTypeArguments()[0] ?? returnType : returnType;
|
|
4296
|
-
return unwrapped.getText(typedCls);
|
|
4297
|
-
}
|
|
4298
|
-
|
|
4299
4323
|
// src/discovery/zod-ast-to-ts.ts
|
|
4300
4324
|
var import_ts_morph9 = require("ts-morph");
|
|
4301
4325
|
function zodAstToTs(node) {
|
|
@@ -5029,7 +5053,7 @@ async function watch(config, onChange, options = {}) {
|
|
|
5029
5053
|
}
|
|
5030
5054
|
|
|
5031
5055
|
// src/index.ts
|
|
5032
|
-
var VERSION = "0.17.
|
|
5056
|
+
var VERSION = "0.17.2";
|
|
5033
5057
|
|
|
5034
5058
|
// src/cli/codegen.ts
|
|
5035
5059
|
async function runCodegen(opts = {}) {
|