Skip to content

Conversation

@nicknisi
Copy link
Member

Overview

Version 8 is a major release focused on universal runtime compatibility and API modernization. The SDK now works seamlessly across Node.js, Deno, Bun, and Cloudflare Workers while removing long-deprecated APIs.


🔴 BREAKING CHANGES

Runtime & Build System

1. Node.js Version Requirement (BREAKING)

  • Changed: Minimum Node.js version: 1620
  • Reason: Node 18 reached end-of-life in April 2025
  • Files: package.json (engines.node)
  • Migration: Update to Node.js 20 or higher

2. Package Type Change to ESM-First (BREAKING)

  • Changed: package.json now includes "type": "module"
  • Impact: The package is now ESM-first with dual CJS/ESM exports
  • Files: package.json
  • Migration: Most users won't need changes due to conditional exports, but projects with custom build configurations may need adjustments

3. Build System Migration (Internal)

  • Changed: Migrated from tsc to tsup for building
  • Added: tsup.config.ts configuration
  • Removed: tslint.json
  • Impact: Better bundle output, improved tree-shaking, cleaner dist files

Removed Internal Classes (BREAKING)

4. HTTP Client Removal (BREAKING)

  • Removed: NodeHttpClient class and createHttpClient() method
  • Files: src/common/net/node-client.ts (deleted)
  • Impact: Only affects deep imports into internal modules (never part of public API)
  • Migration: Use WorkOS instance instead - HTTP is handled automatically

5. Crypto Provider Removal (BREAKING)

  • Removed: NodeCryptoProvider, IronSessionProvider, EdgeIronSessionProvider, WebIronSessionProvider
  • Changed: Now using iron-session library directly (sealData/unsealData)
  • Files: src/common/crypto/node-crypto-provider.ts (deleted), src/common/iron-session/* (deleted)
  • Impact: Only affects deep imports into internal modules
  • Migration: Use WorkOS instance methods - crypto is handled automatically

Directory Sync (BREAKING)

6. DirectoryUser Interface Changes (BREAKING)

  • Removed fields:
    • emails → Use customAttributes.emails
    • username → Use customAttributes.username
    • jobTitle → Use customAttributes.jobTitle
  • Removed utility: getPrimaryEmail() function
  • Files: src/directory-sync/interfaces/directory-user.interface.ts, src/directory-sync/utils/get-primary-email.ts (deleted)
  • Migration:
    // v7
    user.emails
    user.username
    user.jobTitle
    
    // v8
    user.customAttributes?.emails
    user.customAttributes?.username
    user.customAttributes?.jobTitle

User Management (BREAKING)

7. AuthorizationURLOptions Changes (BREAKING)

  • Removed: context field (no longer supported)
  • Files: src/user-management/interfaces/authorization-url-options.interface.ts
  • Migration: Remove the context parameter from authorization URL calls

8. Removed Deprecated Methods (BREAKING)

  • Removed:
    • sendMagicAuthCode() → Use userManagement.sendMagicCode() instead
    • sendPasswordResetEmail() → Use userManagement.sendPasswordResetEmail() instead
    • refreshAndSealSessionData() → Use new session helper methods instead
  • Files: src/user-management/user-management.ts, serializers removed

SSO (BREAKING)

9. SSOAuthorizationURLOptions Type Changes (BREAKING)

  • Changed: Converted to discriminated union for type safety
  • Removed: domain field (deprecated)
  • Files: src/sso/interfaces/authorization-url-options.interface.ts
  • Impact: Stricter TypeScript types - must now specify exactly one of: connection, organization, or provider
  • Migration:
    // v7 - Multiple options allowed
    { connection: 'conn_123', organization: 'org_456' } // Both accepted
    
    // v8 - Mutually exclusive (enforced by types)
    { connection: 'conn_123' } // OR
    { organization: 'org_456' } // OR
    { provider: 'GoogleOAuth' }

10. Connection Interface (BREAKING)

  • Removed: Several deprecated internal fields
  • Files: src/sso/interfaces/connection.interface.ts
  • Migration: Use only documented fields

MFA (BREAKING)

11. Method Removal (BREAKING)

  • Removed: verifyFactor() method
  • Files: src/mfa/mfa.ts, src/mfa/interfaces/verify-factor-options.ts (deleted)
  • Migration: Use verifyChallenge() instead (same functionality)
    // v7
    await workos.mfa.verifyFactor({ authenticationFactorId, code });
    
    // v8
    await workos.mfa.verifyChallenge({ authenticationFactorId, code });

Organizations (BREAKING)

12. Organization Options Changes (BREAKING)

  • Removed from CreateOrganizationOptions and UpdateOrganizationOptions:
    • allowProfilesOutsideOrganization
    • domains (use domainData instead)
  • Files: src/organizations/interfaces/*.interface.ts
  • Migration: Remove these fields from organization creation/update calls

13. Organization Domain Enum (BREAKING)

  • Removed: LegacyVerified from OrganizationDomainState enum
  • Files: src/organizations/interfaces/organization-domain.interface.ts
  • Migration: Use Verified instead

Events (BREAKING)

14. Event Type Removals (BREAKING)

  • Removed event interfaces:
    • DsyncDeactivatedEvent → Use dsync.deleted instead
    • OrganizationMembershipAdded → Not applicable in v8
    • OrganizationMembershipRemoved → Not applicable in v8
  • Files: src/common/interfaces/event.interface.ts
  • Migration:
    // v7
    if (event.event === 'dsync.deactivated') { }
    
    // v8
    if (event.event === 'dsync.deleted') { }

Vault (BREAKING)

15. Removed Deprecated Method Aliases (BREAKING)

  • Removed methods:
    • createSecret() → Use createObject() instead
    • listSecrets() → Use listObjects() instead
    • listSecretVersions() → Use listObjectVersions() instead
    • readSecret() → Use readObject() instead
    • describeSecret() → Use describeObject() instead
    • updateSecret() → Use updateObject() instead
    • deleteSecret() → Use deleteObject() instead
  • Files: src/vault/vault.ts
  • Migration: Replace all *Secret methods with *Object equivalents

✅ NEW FEATURES

16. Client API for PKCE Flows (NON-BREAKING)

  • Added: New @workos-inc/node/client export for client-side operations without API key
  • Files: src/client/*, src/index.client.ts
  • Use case: Browser-based PKCE flows, public client operations
  • Example:
    import * as userManagement from '@workos-inc/node/client';
    
    const url = userManagement.getAuthorizationUrl({
      clientId: 'client_123',
      redirectUri: 'https://example.com/callback',
      provider: 'authkit',
    });

17. Universal Runtime Support (NON-BREAKING)

  • Improved: Better support for Deno, Bun, and Cloudflare Workers
  • Added: Conditional exports in package.json for runtime-specific entry points
  • Files: package.json (exports), src/index.worker.ts
  • Example:
    // Cloudflare Workers
    import { WorkOS } from '@workos-inc/node/worker';
    
    // Deno
    import { WorkOS } from 'npm:@workos-inc/node';
    
    // Bun (same as Node.js)
    import { WorkOS } from '@workos-inc/node';

18. Environment Variable Helper (NON-BREAKING)

  • Added: Internal getEnv() helper for better cross-runtime environment variable access
  • Files: src/common/utils/env.ts
  • Benefit: Works consistently across Node.js, Deno, Cloudflare Workers, etc.

19. Pagination Improvements (NON-BREAKING)

  • Changed: AutoPaginatable now properly defaults PaginationOptions generic parameter
  • Files: src/common/utils/pagination.ts
  • Benefit: Better TypeScript inference and type safety

🔧 INTERNAL IMPROVEMENTS

20. Linting Migration (Internal)

  • Changed: Migrated from TSLint to ESLint with flat config
  • Added: eslint.config.mjs
  • Removed: tslint.json
  • Impact: Better code quality checks, modern linting setup

21. Runtime Testing (Internal)

  • Added: New GitHub Actions workflow for testing across multiple runtimes
  • Added: Ecosystem check script (scripts/ecosystem-check.ts)
  • Files: .github/workflows/runtime-tests.yml
  • Benefit: Ensures SDK works correctly in all supported runtimes

22. Dependency Updates (Internal)

  • Updated: All dependencies to latest compatible versions
  • Updated: Development tooling (Jest 30, TypeScript 5.9, etc.)
  • Files: package.json, package-lock.json

23. Test Infrastructure (Internal)

  • Updated: Jest configuration migrated to CommonJS
  • Added: Jest ESM transform
  • Files: jest.config.cjs, jest-transform-esm.cjs
  • Updated: Worker test environment with latest Miniflare

📋 Files Changed Summary

  • 104 files changed: 9,161 insertions, 3,879 deletions
  • Major additions: Client API module, runtime-specific exports, environment helper
  • Major deletions: Internal HTTP/crypto providers, deprecated methods, legacy event types
  • Configuration: New build system (tsup), new linting (ESLint), updated Jest

📖 Migration Guide

See V8_MIGRATION_GUIDE.md for detailed migration instructions.

Note: The migration guide needs minor updates for:

  • Package type change to ESM-first
  • SSO AuthorizationURLOptions discriminated union
  • Vault method aliases removal
  • Complete refreshAndSealSessionData() examples

🧪 Testing

  • ✅ All existing tests updated and passing
  • ✅ Runtime compatibility tests added
  • ✅ Worker environment tests updated
  • ✅ Ecosystem check script validates multi-runtime support

@nicknisi nicknisi requested a review from a team as a code owner October 13, 2025 17:50
@nicknisi nicknisi requested a review from amygdalama October 13, 2025 17:50
@nicknisi nicknisi marked this pull request as draft October 17, 2025 13:34
@benasher44
Copy link

Since you're going for dual ESM/CJS, you might want to check "are the types wrong". For example: https://arethetypeswrong.github.io/?p=%40workos-inc%2Fnode%408.0.0-rc.2

kendallstrautman and others added 25 commits November 6, 2025 11:10
Drop support for Node 16, which is long past EOL. This will be merged
into the `version-8` branch.

>[!WARNING]
>
>Node 18 is where we're moving to, but that will also be EOL in April,
2025.

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.
>[!Note]
>
>This PR is against the `version-8` branch.

TSLint has been EOL for several years. This replaces it with
typeScript-eslint and provides a comparable configuration for minimal
changes to the code.

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.
## 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.
>[!note]
>This is against the `version-8` branch, which drops support for Node
16, allowing for this update to happen.

Update to latest version of iron-session.

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.
>[!note]
>This change is against the `version-8` branch.

## Description

Upgrade to Prettier v3 and commit minimal changes resulting from that.

## 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.
>[!note]
>This change is against the `version-8` branch.

Update to latest of the following dev dependencies
- TypeScript
- ts-jest
- Jest
- Supertest

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.
Adds tests and updates typing for pagination utils.
…rt resolution across all target runtimes (#1301)

This PR implements comprehensive universal runtime compatibility for the
WorkOS Node.js SDK v8, addressing critical module resolution issues that
prevented the package from working correctly across different JavaScript
runtimes.

The current v8 build configuration with `tsup` and `bundle: false`
created incompatible import patterns:
- **CJS files** attempted to `require()` ESM files (`.js` extension)
- **ESM files** imported without explicit file extensions, breaking
strict runtimes like Deno
- **Standalone Node.js** execution failed due to cross-format imports
- **Edge Runtime** and **Cloudflare Workers** compatibility was broken

**Phase 1: Import Path Rewriting** ✅
- Implemented custom `fixImportsPlugin` to rewrite import paths during
build
- ESM builds now use explicit `.js` extensions for all relative imports
- CJS builds use `.cjs` extensions for internal module references
- Maintains bundler compatibility while fixing standalone runtime
execution

**Phase 2: Enhanced Export Mapping** ✅
- Added runtime-specific export conditions for optimal module resolution
- Separate TypeScript type paths for CJS (`.d.cts`) and ESM (`.d.ts`)
- Dedicated worker builds for edge runtimes (`workerd`, `edge-light`)
- Performance-ordered conditions for faster resolution

**Phase 3: Comprehensive Testing Infrastructure** ✅
- Created ecosystem compatibility test suite covering 6 runtime
scenarios
- Manual validation commands for immediate testing
- Automated CI/CD workflow with matrix strategy testing Node.js 18/20,
Deno, and Bun
- Fail-fast smoke tests for quick compatibility validation

| Runtime | CJS Build | ESM Build | Status | Notes |
|---------|-----------|-----------|---------|-------|
| **Next.js/webpack** | ✅ | ✅ | Working | Bundler handles resolution |
| **Node.js standalone** | ✅ | ✅ | **FIXED** | Import rewriting resolved
cross-format issues |
| **Deno** | N/A | ✅ | **FIXED** | Explicit .js extensions now provided
|
| **Bun** | ✅ | ✅ | Working | Enhanced with runtime-specific exports |
| **Edge Runtime** | ✅ | ✅ | **FIXED** | Dedicated worker builds |
| **Cloudflare Workers** | ✅ | ✅ | **FIXED** | Optimized for workerd
environment |

1. **Custom Import Rewriter Plugin** (`scripts/fix-imports-plugin.ts`)
   - Transforms relative imports to include appropriate file extensions
   - Format-aware: `.js` for ESM, `.cjs` for CommonJS
   - Preserves external module imports unchanged

2. **Enhanced Package.json Exports**
   ```json
   {
     "exports": {
       ".": {
         "types": {
           "require": "./lib/cjs/index.d.cts",
           "import": "./lib/esm/index.d.ts"
         },
         "workerd": "./lib/esm/index.worker.js",
         "edge-light": "./lib/esm/index.worker.js",
         "deno": "./lib/esm/index.js",
         "bun": {
           "import": "./lib/esm/index.js",
           "require": "./lib/cjs/index.cjs"
         },
         "node": {
           "import": "./lib/esm/index.js",
           "require": "./lib/cjs/index.cjs"
         },
         "import": "./lib/esm/index.js",
         "require": "./lib/cjs/index.cjs",
         "default": "./lib/esm/index.js"
       }
     }
   }
   ```

3. **CI/CD Integration** (`.github/workflows/runtime-tests.yml`)
- Matrix strategy testing across Node.js versions and alternative
runtimes
   - Automated validation on every PR and push
   - Quick smoke tests for immediate feedback

All 6 runtime scenarios now pass:
- ✅ Node.js CJS: `WorkOSNode`
- ✅ Node.js ESM: `WorkOSNode`
- ✅ Deno: `WorkOSNode`
- ✅ Bun CJS: `WorkOSNode`
- ✅ Bun ESM: `WorkOSNode`
- ✅ Worker: Module resolution successful

```bash
node -e "console.log('CJS:', require('./lib/cjs/index.cjs').WorkOS.name)"

node -e "import('./lib/esm/index.js').then(m => console.log('ESM:', m.WorkOS.name))"

deno eval "import('./lib/esm/index.js').then(m => console.log('Deno:', m.WorkOS.name))"

bun -e "console.log('Bun:', require('./lib/cjs/index.cjs').WorkOS.name)"

pnpm check:runtimes
```

- ✅ **No breaking changes** to existing API surface
- ✅ **Bundler compatibility** maintained (Next.js, webpack, Vite, etc.)
- ✅ **Tree-shaking** still works properly
- ✅ **Package size** unchanged (unbundled builds)
- ✅ **TypeScript support** enhanced with improved type resolution

- Extensive testing across all target runtimes before merge
- Automated CI validation prevents regressions
- Rollback plan available (revert to `bundle: true` if needed)
- Industry-standard patterns based on OpenAI SDK, Drizzle ORM practices

```
[ ] Yes
```

This change improves internal module resolution and doesn't affect the
public API, so no documentation updates are required.
Type constructEvent payload parameter as Record<string, unknown>.
This pull request introduces a new set of client-only methods for
building OAuth and SSO URLs that do not require a WorkOS API key, making
them suitable for browser-based PKCE flows and similar use cases. The
changes include the addition of new client modules for user management
and SSO, comprehensive tests for these modules, a shared query string
utility, and updates to the main SDK exports. Additionally, the
server-side SDK now delegates URL generation to the new client modules
for consistency and maintainability.

**Client Module Additions and Exports:**

* Added new `src/client/user-management.ts` and `src/client/sso.ts`
modules, providing functions to build authorization, logout, and JWKS
URLs for OAuth and SSO flows without requiring an API key. These modules
include robust argument validation and support for custom query
parameters and PKCE.
[[1]](diffhunk://#diff-b5a04503adce4aaadee02b4511ee9bd11ec26a46927bde7c07d85ad31786e4bbR1-R147)
[[2]](diffhunk://#diff-aba556dc64a77e993f9ce2de8ffd20b276128d1f6f4ba69bf2967e05dc1f7676R1-R62)
* Updated `src/index.client.ts` and `src/client/index.ts` to export the
new client modules and their types, making them easily accessible for
browser environments.
[[1]](diffhunk://#diff-0311bcbdf2e78d79d36c4417c3c6d6409834421d79d111e294dbacf47e487984R1-R19)
[[2]](diffhunk://#diff-24f1ac19d22913269d99a8a5afa4c13aa7fd2c8b9858529046424841ca6421daR1-R18)
* Updated the package export map in `package.json` to include the new
client entry points for both ESM and CJS consumers.

**Testing and Utilities:**

* Added comprehensive test suites for the new client modules in
`src/client/user-management.spec.ts`, `src/client/sso.spec.ts`, and
integration tests in `src/index.client.spec.ts`, ensuring correct URL
generation and error handling for all supported options.
[[1]](diffhunk://#diff-01061808fc40490ae09053b5553be015aa94e42cb7efcf8dbeba57a23c699e80R1-R219)
[[2]](diffhunk://#diff-28da04c6058919471ee96a352c58c206146b8ac07454e7ab25613a59a20fc7bdR1-R114)
[[3]](diffhunk://#diff-da4fa2fd6101519fd777b8803892a919b567b988b1bb48fc941671e20beb23ecR1-R47)
* Introduced a shared `toQueryString` utility in `src/client/utils.ts`
for consistent and backwards-compatible query string generation across
client modules.

**Server SDK Refactoring:**

* Updated server-side SDK modules (`src/sso/sso.ts` and
`src/user-management/user-management.ts`) to delegate authorization URL
generation to the new client modules, ensuring consistency and reducing
code duplication.
[[1]](diffhunk://#diff-40f88259248b65c47b88e6460bbb0e52cd4f70fc298c96319889051c19bcd3a6L1-R1)
[[2]](diffhunk://#diff-40f88259248b65c47b88e6460bbb0e52cd4f70fc298c96319889051c19bcd3a6L26-L40)
[[3]](diffhunk://#diff-40f88259248b65c47b88e6460bbb0e52cd4f70fc298c96319889051c19bcd3a6L68-L100)
[[4]](diffhunk://#diff-5df813524b03843b7a76359f2c080a36e82f2c065c578794071eb6ffcc0efa7cL3-R3)

These changes collectively improve the SDK's usability for client-side
OAuth flows, enhance maintainability, and ensure robust, well-tested URL
generation logic.
## Description

This pull request removes several deprecated fields and enum values from
user management and directory sync interfaces, as well as from
organization domain state definitions. These changes help clean up the
codebase and ensure that only current, supported attributes are exposed
in the interfaces.

### Deprecated field removals

**User management authorization options:**
* Removed the deprecated `context` field from both
`AuthorizationURLOptions` and `UserManagementAuthorizationURLOptions`
interfaces, as it is no longer required for getting authorization URLs.
[[1]](diffhunk://#diff-b5a04503adce4aaadee02b4511ee9bd11ec26a46927bde7c07d85ad31786e4bbL9-L13)
[[2]](diffhunk://#diff-22f5a89986b17dd45c06dbbba9f624690b22d5ede6e7455dade9d3fb7924f131L6-L10)

**Directory user interfaces:**
* Removed deprecated fields (`emails`, `username`, and `jobTitle`) from
both `DirectoryUser` and `DirectoryUserResponse` interfaces, as these
should now be accessed through custom attributes.
[[1]](diffhunk://#diff-2151436e8d7d3a67c1165760fdfa80802fd72276034e54114c3ddfcdfe03e7fcL22-L41)
[[2]](diffhunk://#diff-2151436e8d7d3a67c1165760fdfa80802fd72276034e54114c3ddfcdfe03e7fcL61-L80)

### Enum cleanup

**Organization domain state:**
* Removed the deprecated `LegacyVerified` value from the
`OrganizationDomainState` enum.

## 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 pull request updates the project's Node.js version requirements and
related configuration files to use Node.js 20 or newer, and removes
support for Node.js 18. These changes help ensure compatibility with the
latest Node.js features and security updates.

**Node.js version updates:**

* Updated the required Node.js engine in `package.json` from `>=18` to
`>=20`.
* Changed the `@types/node` development dependency in `package.json`
from version `~18` to `~20`.

**CI/CD workflow updates:**

* Modified the matrix in `.github/workflows/ci.yml` to run tests only on
Node.js versions 20, 22, and 24, removing Node.js 18.
* Updated the Node.js version used in
`.github/workflows/fix-latest.yml`, `.github/workflows/release.yml`, and
`.github/workflows/runtime-tests.yml` from 18 to 22.
[[1]](diffhunk://#diff-942585ab102b61d7fc2b3ebd901f78b627f006e4fe9ed539189fce8bfc503740L23-R23)
[[2]](diffhunk://#diff-87db21a973eed4fef5f32b267aa60fcee5cbdf03c67fafdc2a9b553bb0b15f34L22-R22)
[[3]](diffhunk://#diff-8240caaafb609c069828d284a282ebeb4f57b1ce1668ab60c97ad12412dfeb6dL12-R12)

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 pull request primarily updates dependencies and refactors test
suites to improve consistency and compatibility with newer libraries.
The most significant changes are grouped below:

**Dependency Upgrades:**

* Updated several dependencies in `package.json`, including major
upgrades to `jose`, `eslint`, `jest`, `babel-jest`, `miniflare`, `nock`,
`supertest`, `ts-jest`, `tsx`, `typescript`, and related type packages.
These upgrades ensure compatibility with the latest features and
security patches.
[[1]](diffhunk://#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519L44-R44)
[[2]](diffhunk://#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519L53-R78)

**Testing Consistency & Modernization:**

* Replaced all usages of `.toThrowError` in Jest test assertions with
`.toThrow` for error checking across multiple test files, aligning with
best practices for newer Jest versions.
[[1]](diffhunk://#diff-674b12b55633a96dd5a8eb3177311ff4d2253741edc2a281166a829225aba040L129-R135)
[[2]](diffhunk://#diff-674b12b55633a96dd5a8eb3177311ff4d2253741edc2a281166a829225aba040L284-R286)
[[3]](diffhunk://#diff-674b12b55633a96dd5a8eb3177311ff4d2253741edc2a281166a829225aba040L346-R344)
[[4]](diffhunk://#diff-cd36b281a0abacada2f46ce13c54911e6c24a720de104792fec5f1b529f10f74L183-R185)
[[5]](diffhunk://#diff-cd36b281a0abacada2f46ce13c54911e6c24a720de104792fec5f1b529f10f74L203-R205)
[[6]](diffhunk://#diff-6b41d79b4db8c635487ebe8aa7e41eae6e10899ed0876c1de5f81e3b8a97b529L205-R205)
[[7]](diffhunk://#diff-6b41d79b4db8c635487ebe8aa7e41eae6e10899ed0876c1de5f81e3b8a97b529L357-R357)
[[8]](diffhunk://#diff-f5f65d907d4110a523dd2249817af8ee20f4f9e2f8259fd0594f0ba909237b47L154-R154)
[[9]](diffhunk://#diff-f5f65d907d4110a523dd2249817af8ee20f4f9e2f8259fd0594f0ba909237b47L178-R178)
[[10]](diffhunk://#diff-59f7ea4f069122023e354579e47852aa960f15a06c522ceedde35f7c66db0400L2201-R2203)
[[11]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL102-R104)
[[12]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL113-R115)
[[13]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL124-R126)
[[14]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL136-R138)
[[15]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL148-R150)

* Updated Jest snapshot file headers to reference the current Jest
documentation URL instead of the deprecated link.
[[1]](diffhunk://#diff-51e4a0fec533fa983dab0091ee91e95a2de52e2c42836ff8de594153df44bbecL1-R1)
[[2]](diffhunk://#diff-e3850ae39761cff3333b5cf46beb64fb7171cc18c9a91eaa3693ba3c6a4985dcL1-R1)

**Mocking Improvements for JWT Handling:**

* Refactored mocking of the `jose` library in tests, switching from
`jest.spyOn` to `jest.mocked` for `jwtVerify` and `createRemoteJWKSet`.
This approach is more robust and compatible with newer Jest and
TypeScript versions.
[[1]](diffhunk://#diff-19c19386dcd41859de57e28e16189fe3fa794ae5bb588b15ddde89eee5c9b327R9-R13)
[[2]](diffhunk://#diff-19c19386dcd41859de57e28e16189fe3fa794ae5bb588b15ddde89eee5c9b327L69-R74)
[[3]](diffhunk://#diff-19c19386dcd41859de57e28e16189fe3fa794ae5bb588b15ddde89eee5c9b327L102-R107)
[[4]](diffhunk://#diff-19c19386dcd41859de57e28e16189fe3fa794ae5bb588b15ddde89eee5c9b327L250-R254)
[[5]](diffhunk://#diff-19c19386dcd41859de57e28e16189fe3fa794ae5bb588b15ddde89eee5c9b327L338-R342)
[[6]](diffhunk://#diff-19c19386dcd41859de57e28e16189fe3fa794ae5bb588b15ddde89eee5c9b327L384-R387)
[[7]](diffhunk://#diff-59f7ea4f069122023e354579e47852aa960f15a06c522ceedde35f7c66db0400R25-R30)
[[8]](diffhunk://#diff-59f7ea4f069122023e354579e47852aa960f15a06c522ceedde35f7c66db0400L888-R900)
[[9]](diffhunk://#diff-59f7ea4f069122023e354579e47852aa960f15a06c522ceedde35f7c66db0400L974-R978)
[[10]](diffhunk://#diff-59f7ea4f069122023e354579e47852aa960f15a06c522ceedde35f7c66db0400L1001-R1005)
[[11]](diffhunk://#diff-59f7ea4f069122023e354579e47852aa960f15a06c522ceedde35f7c66db0400L1043-R1046)

**Error Handling Standardization:**

* Standardized error throwing in tests by using direct error classes
(e.g., `UnauthorizedException`, `SignatureVerificationException`)
instead of custom error objects, simplifying the test logic and
improving clarity.
[[1]](diffhunk://#diff-674b12b55633a96dd5a8eb3177311ff4d2253741edc2a281166a829225aba040L129-R135)
[[2]](diffhunk://#diff-674b12b55633a96dd5a8eb3177311ff4d2253741edc2a281166a829225aba040L284-R286)
[[3]](diffhunk://#diff-674b12b55633a96dd5a8eb3177311ff4d2253741edc2a281166a829225aba040L346-R344)
[[4]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL102-R104)
[[5]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL113-R115)
[[6]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL124-R126)
[[7]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL136-R138)
[[8]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL148-R150)

**Minor Test Maintenance:**

* Removed unused imports and made minor code cleanups in test files to
reduce noise and improve maintainability.

These changes collectively modernize the codebase, improve test
reliability, and ensure compatibility with the latest tooling.

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

This pull request introduces a minor improvement to the
`AutoPaginatable` class in `src/common/utils/pagination.ts`. The change
sets a default type for the `ParametersType` generic parameter, making
the class easier to use when the default `PaginationOptions` are
sufficient.

* TypeScript Improvement:
* Set a default value for the `ParametersType` generic parameter to
`PaginationOptions` in the `AutoPaginatable` class, simplifying
instantiation when custom options are not needed.

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

Add runtime and version detection to the WorkOS Node SDK User-Agent
string to gather analytics about JavaScript runtime environments and
versions being used by customers.

## Changes

### Core Implementation
- **New utility**: `src/common/utils/runtime-info.ts` - Detects runtime
type and version across Node.js, Deno, Bun, Cloudflare Workers, and
other environments
- **User-Agent enhancement**: Modified `createUserAgent()` method in
`src/workos.ts` to include runtime information in standard format
- **Error handling**: Graceful fallbacks when runtime version detection
fails

### User-Agent Format
**Before**: `workos-node/8.0.0-beta.1 MyApp: 1.0.0`
**After**: `workos-node/8.0.0-beta.1 (node/v20.5.0) MyApp: 1.0.0`

The new format follows standard User-Agent conventions with runtime
information in parentheses, maintaining backward compatibility with
existing analytics parsing.

### Examples
- Node.js: `workos-node/8.0.0-beta.1 (node/v20.5.0)`
- Node.js with appInfo: `workos-node/8.0.0-beta.1 (node/v20.5.0) MyApp:
1.0.0`
- Deno: `workos-node/8.0.0-beta.1 (deno/1.36.4)`
- Edge runtime: `workos-node/8.0.0-beta.1 (edge-light)`

## Testing

### Unit Tests
- **17 comprehensive test cases** for `getRuntimeInfo()` utility
covering all runtime scenarios
- **Mock testing** for different environments (Node.js, Deno, Bun, edge
runtimes)
- **Error handling verification** with graceful degradation
- **Real-world testing** with actual Node.js environment

### Integration Tests
- **Updated `workos.spec.ts`** with runtime info mocking
- **Jest snapshots updated** to reflect new User-Agent format
- **Backward compatibility verified** for existing appInfo functionality

## Benefits

### For WorkOS Analytics
- **Node.js adoption tracking**: Monitor which Node.js versions are most
popular
- **Runtime diversity insights**: Understand usage across Node.js, Deno,
Bun, and edge environments
- **Support optimization**: Prioritize support for popular runtime
versions
- **Migration patterns**: Track adoption of new JavaScript runtime
versions

### For Customer Support
- **Environment debugging**: Quickly identify runtime-specific issues
from API logs
- **Performance optimization**: Focus optimization efforts on popular
runtime combinations
- **Compatibility planning**: Make informed decisions about runtime
support

## Technical Details

### Runtime Detection
- **Cached detection**: Uses existing `detectRuntime()` from `env.ts`
for performance
- **Version extraction**: Safely extracts version numbers from
runtime-specific globals
- **Fallback mechanisms**: Multiple strategies for version detection
(e.g., Bun version from user-agent)
- **Error resilience**: Never crashes, gracefully degrades to runtime
name only

### Implementation Approach
- **No configuration needed**: Runtime info is always included (internal
analytics feature)
- **Zero breaking changes**: Existing functionality unchanged
- **Standards compliant**: Follows established User-Agent format
conventions
- **Minimal overhead**: One-time detection per process with cached
results

## Risk Mitigation

- **Version detection failures**: Graceful fallback to runtime name only
- **Performance impact**: Minimal (cached detection, ~1ms overhead)
- **User-Agent length**: Reasonable increase (~20 characters)
- **Privacy concerns**: No personally identifiable information collected
…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.
## Description

This pull request removes the dependency on the external `leb` and `qs`
packages by introducing an in-house LEB128 encoding/decoding utility and
a custom query string serializer. It updates all relevant imports to use
these new utilities, ensuring compatibility and maintainability.
Comprehensive unit tests for the new LEB128 implementation are also
included. This is to improve cross-runtime compatibility support.

**Dependency Removal and Internal Utility Replacement:**

* Removed the `leb` and `qs` packages from `package.json` and replaced
their usage with internal implementations. (`package.json`,
[package.jsonL45-R45](diffhunk://#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519L45-R45))
* Replaced all imports of `leb`'s `encodeUInt32`/`decodeUInt32` with
internal versions in `src/vault/vault.ts`.
* Removed the old `toQueryString` implementation from
`src/client/utils.ts` and updated all imports in `src/client/sso.ts` and
`src/client/user-management.ts` to use the new internal utility.
[[1]](diffhunk://#diff-3973d52ad7d2360214857fd42a183273a2e3904458c1eb573c34b3ec6151ab02L1-L20)
[[2]](diffhunk://#diff-aba556dc64a77e993f9ce2de8ffd20b276128d1f6f4ba69bf2967e05dc1f7676L1-R1)
[[3]](diffhunk://#diff-b5a04503adce4aaadee02b4511ee9bd11ec26a46927bde7c07d85ad31786e4bbL1-R1)

**New Utility Implementations:**

* Added `src/common/utils/leb128.ts`: Implements `encodeUInt32` and
`decodeUInt32` for LEB128 encoding/decoding of unsigned 32-bit integers,
with input validation and error handling.
* Added `src/common/utils/query-string.ts`: Implements `toQueryString`,
matching the old behavior (RFC1738 encoding, key sorting, array/object
handling) without external dependencies.

**Testing and Compatibility:**

* Added comprehensive unit tests for the new LEB128 implementation in
`src/common/utils/leb128.spec.ts`, including boundary values, invalid
input handling, and compatibility with the previous `leb` package's
output.

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

6 participants