Core Components
Overview
The @nx/core package provides essential base classes, helpers, and infrastructure components that all backend services extend. These components standardize application setup, data access patterns, cross-service communication, real-time messaging, and event-driven architecture.
Quick Links
| Component | Description | IGNIS Reference |
|---|---|---|
| DefaultApplication | Base application class with auth, CORS, Swagger, and health checks | Application |
| SoftDeletableRepository | Repository with soft-delete pattern (deletedAt timestamp) | Repositories |
| BaseSocketEventService | Base service for WebSocket event broadcasting via WebSocketEmitter | WebSocket |
| IdentityNetworkService | Cross-service HTTP client for identity authentication | Network Helper |
| Bootstrap Helpers | bootstrapApplication() and bootstrapMigration() entry-point helpers | Bootstrapping |
| RedisConnectionFactory | Redis connection management (single or cluster mode) | Redis Helper |
| Event Bus | Pub/sub messaging abstraction with Redis Pub/Sub adapter | - |
Component Hierarchy
Repository Hierarchy
BaseSocketEventService
Base service for broadcasting WebSocket events through the IGNIS WebSocketEmitter. Used by @nx/signal to implement SignalEventService.
Source: packages/core/src/base/service/base-socket-event.service.ts
| Method | Signature | Description |
|---|---|---|
broadcast | broadcast<T>({ topic, data }): Promise<void> | Send to all clients in the default room |
sendToRoom | sendToRoom<T>({ room, topic, data }): Promise<void> | Send to all clients in a specific room |
isReady | isReady(): boolean | Check if the WebSocketEmitter binding is available |
emitter | get emitter(): WebSocketEmitter | Lazy getter for the emitter from the DI container |
Usage:
import { BaseSocketEventService } from '@nx/core';
import { BaseApplication, inject } from '@venizia/ignis';
export class MyEventService extends BaseSocketEventService {
constructor(
@inject({ key: CoreBindings.APPLICATION_INSTANCE })
application: BaseApplication,
) {
super(application, {
scope: MyEventService.name,
emitterBindingKey: '@my-package/websocket-emitter',
});
}
async notifyOrderCreated(orderId: string) {
await this.broadcast({ topic: 'order:created', data: { orderId } });
}
}See the IGNIS WebSocket Component for emitter configuration details.
Bootstrap Helpers
Helper functions that standardize application and migration entry points across all packages.
Source: packages/core/src/helpers/bootstraps/
bootstrapApplication
Creates and starts the application with banner display and graceful shutdown.
// packages/sale/src/index.ts
import { bootstrapApplication } from '@nx/core';
import { Application } from './application';
import { appConfig } from './common/app-config';
bootstrapApplication({
ApplicationClass: Application,
config: appConfig,
options: { bannerPath: resolve(__dirname, '../resources/banner.txt') },
});bootstrapMigration
Creates the application in migration mode and runs seed/migration processes.
// packages/sale/src/migrate.ts
import { bootstrapMigration } from '@nx/core';
import { Application } from './application';
import { getMigrationProcesses } from './migrations/processes/migration-process';
bootstrapMigration({
ApplicationClass: Application,
getMigrationProcesses,
});createMigrationProcessLoader
Factory for loading migration process files from a directory.
// packages/sale/src/migrations/processes/migration-process.ts
import { createMigrationProcessLoader } from '@nx/core';
export const getMigrationProcesses = createMigrationProcessLoader({
seedPaths: ['sale-0001-seed-order-statuses'],
importFn: path => import(`../processes/${path}.js`),
});See IGNIS Bootstrapping for the underlying framework lifecycle.
RedisConnectionFactory
Static factory for creating Redis connections in either single-instance or cluster mode.
Source: packages/core/src/helpers/redis/redis-connection.factory.ts
| Method | Signature | Description |
|---|---|---|
create | static create(opts: TRedisConnectionOptions): DefaultRedisHelper | Create a RedisHelper (single) or RedisClusterHelper (cluster) |
parseClusterNodes | static parseClusterNodes({ raw }): Array<{ host, port }> | Parse "host1:port1,host2:port2" into node objects |
Single mode:
import { RedisConnectionFactory } from '@nx/core';
const redis = RedisConnectionFactory.create({
mode: 'single',
name: 'cache-redis',
host: 'localhost',
port: 6379,
password: 'secret',
database: 0,
maxRetry: 5,
autoConnect: false,
});Cluster mode:
const redis = RedisConnectionFactory.create({
mode: 'cluster',
name: 'cache-redis-cluster',
nodes: RedisConnectionFactory.parseClusterNodes({
raw: 'node1:6379,node2:6379,node3:6379',
}),
password: 'secret',
});See IGNIS Redis Helper for
RedisHelperandRedisClusterHelperAPI details.
Event Bus
Pub/sub messaging abstraction with a pluggable adapter pattern. Currently provides a Redis Pub/Sub adapter.
Source: packages/core/src/helpers/event-bus/
IEventBus Interface
interface IEventBus {
publish<T>(opts: { channel: string; data: T }): Promise<void>;
subscribe<T>(opts: { channel: string; handler: (data: T) => Promise<void> }): Promise<void>;
unsubscribe(opts: { channel: string }): Promise<void>;
disconnect(): Promise<void>;
}IEventBusMessage Envelope
Every published message is wrapped in a standard envelope:
interface IEventBusMessage<T = unknown> {
id: string; // Snowflake ID
type: string; // Channel name
publishedAt: string; // ISO timestamp
data: T; // Payload
metadata?: Record<string, unknown>;
}RedisPubSubAdapter
The default adapter using two RedisHelper instances (one publisher, one subscriber).
import { RedisPubSubAdapter } from '@nx/core';
const eventBus = new RedisPubSubAdapter({
publisher: publisherRedisHelper,
subscriber: subscriberRedisHelper,
});
// Subscribe
await eventBus.subscribe({
channel: 'payment:success',
handler: async (data) => {
console.log('Payment succeeded:', data);
},
});
// Publish
await eventBus.publish({
channel: 'payment:success',
data: { orderId: '123', amount: 50000 },
});| Method | Description |
|---|---|
publish({ channel, data }) | Wrap data in IEventBusMessage and publish to Redis |
subscribe({ channel, handler }) | Register a handler for a channel (idempotent) |
unsubscribe({ channel }) | Remove handler and unsubscribe from Redis |
disconnect() | Unsubscribe all channels and close Redis connections |
getSubscriptions() | Return list of subscribed channel names |
getHandlerCount() | Return number of registered handlers |
isSubscribed(channel) | Check if a channel has an active subscription |
WARNING
Redis Pub/Sub does not support message acknowledgment or retry. If a handler throws an error, the message is lost. Implement retry logic within your handler if needed, or use BullMQ queues for at-least-once delivery.
Next Steps
- Explore DefaultApplication lifecycle and configuration in detail
- Learn about SoftDeletableRepository soft-delete patterns
- Review Network Services for cross-service communication
- Read Bootstrap Helpers for application and migration entry points
- Read BaseSocketEventService for WebSocket event broadcasting
- Read RedisConnectionFactory for Redis connection management
- Read Event Bus for pub/sub messaging with Redis