Skip to content

Add NestJS SDK (@thunderid/nestjs)#26

Open
webdevelopersrinu wants to merge 2 commits into
thunder-id:mainfrom
webdevelopersrinu:add-nestjs-sdk
Open

Add NestJS SDK (@thunderid/nestjs)#26
webdevelopersrinu wants to merge 2 commits into
thunder-id:mainfrom
webdevelopersrinu:add-nestjs-sdk

Conversation

@webdevelopersrinu

@webdevelopersrinu webdevelopersrinu commented Jul 11, 2026

Copy link
Copy Markdown

Purpose

Adds @thunderid/nestjs, a NestJS SDK built on top of @thunderid/express.
NestJS is widely used in enterprise Node.js backends, and every major auth
vendor (Auth0, Clerk, etc.) ships a NestJS integration — this fills that gap
in the ThunderID JavaScript ecosystem.

Approach

Thin idiomatic-NestJS wrapper over the existing Express SDK (no re-implemented
auth logic), mirroring how @thunderid/express wraps @thunderid/node:

Export Maps to
ThunderIDModule.forRoot(config) global dynamic module; provides config + service
ThunderIDService signIn, signOut, isSignOutSuccess, isSignedIn, getUser over ThunderIDExpressClient
ThunderIDGuard NestJS equivalent of the Express protect() middleware (401 on no/invalid session)
@CurrentUser() param decorator resolving the user attached by the guard

Everything from @thunderid/express (and transitively node/javascript) is
re-exported. Response handling stays in the consumer's controllers instead of
config hooks (onSignIn/onError), which is the idiomatic NestJS shape.

Build/lint/test setup is copied from packages/express (rolldown ESM+CJS,
tsc declarations, shared eslint/prettier/vitest configs). Works with NestJS
apps on the default Express platform; requires cookie-parser (same as the
Express SDK).

Testing

  • Unit tests for the guard (401 / user attachment) and module registration.
  • Full end-to-end verification with a standalone NestJS 11 app consuming the
    packed npm tarball (registry versions of @thunderid/express@0.2.5,
    @thunderid/node@0.2.3, @thunderid/javascript@0.3.10) against a local
    mock OIDC provider (discovery, authorize, token, JWKS, end-session):
    • /login → 302 to /oauth2/authorize with PKCE (S256), session cookie set
    • code callback → token exchange, RS256 ID token validated against JWKS
    • guarded route → 401 without session, 200 with user via @CurrentUser()
    • /logout → cookie cleared, redirect to end-session endpoint,
      state=sign_out_success round-trip, session invalidated (401 after)
  • Consumer type resolution verified under moduleResolution: nodenext with
    noImplicitAny — this required adding a "types" condition to the
    exports map (with exports present, TypeScript ignores the top-level
    "types" field). Note: the other packages in this repo that use bare
    {"import", "require"} exports (javascript, node, browser, react,
    express) have the same latent issue for nodenext consumers — happy to
    fix those in a follow-up PR.

Related

  • Docs page and a samples/nestjs/quickstart app can follow in separate PRs.

Summary by CodeRabbit

  • New Features
    • Added the @thunderid/nestjs SDK, including ThunderIDModule.forRoot, ThunderIDService sign-in/sign-out handling, and ThunderIDGuard route protection.
    • Added @CurrentUser() decorator for retrieving the authenticated user from requests.
    • Added NestJS package documentation with setup/config examples and API reference.
  • Tests
    • Added Vitest coverage for the guard behavior, CurrentUser-related request user attachment, and forRoot module configuration.
  • Documentation
    • Updated the main README to include the @thunderid/nestjs package in the Packages table and added the package’s README.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 26be4b6c-2b7b-486d-a873-88f80ad458b2

📥 Commits

Reviewing files that changed from the base of the PR and between 8f236e8 and df3e225.

📒 Files selected for processing (4)
  • packages/nestjs/README.md
  • packages/nestjs/src/ThunderIDService.ts
  • packages/nestjs/src/__tests__/ThunderIDGuard.test.ts
  • packages/nestjs/tsconfig.spec.json
✅ Files skipped from review due to trivial changes (1)
  • packages/nestjs/README.md

📝 Walkthrough

Walkthrough

Adds the @thunderid/nestjs SDK with NestJS module registration, authentication service, route guard, current-user decorator, package exports, build tooling, tests, and documentation.

Changes

NestJS SDK

Layer / File(s) Summary
Package foundation and build pipeline
packages/nestjs/package.json, packages/nestjs/rolldown.config.js, packages/nestjs/tsconfig*.json, packages/nestjs/eslint.config.js, packages/nestjs/vitest.config.ts, packages/nestjs/prettier.config.js, packages/nestjs/.gitignore, packages/nestjs/.prettierignore, packages/nestjs/.editorconfig
Defines package metadata, ESM/CJS builds, declaration output, compiler settings, linting, formatting, testing, and generated-file exclusions.
NestJS module contracts and registration
packages/nestjs/src/models/config.ts, packages/nestjs/src/constants/InjectionTokens.ts, packages/nestjs/src/ThunderIDModule.ts, packages/nestjs/src/index.ts
Adds configuration and request types, the THUNDERID_CONFIG token, global ThunderIDModule.forRoot, and public package exports.
Authentication service flow
packages/nestjs/src/ThunderIDService.ts
Wraps the Express SDK with lazy initialization and request-based sign-in, sign-out, session checks, and user retrieval.
Route protection and documentation
packages/nestjs/src/guards/ThunderIDGuard.ts, packages/nestjs/src/decorators/CurrentUser.ts, packages/nestjs/src/__tests__/ThunderIDGuard.test.ts, packages/nestjs/README.md, README.md
Adds route authentication and current-user resolution, tests guard/module behavior, and documents the new SDK and package listing.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant NestController
  participant ThunderIDGuard
  participant ThunderIDService
  participant ThunderIDExpressClient
  NestController->>ThunderIDGuard: canActivate(context)
  ThunderIDGuard->>ThunderIDService: isSignedIn(req)
  ThunderIDService->>ThunderIDExpressClient: initialize and check session
  ThunderIDExpressClient-->>ThunderIDService: signed-in status
  ThunderIDGuard->>ThunderIDService: getUser(req)
  ThunderIDService->>ThunderIDExpressClient: retrieve authenticated user
  ThunderIDExpressClient-->>ThunderIDGuard: User
  ThunderIDGuard-->>NestController: allow request with req.thunderIDUser
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately names the new NestJS SDK package.
Description check ✅ Passed The description covers Purpose, Approach, and Testing well, though the template’s checklist and security sections are omitted.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (1)
packages/nestjs/src/__tests__/ThunderIDGuard.test.ts (1)

56-64: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the shared THUNDERID_CONFIG constant here. Replace the raw 'THUNDERID_CONFIG' literal in the assertion so the test stays aligned with the exported token.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nestjs/src/__tests__/ThunderIDGuard.test.ts` around lines 56 - 64,
Replace the raw 'THUNDERID_CONFIG' token in the forRoot registration test with
the shared exported THUNDERID_CONFIG constant, importing it if necessary, so the
assertion remains aligned with the module’s provider token.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/nestjs/README.md`:
- Around line 51-57: Clarify the no-token path in the login example’s `login`
method: either add an `else` response handling branch for when `signIn` returns
without tokens, or document that `this.thunderID.signIn` completes the OIDC
redirect internally in that case.

In `@packages/nestjs/src/index.ts`:
- Line 38: Make the `@thunderid/express` re-export in packages/nestjs/src/index.ts
resolvable during lint by configuring ESLint’s import resolver to include
workspace source paths or ensuring the workspace dependency is built/available
before pnpm lint; verify the NestJS lint step passes.

In `@packages/nestjs/src/ThunderIDService.ts`:
- Around line 125-127: Update ThunderIDService.isSignOutSuccess to safely handle
Express 5 query values by returning true only when req.query['state'] is a
string equal to 'sign_out_success'; explicitly guard against arrays, ParsedQs
values, and undefined before comparing.
- Around line 69-79: Update ensureInitialized to clear the cached initPromise
when client.initialize rejects, while preserving the rejection for the current
caller. Add a catch handler around the initialization promise that resets
this.initPromise to undefined before rethrowing the original error, allowing
subsequent requests to retry initialization.

In `@packages/nestjs/tsconfig.spec.json`:
- Around line 3-7: Update packages/nestjs/tsconfig.spec.json to replace "jest"
with the Vitest type definitions in compilerOptions.types, and remove the
obsolete test-configs and jest.config.js entries from the include configuration.

---

Nitpick comments:
In `@packages/nestjs/src/__tests__/ThunderIDGuard.test.ts`:
- Around line 56-64: Replace the raw 'THUNDERID_CONFIG' token in the forRoot
registration test with the shared exported THUNDERID_CONFIG constant, importing
it if necessary, so the assertion remains aligned with the module’s provider
token.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: dc97789a-eeaa-42c3-9bc8-65ddbdeb98a3

📥 Commits

Reviewing files that changed from the base of the PR and between a4866f0 and 8f236e8.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (22)
  • README.md
  • packages/nestjs/.editorconfig
  • packages/nestjs/.gitignore
  • packages/nestjs/.prettierignore
  • packages/nestjs/README.md
  • packages/nestjs/eslint.config.js
  • packages/nestjs/package.json
  • packages/nestjs/prettier.config.js
  • packages/nestjs/rolldown.config.js
  • packages/nestjs/src/ThunderIDModule.ts
  • packages/nestjs/src/ThunderIDService.ts
  • packages/nestjs/src/__tests__/ThunderIDGuard.test.ts
  • packages/nestjs/src/constants/InjectionTokens.ts
  • packages/nestjs/src/decorators/CurrentUser.ts
  • packages/nestjs/src/guards/ThunderIDGuard.ts
  • packages/nestjs/src/index.ts
  • packages/nestjs/src/models/config.ts
  • packages/nestjs/tsconfig.eslint.json
  • packages/nestjs/tsconfig.json
  • packages/nestjs/tsconfig.lib.json
  • packages/nestjs/tsconfig.spec.json
  • packages/nestjs/vitest.config.ts

Comment thread packages/nestjs/README.md
export {THUNDERID_CONFIG} from './constants/InjectionTokens';

// Re-export everything from the Express SDK (includes the Node and JavaScript SDK re-exports)
export * from '@thunderid/express';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
pnpm --filter `@thunderid/nestjs` lint
pnpm --filter `@thunderid/express` build
pnpm --filter `@thunderid/nestjs` lint

Repository: thunder-id/javascript-sdks

Length of output: 11447


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== workspace files ==\n'
git ls-files 'pnpm-workspace.yaml' 'package.json' '.eslintrc*' 'eslint.config.*' 'packages/nestjs/package.json' 'packages/express/package.json' 'packages/node/package.json' 'packages/*/package.json' | sed 's#^`#-` #'

printf '\n== workspace root package.json ==\n'
cat -n package.json | sed -n '1,220p'

printf '\n== pnpm-workspace.yaml ==\n'
cat -n pnpm-workspace.yaml | sed -n '1,120p'

printf '\n== eslint config files ==\n'
for f in .eslintrc .eslintrc.json .eslintrc.js .eslintrc.cjs .eslintrc.mjs eslint.config.js eslint.config.mjs eslint.config.cjs; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    cat -n "$f" | sed -n '1,260p'
  fi
done

printf '\n== package manifests ==\n'
for f in packages/nestjs/package.json packages/express/package.json packages/node/package.json; do
  echo "--- $f ---"
  cat -n "$f" | sed -n '1,220p'
done

Repository: thunder-id/javascript-sdks

Length of output: 12884


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== express package files ==\n'
git ls-files 'packages/express/*' | sed 's#^`#-` #'

printf '\n== express tsconfig files ==\n'
for f in packages/express/tsconfig*.json; do
  echo "--- $f ---"
  cat -n "$f" | sed -n '1,260p'
done

printf '\n== express source entrypoints ==\n'
for f in packages/express/src/index.ts packages/express/src/index.js packages/express/src/index.mts packages/express/src/index.cts; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    cat -n "$f" | sed -n '1,220p'
  fi
done

printf '\n== any workspace source exports or path aliases referencing `@thunderid/express` ==\n'
rg -n --hidden --glob '!**/dist/**' --glob '!**/node_modules/**' '`@thunderid/express`|paths|exports' packages/express packages/nestjs package.json pnpm-workspace.yaml eslint.config.js

Repository: thunder-id/javascript-sdks

Length of output: 6599


Make the workspace re-export lint-resolvable. packages/nestjs/src/index.ts:38 re-exports @thunderid/express, but ESLint can’t resolve that workspace package in the current setup. Point the resolver at workspace source or make the dependency chain available before pnpm lint; otherwise the NestJS lint step stays red.

🧰 Tools
🪛 ESLint

[error] 38-38: Unable to resolve path to module '@thunderid/express'.

(import-x/no-unresolved)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nestjs/src/index.ts` at line 38, Make the `@thunderid/express`
re-export in packages/nestjs/src/index.ts resolvable during lint by configuring
ESLint’s import resolver to include workspace source paths or ensuring the
workspace dependency is built/available before pnpm lint; verify the NestJS lint
step passes.

Source: Linters/SAST tools

Comment thread packages/nestjs/src/ThunderIDService.ts
Comment thread packages/nestjs/src/ThunderIDService.ts
Comment thread packages/nestjs/tsconfig.spec.json
- Reset cached init promise on failure so transient startup errors recover
- Handle array/missing state query values in isSignOutSuccess (Express 5)
- Replace Jest types and drop dead include entries in tsconfig.spec.json
- Clarify sign-in redirect behavior in README and service docs
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.

1 participant