Skip to content

[v8] Add dynamic import wrapper for jose to support Node.js 20.15-20.18#1371

Merged
nicknisi merged 1 commit intoversion-8from
nicknisi/cjs-build-fixes
Oct 28, 2025
Merged

[v8] Add dynamic import wrapper for jose to support Node.js 20.15-20.18#1371
nicknisi merged 1 commit intoversion-8from
nicknisi/cjs-build-fixes

Conversation

@nicknisi
Copy link
Member

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

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)
@nicknisi nicknisi requested a review from a team as a code owner October 20, 2025 19:38
@nicknisi nicknisi requested review from dandorman and mattgd and removed request for a team and dandorman October 20, 2025 19:38
@nicknisi nicknisi changed the title [v8] Add dynamic import wrapper for jose to support Node.js 20.0-20.18 [v8] Add dynamic import wrapper for jose to support Node.js 20.15-20.18 Oct 20, 2025
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

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.ts with singleton pattern for dynamic jose imports
  • Changed UserManagement.jwks getter to async UserManagement.getJWKS() method
  • Removed CookieSession.jwks property, now uses UserManagement.getJWKS()
  • Updated minimum Node version to 20.15.0 for better stability
  • Cleaned up tsup config by removing redundant external arrays

Breaking Changes:

  • UserManagement.jwks getter → UserManagement.getJWKS() async method
  • CookieSession.jwks property 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
Loading

5 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

@nicknisi nicknisi merged commit 0a318dc into version-8 Oct 28, 2025
6 checks passed
@nicknisi nicknisi deleted the nicknisi/cjs-build-fixes branch October 28, 2025 17:21
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.
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.

2 participants