Skip to content

End-to-end, copy-pasteable examples for the Bridge NestJS plugin. Every snippet compiles against the current API. For conceptual depth, follow the links to the topic guides.


import { Module } from '@nestjs/common';
import { BridgeModule } from '@nebulr-group/bridge-nestjs';
@Module({
imports: [
BridgeModule.forRoot({
appId: process.env.BRIDGE_APP_ID!,
guard: {
global: true,
defaultAccess: 'protected',
rules: [
{ path: '/health', privilege: 'ANONYMOUS' },
{ path: '/webhooks/*', privilege: 'ANONYMOUS' },
{ path: '/account/users', privilege: 'USER_READ' },
{ path: '/reports/*', privilege: 'TENANT_READ', plans: ['pro', 'enterprise'] },
],
},
}),
],
})
export class AppModule {}

Async variant (reading config from @nestjs/config):

BridgeModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
appId: config.get('BRIDGE_APP_ID'),
debug: config.get('BRIDGE_DEBUG') === 'true',
}),
});
import { Controller, Get, UseGuards } from '@nestjs/common';
import {
BridgeAuthGuard,
CurrentUser,
CurrentTenant,
BridgeUser,
BridgeTenant,
} from '@nebulr-group/bridge-nestjs';
@Controller('me')
@UseGuards(BridgeAuthGuard)
export class MeController {
@Get()
whoAmI(@CurrentUser() user: BridgeUser, @CurrentTenant() tenant: BridgeTenant) {
return {
userId: user.id,
email: user.email,
role: user.role,
privileges: user.privileges, // ['AUTHENTICATED', 'USER_READ', ...]
tenantId: tenant.id,
tenantName: tenant.name,
};
}
}
import { Controller, Get, UseGuards } from '@nestjs/common';
import { BridgeAuthGuard, RequireRole } from '@nebulr-group/bridge-nestjs';
@Controller('admin')
@UseGuards(BridgeAuthGuard)
@RequireRole('ADMIN') // applies to the whole controller
export class AdminController {
@Get('settings')
@RequireRole('OWNER') // tighter requirement for this route
getSettings() { ... }
}

4. API tokens, privileges, and @AcceptAuth

Section titled “4. API tokens, privileges, and @AcceptAuth”
import { Controller, Get, UseGuards } from '@nestjs/common';
import { BridgeAuthGuard, RequirePrivilege, AcceptAuth } from '@nebulr-group/bridge-nestjs';
// Machine-to-machine endpoint: only an API token (x-api-key) is accepted.
@Controller('integrations/users')
@AcceptAuth('api_token')
@UseGuards(BridgeAuthGuard)
export class IntegrationUsersController {
@Get()
@RequirePrivilege('USER_READ') // enforced for API tokens; user JWTs bypass @RequirePrivilege
list() { ... }
}
import { Controller, Get } from '@nestjs/common';
import { Public } from '@nebulr-group/bridge-nestjs';
@Controller('health')
export class HealthController {
@Get()
@Public()
check() {
return { status: 'ok' };
}
}
import { Controller, Get, UseGuards } from '@nestjs/common';
import { BridgeFlagGuard, RequireFlag, Flag } from '@nebulr-group/bridge-nestjs/flags';
@Controller('beta')
@UseGuards(BridgeFlagGuard)
export class BetaController {
@Get('feature-x')
@RequireFlag('feature_x') // 403 when the flag is off
getFeatureX() { ... }
@Get('home')
home(@Flag({ key: 'show_new_home', defaultValue: false }) showNew: boolean) {
// NOTE: @Flag takes ONE object argument { key, defaultValue } — not positional args.
return showNew ? this.newHome() : this.oldHome();
}
}

On-demand — @RequireFeatureFlag + FeatureFlagService

Section titled “On-demand — @RequireFeatureFlag + FeatureFlagService”
import { Controller, Get, Injectable } from '@nestjs/common';
import { RequireFeatureFlag, FeatureFlagService } from '@nebulr-group/bridge-nestjs';
@Controller('premium')
export class PremiumController {
@Get()
@RequireFeatureFlag({ all: ['premium-tier', 'active-subscription'] })
getPremium() { ... }
}
@Injectable()
export class ReportsService {
constructor(private readonly featureFlags: FeatureFlagService) {}
async generate(accessToken: string) {
return (await this.featureFlags.isEnabled('pdf-export', accessToken))
? this.generatePdf()
: this.generateBasic();
}
}

7. Tenant data — subscription & entitlement gating

Section titled “7. Tenant data — subscription & entitlement gating”
import { Controller, Get, Headers, ForbiddenException } from '@nestjs/common';
import { BridgeService } from '@nebulr-group/bridge-nestjs';
@Controller('reports')
export class ReportsController {
constructor(private readonly bridge: BridgeService) {}
@Get('export')
async export(@Headers('authorization') auth: string) {
const tenant = this.bridge.fromJwt(auth.replace(/^Bearer\s+/i, ''));
if (!(await tenant.entitlements.can('pdf-export'))) {
throw new ForbiddenException('Your plan does not include PDF export');
}
const sub = await tenant.subscription; // { plan: { slug, name }, status, endsAt?, gateEngaged? }
return this.buildExport(sub.plan.slug);
}
}

See Tenant Data — BridgeService for the full reference.

import { Controller, Get, Req } from '@nestjs/common';
import { BridgeHttpService } from '@nebulr-group/bridge-nestjs';
import { Request } from 'express';
@Controller('items')
export class ItemsController {
constructor(private readonly http: BridgeHttpService) {}
@Get('from-service-b')
async getFromServiceB(@Req() req: Request) {
// Forwards the verified user token so service-b authenticates the same user.
return this.http.get('http://service-b/items', req.bridgeAccessToken);
}
}
import { Controller, Post, Body } from '@nestjs/common';
import { Public } from '@nebulr-group/bridge-nestjs';
@Controller('webhooks')
export class WebhooksController {
@Post('bridge')
@Public() // webhooks carry no user JWT
async handle(@Body() event: { type: string; tenantId: string }) {
// Resolve tenant from the event payload, then act on it.
return { received: true };
}
}