Skip to content

feat!: migrate to @openapi-spec types and target OpenAPI 3.2 with a version option - #1998

Merged
dinwwwh merged 2 commits into
middleapi:mainfrom
dinwwwh:claude/openapi-spec-types-migration-040bbc
Sep 7, 2026
Merged

feat!: migrate to @openapi-spec types and target OpenAPI 3.2 with a version option#1998
dinwwwh merged 2 commits into
middleapi:mainfrom
dinwwwh:claude/openapi-spec-types-migration-040bbc

Conversation

@dinwwwh

@dinwwwh dinwwwh commented Sep 7, 2026

Copy link
Copy Markdown
Member

Replaces json-schema-typed and @hey-api/spec-types with @openapi-spec/types, so JsonSchema is the OpenAPI 3.2 Schema Object and @orpc/openapi re-exports the OpenAPIV3_0, OpenAPIV3_1, and OpenAPIV3_2 namespaces. OpenAPIGenerator now builds OpenAPI 3.2 documents and takes a version option that downgrades to 3.1 or 3.0 through @openapi-spec/downgrader, with the return type following the requested version.

Breaking changes

  • generate() emits 3.2.0 by default (was 3.1.2). Pass version: '3.1.2' to keep 3.1 documents. base no longer accepts openapi.
  • OpenAPIDocument requires a version argument; OpenAPIDocument<OpenAPIVersion> is the union of every supported document. OpenAPIOperationObject is replaced by OpenAPIV3_2.OperationObject.
  • JsonSchemaKeywords is derived from the 3.2 Schema Object, so legacy keywords such as additionalItems are no longer part of it.

Behavior

  • Any 3.0.x, 3.1.x, or 3.2.x version is accepted. The minor version selects the conversion and the document carries the exact requested value.
  • Everything authored (base, openapi({ spec }), converter output) stays OpenAPI 3.2 and is downgraded with the rest of the document, so type: ['string', 'null'] becomes nullable: true in 3.0 output.
  • Downgrading runs before serialization: the serializer output is not made of plain objects and the downgrader would pass it through untouched.
  • QUERY operations still require 3.2 and throw when an older version is requested.

Docs

  • The specification page documents version in its own section, and the v1 migration guide notes the new default.

Testing

  • Version tests compare whole output documents for 3.2.0, 3.2.7, 3.1.2, 3.1.0, 3.0.4, and 3.0.0, with type tests for the version-dependent return type.
  • Root type check, lint, the docs JSDoc backlink checker, and both package builds pass.

…ersion option

Replace json-schema-typed and @hey-api/spec-types with @openapi-spec/types.
JsonSchema is the OpenAPI 3.2 Schema Object, @orpc/openapi re-exports the
OpenAPIV3_0/1/2 namespaces and builds documents as OpenAPI 3.2. A new
`version` option on generate() downgrades to 3.1 or 3.0 with
@openapi-spec/downgrader, base no longer carries `openapi`, and the
returned document type follows the requested version.
@codecov

codecov Bot commented Sep 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@codspeed-hq

codspeed-hq Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 30 untouched benchmarks


Comparing dinwwwh:claude/openapi-spec-types-migration-040bbc (ec9ca17) with main (a89c5a9)

Open in CodSpeed

@pkg-pr-new

pkg-pr-new Bot commented Sep 7, 2026

Copy link
Copy Markdown
More templates

@orpc/ai-sdk

npm i https://pkg.pr.new/@orpc/ai-sdk@1998

@orpc/arktype

npm i https://pkg.pr.new/@orpc/arktype@1998

@orpc/bun

npm i https://pkg.pr.new/@orpc/bun@1998

@orpc/client

npm i https://pkg.pr.new/@orpc/client@1998

@orpc/cloudflare

npm i https://pkg.pr.new/@orpc/cloudflare@1998

@orpc/contract

npm i https://pkg.pr.new/@orpc/contract@1998

@orpc/experimental-effect

npm i https://pkg.pr.new/@orpc/experimental-effect@1998

@orpc/evlog

npm i https://pkg.pr.new/@orpc/evlog@1998

@orpc/hibernation

npm i https://pkg.pr.new/@orpc/hibernation@1998

@orpc/json-schema

npm i https://pkg.pr.new/@orpc/json-schema@1998

@orpc/experimental-msw

npm i https://pkg.pr.new/@orpc/experimental-msw@1998

@orpc/nest

npm i https://pkg.pr.new/@orpc/nest@1998

@orpc/next

npm i https://pkg.pr.new/@orpc/next@1998

@orpc/node

npm i https://pkg.pr.new/@orpc/node@1998

@orpc/openapi

npm i https://pkg.pr.new/@orpc/openapi@1998

@orpc/opentelemetry

npm i https://pkg.pr.new/@orpc/opentelemetry@1998

@orpc/pinia-colada

npm i https://pkg.pr.new/@orpc/pinia-colada@1998

@orpc/pino

npm i https://pkg.pr.new/@orpc/pino@1998

@orpc/publisher

npm i https://pkg.pr.new/@orpc/publisher@1998

@orpc/ratelimit

npm i https://pkg.pr.new/@orpc/ratelimit@1998

@orpc/server

npm i https://pkg.pr.new/@orpc/server@1998

@orpc/shared

npm i https://pkg.pr.new/@orpc/shared@1998

@orpc/swr

npm i https://pkg.pr.new/@orpc/swr@1998

@orpc/tanstack-query

npm i https://pkg.pr.new/@orpc/tanstack-query@1998

@orpc/trpc

npm i https://pkg.pr.new/@orpc/trpc@1998

@orpc/valibot

npm i https://pkg.pr.new/@orpc/valibot@1998

@orpc/zod

npm i https://pkg.pr.new/@orpc/zod@1998

commit: ec9ca17

@pullfrog pullfrog Bot 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.

ℹ️ The migration is in good shape — one wrong literal in the migration guide, plus a coverage gap worth a cheap safety net.

Reviewed changes

This PR migrates @orpc/json-schema and @orpc/openapi from json-schema-typed / @hey-api/spec-types to @openapi-spec/types, and makes OpenAPIGenerator emit OpenAPI 3.2 by default with a version option that downgrades the finished document to 3.1/3.0 through @openapi-spec/downgrader:

  • @orpc/json-schemaJsonSchema is now the OpenAPI 3.2 Schema Object; JsonSchemaKeywords derives from its declared fields; JsonSchemaType/JsonSchemaFormat become hand-written enums replacing the json-schema-typed re-exports.
  • @orpc/openapi types — the OpenAPIVersion template type and version-conditional OpenAPIDocument<TVersion>; OpenAPIV3_0/OpenAPIV3_1/OpenAPIV3_2 re-exported; OpenAPIOperationObject removed.
  • OpenAPIGenerator — the version option (default 3.2.0), version-typed return, the 3.2 → 3.1 → 3.0 downgrade pipeline before serialization, base.openapi no longer accepted, and the QUERY guard now keyed off the requested version.
  • Mechanics — numeric response statuses stringified via toResponseStatusKey (the 3.2 ResponsesObject index signature is string-typed); the coercer adjusted for the narrower items/additionalItems typing.
  • Docs & skills — the ### OpenAPI Version section, the v1 migration note, and the orpc-openapi skill description.

I ran the openapi + json-schema suites (617 tests, all pass) and the root type check (exit 0, which validates the new openapi-generator.test-d.ts version-return assertions). I also pushed a real $defs-heavy e2e router (zod converter, shared Planet component, output unions) through 3.1.2 and 3.0.4: hoisted components rewrite cleanly to #/components/schemas/… with no dangling #/$defs/ refs after the downgrade, and type: ['string', 'null'] becomes nullable: true.

ℹ️ The downgrade path is only exercised by one synthetic router

The new version tests all drive a single hand-built router (one path param, one nullable string output). Nothing runs a real e2e router — crud, reusable-components, or typed-errors, which exercise $defs hoisting, component reuse, allOf compositions, and error bodies — at 3.1 or 3.0. The @openapi-spec/downgrader README documents that 3.1 → 3.0 removes the $defs keyword and can leave #/$defs/… refs dangling ("hoist reusable subschemas into components.schemas before downgrading"); oRPC's registry hoists root $defs (rewriting refs), which sidesteps that for zod-derived schemas, but $defs nested inside a component body or in a user-supplied base.components would not be. My probe showed the common path is clean, so this is a safety net rather than a known bug — generating the existing crud router at version: '3.1.2' and '3.0.4' (asserting no #/$defs/ refs and nullable conversion) would pin the behavior the feature promises.

Technical details
# Add a version-parameterized e2e downgrade test

## Affected sites
- packages/openapi/tests/openapi-generator/crud.test.ts (or reusable-components.test.ts) — currently only generate without a `version` (default 3.2.0)

## Required outcome
- Generate an existing $defs/component-heavy e2e router at 3.1.x and 3.0.x and assert the document downgrades cleanly: every `$ref` resolves (`#/components/schemas/…`), no `#/$defs/…` refs remain, and a `type: [T, 'null']` schema becomes `nullable: true`.

## Suggested approach
- Parameterize the existing e2e `describe` with `it.each(['3.2.0', '3.1.2', '3.0.4'])` and assert the `openapi` field, a couple of `$ref`-anchored schemas, and one nullable conversion.

ℹ️ Nitpicks

  • packages/openapi/src/openapi-generator.ts:198 — the as OpenAPIDocument<TVersion> cast on the serializer result is the same shape as before; nothing to change, just noting the serializer return goes straight through the versioned type.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

Comment thread apps/content/docs/migrations/from-v1.mdx

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

Version validation and keyword typing can accept invalid values, and the migration guide names the wrong legacy version.

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

Pull request overview

Migrates OpenAPI and JSON Schema typing to @openapi-spec, defaults generation to OpenAPI 3.2, and adds downgrade support.

Changes:

  • Adds version-aware OpenAPI 3.0/3.1/3.2 generation.
  • Replaces legacy schema/spec type dependencies.
  • Updates tests, documentation, and skills for OpenAPI 3.2.
File summaries
File Description
tests/plugins/all-plugins.test.ts Updates the integration spec to OpenAPI 3.2.
skills/orpc/SKILL.md Documents OpenAPI 3.2 generation.
skills/orpc-openapi/SKILL.md Documents selectable versions and downgrading.
pnpm-workspace.yaml Exempts new dependencies from release-age checks.
pnpm-lock.yaml Updates resolved dependencies.
packages/zod/package.json Replaces the legacy schema type dependency.
packages/openapi/tests/openapi-generator/typed-errors.test.ts Uses string response status keys.
packages/openapi/tests/openapi-generator/reusable-components.test.ts Uses string response status keys.
packages/openapi/tests/openapi-generator/file-transfer.test.ts Uses string response status keys.
packages/openapi/tests/openapi-generator/event-streaming.test.ts Uses string response status keys.
packages/openapi/tests/openapi-generator/crud.test.ts Uses string response status keys.
packages/openapi/src/types.ts Adds versioned OpenAPI document types and namespace exports.
packages/openapi/src/types.test-d.ts Tests document type selection.
packages/openapi/src/plugins/openapi-reference.ts Accepts documents from all supported versions.
packages/openapi/src/plugins/openapi-reference.test.ts Updates plugin test document typing.
packages/openapi/src/openapi-generator.ts Adds version selection and document downgrading.
packages/openapi/src/openapi-generator.test.ts Tests versioned output and serialization order.
packages/openapi/src/openapi-generator.test-d.ts Tests version-dependent return types.
packages/openapi/src/openapi-generator-operation.ts Migrates operation generation to 3.2 types.
packages/openapi/src/openapi-generator-operation.test.ts Updates operation tests for 3.2 types.
packages/openapi/src/openapi-generator-components.ts Migrates component handling to 3.2 types.
packages/openapi/src/openapi-generator-components.test.ts Updates component test documents.
packages/openapi/src/meta.ts Types custom operation metadata as OpenAPI 3.2.
packages/openapi/package.json Adds types and downgrader dependencies.
packages/json-schema/src/types.ts Derives JSON Schema types from OpenAPI 3.2.
packages/json-schema/src/composition-utils.test.ts Adjusts contextual schema typing.
packages/json-schema/src/coercer.ts Preserves legacy additionalItems coercion.
packages/json-schema/package.json Replaces json-schema-typed.
eslint.config.js Restricts direct imports of the new type package.
apps/content/docs/openapi/specification.mdx Documents version selection and downgrading.
apps/content/docs/migrations/from-v1.mdx Adds migration guidance for the new default.
Review details

Files not reviewed (1)

  • pnpm-lock.yaml: Generated file
  • Files reviewed: 30/31 changed files
  • Comments generated: 3
  • Review effort level: Balanced

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

Comment on lines +17 to +19
export type JsonSchemaKeywords = keyof {
[K in keyof OpenAPIV3_2.SchemaObjectFields as string extends K ? never : K]: unknown
}
*
* @see {@link https://orpc.dev/docs/openapi/specification#openapi-version | OpenAPI Specification - OpenAPI Version}
*/
export type OpenAPIVersion = `3.0.${number}` | `3.1.${number}` | `3.2.${number}`

- The `oo` helper (`oo.spec`) was removed. To customize the operation object, attach [`openapi({ spec })` metadata](/docs/openapi/specification#customizing-the-operation-object) directly on the procedure or router.
- The `shouldHoistDef` option was replaced by [`customComponentName`](/docs/openapi/specification#hoisting-defs). Root `$defs` are now always hoisted into `components.schemas`; this option only renames them.
- Documents are generated as OpenAPI 3.2.0 by default. Pass [`version: '3.1.1'`](/docs/openapi/specification#openapi-version) to keep old behavior.
@dinwwwh
dinwwwh merged commit 15044d4 into middleapi:main Sep 7, 2026
10 checks passed
@dinwwwh dinwwwh mentioned this pull request Sep 7, 2026
1 task
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