Skip to content

fix: export classes and namespaces that were re-exported with export type - #2333

Closed
dinwwwh wants to merge 1 commit into
mainfrom
claude/fix-type-only-class-reexports
Closed

dinwwwh wants to merge 1 commit into
mainfrom
claude/fix-type-only-class-reexports

Conversation

@dinwwwh

@dinwwwh dinwwwh commented Oct 24, 2026

Copy link
Copy Markdown
Member

Problem

Six re-exports used export type for something that is a runtime value:

Entry point Symbol Kind Re-exported from
@orpc/server ProcedureContract class @orpc/contract
@orpc/contract AsyncIteratorClass class @orpc/shared
@orpc/publisher AsyncIteratorClass class @orpc/shared
@orpc/openapi OpenAPIV3_0, OpenAPIV3_1, OpenAPIV3_2 module namespaces @openapi-spec/types

The bundled .d.mts drops the type modifier, so each one is declared as a value export (declare class … / import * as … plus export { … }). The runtime module did not export them. As a result, these type-check but crash when the module loads:

  • a value use such as x instanceof ProcedureContract;
  • under verbatimModuleSyntax, even an import without type that is used only in type positions. That combination is common, for example in Vite's templates.
import { ProcedureContract } from '@orpc/server' // tsc: OK
// node: SyntaxError: The requested module '@orpc/server' does not provide an export named 'ProcedureContract'

The OpenAPIV3_x namespaces are affected the same way. The repo's lint rule tells users to get them from @orpc/* rather than @openapi-spec/types.

Fix

Re-export them as values so the runtime matches the declarations:

  • @orpc/server: ProcedureContract moves into the value export { … } from '@orpc/contract' list.
  • @orpc/contract, @orpc/publisher: export { AsyncIteratorClass } from '@orpc/shared'.
  • @orpc/openapi: types.ts imports the three namespaces with import * as and re-exports them with a plain export { … }.

Nothing new becomes public:

  • ProcedureContract is already a value export of @orpc/contract.
  • AsyncIteratorClass is already a value export of @orpc/client and @orpc/server; these re-exports are the same class object.
  • The @openapi-spec/types modules are empty (1 byte) at runtime and were already a runtime dependency of @orpc/openapi.

The emitted .d.mts declarations do not change.

Verification

  • Every export type re-export of a runtime value, across all entry points of every package, was found with the TypeScript checker. These six are the complete list.
  • pnpm lint, pnpm type:check (including the playgrounds and @orpc/nest), the tests of the touched and dependent packages, and pnpm docs:validate pass.
  • Every package was packed from main and from this branch. On each of the 72 entry points, the names the .d.mts exports as values were compared with the runtime module's exports:
    • on main: the six names above are missing at runtime;
    • on this branch: nothing is missing.
    • @orpc/next and @orpc/cloudflare cannot load in plain Node, so their runtime exports could not be compared; they have no affected re-exports.
  • No type referenced by a package's public declarations became unnameable for consumers.

Generated by Claude Code

… type`

`ProcedureContract` (@orpc/server), `AsyncIteratorClass` (@orpc/contract,
@orpc/publisher) and `OpenAPIV3_0`/`OpenAPIV3_1`/`OpenAPIV3_2`
(@orpc/openapi) were re-exported with `export type`. The bundled .d.mts
drops the `type` modifier and declares them as value exports, while the
runtime modules did not export them. A value import (an import without
`type` under `verbatimModuleSyntax`, `instanceof`, ...) type-checked and
then failed at load with "does not provide an export named ...".

Re-export them as values so the runtime matches the declarations. The
classes are already value exports of @orpc/contract, @orpc/client and
@orpc/server, and the @openapi-spec/types modules are empty at runtime.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U63hBfpeESmJiHXznRFzjN
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
orpc 494334c Commit Preview URL

Branch Preview URL
Oct 24 2026, 01:33 PM

@codspeed

codspeed Bot commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

1 warning

⚠️ 5 benchmarks are dominated by system calls

System calls cannot be simulated consistently and are left out of the measure. The reported value understates the real cost. Switch to the Walltime instrument to measure them.

Learn more about system calls

See affected benchmarks

✅ 28 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing claude/fix-type-only-class-reexports (494334c) with main (72feedb)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

@pkg-pr-new

pkg-pr-new Bot commented Oct 24, 2026

Copy link
Copy Markdown
More templates

@orpc/ai-sdk

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

@orpc/arktype

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

@orpc/bun

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

@orpc/client

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

@orpc/cloudflare

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

@orpc/contract

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

@orpc/effect

npm i https://pkg.pr.new/@orpc/effect@2333

@orpc/evlog

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

@orpc/hibernation

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

@orpc/json-schema

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

@orpc/experimental-lock

npm i https://pkg.pr.new/@orpc/experimental-lock@2333

@orpc/mcp

npm i https://pkg.pr.new/@orpc/mcp@2333

@orpc/msw

npm i https://pkg.pr.new/@orpc/msw@2333

@orpc/nest

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

@orpc/next

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

@orpc/node

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

@orpc/openapi

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

@orpc/opentelemetry

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

@orpc/pinia-colada

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

@orpc/pino

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

@orpc/publisher

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

@orpc/ratelimit

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

@orpc/server

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

@orpc/shared

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

@orpc/swr

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

@orpc/tanstack-query

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

@orpc/trpc

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

@orpc/valibot

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

@orpc/zod

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

commit: 494334c

@codecov

codecov Bot commented Oct 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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

✅ No new issues found.

Reviewed changes

  • @orpc/server — ProcedureContract moved out of the type-only @orpc/contract re-export list into the value export { … } from '@orpc/contract' list.
  • @orpc/contract / @orpc/publisher — AsyncIteratorClass re-exported from @orpc/shared as a value instead of export type.
  • @orpc/openapi — OpenAPIV3_0/1/2 switched from import type * as + export type to import * as + export, so the namespaces exist at runtime.

I reproduced the defect independently: reverting only the @orpc/contract index change and rebuilding produces a dist/index.d.mts that declares export { AsyncIteratorClass, … } as a value while dist/index.mjs exports nothing by that name — exactly the dts/runtime split described. On the branch, the built .mjs for all four packages exports the six names, and the .d.mts declarations are unchanged in what they expose. @openapi-spec/types/v3.x resolves to 1-byte empty .mjs modules, so the namespace re-exports safely yield {} at runtime, and the package was already a declared dependency. I also swept every export type in packages/*/src — all remaining ones are genuine type aliases/interfaces/callbacks, no export type * anywhere, so the six listed are the complete set.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

@dinwwwh dinwwwh closed this Oct 24, 2026
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