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

@arxjs/nestjs

v0.0.1

Published

NestJS module for @arxjs/core — guards, decorators and injectable service

Readme

@arxjs/nestjs

NestJS module for @arxjs/core. Provides an injectable ArxService, a route guard, and declarative decorators for permission and role checks.

Installation

pnpm add @arxjs/nestjs @arxjs/core
# npm install @arxjs/nestjs @arxjs/core

Install a storage adapter:

pnpm add @arxjs/prisma    # Prisma
pnpm add @arxjs/drizzle   # Drizzle ORM
pnpm add @arxjs/typeorm   # TypeORM (also requires: typeorm reflect-metadata)

Setup

Register ArxModule once in your root AppModule. It is global by default, so you only need to import it once.

// app.module.ts
import { Module } from '@nestjs/common'
import { ArxModule } from '@arxjs/nestjs'
import { PrismaAdapter } from '@arxjs/prisma'
import { PrismaService } from './prisma.service'

@Module({
  imports: [
    ArxModule.forRoot({
      adapter: new PrismaAdapter(prisma),
      getUserId: (req) => req.user?.id,
    }),
  ],
})
export class AppModule {}

Async configuration

Use forRootAsync when the adapter depends on other services (e.g. PrismaService, DataSource, ConfigService):

ArxModule.forRootAsync({
  inject: [PrismaService],
  useFactory: (prisma: PrismaService) => ({
    adapter: new PrismaAdapter(prisma),
    getUserId: (req) => req.user?.id,
  }),
})

Setup with TypeORM

When using @arxjs/typeorm, the DataSource is managed by @nestjs/typeorm — inject it via forRootAsync:

pnpm add @arxjs/typeorm @nestjs/typeorm typeorm reflect-metadata
// app.module.ts
import 'reflect-metadata'
import { Module } from '@nestjs/common'
import { TypeOrmModule } from '@nestjs/typeorm'
import { APP_GUARD } from '@nestjs/core'
import { ArxModule, ArxGuard } from '@arxjs/nestjs'
import { TypeOrmAdapter, ARX_TYPEORM_ENTITIES } from '@arxjs/typeorm'
import { DataSource } from 'typeorm'

@Module({
  imports: [
    // 1. Set up TypeORM with the arx entities
    TypeOrmModule.forRoot({
      type: 'postgres',
      url: process.env.DATABASE_URL,
      entities: [...ARX_TYPEORM_ENTITIES],
      migrations: ['dist/migrations/*.js'],
      migrationsRun: true, // run pending migrations automatically on startup
    }),

    // 2. Register ArxModule — inject DataSource managed by @nestjs/typeorm
    ArxModule.forRootAsync({
      inject: [DataSource],
      useFactory: (dataSource: DataSource) => ({
        adapter: new TypeOrmAdapter(dataSource),
        getUserId: (req) => (req as { user?: { id?: string } }).user?.id,
      }),
    }),
  ],
  providers: [
    // 3. (Optional) protect every route globally
    { provide: APP_GUARD, useClass: ArxGuard },
  ],
})
export class AppModule {}

From here, everything works the same as with any other adapter — use @RequirePermissions, @RequireRole, and ArxService as shown below.

getUserId

The getUserId function receives the raw HTTP request object and must return the current user's ID as a string, or undefined if the user is not authenticated.

// Passport / JWT (request.user populated by a JwtAuthGuard)
getUserId: (req) => req.user?.id

// Custom header
getUserId: (req) => req.headers['x-user-id'] as string | undefined

When getUserId returns undefined on a route protected by @RequirePermissions or @RequireRole, the guard throws UnauthorizedException (HTTP 401).

Protecting routes

Apply @RequirePermissions() or @RequireRole() to your controllers or handlers, then add ArxGuard to enforce them.

// posts.controller.ts
import { Controller, Delete, Get, Post, UseGuards } from '@nestjs/common'
import { ArxGuard, RequirePermissions, RequireRole } from '@arxjs/nestjs'

@Controller('posts')
@UseGuards(ArxGuard)
export class PostsController {

  @Get()
  @RequirePermissions('post:view')
  findAll() { ... }

  @Post()
  @RequirePermissions('post:create')
  create() { ... }

  @Delete(':id')
  @RequirePermissions('post:delete')
  remove() { ... }

  @Post('bulk-delete')
  @RequireRole('admin', 'moderator')   // any one of these roles is sufficient
  bulkDelete() { ... }
}

Decorator semantics

| Decorator | Logic | |---|---| | @RequirePermissions('a', 'b') | User must hold all listed permissions (AND) | | @RequireRole('admin', 'mod') | User must hold at least one listed role (OR) |

Handler-level decorators take precedence over controller-level ones when both are present.

Global guard

To protect every route in the application without adding @UseGuards(ArxGuard) to every controller:

// app.module.ts
import { APP_GUARD } from '@nestjs/core'
import { ArxGuard } from '@arxjs/nestjs'

@Module({
  providers: [
    { provide: APP_GUARD, useClass: ArxGuard },
  ],
})
export class AppModule {}

Important: routes without @RequirePermissions or @RequireRole are allowed through even with the global guard active. This means your public routes (e.g. login, health check) require no extra work — the guard only enforces routes that have one of the decorators. If you want a route to be explicitly public and self-documenting, you can omit the decorators — it will pass through automatically.

Programmatic checks

Inject ArxService for imperative permission checks inside services, guards, or resolvers:

// posts.service.ts
import { Injectable, ForbiddenException } from '@nestjs/common'
import { ArxService } from '@arxjs/nestjs'

@Injectable()
export class PostsService {
  constructor(private readonly arx: ArxService) {}

  async publish(userId: string, postId: string) {
    const canPublish = await this.arx.can(userId, 'post:publish')
    if (!canPublish) throw new ForbiddenException()
    // ...
  }
}

ArxService exposes the full @arxjs/core API — see @arxjs/core docs for the complete reference.

Peer dependencies

| Package | Version | |---|---| | @arxjs/core | * | | @nestjs/common | >=10.0.0 | | @nestjs/core | >=10.0.0 | | reflect-metadata | >=0.1.12 |

License

MIT