Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ JavaScript SDKs for ThunderID. Provides authentication and user management for b
| [`@thunderid/vue`](packages/vue) | ![npm](https://img.shields.io/npm/v/@thunderid/vue) | Vue SDK |
| [`@thunderid/nuxt`](packages/nuxt) | ![npm](https://img.shields.io/npm/v/@thunderid/nuxt) | Nuxt SDK |
| [`@thunderid/express`](packages/express) | ![npm](https://img.shields.io/npm/v/@thunderid/express) | Express.js SDK |
| [`@thunderid/nestjs`](packages/nestjs) | ![npm](https://img.shields.io/npm/v/@thunderid/nestjs) | NestJS SDK |
| [`@thunderid/tanstack-router`](packages/tanstack-router) | ![npm](https://img.shields.io/npm/v/@thunderid/tanstack-router) | TanStack Router integration |

## License
Expand Down
1 change: 1 addition & 0 deletions packages/nestjs/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
../../.editorconfig
141 changes: 141 additions & 0 deletions packages/nestjs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.*
!.env.example

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist
.output

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp
.cache

# Sveltekit cache directory
.svelte-kit/

# vitepress build output
**/.vitepress/dist

# vitepress cache directory
**/.vitepress/cache

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# Firebase cache directory
.firebase/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v3
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions

# Vite files
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
.vite/
4 changes: 4 additions & 0 deletions packages/nestjs/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/dist
/build
/node_modules
/coverage
101 changes: 101 additions & 0 deletions packages/nestjs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# @thunderid/nestjs

NestJS SDK for [ThunderID](https://github.com/thunder-id/thunderid). Built on top of [`@thunderid/express`](../express)
— works with NestJS applications running on the default Express platform.

## Installation

```bash
npm install @thunderid/nestjs cookie-parser
```

## Setup

Register `cookie-parser` and the ThunderID module:

```ts
// main.ts
import cookieParser from 'cookie-parser';

const app = await NestFactory.create(AppModule);
app.use(cookieParser());
```

```ts
// app.module.ts
import {ThunderIDModule} from '@thunderid/nestjs';

@Module({
imports: [
ThunderIDModule.forRoot({
clientId: process.env.THUNDERID_CLIENT_ID,
baseUrl: process.env.THUNDERID_BASE_URL,
}),
],
})
export class AppModule {}
```

The module is global — `ThunderIDService` and `ThunderIDGuard` are injectable everywhere.

## Sign-in / sign-out routes

```ts
import {Request, Response} from 'express';
import {ThunderIDService} from '@thunderid/nestjs';

@Controller()
export class AuthController {
constructor(private readonly thunderID: ThunderIDService) {}

@Get('login')
async login(@Req() req: Request, @Res() res: Response) {
const tokens = await this.thunderID.signIn(req, res);
if (tokens.accessToken || tokens.idToken) {
res.redirect('/');
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

@Get('logout')
async logout(@Req() req: Request, @Res() res: Response) {
if (this.thunderID.isSignOutSuccess(req)) {
res.redirect('/');
return;
}
await this.thunderID.signOut(req, res);
}
}
```

## Protecting routes

```ts
import {CurrentUser, ThunderIDGuard, User} from '@thunderid/nestjs';

@Controller()
export class ProfileController {
@UseGuards(ThunderIDGuard)
@Get('profile')
profile(@CurrentUser() user: User) {
return user;
}
}
```

`ThunderIDGuard` returns `401 Unauthorized` for requests without a valid session. `@CurrentUser()` resolves the
authenticated user attached by the guard.

## API

| Export | Description |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `ThunderIDModule.forRoot(config)` | Global module; accepts `ThunderIDNestConfig` (same shape as the Node SDK config) |
| `ThunderIDService` | `signIn(req, res)`, `signOut(req, res)`, `isSignOutSuccess(req)`, `isSignedIn(req)`, `getUser(req)`, `getClient()` |
| `ThunderIDGuard` | Route guard that blocks unauthenticated requests |
| `@CurrentUser()` | Param decorator resolving the authenticated `User` (requires `ThunderIDGuard`) |

Everything from `@thunderid/express` (and transitively `@thunderid/node` / `@thunderid/javascript`) is re-exported.

## License

Apache-2.0
27 changes: 27 additions & 0 deletions packages/nestjs/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import thunderIdPlugin from '@thunderid/eslint-plugin';

export default [
{
ignores: ['dist/**', 'build/**', 'node_modules/**', 'coverage/**'],
},
...thunderIdPlugin.configs.typescript,
...thunderIdPlugin.configs.vitest,
];
75 changes: 75 additions & 0 deletions packages/nestjs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
"name": "@thunderid/nestjs",
"version": "0.1.0",
"description": "NestJS SDK for ThunderID",
"keywords": [
"thunderid",
"nestjs",
"server"
],
"homepage": "https://github.com/thunder-id/javascript-sdks/tree/main/packages/nestjs#readme",
"bugs": {
"url": "https://github.com/thunder-id/thunderid/issues"
},
"author": "WSO2",
"license": "Apache-2.0",
"type": "module",
"main": "dist/index.js",
"module": "dist/index.js",
"commonjs": "dist/cjs/index.cjs",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/cjs/index.cjs"
}
},
"files": [
"dist",
"README.md",
"LICENSE"
],
"types": "dist/index.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/thunder-id/javascript-sdks",
"directory": "packages/nestjs"
},
"scripts": {
"build": "pnpm clean:dist && rolldown -c rolldown.config.js && tsc -p tsconfig.lib.json --emitDeclarationOnly --outDir dist",
"clean": "pnpm clean:node_modules && pnpm clean:dist",
"clean:dist": "rimraf dist",
"clean:node_modules": "rimraf node_modules",
"format:check": "prettier --check --cache .",
"format:fix": "prettier --write --cache .",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx,.cjs,.mjs",
"lint:fix": "eslint . --fix --ext .js,.jsx,.ts,.tsx,.cjs,.mjs",
"test": "vitest run --passWithNoTests",
"typecheck": "tsc -p tsconfig.lib.json"
},
"devDependencies": {
"@nestjs/common": "^11.0.0",
"@thunderid/eslint-plugin": "catalog:",
"@thunderid/prettier-config": "catalog:",
"@types/cookie-parser": "^1.4.8",
"@types/express": "^5.0.6",
"@types/node": "22.15.3",
"eslint": "catalog:",
"prettier": "catalog:",
"reflect-metadata": "^0.2.2",
"rimraf": "catalog:",
"rolldown": "catalog:",
"rxjs": "^7.8.1",
"typescript": "catalog:",
"vitest": "catalog:"
},
"dependencies": {
"@thunderid/express": "workspace:^"
},
"peerDependencies": {
"@nestjs/common": ">=10.0.0"
},
"publishConfig": {
"access": "public"
}
}
21 changes: 21 additions & 0 deletions packages/nestjs/prettier.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import config from '@thunderid/prettier-config';

export default config;
Loading