NestJS-YALC
NestJS-YALC logo

NestJS production toolkit

Production-grade NestJS, generated from your domain model.

Define resources once. NestJS-YALC generates CRUD APIs, protects service boundaries with API Strategy, and standardizes events, errors, and observability with EventManager.

Define a resource once. YALC turns it into REST, GraphQL, service, repository, and dataloader surfaces that share the same contract.

export const usersResource = CrudGenResourceFactory<SkeletonUser>({
  entityModel: SkeletonUser,
  graphql: true,
  rest: true,
});
Resource model SkeletonUser
REST controller
GET/skeleton-user?$top=20
GET/skeleton-user/:id
POST/skeleton-user
PUT/skeleton-user/:id
DELETE/skeleton-user/:id
GraphQL resolver
querygetSkeletonUser
querygetSkeletonUserGrid
mutationcreateSkeletonUser
DataLoader cache

Keep caller and emitter code stable while the selected strategy swaps between local calls, HTTP calls, and event emission.

{
  provide: USERS_API,
  useFactory: (adapter, cls, config) =>
    new NestLocalCallStrategy(adapter, cls, config),
}

@Injectable()
export class UsersApiClient {
  constructor(
    @Inject(USERS_API)
    private readonly api: IHttpCallStrategy,
  ) {}

  listUsers() {
    return this.api.get('/users');
  }
}
same client call await usersApi.listUsers()
Caller UsersApiClient
Strategy token USERS_API
Same runtime Nest app
transport Fastify inject('/users')
output 200 { list, pageData }
{
  provide: USERS_API,
  useFactory: (http, cls) =>
    new NestHttpCallStrategy(http, cls, process.env.USERS_BASE_URL ?? ''),
}

@Injectable()
export class UsersApiClient {
  constructor(
    @Inject(USERS_API)
    private readonly api: IHttpCallStrategy,
  ) {}

  listUsers() {
    return this.api.get('/users');
  }
}
same client call await usersApi.listUsers()
Caller UsersApiClient
Strategy token USERS_API
Remote API Users service
transport Axios GET /users
output 200 { list, pageData }
{
  provide: USER_EVENTS,
  useFactory: (eventManager: YalcEventService) =>
    new NestLocalEventStrategy(eventManager.emitter),
  inject: [YalcEventService],
}

class UsersEventsClient {
  constructor(
    @Inject(USER_EVENTS)
    private readonly events: IEventStrategy,
  ) {}

  userCreated(userId: string) {
    return this.events.emitAsync('user.created', { userId });
  }
}
same event contract emitAsync('user.created', payload)
Emitter UserService
Event token USER_EVENTS
EventManager YalcEventService
local branch events.emitter.emitAsync(...)
output listeners + logs + optional broker

EventManager centralizes logs, domain events, and HTTP-aware errors behind one YalcEventService call surface. Observability can subscribe to the same stream and export traces, metrics, and logs.

@Injectable()
export class UserService {
  constructor(
    private readonly events: YalcEventService,
    private readonly users: UserRepository,
  ) {}

  async findOrFail(userId: string) {
    const user = await this.users.findById(userId);
    if (!user) {
      throw this.events.errorNotFound('user.notFound', {
        data: { userId },
      });
    }

    await this.events.logAsync(['user', 'loaded'], {
      data: { userId },
    });

    return user;
  }
}
event source user.loaded
structured log listener notified HTTP-aware error
{ "event": "user.loaded" } userId: 42
Traces
Metrics
OTLP export 127.0.0.1:4318

Everything NestJS gives you, plus the YALC production layer.

NestJS already gives you modular architecture, dependency injection, TypeScript, and a strong backend ecosystem. YALC adds generated resource contracts, swappable service boundaries, operational primitives, and pre-optimized modules with AppBootstrap helpers for production-ready NestJS applications.

01

Extensible modules

Keep Nest's module-first structure and generate the repetitive resource layer around explicit entity, DTO, service, and repository contracts.

Modules DI Typed contracts

02

Versatile APIs

Build REST, GraphQL, event-driven flows, and background-ready boundaries from the same resource definitions instead of hand-maintaining each surface.

REST GraphQL Events

03

Progressive boundaries

Move from one runtime to distributed services by switching strategy providers while preserving the caller contract and testable Nest wiring.

Local calls HTTP Microservices

04

Everything you need to operate it

Add structured events, HTTP-aware errors, traces, metrics, and logs so generated backends are easier to observe, debug, and evolve in production.

Errors Logs OTLP

Used in real production contexts.

The framework patterns have been used in backend work for teams and products that needed stronger NestJS foundations.

Explore the full documentation.

Move from first setup to production architecture, generated resources, runtime strategies, EventManager, observability, and runnable examples.

New to the project?

Start with the short setup path, then open the skeleton app and copy the resource factory pattern into your own module.

Go to getting started

Need the full reference?

The documentation index groups architecture guides, package references, example applications, test commands, and publication notes.

Open the documentation index