UNPKG

nestjs-temporal-core

Version:

Complete NestJS integration for Temporal.io with auto-discovery, declarative scheduling, enhanced monitoring, and enterprise-ready features

198 lines 8.45 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var TemporalClientModule_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.TemporalClientModule = void 0; const common_1 = require("@nestjs/common"); const client_1 = require("@temporalio/client"); const constants_1 = require("../constants"); const temporal_client_service_1 = require("./temporal-client.service"); const temporal_schedule_service_1 = require("./temporal-schedule.service"); const logger_1 = require("../utils/logger"); let TemporalClientModule = TemporalClientModule_1 = class TemporalClientModule { static createModuleLogger(_options) { return (0, logger_1.createLogger)(TemporalClientModule_1.name); } static register(options) { const clientOptions = this.extractClientOptions(options); return { module: TemporalClientModule_1, providers: [ { provide: constants_1.TEMPORAL_MODULE_OPTIONS, useValue: clientOptions, }, this.createClientProvider(clientOptions), temporal_client_service_1.TemporalClientService, temporal_schedule_service_1.TemporalScheduleService, ], exports: [temporal_client_service_1.TemporalClientService, temporal_schedule_service_1.TemporalScheduleService, constants_1.TEMPORAL_CLIENT], }; } static registerAsync(options) { return { module: TemporalClientModule_1, imports: options.imports || [], providers: [ ...this.createAsyncProviders(options), this.createAsyncClientProvider(), temporal_client_service_1.TemporalClientService, temporal_schedule_service_1.TemporalScheduleService, ], exports: [temporal_client_service_1.TemporalClientService, temporal_schedule_service_1.TemporalScheduleService, constants_1.TEMPORAL_CLIENT], }; } static forClient(options) { return this.register({ connection: options.connection, isGlobal: options.isGlobal, }); } static createClientProvider(options) { return { provide: constants_1.TEMPORAL_CLIENT, useFactory: async () => { const logger = this.createModuleLogger(options); return this.createClientInstance(options, logger); }, }; } static createAsyncClientProvider() { return { provide: constants_1.TEMPORAL_CLIENT, useFactory: async (options) => { const logger = this.createModuleLogger(options); return this.createClientInstance(options, logger); }, inject: [constants_1.TEMPORAL_MODULE_OPTIONS], }; } static createAsyncProviders(options) { if (options.useFactory) { return [ { provide: constants_1.TEMPORAL_MODULE_OPTIONS, useFactory: async (...args) => { const temporalOptions = await options.useFactory(...args); return this.extractClientOptions(temporalOptions); }, inject: options.inject || [], }, ]; } if (options.useClass) { return [ { provide: options.useClass, useClass: options.useClass, }, { provide: constants_1.TEMPORAL_MODULE_OPTIONS, useFactory: async (optionsFactory) => { const temporalOptions = await optionsFactory.createTemporalOptions(); return this.extractClientOptions(temporalOptions); }, inject: [options.useClass], }, ]; } if (options.useExisting) { return [ { provide: constants_1.TEMPORAL_MODULE_OPTIONS, useFactory: async (optionsFactory) => { const temporalOptions = await optionsFactory.createTemporalOptions(); return this.extractClientOptions(temporalOptions); }, inject: [options.useExisting], }, ]; } throw new Error(constants_1.ERRORS.INVALID_OPTIONS); } static async createClientInstance(options, logger) { let temporalConnection = null; try { const connection = options.connection; logger.log(`Connecting to Temporal server at ${connection.address}`); const connectionConfig = { address: connection.address, tls: connection.tls, metadata: connection.metadata, }; if (connection.apiKey) { connectionConfig.metadata = { ...(connectionConfig.metadata || {}), authorization: `Bearer ${connection.apiKey}`, }; } temporalConnection = await client_1.Connection.connect(connectionConfig); const namespace = connection.namespace || constants_1.DEFAULT_NAMESPACE; logger.log(`Connected to Temporal server, using namespace "${namespace}"`); const client = new client_1.Client({ connection: temporalConnection, namespace }); return this.enhanceClientWithShutdown(client, logger); } catch (error) { if (temporalConnection) { await temporalConnection.close().catch((closeError) => { logger.warn(`Error closing connection: ${closeError.message}`); }); } const errorMsg = `${constants_1.ERRORS.CLIENT_INITIALIZATION}: ${error.message}`; logger.error(errorMsg, error.stack); if (options.allowConnectionFailure !== false) { logger.warn('Continuing application startup without Temporal client'); return null; } throw new Error(errorMsg); } } static enhanceClientWithShutdown(client, logger) { const originalConnection = client.connection; process.on('SIGTERM', async () => { logger.log('Gracefully shutting down Temporal client...'); try { await originalConnection.close(); logger.log('Temporal client shutdown completed'); } catch (error) { logger.error(`Error during client shutdown: ${error.message}`); } }); return client; } static extractClientOptions(options) { return { connection: { address: options.connection.address, namespace: options.connection.namespace, tls: options.connection.tls, apiKey: options.connection.apiKey, metadata: options.connection.metadata, }, allowConnectionFailure: true, enableLogger: options.enableLogger, logLevel: options.logLevel, }; } static validateOptions(options) { if (!options.connection) { throw new Error('Connection configuration is required'); } const connection = options.connection; if (!connection.address) { throw new Error('Connection address is required'); } } }; exports.TemporalClientModule = TemporalClientModule; exports.TemporalClientModule = TemporalClientModule = TemporalClientModule_1 = __decorate([ (0, common_1.Global)(), (0, common_1.Module)({}) ], TemporalClientModule); //# sourceMappingURL=temporal-client.module.js.map