Skip to content

feat: mechanical policy-free codegen surface - #158

Merged
zedrdave merged 5 commits into
mainfrom
feat/mechanical-codegen-surface
Sep 9, 2026
Merged

zedrdave merged 5 commits into
mainfrom
feat/mechanical-codegen-surface

Conversation

@zedrdave

@zedrdave zedrdave commented Sep 8, 2026

Copy link
Copy Markdown
Member

Summary

0.28.0 minor release: makes the package a purely mechanical spec→types+runtime surface. All contract policy stays in the OpenAPI spec; consumers no longer need generic type plumbing to compensate for generated-output shape.

Added

  • Direction utilities exported from package root: RequireAll (response presence policy), Writable (now deep: nested readOnly props excluded from request types), and new Mutable (deep readonly-modifier stripper). Leaf guards keep unknown, Date, Blob, File, and functions intact.
  • Direction-explicit api-schemas.ts: new Responses namespace for the response-reachable component set (computed $ref closure, never name-suffix heuristics), each member wrapped in RequireAll with Referenced by: JSDoc. No Requests namespace: request bodies stay operation-shaped (Types.<opId>.Request).
  • Traceability JSDoc: Source: components['schemas'][...] (METHOD /path) on Types.<opId> members; greppable FE-type→BE-schema mapping.
  • --default-non-nullable <true|false> forwarded natively to openapi-typescript (default true this minor; flips to false next major).
  • Config-file mode: openapi-codegen.config.json with shared options + multi-spec list; CLI args override config.
  • x-direction-finalized marker detection (log-only advisory that presence policy is spec-side).

Changed

  • Codegen uses the programmatic openapiTS + astToString API (no npx shell-out).
  • Generated output is lint-clean by construction (prettier programmatic; internal eslint --fix post-step removed).
  • Response/StrictResponse duality documented as transitional.

Deprecated

  • Bare api-schemas.ts aliases (@deprecated pointing to Responses.X or Types.<opId>.Request); removal in next major.

Fixed

  • Record<string, never> sentinel stripped from generated group unions.

Validation

  • npm run lint, types, types:test, format:check: clean
  • npm run test:run: 642/642 across 25 files, including fixture byte-equality and generated-output eslint-zero-errors integration tests

- Export RequireAll, deep Writable, and new deep Mutable direction utilities
- Direction-explicit api-schemas.ts: reachability-filtered Responses namespace,
  @deprecated bare aliases, traceability Source/Referenced-by JSDoc
- --default-non-nullable flag forwarded via programmatic openapi-typescript API
- Config-file multi-spec codegen (openapi-codegen.config.json), lint-clean
  output by construction (internal eslint --fix removed, prettier programmatic)
- Strip Record<string, never> sentinel from generated unions
- x-direction-finalized root-marker detection (log-only advisory)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

It introduces a type-level regression/inconsistency (RequireAll lacks the documented leaf guard) and a packaging issue (openapi-typescript listed as both peer and direct dependency) that should be corrected before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR updates the library/CLI for the 0.28.0 release to make code generation fully programmatic (OpenAPI spec → formatted TS output) while expanding the exported “direction” type utilities and adding new codegen surface features (Responses namespace, config-file mode, and traceability JSDoc).

Changes:

  • Switch CLI type generation to the programmatic openapi-typescript API + programmatic Prettier formatting, plus a post-transform to strip Record<string, never> union sentinels.
  • Add/expand “direction vocabulary” utilities (RequireAll, deep Writable, new Mutable) and export them from the package root.
  • Add config-file mode and new/updated tests/fixtures to cover marker detection, defaultNonNullable forwarding, schema direction output, and regression cases.
File summaries
File Description
vitest.config.ts Increases suite timeouts to accommodate heavier integration/codegen tests.
tests/unit/value-schemas-emit.test.ts Makes value-schema extraction tolerant of prettier-formatted TS literals; fixes bundling by defining import.meta.url.
tests/unit/union-sentinel.test.ts Adds regression + integration coverage for stripping Record<string, never> from unions.
tests/unit/direction-marker.test.ts Adds subprocess coverage for x-direction-finalized advisory logging behavior.
tests/unit/cli.test.ts Adds unit coverage for --default-non-nullable parsing behavior.
tests/unit/cli-integration.test.ts Expands integration tests for defaultNonNullable, config-file mode, and lint-clean generated output.
tests/unit/api-schemas-direction.test.ts Adds integration tests for Responses namespace emission and Source/Referenced-by JSDoc.
tests/typing/direction-utilities.ts Adds type-level assertions for RequireAll, deep Writable, and Mutable.
tests/fixtures/group-union-openapi.json Adds fixture spec reproducing the union sentinel issue.
tests/fixtures/finalized-openapi.json Adds fixture spec containing x-direction-finalized: true.
tests/fixtures/direction-openapi.json Adds fixture spec to validate response-reachability and Source JSDoc behavior.
tests/fixtures/api-types.ts Updates fixtures for new multi-line JSDoc (Response/StrictResponse) + Source annotations.
tests/fixtures/api-schemas.ts Updates fixtures for Responses namespace + deprecated bare aliases.
src/types.ts Exports and documents RequireAll/deep Writable and adds new deep Mutable utility.
src/index.ts Re-exports the direction utilities from the package root with public-facing docs.
src/codegen-transforms.ts Introduces post-generation transform for stripping the union sentinel artifact.
src/cli.ts Implements programmatic codegen + prettier formatting, config-file mode, marker advisory logging, response-reachability, and Source/Referenced-by JSDoc.
README.md Documents config-file mode, new flags, and direction utilities/Responses namespace usage.
package.json Bumps version to 0.28.0 and adds runtime dependencies for the programmatic CLI.
package-lock.json Lockfile updates for the new runtime dependencies and version bump.
CHANGELOG.md Adds 0.28.0 release notes describing new features, changes, deprecations, and fixes.
.gitignore Adds .pi/ to ignored artifacts.
Review details

Suppressed comments (1)

src/types.ts:415

  • RequireAll<T> currently deep-maps any object type, which will also expand built-ins like Date, Blob, File, and function types into huge structural object types. This contradicts the documented “leaf guard” behavior and can break consumer types (e.g., RequireAll<Date> no longer being Date).
export type RequireAll<T> = T extends (infer E)[]
  ? RequireAll<E>[]
  : T extends readonly (infer E)[]
    ? readonly RequireAll<E>[]
    : { [K in keyof T]-?: RequireAll<T[K]> }
  • Files reviewed: 20/22 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread package.json
Comment thread src/cli.ts
- RequireAll gains the same leaf guard as Writable/Mutable: unknown, Date,
  Blob, File and function values pass through instead of degrading to {}
- Sentinel-strip transform preserves unions whose only other member is
  null/undefined (e.g. index-signature value types)
- api-schemas.ts omits the RequireAll import when no schema is
  response-reachable (avoids TS6133 under noUnusedLocals)
- generateTypes receives a structuredClone of the spec so openapiTS cannot
  mutate the object concurrently read by sibling generators
- Config loader validates option values and fails fast on invalid ones
- README no longer claims CLI args override config values
- Comments referencing internal planning documents removed or made
  self-contained
@zedrdave
zedrdave merged commit 50a2f68 into main Sep 9, 2026
3 checks passed
@zedrdave
zedrdave deleted the feat/mechanical-codegen-surface branch September 9, 2026 14:08

This branch was successfully deployed

1 active deployment
github-pages — 28ee7ef8 Deployed Sep 9, 2026 by zedrdave via publish-docs #84
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants