[v8] Add dynamic import wrapper for jose to support Node.js 20.15-20.18#1371
Merged
[v8] Add dynamic import wrapper for jose to support Node.js 20.15-20.18#1371
Conversation
The jose library is ESM-only and cannot be loaded via require() in Node.js versions before 20.19.0. This adds a dynamic import wrapper that works across all Node.js 20+ versions using import() which is supported in both ESM and CJS. Breaking changes: - UserManagement.jwks getter changed to async UserManagement.getJWKS() method - CookieSession.jwks property removed (uses UserManagement.getJWKS() instead) The wrapper enables: - Lazy loading of jose (only when JWT methods are called) - Support for all Node.js 20.x versions - Smaller bundle size (no jose bundling needed) - Clean migration path when Node 20 reaches EOL (April 2026) Also updates: - Minimum Node version to 20.15.0 (conservative choice within 20.x) - tsup config: removes redundant external arrays (not needed with bundle: false)
Contributor
There was a problem hiding this comment.
Greptile Overview
Summary
This PR adds a dynamic import wrapper for the jose library to support Node.js 20.0-20.18, which cannot use ESM-only modules via require(). The changes enable lazy loading of jose through import(), which works in both ESM and CJS contexts.
Key Changes:
- Created
src/utils/jose.tswith singleton pattern for dynamic jose imports - Changed
UserManagement.jwksgetter to asyncUserManagement.getJWKS()method - Removed
CookieSession.jwksproperty, now usesUserManagement.getJWKS() - Updated minimum Node version to 20.15.0 for better stability
- Cleaned up tsup config by removing redundant external arrays
Breaking Changes:
UserManagement.jwksgetter →UserManagement.getJWKS()async methodCookieSession.jwksproperty removed
The implementation uses nullish coalescing assignment (??=) to cache the jose module promise, ensuring it's only loaded once. All methods that use jose functions (decodeJwt, jwtVerify, createRemoteJWKSet) now await getJose() first.
Confidence Score: 5/5
- This PR is safe to merge with minimal risk - well-architected solution to a clear Node.js compatibility issue
- The implementation is clean, uses proper singleton pattern for caching, maintains backward compatibility through controlled breaking changes in a major version, and solves a real Node.js 20.0-20.18 compatibility issue. The dynamic import approach is industry standard for ESM-only dependencies in dual CJS/ESM packages.
- No files require special attention - all changes are well-structured and appropriate
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| src/utils/jose.ts | 5/5 | New dynamic import wrapper for jose library using nullish coalescing for singleton pattern |
| src/user-management/user-management.ts | 5/5 | Changed jwks from sync getter to async getJWKS() method, uses dynamic jose imports |
| src/user-management/session.ts | 5/5 | Removed jwks property, uses UserManagement.getJWKS() and dynamic jose imports instead |
| package.json | 5/5 | Updated minimum Node version to 20.15.0 for better stability within Node 20.x line |
| tsup.config.ts | 5/5 | Removed redundant external arrays (not needed with bundle: false), formatting improvements |
Sequence Diagram
sequenceDiagram
participant App
participant UserManagement
participant CookieSession
participant getJose
participant jose
App->>UserManagement: authenticateWithSessionCookie(options)
UserManagement->>UserManagement: getJWKS()
UserManagement->>getJose: getJose()
alt First call
getJose->>jose: import('jose')
jose-->>getJose: jose module
getJose-->>UserManagement: cached promise
else Subsequent calls
getJose-->>UserManagement: cached promise
end
UserManagement->>jose: createRemoteJWKSet(url)
jose-->>UserManagement: jwks instance
UserManagement->>getJose: getJose()
getJose-->>UserManagement: cached jose module
UserManagement->>jose: decodeJwt(token)
jose-->>UserManagement: decoded token
UserManagement->>UserManagement: isValidJwt(accessToken)
UserManagement->>getJose: getJose()
getJose-->>UserManagement: cached jose module
UserManagement->>jose: jwtVerify(token, jwks)
jose-->>UserManagement: verified
UserManagement-->>App: authentication response
App->>CookieSession: authenticate()
CookieSession->>UserManagement: getJWKS()
UserManagement->>getJose: getJose() [cached]
getJose-->>UserManagement: jose module
UserManagement-->>CookieSession: jwks
CookieSession->>getJose: getJose() [cached]
getJose-->>CookieSession: jose module
CookieSession->>jose: jwtVerify(token, jwks)
jose-->>CookieSession: verified
CookieSession->>jose: decodeJwt(token)
jose-->>CookieSession: decoded token
CookieSession-->>App: session data
5 files reviewed, no comments
dandorman
approved these changes
Oct 28, 2025
nicknisi
added a commit
that referenced
this pull request
Oct 28, 2025
…18 (#1371) The jose library is ESM-only and cannot be loaded via require() in Node.js versions before 20.19.0. This adds a dynamic import wrapper that works across all Node.js 20+ versions using import() which is supported in both ESM and CJS. Breaking changes: - UserManagement.jwks getter changed to async UserManagement.getJWKS() method - CookieSession.jwks property removed (uses UserManagement.getJWKS() instead) The wrapper enables: - Lazy loading of jose (only when JWT methods are called) - Support for all Node.js 20.x versions - Smaller bundle size (no jose bundling needed) - Clean migration path when Node 20 reaches EOL (April 2026) Also updates: - Minimum Node version to 20.15.0 (conservative choice within 20.x) - tsup config: removes redundant external arrays (not needed with bundle: false) ## Description ## Documentation Does this require changes to the WorkOS Docs? E.g. the [API Reference](https://workos.com/docs/reference) or code snippets need updates. ``` [ ] Yes ``` If yes, link a related docs PR and add a docs maintainer as a reviewer. Their approval is required.
nicknisi
added a commit
that referenced
this pull request
Nov 6, 2025
…18 (#1371) The jose library is ESM-only and cannot be loaded via require() in Node.js versions before 20.19.0. This adds a dynamic import wrapper that works across all Node.js 20+ versions using import() which is supported in both ESM and CJS. Breaking changes: - UserManagement.jwks getter changed to async UserManagement.getJWKS() method - CookieSession.jwks property removed (uses UserManagement.getJWKS() instead) The wrapper enables: - Lazy loading of jose (only when JWT methods are called) - Support for all Node.js 20.x versions - Smaller bundle size (no jose bundling needed) - Clean migration path when Node 20 reaches EOL (April 2026) Also updates: - Minimum Node version to 20.15.0 (conservative choice within 20.x) - tsup config: removes redundant external arrays (not needed with bundle: false) ## Description ## Documentation Does this require changes to the WorkOS Docs? E.g. the [API Reference](https://workos.com/docs/reference) or code snippets need updates. ``` [ ] Yes ``` If yes, link a related docs PR and add a docs maintainer as a reviewer. Their approval is required.
nicknisi
added a commit
that referenced
this pull request
Nov 24, 2025
…18 (#1371) The jose library is ESM-only and cannot be loaded via require() in Node.js versions before 20.19.0. This adds a dynamic import wrapper that works across all Node.js 20+ versions using import() which is supported in both ESM and CJS. Breaking changes: - UserManagement.jwks getter changed to async UserManagement.getJWKS() method - CookieSession.jwks property removed (uses UserManagement.getJWKS() instead) The wrapper enables: - Lazy loading of jose (only when JWT methods are called) - Support for all Node.js 20.x versions - Smaller bundle size (no jose bundling needed) - Clean migration path when Node 20 reaches EOL (April 2026) Also updates: - Minimum Node version to 20.15.0 (conservative choice within 20.x) - tsup config: removes redundant external arrays (not needed with bundle: false) ## Description ## Documentation Does this require changes to the WorkOS Docs? E.g. the [API Reference](https://workos.com/docs/reference) or code snippets need updates. ``` [ ] Yes ``` If yes, link a related docs PR and add a docs maintainer as a reviewer. Their approval is required.
nicknisi
added a commit
that referenced
this pull request
Dec 2, 2025
…18 (#1371) The jose library is ESM-only and cannot be loaded via require() in Node.js versions before 20.19.0. This adds a dynamic import wrapper that works across all Node.js 20+ versions using import() which is supported in both ESM and CJS. Breaking changes: - UserManagement.jwks getter changed to async UserManagement.getJWKS() method - CookieSession.jwks property removed (uses UserManagement.getJWKS() instead) The wrapper enables: - Lazy loading of jose (only when JWT methods are called) - Support for all Node.js 20.x versions - Smaller bundle size (no jose bundling needed) - Clean migration path when Node 20 reaches EOL (April 2026) Also updates: - Minimum Node version to 20.15.0 (conservative choice within 20.x) - tsup config: removes redundant external arrays (not needed with bundle: false) ## Description ## Documentation Does this require changes to the WorkOS Docs? E.g. the [API Reference](https://workos.com/docs/reference) or code snippets need updates. ``` [ ] Yes ``` If yes, link a related docs PR and add a docs maintainer as a reviewer. Their approval is required.
nicknisi
added a commit
that referenced
this pull request
Dec 4, 2025
…18 (#1371) The jose library is ESM-only and cannot be loaded via require() in Node.js versions before 20.19.0. This adds a dynamic import wrapper that works across all Node.js 20+ versions using import() which is supported in both ESM and CJS. Breaking changes: - UserManagement.jwks getter changed to async UserManagement.getJWKS() method - CookieSession.jwks property removed (uses UserManagement.getJWKS() instead) The wrapper enables: - Lazy loading of jose (only when JWT methods are called) - Support for all Node.js 20.x versions - Smaller bundle size (no jose bundling needed) - Clean migration path when Node 20 reaches EOL (April 2026) Also updates: - Minimum Node version to 20.15.0 (conservative choice within 20.x) - tsup config: removes redundant external arrays (not needed with bundle: false) ## Description ## Documentation Does this require changes to the WorkOS Docs? E.g. the [API Reference](https://workos.com/docs/reference) or code snippets need updates. ``` [ ] Yes ``` If yes, link a related docs PR and add a docs maintainer as a reviewer. Their approval is required.
nicknisi
added a commit
that referenced
this pull request
Dec 4, 2025
…18 (#1371) The jose library is ESM-only and cannot be loaded via require() in Node.js versions before 20.19.0. This adds a dynamic import wrapper that works across all Node.js 20+ versions using import() which is supported in both ESM and CJS. Breaking changes: - UserManagement.jwks getter changed to async UserManagement.getJWKS() method - CookieSession.jwks property removed (uses UserManagement.getJWKS() instead) The wrapper enables: - Lazy loading of jose (only when JWT methods are called) - Support for all Node.js 20.x versions - Smaller bundle size (no jose bundling needed) - Clean migration path when Node 20 reaches EOL (April 2026) Also updates: - Minimum Node version to 20.15.0 (conservative choice within 20.x) - tsup config: removes redundant external arrays (not needed with bundle: false) ## Description ## Documentation Does this require changes to the WorkOS Docs? E.g. the [API Reference](https://workos.com/docs/reference) or code snippets need updates. ``` [ ] Yes ``` If yes, link a related docs PR and add a docs maintainer as a reviewer. Their approval is required.
nicknisi
added a commit
that referenced
this pull request
Dec 16, 2025
…18 (#1371) The jose library is ESM-only and cannot be loaded via require() in Node.js versions before 20.19.0. This adds a dynamic import wrapper that works across all Node.js 20+ versions using import() which is supported in both ESM and CJS. Breaking changes: - UserManagement.jwks getter changed to async UserManagement.getJWKS() method - CookieSession.jwks property removed (uses UserManagement.getJWKS() instead) The wrapper enables: - Lazy loading of jose (only when JWT methods are called) - Support for all Node.js 20.x versions - Smaller bundle size (no jose bundling needed) - Clean migration path when Node 20 reaches EOL (April 2026) Also updates: - Minimum Node version to 20.15.0 (conservative choice within 20.x) - tsup config: removes redundant external arrays (not needed with bundle: false) ## Description ## Documentation Does this require changes to the WorkOS Docs? E.g. the [API Reference](https://workos.com/docs/reference) or code snippets need updates. ``` [ ] Yes ``` If yes, link a related docs PR and add a docs maintainer as a reviewer. Their approval is required.
nicknisi
added a commit
that referenced
this pull request
Dec 22, 2025
…18 (#1371) The jose library is ESM-only and cannot be loaded via require() in Node.js versions before 20.19.0. This adds a dynamic import wrapper that works across all Node.js 20+ versions using import() which is supported in both ESM and CJS. Breaking changes: - UserManagement.jwks getter changed to async UserManagement.getJWKS() method - CookieSession.jwks property removed (uses UserManagement.getJWKS() instead) The wrapper enables: - Lazy loading of jose (only when JWT methods are called) - Support for all Node.js 20.x versions - Smaller bundle size (no jose bundling needed) - Clean migration path when Node 20 reaches EOL (April 2026) Also updates: - Minimum Node version to 20.15.0 (conservative choice within 20.x) - tsup config: removes redundant external arrays (not needed with bundle: false) ## Description ## Documentation Does this require changes to the WorkOS Docs? E.g. the [API Reference](https://workos.com/docs/reference) or code snippets need updates. ``` [ ] Yes ``` If yes, link a related docs PR and add a docs maintainer as a reviewer. Their approval is required.
nicknisi
added a commit
that referenced
this pull request
Jan 8, 2026
…18 (#1371) The jose library is ESM-only and cannot be loaded via require() in Node.js versions before 20.19.0. This adds a dynamic import wrapper that works across all Node.js 20+ versions using import() which is supported in both ESM and CJS. Breaking changes: - UserManagement.jwks getter changed to async UserManagement.getJWKS() method - CookieSession.jwks property removed (uses UserManagement.getJWKS() instead) The wrapper enables: - Lazy loading of jose (only when JWT methods are called) - Support for all Node.js 20.x versions - Smaller bundle size (no jose bundling needed) - Clean migration path when Node 20 reaches EOL (April 2026) Also updates: - Minimum Node version to 20.15.0 (conservative choice within 20.x) - tsup config: removes redundant external arrays (not needed with bundle: false) ## Description ## Documentation Does this require changes to the WorkOS Docs? E.g. the [API Reference](https://workos.com/docs/reference) or code snippets need updates. ``` [ ] Yes ``` If yes, link a related docs PR and add a docs maintainer as a reviewer. Their approval is required.
nicknisi
added a commit
that referenced
this pull request
Jan 9, 2026
…18 (#1371) The jose library is ESM-only and cannot be loaded via require() in Node.js versions before 20.19.0. This adds a dynamic import wrapper that works across all Node.js 20+ versions using import() which is supported in both ESM and CJS. Breaking changes: - UserManagement.jwks getter changed to async UserManagement.getJWKS() method - CookieSession.jwks property removed (uses UserManagement.getJWKS() instead) The wrapper enables: - Lazy loading of jose (only when JWT methods are called) - Support for all Node.js 20.x versions - Smaller bundle size (no jose bundling needed) - Clean migration path when Node 20 reaches EOL (April 2026) Also updates: - Minimum Node version to 20.15.0 (conservative choice within 20.x) - tsup config: removes redundant external arrays (not needed with bundle: false) ## Description ## Documentation Does this require changes to the WorkOS Docs? E.g. the [API Reference](https://workos.com/docs/reference) or code snippets need updates. ``` [ ] Yes ``` If yes, link a related docs PR and add a docs maintainer as a reviewer. Their approval is required.
nicknisi
added a commit
that referenced
this pull request
Jan 12, 2026
…18 (#1371) The jose library is ESM-only and cannot be loaded via require() in Node.js versions before 20.19.0. This adds a dynamic import wrapper that works across all Node.js 20+ versions using import() which is supported in both ESM and CJS. Breaking changes: - UserManagement.jwks getter changed to async UserManagement.getJWKS() method - CookieSession.jwks property removed (uses UserManagement.getJWKS() instead) The wrapper enables: - Lazy loading of jose (only when JWT methods are called) - Support for all Node.js 20.x versions - Smaller bundle size (no jose bundling needed) - Clean migration path when Node 20 reaches EOL (April 2026) Also updates: - Minimum Node version to 20.15.0 (conservative choice within 20.x) - tsup config: removes redundant external arrays (not needed with bundle: false) ## Description ## Documentation Does this require changes to the WorkOS Docs? E.g. the [API Reference](https://workos.com/docs/reference) or code snippets need updates. ``` [ ] Yes ``` If yes, link a related docs PR and add a docs maintainer as a reviewer. Their approval is required.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The jose library is ESM-only and cannot be loaded via require() in Node.js versions before 20.19.0. This adds a dynamic import wrapper that works across all Node.js 20+ versions using import() which is supported in both ESM and CJS.
Breaking changes:
The wrapper enables:
Also updates:
Description
Documentation
Does this require changes to the WorkOS Docs? E.g. the API Reference or code snippets need updates.
If yes, link a related docs PR and add a docs maintainer as a reviewer. Their approval is required.