apsis-helper
v0.1.3
Published
Shared NestJS utilities (audit trail, and future helpers) originally built for the Apsis microservices ecosystem.
Readme
apsis-helper
Shared NestJS utilities. v1 ships an audit-trail service — originally built for, and still used by, the Apsis microservices ecosystem, and now a standalone public package anyone can use. Future shared utilities (not tied to a specific service) belong here too.
Design
- The package never opens a DB or Redis connection, and never reads
process.env. Each host app keeps owning its ownknex/ioredisinstances and its own env config; this package only owns the audit-trail logic. That's what makes "fix once, works everywhere" possible without also having to reconcile every consumer's connection setup. ApsisDbService's public API (insert,update,deleteRecordWithAuditTrail,enqueue) doesn't touch your schema at all — every caller passesprimary_keyexplicitly, so there's no per-table config baked into this package.- DB error formatting is intentionally not bundled — pass your own
onDbErrorinforRootAsyncif you want custom error shaping; otherwise a genericInternalServerErrorExceptionis thrown. - If you build your own consumer for
AUDIT_TRAIL_REDIS_QUEUE_KEY, add a unique index on whatever columns make a history row idempotent (e.g. a uid/table/reference-type combination) so the same row can't be written twice if two workers process one entry. - Currently NestJS-only (
ApsisDbService/AuditTrailModuleuse@nestjs/commondecorators and DI). Framework-agnostic use (e.g. Express) would need the logic pulled into a plain, decorator-free core class with a thin adapter per framework — PRs welcome.
Install
npm install apsis-helperNo .npmrc or auth needed — it's on the public registry.
Wiring into a host app
Register once, typically in your existing global/shared module:
import { AuditTrailModule, ApsisDbService } from 'apsis-helper';
import { KNEX_CONNECTION } from 'src/knexmodule';
import { REDIS_CLIENT } from 'src/global/redis'; // wherever your app provides its Redis client
import { KnexErrorService } from 'src/common/knexerrors';
const AuditTrailModuleForRoot = AuditTrailModule.forRootAsync({
inject: [KNEX_CONNECTION, REDIS_CLIENT, KnexErrorService],
useFactory: (knex, redis, knexErrorService: KnexErrorService) => ({
knex,
redis,
onDbError: (message: string) => knexErrorService.errorMessage(message),
}),
});
@Global()
@Module({
// Nest only lets a module re-export a *module* it imports, not a provider
// cherry-picked out of that module — AuditTrailModuleForRoot must be the same
// object reference in both imports and exports.
imports: [AuditTrailModuleForRoot],
exports: [AuditTrailModuleForRoot],
})
export class GlobalModule {}Everywhere else in the app, just:
import { ApsisDbService } from 'apsis-helper';AUDIT_TRAIL_REDIS_QUEUE_KEY and AUDIT_TRAIL_OUTBOX_TABLE are exported constants —
keep them consistent with whatever downstream process drains that queue/table.
Publishing a new version
npm version patch # or minor/major
npm run build
npm publishRequires being logged in to npmjs.com (npm login) with an account that has publish
rights on this package, and 2FA enabled — npm requires it for publishing.
License
MIT — see LICENSE.
