npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@flusys/nestjs-auth

v5.1.1

Published

Authentication and authorization infrastructure for NestJS applications

Readme

@flusys/nestjs-auth

Drop-in authentication for NestJS — JWT access/refresh tokens, bcrypt passwords, multi-company hierarchy, email verification, and pluggable email + user enrichment.

npm version License: MIT


Installation

npm install @flusys/nestjs-auth @flusys/nestjs-shared @flusys/nestjs-core
npm install @nestjs/jwt @nestjs/passport passport-jwt bcrypt cookie-parser

1. Module Registration

Sync (forRoot)

Mode 1: Single Database

import { AuthModule } from '@flusys/nestjs-auth';

AuthModule.forRoot({
  global: true,
  includeController: true,
  bootstrapAppConfig: {
    databaseMode: 'single',
    enableCompanyFeature: false,
    enableEmailVerification: true,
  },
  config: {
    defaultDatabaseConfig: {
      type: 'mysql',
      host: process.env.DB_HOST,
      port: Number(process.env.DB_PORT ?? 3306),
      username: process.env.DB_USER,
      password: process.env.DB_PASSWORD,
      database: process.env.DB_NAME,
    },
    jwtSecret: process.env.JWT_SECRET,
    jwtExpiration: '15m',
    refreshTokenSecret: process.env.REFRESH_TOKEN_SECRET,
    refreshTokenExpiration: '7d',
    // refreshTokenCookieName: 'fsn_refresh_token', // optional, this is the default
  },
});

Mode 2: Multi-Tenant

In multi-tenant mode you provide:

  • tenantDefaultDatabaseConfig — connection template applied to all tenants; individual tenants override only the fields that differ
  • tenants — per-tenant database config (ITenantDatabaseConfig[]); tenant resolved per request via x-tenant-id header

defaultDatabaseConfig is not needed — tenantDefaultDatabaseConfig serves as the fallback for both template building and single-datasource resolution.

AuthModule.forRoot({
  global: true,
  includeController: true,
  bootstrapAppConfig: {
    databaseMode: 'multi-tenant',
    enableCompanyFeature: true,
    enableEmailVerification: true,
  },
  config: {
    // Default template applied to every tenant unless overridden
    tenantDefaultDatabaseConfig: {
      type: 'mysql',
      host: process.env.TENANT_DB_HOST,
      port: Number(process.env.TENANT_DB_PORT ?? 3306),
      username: process.env.TENANT_DB_USER,
      password: process.env.TENANT_DB_PASSWORD,
      database: process.env.TENANT_DB_NAME,
    },
    // Per-tenant overrides — only fields that differ from tenantDefaultDatabaseConfig
    tenants: [
      {
        id: 'tenant-a',
        name: 'Tenant A',
        database: 'tenant_a_db',
        enableCompanyFeature: true,
        permissionMode: 'FULL',
      },
      {
        id: 'tenant-b',
        name: 'Tenant B',
        host: 'tenant-b.db.example.com',
        database: 'tenant_b_db',
        enableCompanyFeature: false,
        permissionMode: 'RBAC',
      },
    ],
    jwtSecret: process.env.JWT_SECRET,
    jwtExpiration: '15m',
    refreshTokenSecret: process.env.REFRESH_TOKEN_SECRET,
    refreshTokenExpiration: '7d',
  },
});

Async (forRootAsync)

Use when config comes from ConfigService or another async source:

import { ConfigModule, ConfigService } from '@nestjs/config';
import { AuthModule, ITenantDatabaseConfig } from '@flusys/nestjs-auth';

// Single database
AuthModule.forRootAsync({
  global: true,
  includeController: true,
  imports: [ConfigModule],
  bootstrapAppConfig: {
    databaseMode: 'single',
    enableCompanyFeature: true,
    enableEmailVerification: true,
  },why you cannot fix it,, need to need gap bellow LAB REPORT text
  useFactory: (cfg: ConfigService) => ({
    defaultDatabaseConfig: {
      type: 'mysql',
      host: cfg.get('DB_HOST'),
      port: cfg.get<number>('DB_PORT'),
      username: cfg.get('DB_USER'),
      password: cfg.get('DB_PASSWORD'),
      database: cfg.get('DB_NAME'),
    },
    jwtSecret: cfg.get('JWT_SECRET'),
    jwtExpiration: cfg.get('JWT_EXPIRATION', '15m'),
    refreshTokenSecret: cfg.get('REFRESH_TOKEN_SECRET'),
    refreshTokenExpiration: cfg.get('REFRESH_TOKEN_EXPIRATION', '7d'),
  }),
  inject: [ConfigService],
  providers: [authEmailProvider, userEnricherProvider],
});

// Multi-tenant
AuthModule.forRootAsync({
  global: true,
  includeController: true,
  imports: [ConfigModule],
  bootstrapAppConfig: {
    databaseMode: 'multi-tenant',
    enableCompanyFeature: true,
    enableEmailVerification: true,
  },
  useFactory: (cfg: ConfigService) => ({
    tenantDefaultDatabaseConfig: {
      type: 'mysql',
      host: cfg.get('TENANT_DB_HOST'),
      port: cfg.get<number>('TENANT_DB_PORT'),
      username: cfg.get('TENANT_DB_USER'),
      password: cfg.get('TENANT_DB_PASSWORD'),
      database: cfg.get('TENANT_DB_NAME'),
    },
    tenants: cfg.get<ITenantDatabaseConfig[]>('TENANTS'),
    jwtSecret: cfg.get('JWT_SECRET'),
    jwtExpiration: cfg.get('JWT_EXPIRATION', '15m'),
    refreshTokenSecret: cfg.get('REFRESH_TOKEN_SECRET'),
    refreshTokenExpiration: cfg.get('REFRESH_TOKEN_EXPIRATION', '7d'),
  }),
  inject: [ConfigService],
  providers: [authEmailProvider, userEnricherProvider],
});

2. Entity Registration

Pass auth entities to your TypeORM setup using the static helper:

import { getEntitiesByConfig } from '@flusys/nestjs-auth/entities';

TypeOrmModule.forRoot({
  entities: [
    ...getEntitiesByConfig({
      enableCompanyFeature: true,
      enableEmailVerification: false,
    }),
  ],
});

Keep the flags here in sync with those passed to forRoot/forRootAsync.

3. Pluggable Email — AUTH_EMAIL_PROVIDER

Auth never imports nestjs-email. Connect them via a factory provider:

import { AUTH_EMAIL_PROVIDER, IAuthEmailProvider } from '@flusys/nestjs-auth';
import { EmailSendService } from '@flusys/nestjs-email';

export const authEmailProvider = {
  provide: AUTH_EMAIL_PROVIDER,
  useFactory: (emailSendService: EmailSendService): IAuthEmailProvider => ({
    sendPasswordResetEmail: async (email, token, resetUrl) => {
      await emailSendService.sendTemplateEmail({
        templateSlug: 'password-reset',
        to: email,
        variables: { resetUrl, token },
      });
    },
    sendVerificationEmail: async (email, token, verifyUrl) => {
      await emailSendService.sendTemplateEmail({
        templateSlug: 'email-verification',
        to: email,
        variables: { verifyUrl, token },
      });
    },
    // sendWelcomeEmail is optional
  }),
  inject: [EmailSendService],
};

// Register:
AuthModule.forRootAsync({ ..., providers: [authEmailProvider] });

When AUTH_EMAIL_PROVIDER is not provided, registration still works but emails are silently skipped.

4. User Enrichment — USER_ENRICHER

Extend user list and profile responses without creating circular imports. All methods are optional — implement only what you need.

| Method | When called | Purpose | | ---------------------------- | ---------------------- | ---------------------------------------------- | | enrichListItems | After user list fetch | Attach computed data to list items | | getProfileExtras | POST /users/get/:id | Add roles, actions, sections to profile | | updateProfileExtras | Profile update (in tx) | Persist extra profile fields | | validateProfileExtras | Before profile update | Validate extra fields | | getProfileSections | Profile form init | Return multi-step section definitions | | getProfileSectionData | Section fetch | Return section-specific data | | updateProfileSection | Section save (in tx) | Persist section data | | handleSectionFileUpload | File upload (in tx) | Handle file attach to section | | handleSectionFileDelete | File delete (in tx) | Handle file removal from section | | calculateProfileCompletion | Profile fetch | Return 0–100 completion score | | onUserCreated | Registration (in tx) | Hook after user row created; throw to rollback |

import { USER_ENRICHER, IUserEnricher, IProfileExtras } from '@flusys/nestjs-auth';
import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
import { Injectable, Inject } from '@nestjs/common';

@Injectable()
export class IamUserEnricher implements IUserEnricher {
  constructor(@Inject(PermissionService) private readonly permissionService: PermissionService) {}

  async getProfileExtras(userId: string, user: ILoggedUserInfo): Promise<IProfileExtras> {
    const roles = await this.permissionService.getRolesForUser(userId);
    return { roles };
  }
}

export const userEnricherProvider = {
  provide: USER_ENRICHER,
  useClass: IamUserEnricher,
};

// Register:
AuthModule.forRootAsync({ ..., providers: [userEnricherProvider] });

License

MIT © FLUSYS