Skip to content

fix(deps): move @workos-inc/node to peerDependencies#423

Merged
gjtorikian merged 4 commits into
workos:mainfrom
Leestex:fix/peer-dep-workos-node
Jun 25, 2026
Merged

fix(deps): move @workos-inc/node to peerDependencies#423
gjtorikian merged 4 commits into
workos:mainfrom
Leestex:fix/peer-dep-workos-node

Conversation

@Leestex

@Leestex Leestex commented May 6, 2026

Copy link
Copy Markdown
Contributor

Closes #422.

Why

@workos-inc/node's types (User, OauthTokens, AuthenticationResponse) are surfaced into authkit-nextjs's public-API interfaces in src/interfaces.ts (Session, UserInfo, HandleAuthSuccessData), but @workos-inc/node is declared in regular dependencies. Any time a consumer's resolved version of @workos-inc/node diverges from the version satisfying the transitive ^9.0.0 range, package managers install a duplicate nested copy under node_modules/@workos-inc/authkit-nextjs/node_modules/@workos-inc/node/. Consumer code that infers return types from withAuth() / refreshSession() then hits TS2883 ("inferred type cannot be named without a reference to 'User' from … This is likely not portable"). Full repro and analysis in #422.

What

Move @workos-inc/node from dependenciespeerDependencies (and add it to devDependencies so the package's own build / typecheck / tests continue to find it). Same pattern as the existing next, react, react-dom peer-dep declarations — the peer-dep contract forces a single resolved copy in the consumer tree by construction.

   "dependencies": {
     "@sindresorhus/fnv1a": "^3.1.0",
-    "@workos-inc/node": "^9.0.0",
     "iron-session": "^8.0.4",
     "jose": "^5.10.0",
     "path-to-regexp": "^6.3.0",
     "valibot": "^1.2.0"
   },
   "peerDependencies": {
+    "@workos-inc/node": "^9.0.0",
     "next": "^13.5.9 || ^14.2.26 || ^15.2.3 || ^16",
     "react": "^18.0 || ^19.0.0",
     "react-dom": "^18.0 || ^19.0.0"
   },
   "devDependencies": {
     ...
+    "@workos-inc/node": "^9.0.0",
     ...
   }

Verification

Locally on this branch:

  • pnpm install — clean install, lockfile regenerates as expected (only the dep-tree @workos-inc/node block moves; no version churn).
  • pnpm run build — green (tsc --project tsconfig.app.json).
  • pnpm run typecheck — green (tsc --project tsconfig.app.json --noEmit && tsc --project tsconfig.test.json --noEmit).
  • pnpm run lint — green (oxlint, 0 warnings / 0 errors).
  • pnpm run test — green (21 test files, 349 tests, 0 failures).

End-to-end: cloning a fresh consumer, removing the resolutions / dedupe workaround, and pointing at this branch via pnpm pack → consumer install resolves a single copy of @workos-inc/node regardless of the consumer's pinned version, and the TS2883 from #422 is gone.

Compatibility / migration

This is a breaking change for any consumer that doesn't already have @workos-inc/node listed in their own dependencies. In practice the realistic impact is small — every authkit-nextjs consumer already calls @workos-inc/node directly for the parts of the WorkOS SDK that authkit-nextjs doesn't wrap (organization management, user management, FGA, audit logs, vault, etc.). The chore(deps)!: prefix on the commit signals the major-bump intent for release-please.

Suggested follow-up release notes (drop into the next major):

@workos-inc/node is now a peer dependency. Consumers must install it directly: pnpm add @workos-inc/node. This prevents TS2883 errors on inferred types from withAuth() and related helpers when the consumer pins a specific version of @workos-inc/node.

If a softer landing is preferred, a backportable variant is to keep @workos-inc/node in both dependencies and peerDependencies — but Yarn / npm / pnpm don't all dedupe that consistently, and the simpler peer-only declaration matches what's already in place for next and react. Happy to adjust if maintainers prefer a different shape.

@workos-inc/node's types (User, OauthTokens, AuthenticationResponse)
are surfaced into authkit-nextjs's public-API interfaces in
src/interfaces.ts (Session, UserInfo, HandleAuthSuccessData). When a
consumer's resolved version of @workos-inc/node differs from the
version satisfying authkit-nextjs's transitive ^9.0.0 range, package
managers install a duplicate copy under
node_modules/@workos-inc/authkit-nextjs/node_modules/@workos-inc/node/.
TypeScript then emits TS2883 on consumer code that infers return types
from withAuth() / refreshSession(), because the canonical path of the
referenced User type crosses a nested node_modules.

Declaring @workos-inc/node as a peer dependency forces a single resolved
copy in the consumer tree by construction — the same pattern already
used here for next, react, and react-dom. Added to devDependencies so
the package's own build, typecheck, and tests continue to find it.

BREAKING CHANGE: consumers must now have @workos-inc/node listed in
their own dependencies. In practice most consumers already do, since
authkit-nextjs only wraps a subset of the WorkOS server SDK and
production code paths typically call WorkOS directly for organization
and user management.
@Leestex Leestex requested a review from a team as a code owner May 6, 2026 16:27
Leestex and others added 2 commits May 6, 2026 18:31
@workos-inc/node is now a peer dependency, so consumers must install it
explicitly alongside @workos-inc/authkit-nextjs.
@gjtorikian gjtorikian changed the title chore(deps)!: move @workos-inc/node to peerDependencies fix(deps): move @workos-inc/node to peerDependencies Jun 25, 2026
@greptile-apps

greptile-apps Bot commented Jun 25, 2026

Copy link
Copy Markdown

Greptile Summary

This PR makes the WorkOS Node SDK a peer dependency. The main changes are:

  • @workos-inc/node moved from dependencies to peer and dev dependencies.
  • The lockfile now resolves the SDK from the dev dependency.
  • Installation docs now tell users to install the SDK directly.
  • Test fixtures now include the v10 User.name field.

Confidence Score: 5/5

The dependency-contract change is narrowly scoped to package metadata, lockfile resolution, documentation, and test fixture updates.

No code issues were identified. The package metadata now reflects the intended peer dependency shape, documentation instructs consumers to install the SDK directly, and the repository retains the SDK for local typechecking through development dependencies.

None.

T-Rex T-Rex Logs

What T-Rex did

  • Recorded the before-state of the peer-dependency contract, noting that base package dependencies included @workos-inc/node and that a temporary consumer install lists @workos-inc/authkit-nextjs -> @workos-inc/node 9.3.1 along with top-level @workos-inc/node 10.0.0.
  • Recorded the after-state of the peer-dependency contract, noting that head package fields include @workos-inc/node in peerDependencies and devDependencies, README shows the install command, and the temp consumer install uses @workos-inc/node 10.0.0 as a peer with no nested filesystem copy; the repo typecheck exits successfully.

View all artifacts

T-Rex Ran code and verified through T-Rex

Reviews (2): Last reviewed commit: "test: Add required name field to mock Us..." | Re-trigger Greptile

Comment thread package.json
"valibot": "^1.2.0"
},
"peerDependencies": {
"@workos-inc/node": "^9.0.0 || ^10.0.0",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Peer Range Allows Missing SDK API

This package now builds against @workos-inc/node v10 but still declares every v9 release as a valid peer. If the public feature-flags helper reaches featureFlags.createRuntimeClient on a v9 install that does not expose that API, consumers can satisfy the peer range and still hit a type error or runtime createRuntimeClient is not a function failure.

Prompt To Fix With AI
This is a comment left during a code review.
Path: package.json
Line: 47

Comment:
**Peer Range Allows Missing SDK API**

This package now builds against `@workos-inc/node` v10 but still declares every v9 release as a valid peer. If the public feature-flags helper reaches `featureFlags.createRuntimeClient` on a v9 install that does not expose that API, consumers can satisfy the peer range and still hit a type error or runtime `createRuntimeClient is not a function` failure.

How can I resolve this? If you propose a fix, please make it concise.

@workos-inc/node v10 added a required `name: string | null`
field to its User interface. Moving the dependency to a peer
dep let v10 resolve in CI, so the existing test mocks failed
the typecheck step. Setting `name` keeps the fixtures valid
across the supported v9/v10 range.
@gjtorikian

Copy link
Copy Markdown
Contributor

thanks!

@gjtorikian gjtorikian merged commit 18163d7 into workos:main Jun 25, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

TS2883: inferred return types from withAuth() / refreshSession() are non-portable when consumer pins a different @workos-inc/node version

2 participants