Skip to content

fix: add subpath exports, deprecate namespace re-exports for turbopack compat#987

Open
DBosley wants to merge 2 commits intomainfrom
fix/turbopack-namespace-exports
Open

fix: add subpath exports, deprecate namespace re-exports for turbopack compat#987
DBosley wants to merge 2 commits intomainfrom
fix/turbopack-namespace-exports

Conversation

@DBosley
Copy link
Contributor

@DBosley DBosley commented Feb 18, 2026

Summary

  • Add subpath exports (./routes, ./tasks, ./circle-api, ./whscan-api) to connect/package.json
  • Wrap existing namespace re-exports (routes, tasks, circleApi, api) in deprecation Proxies that emit a one-time console.warn directing consumers to use subpath imports
  • Add @deprecated JSDoc tags for IDE strikethrough hints
  • Move RelayFailedError from routes/types.ts to types.ts to break circular dependency; re-export from routes/types.ts for backward compat
  • Fix self-referential import { routes } from "../../index.js" in tokenTransfer.ts
  • Update examples to use new subpath imports

Non-Breaking

Existing imports continue to work — consumers will see a deprecation warning:

[@wormhole-foundation/sdk-connect] Accessing "routes" from the barrel export is deprecated
and will be removed in a future version.
Use: import * as routes from "@wormhole-foundation/sdk-connect/routes"

Migration

// Before (deprecated, still works):
import { routes } from "@wormhole-foundation/sdk-connect";

// After (recommended):
import * as routes from "@wormhole-foundation/sdk-connect/routes";

Same pattern for tasks./tasks, circleApi./circle-api, api./whscan-api.

Context

Turbopack (default bundler in Next.js 15+) has a scope hoisting bug where namespace re-exports generate a wrapper module whose factory is never emitted into client chunks. SSR works fine but client hydration crashes with "module factory is not available". This affects all syntax variants.

Consumers using turbopack must use the subpath imports to avoid the crash. The deprecation warnings guide all consumers toward the new pattern ahead of a future removal.

Tracked in Next.js: vercel/next.js#82827

Test plan

  • cd connect && npm run build passes (pre-existing type errors on main unrelated to this PR)
  • cd connect && npm run test passes
  • import { routes } from "@wormhole-foundation/sdk-connect" still works (logs deprecation warning)
  • import * as routes from "@wormhole-foundation/sdk-connect/routes" resolves correctly
  • RelayFailedError accessible from both types and routes/types paths

Summary by CodeRabbit

  • Refactor
    • Introduced modular subpath exports for routes, tasks, circle-api, and whscan-api modules to enable granular imports.
    • Deprecated namespace-based imports (routes, tasks, circleApi, api) in favor of direct subpath imports. Users should migrate to the new import pattern.
    • Consolidated type declarations for improved organization.

@coderabbitai
Copy link

coderabbitai bot commented Feb 18, 2026

📝 Walkthrough

Walkthrough

Package export surface expanded with new subpath exports and CTS/MTS type entry points. Namespace re-exports replaced by deprecation proxies in the index. RelayFailedError/RelayExplorer type declarations moved and re-exported; a few imports and examples updated to use the new submodule packages.

Changes

Cohort / File(s) Summary
Package manifest / exports
connect/package.json
Adds subpath exports (./routes, ./tasks, ./circle-api, ./whscan-api) with react-native/import/require/default targets; moves top-level types to index.d.cts/index.d.mts; updates typesVersions and files.
Index runtime / deprecation proxies
connect/src/index.ts, connect/index.d.cts, connect/index.d.mts
Replaces namespace export * as ... re-exports with internal imports and a _deprecate proxy exposing routes, tasks, circleApi, api (logs once on first access); adds consolidated declaration barrels for CTS/MTS.
Type consolidation
connect/src/types.ts, connect/src/routes/types.ts
Moves/defines RelayFailedError and RelayExplorer into types.ts; routes/types.ts now re-exports these types from the central file.
Protocol code update
connect/src/protocols/tokenBridge/tokenTransfer.ts
Imports RelayFailedError from ../../types.js and replaces routes.RelayFailedError usage with the direct constructor.
Examples / import updates
examples/src/quorum.ts, examples/src/router.ts
Switches route/api imports to the new dedicated submodule packages (@wormhole-foundation/sdk-connect/whscan-api, .../routes).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • kev1n-peters

Poem

🐰🌿 I hopped through exports, neat and spry,
Moved types and paths beneath the sky.
A gentle nudge — "deprecated" I sing,
New submodules bloom in early spring.
✨🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding subpath exports and deprecating namespace re-exports to resolve a Turbopack compatibility issue.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/turbopack-namespace-exports

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
connect/src/protocols/tokenBridge/tokenTransfer.ts (1)

61-75: Merge split imports from the same module.

RelayFailedError on Line 75 is imported from ../../types.js — the exact same specifier already used for the value import block on Lines 61–69. Consolidate them to avoid the redundant module reference.

♻️ Proposed consolidation
 import {
   TransferState,
   isAttested,
   isInReview,
   isRedeemed,
   isRelayFailed,
   isSourceFinalized,
   isSourceInitiated,
+  RelayFailedError,
 } from "../../types.js";
 import { getGovernedTokens, getGovernorLimits } from "../../whscan-api.js";
 import { Wormhole } from "../../wormhole.js";
 import type { WormholeTransfer } from "../wormholeTransfer.js";
 import type { QuoteWarning } from "../../warnings.js";
 import { RelayStatus } from "@wormhole-foundation/sdk-definitions";
-import { RelayFailedError } from "../../types.js";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@connect/src/protocols/tokenBridge/tokenTransfer.ts` around lines 61 - 75, The
file imports several symbols from ../../types.js in one block (TransferState,
isAttested, isInReview, isRedeemed, isRelayFailed, isSourceFinalized,
isSourceInitiated) and then re-imports RelayFailedError from the same module;
consolidate these into a single import from ../../types.js that includes
RelayFailedError along with TransferState and the is* helpers to remove the
redundant module reference and keep imports grouped (update the import that
currently lists TransferState... to also include RelayFailedError and remove the
separate RelayFailedError import).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@connect/src/protocols/tokenBridge/tokenTransfer.ts`:
- Around line 61-75: The file imports several symbols from ../../types.js in one
block (TransferState, isAttested, isInReview, isRedeemed, isRelayFailed,
isSourceFinalized, isSourceInitiated) and then re-imports RelayFailedError from
the same module; consolidate these into a single import from ../../types.js that
includes RelayFailedError along with TransferState and the is* helpers to remove
the redundant module reference and keep imports grouped (update the import that
currently lists TransferState... to also include RelayFailedError and remove the
separate RelayFailedError import).

@DBosley DBosley changed the title fix!: remove namespace re-exports, add subpath exports for turbopack compat fix: add subpath exports, deprecate namespace re-exports for turbopack compat Feb 18, 2026
@DBosley DBosley force-pushed the fix/turbopack-namespace-exports branch from 75d9822 to a5634ee Compare February 18, 2026 17:50
…k compat

Turbopack's scope hoisting generates broken module wrappers for namespace
re-exports, causing "module factory is not available" hydration crashes.

- Add subpath exports (./routes, ./tasks, ./circle-api, ./whscan-api)
- Wrap existing namespace re-exports in deprecation Proxies that emit a
  one-time console.warn directing consumers to subpath imports
- Move RelayFailedError from routes/types.ts to types.ts to break
  circular dependency; re-export from routes/types.ts for compat
- Fix self-referential import in tokenTransfer.ts
- Update examples to use new subpath imports
@DBosley DBosley force-pushed the fix/turbopack-namespace-exports branch from a5634ee to 7125459 Compare February 18, 2026 17:58
Copy link
Collaborator

@kev1n-peters kev1n-peters left a comment

Choose a reason for hiding this comment

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

Should we publish a beta version with this change and verify it works in Connect?

The deprecation Proxy change (7125459) broke TypeScript namespace
access: tsc emits `export declare const routes: typeof _routes`
which consumers can't use as a namespace (TS2503).

Add hand-written index.d.cts/index.d.mts at the package root with
proper `export * as routes` namespace re-exports. The `exports.types`
condition redirects consumers to these files while the runtime JS
keeps the Proxy. Paths reference dist/ so resolution works in both
the source repo and published package.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
connect/src/types.ts (1)

16-22: Nit: this.name is not set in the custom Error subclass.

RelayFailedError inherits name = "Error" from Error.prototype, so stack traces / serialization won't show the subclass name. The same pattern exists in MinAmountError and UnavailableError in routes/types.ts, so this is consistent — but worth noting as a potential future improvement across all custom error classes.

Optional improvement
 export class RelayFailedError extends Error {
   readonly relayExplorer?: RelayExplorer;
 
   constructor(message: string, relayExplorer?: RelayExplorer) {
     super(message);
+    this.name = "RelayFailedError";
     this.relayExplorer = relayExplorer;
   }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@connect/src/types.ts` around lines 16 - 22, Custom error subclasses
(RelayFailedError, and similarly MinAmountError and UnavailableError) do not set
this.name, so stack traces and serialization show "Error" instead of the
subclass; update each constructor (e.g., RelayFailedError.constructor) to assign
this.name = "RelayFailedError" (and correspondingly
"MinAmountError"/"UnavailableError") immediately after calling super(message) so
the error instances carry the correct subclass name.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@connect/src/types.ts`:
- Around line 16-22: Custom error subclasses (RelayFailedError, and similarly
MinAmountError and UnavailableError) do not set this.name, so stack traces and
serialization show "Error" instead of the subclass; update each constructor
(e.g., RelayFailedError.constructor) to assign this.name = "RelayFailedError"
(and correspondingly "MinAmountError"/"UnavailableError") immediately after
calling super(message) so the error instances carry the correct subclass name.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cc44420 and 8ce413a.

📒 Files selected for processing (9)
  • connect/index.d.cts
  • connect/index.d.mts
  • connect/package.json
  • connect/src/index.ts
  • connect/src/protocols/tokenBridge/tokenTransfer.ts
  • connect/src/routes/types.ts
  • connect/src/types.ts
  • examples/src/quorum.ts
  • examples/src/router.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • examples/src/router.ts
  • connect/src/protocols/tokenBridge/tokenTransfer.ts
  • examples/src/quorum.ts

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