| name | nestjs-expert |
| description | Apply NestJS expertise to the Workless repository. Use when changing modules, providers, controllers, lifecycle wiring, TypeORM integration, tenant context, cache integration, or configuration in this NestJS monolith. |
NestJS Expert
Use this skill for NestJS-specific work in Workless.
Project Reality
Workless is a NestJS modular monolith with:
- platform layer under
src/app
- core engine under
src/core
- plugin modules under
src/modules
ConfigModule.forRoot(...) in src/app.module.ts
- global validation pipe in
src/main.ts
- TypeORM + PostgreSQL
- optional Redis-backed cache under
src/core/infrastructure/cache
- tenant scoping through
src/core/tenant/*
- runtime module registry and lifecycle under
src/core/lifecycle and src/core/registry
This repo is backend-first. Do not assume React, Passport auth, or microservices unless the code exists.
Read First
Before structural changes, inspect in this order:
src/app.module.ts
src/core/core.module.ts
src/modules/runtime-modules.ts
- target module
src/modules/<name>/module.ts or target platform module under src/app/<name>
- related runtime files under:
src/core/system
src/core/registry
src/core/lifecycle
src/core/events
src/core/interfaces
src/core/tenant
Active Patterns In Workless
Layering
src/app is stable platform code
src/core is shared runtime engine
src/modules contains optional plugin modules
Module Wiring
Expected responsibilities:
- controllers are thin
- services orchestrate
- repositories own persistence
- DTOs validate public input
- policies own permission and rule checks
- hooks and events are used for extension points
- lifecycle services are added only when a module needs install, upgrade, or uninstall behavior
- backend code should avoid a separate
models/ layer and instead use entities/, dto/, and src/core/interfaces/*
Runtime System
When a module participates in lifecycle management, inspect:
src/core/system/system-module.decorator.ts
src/core/system/system-module.interface.ts
src/core/system/system-module.explorer.ts
src/core/registry/module.registry.ts
src/core/lifecycle/module.lifecycle.ts
src/core/lifecycle/module-lifecycle.runner.ts
Current low-risk runtime pattern:
- registry reads should prefer discoverable modules only
- lifecycle operations emit domain events
- module loading should tolerate missing plugin directories
Tenant Model
Tenant flow is:
TenantContextMiddleware reads x-tenant-id
TenantContextService stores normalized state in async local storage
- repositories and entities use
tenantId
- cache keys must remain tenant-aware
Cache Model
Preferred cache path:
src/core/infrastructure/cache/*
Use this for new cache work:
CacheModule
CacheService
redis.provider.ts
CacheService.remember(...)
Page cache headers live under:
src/core/http/html-cache.interceptor.ts
Workless-Specific Hazards
Runtime vs Scaffold
src/modules/apps exists as scaffold only. Do not treat it as an active runtime module unless the code changes.
CRM Reference Path
Use src/modules/crm as the main reference for:
- controller and service wiring
- repository pattern
- hook and event usage
- lifecycle integration
- tenant-aware cache keys
- backend module structure without
models/
Verification Reality
Current reliable baseline:
npm run build
Useful setup commands:
npm run db:platform
npm run seed
Important:
npm test is still a placeholder
- runtime checks need Postgres, and optional Redis
- do not claim tests passed unless they actually ran
When Solving Problems
Dependency Injection Issues
Check:
- provider is registered in the active module
- provider is exported only when needed externally
- imports and exports match current paths
- modules depend on core interfaces, not app services
TypeORM Issues
Check:
- entity path is the active one
TypeOrmModule.forFeature(...) includes the correct entity
- schema preparation paths align with
src/database/*
- database config aligns with
src/database/typeorm.config.ts
Lifecycle Issues
Check:
- module lifecycle service implements
SystemModuleLifecycle
- module metadata and registry names match
- install, upgrade, and uninstall flows are idempotent where possible
- lifecycle changes invalidate stale cache correctly
Tenant and Cache Bugs
Check:
- repositories filter by
tenantId
- service cache keys include tenant scope
- write paths invalidate detail and collection or version keys
- HTML cache keys remain module and tenant aware
Success Criteria
- changes match active NestJS wiring
- no accidental edits to stale or scaffold-only paths
- tenant, cache, and lifecycle behavior remain coherent
- the project still builds cleanly when the environment is ready