@dudousxd/nestjs-codegen 0.19.0 → 0.21.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.
@@ -3470,10 +3470,15 @@ function resolveInstantiatedReturnType(cls, methodName) {
3470
3470
 
3471
3471
  // src/discovery/filter-for.ts
3472
3472
  function resolveMixinEntityClass(mixin, project) {
3473
- const entityArg = mixin?.namedClassArgs?.entity ?? mixin?.classArgs[0];
3474
- if (!entityArg) return void 0;
3475
- const file = project.getSourceFile(entityArg.filePath) ?? project.addSourceFileAtPathIfExists(entityArg.filePath);
3476
- return file?.getClass(entityArg.name);
3473
+ return resolveClassRef(mixin?.namedClassArgs?.entity ?? mixin?.classArgs[0], project);
3474
+ }
3475
+ function resolveMixinFilterClass(mixin, project) {
3476
+ return resolveClassRef(mixin?.namedClassArgs?.filter, project);
3477
+ }
3478
+ function resolveClassRef(ref, project) {
3479
+ if (!ref) return void 0;
3480
+ const file = project.getSourceFile(ref.filePath) ?? project.addSourceFileAtPathIfExists(ref.filePath);
3481
+ return file?.getClass(ref.name);
3477
3482
  }
3478
3483
  function classifyFilterForHint(typeInit) {
3479
3484
  if (import_ts_morph7.Node.isStringLiteral(typeInit)) {
@@ -3548,7 +3553,7 @@ function extractFilterForHints(classDecl, project) {
3548
3553
  }
3549
3554
  return hints;
3550
3555
  }
3551
- function extractApplyFilterInfo(method, sourceFile, project, mixin) {
3556
+ function extractApplyFilterInfo(method, sourceFile, project, mixin, controllerClass) {
3552
3557
  const declFile = method.getSourceFile();
3553
3558
  const mixinEntity = resolveMixinEntityClass(mixin, project);
3554
3559
  for (const param of method.getParameters()) {
@@ -3573,31 +3578,55 @@ function extractApplyFilterInfo(method, sourceFile, project, mixin) {
3573
3578
  }
3574
3579
  const filterClassName = filterClassArg.getText();
3575
3580
  const resolved = factoryStaticClass ? void 0 : findType(filterClassName, declFile, project);
3576
- const classDecl = factoryStaticClass ?? (resolved?.kind === "class" ? resolved.decl : resolveLocalClassDeclaration(filterClassArg));
3577
- if (classDecl) {
3578
- let fieldTypes = extractClassPropertyTypes(classDecl, project);
3579
- if (fieldTypes.length === 0) {
3580
- fieldTypes = extractFilterableEntityFields(classDecl, project, mixinEntity);
3581
- }
3582
- const filterForHints = extractFilterForHints(classDecl, project);
3583
- if (filterForHints.size > 0) {
3584
- const byName = new Map(fieldTypes.map((f) => [f.name, f]));
3585
- for (const [key, classified] of filterForHints) {
3586
- byName.set(key, toFilterFieldType(key, classified));
3587
- }
3588
- fieldTypes = [...byName.values()];
3589
- }
3590
- if (fieldTypes.length === 0) return null;
3591
- const fieldNames = fieldTypes.map((f) => f.name);
3581
+ const declaredClass = factoryStaticClass ?? (resolved?.kind === "class" ? resolved.decl : resolveLocalClassDeclaration(filterClassArg));
3582
+ const ownRoute = !mixin || (controllerClass ? method.getParent() === controllerClass : declFile.getFilePath() !== mixin.factoryFilePath);
3583
+ const namedByRoute = ownRoute && import_ts_morph7.Node.isIdentifier(filterClassArg) ? declaredClass : void 0;
3584
+ for (const candidate of orderFilterCandidates({
3585
+ namedByRoute,
3586
+ supplied: resolveMixinFilterClass(mixin, project),
3587
+ declared: declaredClass
3588
+ })) {
3589
+ const fieldTypes = collectFilterFields(candidate, project, mixinEntity);
3590
+ if (fieldTypes.length === 0) continue;
3592
3591
  return {
3593
- fieldNames,
3592
+ fieldNames: fieldTypes.map((f) => f.name),
3594
3593
  fieldTypes,
3595
3594
  source
3596
3595
  };
3597
3596
  }
3597
+ if (declaredClass) return null;
3598
3598
  }
3599
3599
  return null;
3600
3600
  }
3601
+ function orderFilterCandidates(sources) {
3602
+ const ordered = [];
3603
+ const seen = /* @__PURE__ */ new Set();
3604
+ const push = (decl, preferDeclaredEntity) => {
3605
+ if (!decl || seen.has(decl)) return;
3606
+ seen.add(decl);
3607
+ ordered.push({ decl, preferDeclaredEntity });
3608
+ };
3609
+ push(sources.namedByRoute, true);
3610
+ push(sources.supplied, true);
3611
+ push(sources.declared, false);
3612
+ return ordered;
3613
+ }
3614
+ function collectFilterFields(candidate, project, mixinEntity) {
3615
+ const { decl, preferDeclaredEntity } = candidate;
3616
+ let fieldTypes = extractClassPropertyTypes(decl, project);
3617
+ if (fieldTypes.length === 0) {
3618
+ fieldTypes = extractFilterableEntityFields(decl, project, mixinEntity, preferDeclaredEntity);
3619
+ }
3620
+ const filterForHints = extractFilterForHints(decl, project);
3621
+ if (filterForHints.size > 0) {
3622
+ const byName = new Map(fieldTypes.map((f) => [f.name, f]));
3623
+ for (const [key, classified] of filterForHints) {
3624
+ byName.set(key, toFilterFieldType(key, classified));
3625
+ }
3626
+ fieldTypes = [...byName.values()];
3627
+ }
3628
+ return fieldTypes;
3629
+ }
3601
3630
  var RELATION_DECORATORS = /* @__PURE__ */ new Set(["OneToMany", "ManyToOne", "ManyToMany", "OneToOne"]);
3602
3631
  function collectEntityFields(entityDecl, sourceFile, project, prefix, visited) {
3603
3632
  const entityName = entityDecl.getName() ?? "";
@@ -3676,21 +3705,53 @@ function resolveDeclaredEntity(optionsArg, filterClass, project) {
3676
3705
  if (!resolved || resolved.kind !== "class") return void 0;
3677
3706
  return resolved.decl;
3678
3707
  }
3679
- function extractFilterableEntityFields(filterClass, project, entityOverride) {
3708
+ function readFieldNameList(optionsArg, key) {
3709
+ if (!import_ts_morph7.Node.isObjectLiteralExpression(optionsArg)) return void 0;
3710
+ const prop = optionsArg.getProperty(key);
3711
+ if (!prop || !import_ts_morph7.Node.isPropertyAssignment(prop)) return void 0;
3712
+ const init = prop.getInitializer();
3713
+ if (!init || !import_ts_morph7.Node.isArrayLiteralExpression(init)) return void 0;
3714
+ const names = /* @__PURE__ */ new Set();
3715
+ for (const el of init.getElements()) {
3716
+ if (import_ts_morph7.Node.isStringLiteral(el)) {
3717
+ names.add(el.getLiteralValue());
3718
+ continue;
3719
+ }
3720
+ if (import_ts_morph7.Node.isObjectLiteralExpression(el)) {
3721
+ const fieldProp = el.getProperty("field");
3722
+ if (fieldProp && import_ts_morph7.Node.isPropertyAssignment(fieldProp)) {
3723
+ const fieldInit = fieldProp.getInitializer();
3724
+ if (fieldInit && import_ts_morph7.Node.isStringLiteral(fieldInit)) {
3725
+ names.add(fieldInit.getLiteralValue());
3726
+ continue;
3727
+ }
3728
+ }
3729
+ }
3730
+ return void 0;
3731
+ }
3732
+ return names;
3733
+ }
3734
+ function narrowToDeclaredFields(fields, optionsArg) {
3735
+ const allowed = readFieldNameList(optionsArg, "allowed");
3736
+ const blocked = readFieldNameList(optionsArg, "blocked");
3737
+ if (!allowed && !blocked) return fields;
3738
+ return fields.filter(
3739
+ (f) => (!allowed || allowed.has(f.name)) && !(blocked?.has(f.name) ?? false)
3740
+ );
3741
+ }
3742
+ function extractFilterableEntityFields(filterClass, project, entityOverride, preferDeclaredEntity = false) {
3680
3743
  const filterableDecorator = filterClass.getDecorators().find((d) => d.getName() === "Filterable");
3681
3744
  if (!filterableDecorator) return [];
3682
3745
  const args = filterableDecorator.getArguments();
3683
3746
  if (args.length === 0) return [];
3684
3747
  const optionsArg = args[0];
3685
3748
  if (!import_ts_morph7.Node.isObjectLiteralExpression(optionsArg)) return [];
3686
- const entityDecl = entityOverride ?? resolveDeclaredEntity(optionsArg, filterClass, project);
3749
+ const declaredEntity = resolveDeclaredEntity(optionsArg, filterClass, project);
3750
+ const entityDecl = preferDeclaredEntity ? declaredEntity ?? entityOverride : entityOverride ?? declaredEntity;
3687
3751
  if (!entityDecl) return [];
3688
- const fields = collectEntityFields(
3689
- entityDecl,
3690
- entityDecl.getSourceFile(),
3691
- project,
3692
- "",
3693
- /* @__PURE__ */ new Set()
3752
+ const fields = narrowToDeclaredFields(
3753
+ collectEntityFields(entityDecl, entityDecl.getSourceFile(), project, "", /* @__PURE__ */ new Set()),
3754
+ optionsArg
3694
3755
  );
3695
3756
  const relationsDecorator = filterClass.getDecorators().find((d) => d.getName() === "Relations");
3696
3757
  if (relationsDecorator) {
@@ -4109,9 +4170,9 @@ function unwrapNamedContainer(node, names) {
4109
4170
  }
4110
4171
  return node;
4111
4172
  }
4112
- function extractDtoContract(method, sourceFile, project, mixin) {
4173
+ function extractDtoContract(method, sourceFile, project, mixin, controllerClass) {
4113
4174
  let body = extractBodyType(method, sourceFile, project);
4114
- const filterInfo = extractApplyFilterInfo(method, sourceFile, project, mixin);
4175
+ const filterInfo = extractApplyFilterInfo(method, sourceFile, project, mixin, controllerClass);
4115
4176
  const query = extractQueryType(method, sourceFile, project);
4116
4177
  const uploads = extractUploadedFiles(method);
4117
4178
  const multipartBody = uploads.fields ? `{ ${uploads.fields} }` : null;
@@ -4655,7 +4716,7 @@ function extractDtoRoute(args) {
4655
4716
  const methodName = method.getName();
4656
4717
  const classAs = readAsDecorator(cls, `class ${className}`);
4657
4718
  const methodAs = readAsDecorator(method, `${className}.${methodName}`);
4658
- const dtoContract = extractDtoContract(method, sourceFile, project, mixin);
4719
+ const dtoContract = extractDtoContract(method, sourceFile, project, mixin, cls);
4659
4720
  const mixinResponse = mixin ? resolveInstantiatedReturnType(cls, methodName) : void 0;
4660
4721
  return buildRoute({
4661
4722
  className,
@@ -4936,7 +4997,7 @@ async function watch(config, onChange, options = {}) {
4936
4997
  }
4937
4998
 
4938
4999
  // src/index.ts
4939
- var VERSION = "0.19.0";
5000
+ var VERSION = "0.21.0";
4940
5001
 
4941
5002
  // src/generate-manifest.ts
4942
5003
  var MANIFEST_FILE = ".codegen-manifest.json";