nestjs-configuard
v1.0.0
Published
NestJS integration for configuard — DB-backed, typed, ABAC-filtered runtime configuration with live reload and TTL auto-refresh.
Maintainers
Readme
nestjs-configuard
🔆 ESM-only. Requires Node ≥ 20 and NestJS 10 / 11.
NestJS integration for configuard — wires a DB-backed, typed, ABAC-filtered runtime configuration object into Nest's DI, with live reload and optional TTL auto-refresh.
Where @nestjs/config handles .env (secrets, bootstrap), configuard handles
the long, ever-growing list of non-secret, admin-editable runtime tunables
stored as flat rows in a config table. This package makes consuming and
refreshing those values idiomatic in NestJS.
Install
npm install nestjs-configuard configuard@nestjs/common, @nestjs/core, reflect-metadata, and configuard are peer
dependencies.
Register the module
Static rows — forRoot
import { Module } from '@nestjs/common';
import { ConfiguardModule, AccessorType } from 'nestjs-configuard';
import { rows } from './config.rows';
@Module({
imports: [
ConfiguardModule.forRoot({
rows,
accessor: { accessor: AccessorType.SYSTEM },
}),
],
})
export class AppModule {}A row mirrors a config table record (see
configuard for the full schema). The
enums and types are re-exported here, so a single import suffices:
// config.rows.ts
import { AccessorType, ListType, ValueType, type IConfigItem } from 'nestjs-configuard';
export const rows: IConfigItem[] = [
{
accessor: AccessorType.SYSTEM,
key: 'device.port',
type: ValueType.INTEGER,
listType: ListType.NONE,
value: '8080',
editable: true,
requiresReboot: true,
encrypt: false
}
];DB-driven rows — forRootAsync
The factory can inject anything (e.g. a Prisma service) and load rows from a
config table. Add refreshIntervalMs to reload them in the background.
import { Module } from '@nestjs/common';
import { ConfiguardModule, AccessorType } from 'nestjs-configuard';
import { PrismaModule, PrismaService } from './prisma';
@Module({
imports: [
ConfiguardModule.forRootAsync({
imports: [PrismaModule],
inject: [PrismaService],
useFactory: async (prisma: PrismaService) => prisma.config.findMany(),
accessor: { accessor: AccessorType.SYSTEM },
refreshIntervalMs: 60_000, // background reload; omit to disable
// refreshEnabled: false, // break-glass: disable the timer entirely
}),
],
})
export class AppModule {}The factory may return a flat IConfigItem[], an object
{ rows, accessor?, options? }, or an already-built Configuard.
Consume
ConfiguardService (recommended — always current)
Reads through the service, so values stay fresh across a reload:
import { Injectable } from '@nestjs/common';
import { ConfiguardService } from 'nestjs-configuard';
@Injectable()
export class PortService {
constructor(private readonly cfg: ConfiguardService) {}
get port(): number {
return this.cfg.get<number>('device.port', 8080)!;
}
// Re-run the factory after an admin saves new values:
async refresh() {
await this.cfg.reload();
}
}ConfiguardService delegates the full read API — get, has, data,
getMeta, isEncrypted, requiresReboot, accessor, appLevel, isLocked,
instance — plus reload(). Static ConfiguardService.parseFlat /
serializeFlat mirror configuard's admin-UI helpers.
reload()re-runs the registration factory, so it only fetches fresh values underforRootAsync. UnderforRoot(staticrows) it rebuilds from the same in-memory list — effectively a no-op.
Raw instance — @InjectConfiguard()
For advanced use where you want the boot instance directly (no live reload):
import { Injectable } from '@nestjs/common';
import { Configuard, InjectConfiguard } from 'nestjs-configuard';
@Injectable()
export class Service {
constructor(@InjectConfiguard() private readonly cfg: Configuard) {}
}TTL auto-refresh
When refreshIntervalMs > 0, the service starts an unref'd timer on
application bootstrap that reloads config every interval (the DB-config
"~60s cache"), and clears it on module destroy. Set refreshEnabled: false to
keep it off (break-glass) without removing the interval config.
Quality
- 100% test coverage (Vitest + istanbul) and a 100% mutation score (Stryker) — both enforced in CI, which also runs on Node 20, 22, and 24.
- ESM-only, TypeScript strict, Node ≥ 20.
- One tool for lint + format (Biome).
Related Projects
- configuard — builds a nested, typed configuration object from a flat list of config items, with templating and accessor-based (ABAC) filtering. (the engine this package wraps)
- accesscontrol — role and attribute-based access control (RBAC/ABAC) for Node.js.
- nestjs-accesscontrol — role & attribute-based access control for NestJS, built natively on accesscontrol v3 — fluent CRUD decorators, fail-closed guard, attribute filtering.
- notation — utility for modifying / processing the contents of objects or arrays via object-notation strings or globs. (configuard is built on it)
License
MIT © Onur Yıldırım
