@lyrolab/nest-shared
v2.3.1
Published
A collection of shared modules for NestJS applications
Readme
Nest Shared
A collection of shared NestJS modules published to npm as @lyrolab/nest-shared. Provides reusable infrastructure components for NestJS applications across LyroLab projects.
Installation
npm install @lyrolab/nest-sharedNote:
@lyrolab/nest-shareddeclares many peer dependencies. You'll need to install the ones you actually use. See each module's README for its specific peer dependency requirements.
Module Catalog
| Module | Import Path | Description | Key Exports | Requires Config |
| ------------------------------------------------ | ------------------------------------- | ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | :-------------: |
| AI | @lyrolab/nest-shared/ai | OpenRouter AI service with response caching | SharedAiModule, AiService, AI_MODULE_OPTIONS | ✅ |
| Auth | @lyrolab/nest-shared/auth | JWT/Keycloak authentication, roles and user provisioning | SharedAuthModule, JwtAuthGuard, RolesGuard, @Roles(), createUserProvisioningGuard() | ✅ |
| Bootstrap | @lyrolab/nest-shared/bootstrap | App setup (CORS, ValidationPipe, Swagger) and OpenAPI generation | configureApp(), generateOpenApi(), buildSwaggerConfig() | ✅ |
| Bull | @lyrolab/nest-shared/bull | BullMQ queue integration backed by Redis | SharedBullModule | ✅ |
| Cache | @lyrolab/nest-shared/cache | Redis-backed caching (preferred over raw Redis) | SharedCacheModule | ✅ |
| CASL | @lyrolab/nest-shared/casl | nest-casl subject hooks and permission test helper | BaseHook, getAbilityFactory() | ❌ |
| Config | @lyrolab/nest-shared/config | Fail-fast environment validation with class-validator | validateEnv(), registerConfig() | ❌ |
| Database | @lyrolab/nest-shared/database | TypeORM + PostgreSQL with TestContainers and TypeORM CLI source | SharedDatabaseModule, TypeOrmExceptionFilter, createCliDataSource() | ✅ |
| ESLint | @lyrolab/nest-shared/eslint | Shared ESLint config with custom architecture rules | nestArchitecturePlugin | ❌ |
| Health | @lyrolab/nest-shared/health | Health check endpoint via Terminus | SharedHealthModule | ❌ |
| Keycloak Admin | @lyrolab/nest-shared/keycloak-admin | Client-credentials Keycloak admin client for user operations | KeycloakAdminModule, KeycloakAdminService | ✅ |
| Observability | @lyrolab/nest-shared/observability | OpenTelemetry traces, metrics and logs over OTLP | startTelemetry() | ✅ |
| Queue | @lyrolab/nest-shared/queue | Job processing with decorator-based processors and named queues | SharedQueueModule, QueueService, @JobProcessor() | ✅ |
| Redis | @lyrolab/nest-shared/redis | Low-level Redis configuration | SharedRedisModule, RedisConfig | ✅ |
Quick Start
// app.module.ts
import { Module } from "@nestjs/common"
import { ConfigModule } from "@nestjs/config"
import { SharedAuthModule } from "@lyrolab/nest-shared/auth"
import { SharedBootstrapModule } from "@lyrolab/nest-shared/bootstrap"
import { SharedCacheModule } from "@lyrolab/nest-shared/cache"
import { SharedDatabaseModule } from "@lyrolab/nest-shared/database"
import { SharedHealthModule } from "@lyrolab/nest-shared/health"
import { keycloakConfig } from "@lyrolab/nest-shared/auth"
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
SharedDatabaseModule.forRoot({
entities: [__dirname + "/**/*.entity{.ts,.js}"],
}),
SharedAuthModule.forRoot(
keycloakConfig(
process.env.KEYCLOAK_URL ?? "http://localhost:8080",
process.env.KEYCLOAK_REALM ?? "lyrochat",
),
),
SharedCacheModule.forRoot(),
SharedHealthModule,
],
})
export class AppModule {}// main.ts
import { NestFactory } from "@nestjs/core"
import { configureApp } from "@lyrolab/nest-shared/bootstrap"
import { AppModule } from "./app.module"
async function bootstrap() {
const app = await NestFactory.create(AppModule)
configureApp(app) // Sets up CORS, ValidationPipe, Swagger, global filters
await app.listen(process.env.PORT ?? 3000)
}
bootstrap()Using Modules in Services
import { Injectable } from "@nestjs/common"
import { Inject } from "@nestjs/common"
import { CACHE_MANAGER } from "@nestjs/cache-manager"
import { Cache } from "cache-manager"
import { AiService } from "@lyrolab/nest-shared/ai"
import { QueueService } from "@lyrolab/nest-shared/queue"
import { generateText } from "ai"
@Injectable()
export class MyService {
constructor(
private readonly aiService: AiService,
private readonly queueService: QueueService,
@Inject(CACHE_MANAGER) private cache: Cache,
) {}
async process(input: string) {
const cached = await this.cache.get(`input:${input}`)
if (cached) return cached
const result = await generateText({
model: this.aiService.model,
system: "You are a helpful assistant.",
prompt: input,
})
await this.cache.set(`input:${input}`, result.text)
return result.text
}
}Environment Variables
| Variable | Required | Used By | Description |
| -------------------- | :------: | ------------------------- | ------------------------------------- |
| DATABASE_URL | ✅ | Database | PostgreSQL connection string |
| REDIS_URL | ✅ | Redis, Cache, Bull, Queue | Redis connection string |
| CORS_ORIGINS | ❌ | Bootstrap | Comma-separated CORS origins |
| FRONTEND_URL | ❌ | Bootstrap | CORS origin when CORS_ORIGINS unset |
| JWKS_URI | ✅ | Auth | JWKS endpoint for JWT verification |
| JWT_ISSUER | ✅ | Auth | JWT issuer to validate against |
| PORT | ❌ | Bootstrap | App listen port (default: 3000) |
| CACHE_TTL | ❌ | Cache | Cache TTL in seconds |
| OPENROUTER_API_KEY | ✅ | AI | OpenRouter API key |
| OTEL_ENABLED | ❌ | Observability | false disables telemetry |
| OTEL_EXPORTER_URL | ❌ | Observability | OTLP/gRPC collector endpoint |
| APP_STAGE | ❌ | Observability | Deployment environment name |
| NODE_ENV | ❌ | All | Set to test for TestContainers mode |
Development
Local Setup
# Clone and install
git clone https://github.com/lyrolab/nest-shared.git
cd nest-shared
npm install
# Build
npm run build
# Run tests
npm test
npm run test:cov # With coverage
# Watch mode
npm run devAdding a New Module
- Create
src/<module>/withindex.tsbarrel export. - Write a
README.mdin the module directory. - Add the export entry in
package.json:
"./<module>": {
"types": "./dist/<module>/index.d.ts",
"import": "./dist/<module>/index.js",
"require": "./dist/<module>/index.js"
}- Add a row to the Module Catalog table in this README.
Code Quality
npm run lint # ESLint
npx lint-staged # Pre-commit checks
npm test # JestPublishing
This package uses semantic-release for automated publishing on the main branch.
feat:commits → minor version bumpfix:commits → patch version bumpfeat!:orfix!:commits → major version bump
See CLAUDE.md for detailed contribution conventions.
