@dudousxd/nestjs-codegen 0.17.0 → 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/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 import_ts_morph7 = require("ts-morph");
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 import_ts_morph6 = require("ts-morph");
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 (import_ts_morph6.Node.isStringLiteral(typeInit)) {
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 (import_ts_morph6.Node.isArrayLiteralExpression(typeInit)) {
3592
+ if (import_ts_morph7.Node.isArrayLiteralExpression(typeInit)) {
3476
3593
  const values = [];
3477
3594
  for (const el of typeInit.getElements()) {
3478
- if (!import_ts_morph6.Node.isStringLiteral(el)) return null;
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 && import_ts_morph6.Node.isStringLiteral(keyArg) ? keyArg.getLiteralValue() : method.getName();
3630
+ const inputKey = keyArg && import_ts_morph7.Node.isStringLiteral(keyArg) ? keyArg.getLiteralValue() : method.getName();
3514
3631
  const optsArg = args[1];
3515
- if (optsArg && import_ts_morph6.Node.isObjectLiteralExpression(optsArg)) {
3632
+ if (optsArg && import_ts_morph7.Node.isObjectLiteralExpression(optsArg)) {
3516
3633
  const typeProp = optsArg.getProperty("type");
3517
- if (typeProp && import_ts_morph6.Node.isPropertyAssignment(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 || !import_ts_morph6.Node.isIdentifier(filterClassArg)) continue;
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 && import_ts_morph6.Node.isObjectLiteralExpression(optionsArg)) {
3664
+ if (optionsArg && import_ts_morph7.Node.isObjectLiteralExpression(optionsArg)) {
3546
3665
  const sourceProp = optionsArg.getProperty("source");
3547
- if (sourceProp && import_ts_morph6.Node.isPropertyAssignment(sourceProp)) {
3666
+ if (sourceProp && import_ts_morph7.Node.isPropertyAssignment(sourceProp)) {
3548
3667
  const init = sourceProp.getInitializer();
3549
- if (init && import_ts_morph6.Node.isStringLiteral(init) && init.getLiteralValue() === "body") {
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 (import_ts_morph6.Node.isObjectLiteralExpression(arg)) {
3731
+ if (import_ts_morph7.Node.isObjectLiteralExpression(arg)) {
3613
3732
  const entityProp = arg.getProperty("entity");
3614
- if (entityProp && import_ts_morph6.Node.isPropertyAssignment(entityProp)) {
3733
+ if (entityProp && import_ts_morph7.Node.isPropertyAssignment(entityProp)) {
3615
3734
  const init = entityProp.getInitializer();
3616
- if (init && import_ts_morph6.Node.isArrowFunction(init)) {
3735
+ if (init && import_ts_morph7.Node.isArrowFunction(init)) {
3617
3736
  const body = init.getBody();
3618
- if (import_ts_morph6.Node.isIdentifier(body)) {
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 (import_ts_morph6.Node.isArrowFunction(arg)) {
3744
+ if (import_ts_morph7.Node.isArrowFunction(arg)) {
3626
3745
  const body = arg.getBody();
3627
- if (import_ts_morph6.Node.isIdentifier(body)) {
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 (!import_ts_morph6.Node.isIdentifier(identifier)) return void 0;
3647
- return identifier.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => n !== void 0 && import_ts_morph6.Node.isClassDeclaration(n));
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 (!import_ts_morph6.Node.isObjectLiteralExpression(optionsArg)) return void 0;
3769
+ if (!import_ts_morph7.Node.isObjectLiteralExpression(optionsArg)) return void 0;
3651
3770
  const entityProp = optionsArg.getProperty("entity");
3652
- if (!entityProp || !import_ts_morph6.Node.isPropertyAssignment(entityProp)) return void 0;
3771
+ if (!entityProp || !import_ts_morph7.Node.isPropertyAssignment(entityProp)) return void 0;
3653
3772
  const entityInit = entityProp.getInitializer();
3654
- if (!entityInit || !import_ts_morph6.Node.isIdentifier(entityInit)) return void 0;
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 (!import_ts_morph6.Node.isObjectLiteralExpression(optionsArg)) return [];
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 && import_ts_morph6.Node.isObjectLiteralExpression(relArgs[0])) {
3797
+ if (relArgs.length > 0 && import_ts_morph7.Node.isObjectLiteralExpression(relArgs[0])) {
3679
3798
  for (const relProp of relArgs[0].getProperties()) {
3680
- if (!import_ts_morph6.Node.isPropertyAssignment(relProp)) continue;
3799
+ if (!import_ts_morph7.Node.isPropertyAssignment(relProp)) continue;
3681
3800
  const relInit = relProp.getInitializer();
3682
- if (!relInit || !import_ts_morph6.Node.isObjectLiteralExpression(relInit)) continue;
3801
+ if (!relInit || !import_ts_morph7.Node.isObjectLiteralExpression(relInit)) continue;
3683
3802
  const keysProp = relInit.getProperty("keys");
3684
- if (!keysProp || !import_ts_morph6.Node.isPropertyAssignment(keysProp)) continue;
3803
+ if (!keysProp || !import_ts_morph7.Node.isPropertyAssignment(keysProp)) continue;
3685
3804
  const keysInit = keysProp.getInitializer();
3686
- if (!keysInit || !import_ts_morph6.Node.isArrayLiteralExpression(keysInit)) continue;
3805
+ if (!keysInit || !import_ts_morph7.Node.isArrayLiteralExpression(keysInit)) continue;
3687
3806
  for (const el of keysInit.getElements()) {
3688
- if (import_ts_morph6.Node.isStringLiteral(el)) {
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 (import_ts_morph7.Node.isArrayTypeNode(typeNode)) {
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 (import_ts_morph7.Node.isUnionTypeNode(typeNode)) {
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 (import_ts_morph7.Node.isIntersectionTypeNode(typeNode)) {
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 (import_ts_morph7.Node.isParenthesizedTypeNode(typeNode)) {
3858
+ if (import_ts_morph8.Node.isParenthesizedTypeNode(typeNode)) {
3740
3859
  return `(${resolveTypeNodeToString(typeNode.getTypeNode(), sourceFile, project, depth, subst)})`;
3741
3860
  }
3742
- if (import_ts_morph7.Node.isTypeReference(typeNode)) {
3861
+ if (import_ts_morph8.Node.isTypeReference(typeNode)) {
3743
3862
  const typeName = typeNode.getTypeName();
3744
- const name = import_ts_morph7.Node.isIdentifier(typeName) ? typeName.getText() : typeNode.getText();
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 (import_ts_morph7.Node.isTypeLiteral(typeNode)) {
3886
+ if (import_ts_morph8.Node.isTypeLiteral(typeNode)) {
3768
3887
  const members = [];
3769
3888
  for (const member of typeNode.getMembers()) {
3770
- if (import_ts_morph7.Node.isPropertySignature(member)) {
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 === import_ts_morph7.SyntaxKind.StringKeyword) return "string";
3782
- if (kind === import_ts_morph7.SyntaxKind.NumberKeyword) return "number";
3783
- if (kind === import_ts_morph7.SyntaxKind.BooleanKeyword) return "boolean";
3784
- if (kind === import_ts_morph7.SyntaxKind.UnknownKeyword) return "unknown";
3785
- if (kind === import_ts_morph7.SyntaxKind.AnyKeyword) return "unknown";
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 || !import_ts_morph7.Node.isStringLiteral(nameArg)) continue;
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 && import_ts_morph7.Node.isUnionTypeNode(typeNode)) {
3882
- return typeNode.getTypeNodes().some((t) => t.getKind() === import_ts_morph7.SyntaxKind.UndefinedKeyword);
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 (!import_ts_morph7.Node.isStringLiteral(nameArg)) continue;
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 (!import_ts_morph7.Node.isCallExpression(arg)) continue;
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 && import_ts_morph7.Node.isStringLiteral(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 && import_ts_morph7.Node.isStringLiteral(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 && import_ts_morph7.Node.isArrayLiteralExpression(firstArg2)) {
4049
+ if (firstArg2 && import_ts_morph8.Node.isArrayLiteralExpression(firstArg2)) {
3931
4050
  for (const el of firstArg2.getElements()) {
3932
- if (!import_ts_morph7.Node.isObjectLiteralExpression(el)) continue;
4051
+ if (!import_ts_morph8.Node.isObjectLiteralExpression(el)) continue;
3933
4052
  const nameProp = el.getProperty("name");
3934
- if (nameProp && import_ts_morph7.Node.isPropertyAssignment(nameProp)) {
4053
+ if (nameProp && import_ts_morph8.Node.isPropertyAssignment(nameProp)) {
3935
4054
  const init = nameProp.getInitializer();
3936
- if (init && import_ts_morph7.Node.isStringLiteral(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 && import_ts_morph7.Node.isObjectLiteralExpression(optsArg)) {
4075
+ if (optsArg && import_ts_morph8.Node.isObjectLiteralExpression(optsArg)) {
3957
4076
  for (const prop of optsArg.getProperties()) {
3958
- if (!import_ts_morph7.Node.isPropertyAssignment(prop)) continue;
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 (import_ts_morph7.Node.isArrayLiteralExpression(val)) {
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 || !import_ts_morph7.Node.isObjectLiteralExpression(optsArg)) return null;
4102
+ if (!optsArg || !import_ts_morph8.Node.isObjectLiteralExpression(optsArg)) return null;
3984
4103
  for (const prop of optsArg.getProperties()) {
3985
- if (!import_ts_morph7.Node.isPropertyAssignment(prop)) continue;
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 && import_ts_morph7.Node.isNumericLiteral(val)) return Number(val.getLiteralValue());
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 || !import_ts_morph7.Node.isObjectLiteralExpression(optsArg)) return null;
4113
+ if (!optsArg || !import_ts_morph8.Node.isObjectLiteralExpression(optsArg)) return null;
3995
4114
  for (const prop of optsArg.getProperties()) {
3996
- if (!import_ts_morph7.Node.isPropertyAssignment(prop)) continue;
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 (import_ts_morph7.Node.isArrayLiteralExpression(val)) {
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 (import_ts_morph7.Node.isIdentifier(typeInfo.node)) {
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 (!import_ts_morph7.Node.isIdentifier(node)) return "unknown";
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 || !import_ts_morph7.Node.isTypeReference(node)) return false;
4174
+ if (!node || !import_ts_morph8.Node.isTypeReference(node)) return false;
4056
4175
  const typeName = node.getTypeName();
4057
- const name = import_ts_morph7.Node.isIdentifier(typeName) ? typeName.getText() : "";
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 || !import_ts_morph7.Node.isTypeReference(node)) return null;
4191
+ if (!node || !import_ts_morph8.Node.isTypeReference(node)) return null;
4073
4192
  const typeName = node.getTypeName();
4074
- const name = import_ts_morph7.Node.isIdentifier(typeName) ? typeName.getText() : "";
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 || !import_ts_morph7.Node.isTypeReference(node)) return node;
4203
+ if (!node || !import_ts_morph8.Node.isTypeReference(node)) return node;
4085
4204
  const typeName = node.getTypeName();
4086
- const name = import_ts_morph7.Node.isIdentifier(typeName) ? typeName.getText() : "";
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 && import_ts_morph7.Node.isObjectLiteralExpression(optsArg)) {
4251
+ if (optsArg && import_ts_morph8.Node.isObjectLiteralExpression(optsArg)) {
4133
4252
  for (const prop of optsArg.getProperties()) {
4134
- if (import_ts_morph7.Node.isPropertyAssignment(prop) && prop.getName() === "type") {
4253
+ if (import_ts_morph8.Node.isPropertyAssignment(prop) && prop.getName() === "type") {
4135
4254
  const val = prop.getInitializer();
4136
- if (val && import_ts_morph7.Node.isIdentifier(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,88 +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 unwrapExpression(node) {
4207
- let current = node;
4208
- 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)) {
4209
- current = current.getExpression();
4210
- }
4211
- return current;
4212
- }
4213
- function resolveReturnedClass(factoryDecl) {
4214
- const body = factoryDecl.getBody();
4215
- if (!body) return void 0;
4216
- const returns = body.getDescendants().filter((n) => import_ts_morph8.Node.isReturnStatement(n));
4217
- for (const ret of returns) {
4218
- const expr = ret.getExpression();
4219
- if (!expr) continue;
4220
- const inner = unwrapExpression(expr);
4221
- if (import_ts_morph8.Node.isClassExpression(inner)) {
4222
- return inner;
4223
- }
4224
- if (import_ts_morph8.Node.isIdentifier(inner)) {
4225
- const name = inner.getText();
4226
- const decl = body.getDescendants().find((n) => import_ts_morph8.Node.isClassDeclaration(n) && n.getName() === name);
4227
- if (decl) return decl;
4228
- }
4229
- }
4230
- return void 0;
4231
- }
4232
- function resolveInheritedMethods(cls) {
4233
- const expr = cls.getExtends()?.getExpression();
4234
- if (!expr || !import_ts_morph8.Node.isCallExpression(expr)) return void 0;
4235
- const callee = expr.getExpression();
4236
- if (!import_ts_morph8.Node.isIdentifier(callee)) return void 0;
4237
- const factoryDecl = callee.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => import_ts_morph8.Node.isFunctionDeclaration(n));
4238
- if (!factoryDecl) return void 0;
4239
- const returnedClass = resolveReturnedClass(factoryDecl);
4240
- if (!returnedClass) return void 0;
4241
- const classArgs = [];
4242
- for (const arg of expr.getArguments()) {
4243
- if (!import_ts_morph8.Node.isIdentifier(arg)) continue;
4244
- const decl = arg.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => import_ts_morph8.Node.isClassDeclaration(n));
4245
- if (decl) {
4246
- classArgs.push({
4247
- name: decl.getName() ?? arg.getText(),
4248
- filePath: decl.getSourceFile().getFilePath()
4249
- });
4250
- }
4251
- }
4252
- return {
4253
- methods: returnedClass.getMethods(),
4254
- factoryName: callee.getText(),
4255
- factoryFilePath: factoryDecl.getSourceFile().getFilePath(),
4256
- classArgs
4257
- };
4258
- }
4259
- var mixinTypeProject;
4260
- function getMixinTypeProject() {
4261
- mixinTypeProject ??= new import_ts_morph8.Project({
4262
- skipAddingFilesFromTsConfig: true,
4263
- compilerOptions: { strict: true }
4264
- });
4265
- return mixinTypeProject;
4266
- }
4267
- function clearMixinTypeProject() {
4268
- mixinTypeProject = void 0;
4269
- }
4270
- function resolveInstantiatedReturnType(cls, methodName) {
4271
- const filePath = cls.getSourceFile().getFilePath();
4272
- const className = cls.getName();
4273
- if (!className) return void 0;
4274
- const project = getMixinTypeProject();
4275
- const sourceFile = project.getSourceFile(filePath) ?? project.addSourceFileAtPathIfExists(filePath);
4276
- const typedCls = sourceFile?.getClass(className);
4277
- if (!typedCls) return void 0;
4278
- const prop = typedCls.getType().getProperty(methodName);
4279
- if (!prop) return void 0;
4280
- const returnType = prop.getTypeAtLocation(typedCls).getCallSignatures()[0]?.getReturnType();
4281
- if (!returnType) return void 0;
4282
- const unwrapped = returnType.getSymbol()?.getName() === "Promise" ? returnType.getTypeArguments()[0] ?? returnType : returnType;
4283
- return unwrapped.getText(typedCls);
4284
- }
4285
-
4286
4323
  // src/discovery/zod-ast-to-ts.ts
4287
4324
  var import_ts_morph9 = require("ts-morph");
4288
4325
  function zodAstToTs(node) {
@@ -4786,9 +4823,11 @@ function extractFromSourceFile(sourceFile, project) {
4786
4823
  factoryFilePath: inherited.factoryFilePath,
4787
4824
  classArgs: inherited.classArgs
4788
4825
  } : void 0;
4826
+ const ownMethods = cls.getMethods();
4827
+ const ownNames = new Set(ownMethods.map((m) => m.getName()));
4789
4828
  const methods = [
4790
- ...cls.getMethods().map((method) => ({ method })),
4791
- ...(inherited?.methods ?? []).map((method) => ({ method, mixin: mixinBinding }))
4829
+ ...ownMethods.map((method) => ({ method, mixin: mixinBinding })),
4830
+ ...(inherited?.methods ?? []).filter((method) => !ownNames.has(method.getName())).map((method) => ({ method, mixin: mixinBinding }))
4792
4831
  ];
4793
4832
  for (const { method, mixin } of methods) {
4794
4833
  const verb = resolveVerb(method);
@@ -5014,7 +5053,7 @@ async function watch(config, onChange, options = {}) {
5014
5053
  }
5015
5054
 
5016
5055
  // src/index.ts
5017
- var VERSION = "0.17.0";
5056
+ var VERSION = "0.17.2";
5018
5057
 
5019
5058
  // src/cli/codegen.ts
5020
5059
  async function runCodegen(opts = {}) {