Skip to content

[codegen] Filter controller classes before importing generated modules #663

Description

@kang-heewon

Priority

P1 - codegen reliability / common controller-file layout

Problem

The OpenAPI and RPC codegen CLIs compile matched source files, then attempt to import every class in those files as if each class were an exported controller. Real controller files commonly contain local DTOs, helper classes, guards, or non-exported classes next to the controller. Those files can make codegen fail with a misleading "Controller class ... is not exported" error or wastefully inspect non-controller classes.

Evidence

Source of truth: trunk@6d61236.

  • packages/openapi-spec/src/cli.ts:84-94 loops over sourceFiles.flatMap((sourceFile) => sourceFile.getClasses()) and imports every class through importController().
  • packages/openapi-spec/src/cli.ts:102-109 throws if that class name is not exported from the emitted module.
  • packages/rpc-codegen/src/cli.ts:80-90 has the same every-class import loop before calling extractRouteIR().
  • packages/rpc-codegen/src/cli.ts:98-105 has the same exported-class requirement.
  • packages/protocols-rest/src/libs/metadata/MetadataReader.ts:126-127 already exposes an isController() helper that can identify actual REST controllers once constructors are available.

Desired Outcome

Codegen ignores non-controller classes in matched files and only extracts routes from real exported controllers.

Implementation Path

  • Decide whether filtering happens before import via decorator metadata/source inspection or after import via exported constructor metadata.
  • Avoid importing by every declared class name; instead inspect module exports and select constructors that carry controller metadata.
  • Share the controller discovery implementation between openapi-spec and rpc-codegen to prevent divergent behavior.
  • Add fixtures with a controller file that includes an unexported DTO/helper class and an exported non-controller class.
  • Make the error for "no controllers found" explicit and actionable.

Acceptance Criteria

  • Codegen succeeds when a matched controller file contains unexported DTO/helper classes.
  • Codegen ignores exported non-controller classes in the same file.
  • Codegen still fails clearly when no exported controller is found in any matched file.
  • OpenAPI and RPC codegen use the same discovery behavior or an explicitly shared test fixture.

Validation

  • Run pnpm --filter @croco/openapi-spec test.
  • Run pnpm --filter @croco/rpc-codegen test.
  • Add CLI/e2e fixture coverage for controller files with co-located non-controller classes.

Scope Boundaries

  • Do not expand this into full project graph discovery.
  • Do not change route extraction semantics beyond controller selection.

Metadata

Metadata

Assignees

Labels

P1Priority 1 issuebugSomething isn't workingtech-debtTechnical debt

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions