@globalart/nestjs-typeorm-outbox 1.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +14 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -4
- package/dist/index.d.mts +5 -4
- package/dist/index.mjs +14 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
1
2
|
let _nestjs_common = require("@nestjs/common");
|
|
2
3
|
let _globalart_text_utils = require("@globalart/text-utils");
|
|
3
4
|
let typeorm = require("typeorm");
|
|
@@ -17,13 +18,13 @@ const InjectTypeormOutboxService = () => (0, _nestjs_common.Inject)(TYPEORM_OUTB
|
|
|
17
18
|
const InjectTypeormOutboxBroker = () => (0, _nestjs_common.Inject)(TYPEORM_OUTBOX_BROKER_TOKEN);
|
|
18
19
|
|
|
19
20
|
//#endregion
|
|
20
|
-
//#region \0@oxc-project+runtime@0.
|
|
21
|
+
//#region \0@oxc-project+runtime@0.112.0/helpers/decorateMetadata.js
|
|
21
22
|
function __decorateMetadata(k, v) {
|
|
22
23
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
//#endregion
|
|
26
|
-
//#region \0@oxc-project+runtime@0.
|
|
27
|
+
//#region \0@oxc-project+runtime@0.112.0/helpers/decorate.js
|
|
27
28
|
function __decorate(decorators, target, key, desc) {
|
|
28
29
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
29
30
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -130,7 +131,7 @@ var TypeormOutboxModuleOptions = class {
|
|
|
130
131
|
};
|
|
131
132
|
|
|
132
133
|
//#endregion
|
|
133
|
-
//#region \0@oxc-project+runtime@0.
|
|
134
|
+
//#region \0@oxc-project+runtime@0.112.0/helpers/decorateParam.js
|
|
134
135
|
function __decorateParam(paramIndex, decorator) {
|
|
135
136
|
return function(target, key) {
|
|
136
137
|
decorator(target, key, paramIndex);
|
|
@@ -146,11 +147,20 @@ let TypeormOutboxCronService = class TypeormOutboxCronService {
|
|
|
146
147
|
this.moduleConfig = moduleConfig;
|
|
147
148
|
this.dataSource = dataSource;
|
|
148
149
|
}
|
|
149
|
-
|
|
150
|
+
onApplicationBootstrap() {
|
|
151
|
+
this.validateBrokerClient();
|
|
150
152
|
new cron.CronJob(this.moduleConfig.cronExpression ?? CronExpression.EVERY_SECOND, () => {
|
|
151
153
|
this.executeCronJob();
|
|
152
154
|
}).start();
|
|
153
155
|
}
|
|
156
|
+
validateBrokerClient() {
|
|
157
|
+
const brokerConfig = this.moduleConfig.brokerConfig;
|
|
158
|
+
if (![
|
|
159
|
+
_nestjs_microservices.Transport.KAFKA,
|
|
160
|
+
_nestjs_microservices.Transport.NATS,
|
|
161
|
+
_nestjs_microservices.Transport.MQTT
|
|
162
|
+
].includes(brokerConfig?.transport)) throw new Error(`[TypeormOutboxCronService] Broker config must be an instance of KafkaOptions, NatsOptions, or MqttOptions`);
|
|
163
|
+
}
|
|
154
164
|
async executeCronJob() {
|
|
155
165
|
const queryRunner = this.dataSource.createQueryRunner();
|
|
156
166
|
await queryRunner.connect();
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["CronJob","TypeOrmModule","ClientProxyFactory"],"sources":["../src/core/typeorm-outbox.di-tokens.ts","../src/core/typeorm-outbox.entity.ts","../src/core/typeorm-outbox.enums.ts","../src/core/typeorm-outbox.interfaces.ts","../src/core/typeorm-outbox-cron.service.ts","../src/core/typeorm-outbox.service.ts","../src/core/typeorm-outbox.module.ts"],"sourcesContent":["import { Inject } from \"@nestjs/common\";\n\nexport const TYPEORM_OUTBOX_CRON_CONFIG_TOKEN = Symbol(\n \"TYPEORM_OUTBOX_CRON_CONFIG_TOKEN\",\n);\nexport const TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN = Symbol(\n \"TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN\",\n);\nexport const TYPEORM_OUTBOX_SERVICE_TOKEN = Symbol(\n \"TYPEORM_OUTBOX_SERVICE_TOKEN\",\n);\nexport const TYPEORM_OUTBOX_BROKER_TOKEN = Symbol(\n \"TYPEORM_OUTBOX_BROKER_TOKEN\",\n);\n\nexport const InjectTypeormOutboxCronConfig = () =>\n Inject(TYPEORM_OUTBOX_CRON_CONFIG_TOKEN);\nexport const InjectTypeormOutboxModuleConfig = () =>\n Inject(TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN);\nexport const InjectTypeormOutboxService = () =>\n Inject(TYPEORM_OUTBOX_SERVICE_TOKEN);\nexport const InjectTypeormOutboxBroker = () =>\n Inject(TYPEORM_OUTBOX_BROKER_TOKEN);\n","import {\n Column,\n CreateDateColumn,\n Entity,\n PrimaryGeneratedColumn,\n UpdateDateColumn,\n} from \"typeorm\";\n\n@Entity('outbox')\nexport class TypeormOutboxEntity {\n @PrimaryGeneratedColumn()\n id!: number;\n\n @CreateDateColumn({ name: 'created_at' })\n createdAt!: Date;\n\n @UpdateDateColumn({ name: 'updated_at' })\n updatedAt!: Date;\n\n @Column(\"character varying\", { name: 'destination_topic' })\n destinationTopic!: string;\n\n @Column(\"jsonb\", { nullable: true })\n headers!: Record<string, string>;\n\n @Column(\"jsonb\", { nullable: true })\n keys!: Record<string, unknown>;\n\n @Column(\"jsonb\")\n payload!: Record<string, any>;\n}\n","export enum CronExpression {\n EVERY_SECOND = \"* * * * * *\",\n EVERY_2_SECONDS = \"*/2 * * * * *\",\n EVERY_3_SECONDS = \"*/3 * * * * *\",\n EVERY_4_SECONDS = \"*/4 * * * * *\",\n EVERY_5_SECONDS = \"*/5 * * * * *\",\n EVERY_6_SECONDS = \"*/6 * * * * *\",\n EVERY_7_SECONDS = \"*/7 * * * * *\",\n EVERY_8_SECONDS = \"*/8 * * * * *\",\n EVERY_9_SECONDS = \"*/9 * * * * *\",\n EVERY_10_SECONDS = \"*/10 * * * * *\",\n EVERY_11_SECONDS = \"*/11 * * * * *\",\n EVERY_12_SECONDS = \"*/12 * * * * *\",\n EVERY_13_SECONDS = \"*/13 * * * * *\",\n EVERY_14_SECONDS = \"*/14 * * * * *\",\n EVERY_15_SECONDS = \"*/15 * * * * *\",\n EVERY_16_SECONDS = \"*/16 * * * * *\",\n EVERY_17_SECONDS = \"*/17 * * * * *\",\n EVERY_18_SECONDS = \"*/18 * * * * *\",\n EVERY_19_SECONDS = \"*/19 * * * * *\",\n EVERY_20_SECONDS = \"*/20 * * * * *\",\n EVERY_21_SECONDS = \"*/21 * * * * *\",\n EVERY_22_SECONDS = \"*/22 * * * * *\",\n EVERY_23_SECONDS = \"*/23 * * * * *\",\n EVERY_24_SECONDS = \"*/24 * * * * *\",\n EVERY_25_SECONDS = \"*/25 * * * * *\",\n EVERY_26_SECONDS = \"*/26 * * * * *\",\n EVERY_27_SECONDS = \"*/27 * * * * *\",\n EVERY_28_SECONDS = \"*/28 * * * * *\",\n EVERY_29_SECONDS = \"*/29 * * * * *\",\n EVERY_30_SECONDS = \"*/30 * * * * *\",\n EVERY_31_SECONDS = \"*/31 * * * * *\",\n EVERY_32_SECONDS = \"*/32 * * * * *\",\n EVERY_33_SECONDS = \"*/33 * * * * *\",\n EVERY_34_SECONDS = \"*/34 * * * * *\",\n EVERY_35_SECONDS = \"*/35 * * * * *\",\n EVERY_36_SECONDS = \"*/36 * * * * *\",\n EVERY_37_SECONDS = \"*/37 * * * * *\",\n EVERY_38_SECONDS = \"*/38 * * * * *\",\n EVERY_39_SECONDS = \"*/39 * * * * *\",\n EVERY_40_SECONDS = \"*/40 * * * * *\",\n EVERY_41_SECONDS = \"*/41 * * * * *\",\n EVERY_42_SECONDS = \"*/42 * * * * *\",\n EVERY_43_SECONDS = \"*/43 * * * * *\",\n EVERY_44_SECONDS = \"*/44 * * * * *\",\n EVERY_45_SECONDS = \"*/45 * * * * *\",\n EVERY_46_SECONDS = \"*/46 * * * * *\",\n EVERY_47_SECONDS = \"*/47 * * * * *\",\n EVERY_48_SECONDS = \"*/48 * * * * *\",\n EVERY_49_SECONDS = \"*/49 * * * * *\",\n EVERY_50_SECONDS = \"*/50 * * * * *\",\n EVERY_51_SECONDS = \"*/51 * * * * *\",\n EVERY_52_SECONDS = \"*/52 * * * * *\",\n EVERY_53_SECONDS = \"*/53 * * * * *\",\n EVERY_54_SECONDS = \"*/54 * * * * *\",\n EVERY_55_SECONDS = \"*/55 * * * * *\",\n EVERY_56_SECONDS = \"*/56 * * * * *\",\n EVERY_57_SECONDS = \"*/57 * * * * *\",\n EVERY_58_SECONDS = \"*/58 * * * * *\",\n EVERY_59_SECONDS = \"*/59 * * * * *\",\n EVERY_MINUTE = \"0 * * * * *\",\n}","import { KafkaOptions, MqttOptions, NatsOptions } from \"@nestjs/microservices\";\nimport { InjectionToken, ModuleMetadata, Type } from \"@nestjs/common\";\nimport { CronExpression } from \"./typeorm-outbox.enums\";\n\ntype BrokerConfig = MqttOptions | NatsOptions | KafkaOptions;\n\nexport class TypeormOutboxRegisterCronModuleOptions {\n brokerConfig: BrokerConfig = {};\n typeOrmConnectionName?: string = \"default\";\n cronExpression?: string = CronExpression.EVERY_SECOND;\n}\n\nexport interface TypeormOutboxRegisterCronAsyncOptions\n extends Pick<ModuleMetadata, \"imports\"> {\n inject?: InjectionToken[];\n useExisting?: Type<TypeormOutboxRegisterCronModuleOptions>;\n useClass?: Type<TypeormOutboxRegisterCronModuleOptions>;\n useFactory?: (\n ...args: unknown[]\n ) =>\n | Promise<TypeormOutboxRegisterCronModuleOptions>\n | TypeormOutboxRegisterCronModuleOptions;\n}\n\nexport class TypeormOutboxModuleOptions {\n typeOrmConnectionName?: string = \"default\";\n}\n\nexport interface TypeormOutboxModuleAsyncOptions\n extends Pick<ModuleMetadata, \"imports\"> {\n inject?: InjectionToken[];\n useFactory?: (\n ...args: unknown[]\n ) => Promise<TypeormOutboxModuleOptions> | TypeormOutboxModuleOptions;\n}\n","import { Injectable, OnModuleInit } from \"@nestjs/common\";\nimport { InjectTypeormOutboxBroker, InjectTypeormOutboxCronConfig } from \"./typeorm-outbox.di-tokens\";\nimport { hashStringToInt } from \"@globalart/text-utils\";\nimport { TypeormOutboxEntity } from \"./typeorm-outbox.entity\";\nimport { firstValueFrom } from \"rxjs\";\nimport { ClientProxy } from \"@nestjs/microservices\";\nimport { CronJob } from \"cron\";\nimport { TypeormOutboxRegisterCronModuleOptions } from \"./typeorm-outbox.interfaces\";\nimport { DataSource } from \"typeorm\";\nimport { CronExpression } from \"./typeorm-outbox.enums\";\n\n@Injectable()\nexport class TypeormOutboxCronService implements OnModuleInit {\n constructor(\n @InjectTypeormOutboxBroker()\n private readonly brokerClient: ClientProxy,\n @InjectTypeormOutboxCronConfig()\n private readonly moduleConfig: TypeormOutboxRegisterCronModuleOptions,\n private readonly dataSource: DataSource,\n ) { }\n\n onModuleInit() {\n const cronJob = new CronJob(this.moduleConfig.cronExpression ?? CronExpression.EVERY_SECOND, () => {\n this.executeCronJob();\n });\n cronJob.start();\n }\n\n async executeCronJob() {\n const queryRunner = this.dataSource.createQueryRunner();\n await queryRunner.connect();\n const lockKey = hashStringToInt('typeorm-outbox-cron-lock');\n\n try {\n const lockResult = await queryRunner.query(\n 'SELECT pg_try_advisory_lock($1) as locked',\n [lockKey],\n );\n\n if (!lockResult[0].locked) {\n return;\n }\n try {\n await queryRunner.startTransaction('REPEATABLE READ');\n \n const entities = await queryRunner.manager.find(TypeormOutboxEntity, {\n order: {\n createdAt: 'ASC',\n },\n });\n \n for (const entity of entities) {\n await firstValueFrom(\n this.brokerClient.emit(entity.destinationTopic, {\n key: entity.keys,\n value: entity.payload,\n headers: entity.headers,\n }),\n );\n await queryRunner.manager.delete(TypeormOutboxEntity, entity.id);\n }\n\n await queryRunner.commitTransaction();\n } catch (error) {\n await queryRunner.rollbackTransaction();\n throw error;\n } finally {\n await queryRunner.query('SELECT pg_advisory_unlock($1)', [lockKey]);\n }\n } finally {\n await queryRunner.release();\n }\n }\n}\n","import { Injectable } from \"@nestjs/common\";\nimport { InjectRepository } from \"@nestjs/typeorm\";\nimport { TypeormOutboxEntity } from \"./typeorm-outbox.entity\";\nimport { Repository } from \"typeorm\";\n\nexport interface CreateOutboxOptions {\n destinationTopic: string;\n payload: Record<string, unknown>;\n headers?: Record<string, string>;\n keys?: Record<string, unknown>;\n}\n\n@Injectable()\nexport class TypeormOutboxService {\n constructor(\n @InjectRepository(TypeormOutboxEntity)\n private readonly outboxRepository: Repository<TypeormOutboxEntity>,\n ) {}\n\n async create(options: CreateOutboxOptions): Promise<TypeormOutboxEntity> {\n return this.outboxRepository.save({\n destinationTopic: options.destinationTopic,\n headers: options.headers,\n keys: options.keys,\n payload: options.payload,\n });\n }\n}\n","import { TypeOrmModule } from \"@nestjs/typeorm\";\nimport { DynamicModule, Module, Provider } from \"@nestjs/common\";\nimport {\n TypeormOutboxRegisterCronAsyncOptions,\n TypeormOutboxRegisterCronModuleOptions,\n TypeormOutboxModuleOptions,\n TypeormOutboxModuleAsyncOptions,\n} from \"./typeorm-outbox.interfaces\";\nimport {\n TYPEORM_OUTBOX_BROKER_TOKEN,\n TYPEORM_OUTBOX_CRON_CONFIG_TOKEN,\n TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN,\n TYPEORM_OUTBOX_SERVICE_TOKEN,\n} from \"./typeorm-outbox.di-tokens\";\nimport { TypeormOutboxEntity } from \"./typeorm-outbox.entity\";\nimport { TypeormOutboxService } from \"./typeorm-outbox.service\";\nimport { ClientProxyFactory } from \"@nestjs/microservices\";\nimport { TypeormOutboxCronService } from \"./typeorm-outbox-cron.service\";\n\n@Module({})\nexport class TypeormOutboxModule {\n private static createServiceProvider(): Provider {\n return {\n provide: TYPEORM_OUTBOX_SERVICE_TOKEN,\n useClass: TypeormOutboxService,\n };\n }\n\n private static createBrokerProvider(useValue: unknown = null): Provider {\n return {\n provide: TYPEORM_OUTBOX_BROKER_TOKEN,\n useValue,\n };\n }\n\n private static createTypeOrmFeature(connectionName?: string) {\n return TypeOrmModule.forFeature(\n [TypeormOutboxEntity],\n connectionName || \"default\",\n );\n }\n\n private static createModuleConfigProvider(\n options: TypeormOutboxModuleOptions,\n ): Provider {\n return {\n provide: TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN,\n useValue: {\n ...new TypeormOutboxModuleOptions(),\n ...options,\n },\n };\n }\n\n private static createAsyncModuleConfigProvider(\n options: TypeormOutboxModuleAsyncOptions,\n ): Provider {\n return {\n provide: TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN,\n useFactory: async (...args: unknown[]) => {\n const moduleOptions = (await options.useFactory?.(...args)) as\n | TypeormOutboxModuleOptions;\n \n return {\n ...new TypeormOutboxModuleOptions(),\n ...moduleOptions,\n };\n },\n inject: options.inject || [],\n };\n }\n\n private static createCronConfigProvider(\n options: TypeormOutboxRegisterCronAsyncOptions,\n ): Provider {\n return {\n provide: TYPEORM_OUTBOX_CRON_CONFIG_TOKEN,\n useFactory: async (...args: unknown[]) => {\n const moduleOptions = await options.useFactory?.(...args);\n return {\n ...new TypeormOutboxRegisterCronModuleOptions(),\n ...moduleOptions,\n };\n },\n inject: options.inject || [],\n };\n }\n\n private static createCronBrokerProvider(\n options: TypeormOutboxRegisterCronAsyncOptions,\n ): Provider {\n return {\n provide: TYPEORM_OUTBOX_BROKER_TOKEN,\n useFactory: async (...args: unknown[]) => {\n const moduleOptions = await options.useFactory?.(...args);\n const config = {\n ...new TypeormOutboxRegisterCronModuleOptions(),\n ...moduleOptions,\n };\n return ClientProxyFactory.create(config?.brokerConfig ?? {});\n },\n inject: options.inject || [],\n };\n }\n\n static forRoot(options: TypeormOutboxModuleOptions = {}): DynamicModule {\n const configProvider = this.createModuleConfigProvider(options);\n const serviceProvider = this.createServiceProvider();\n const brokerProvider = this.createBrokerProvider();\n const PROVIDERS = [configProvider, serviceProvider, brokerProvider];\n\n return {\n module: TypeormOutboxModule,\n global: true,\n imports: [this.createTypeOrmFeature(options.typeOrmConnectionName)],\n providers: [...PROVIDERS],\n exports: [...PROVIDERS],\n };\n }\n\n static forRootAsync(\n options: TypeormOutboxModuleAsyncOptions,\n ): DynamicModule {\n const configProvider = this.createAsyncModuleConfigProvider(options);\n const serviceProvider = this.createServiceProvider();\n const brokerProvider = this.createBrokerProvider();\n\n return {\n module: TypeormOutboxModule,\n global: true,\n imports: [this.createTypeOrmFeature()],\n providers: [configProvider, serviceProvider, brokerProvider],\n exports: [configProvider, serviceProvider, brokerProvider],\n };\n }\n\n static registerCronAsync(\n options: TypeormOutboxRegisterCronAsyncOptions,\n ): DynamicModule {\n const configProvider = this.createCronConfigProvider(options);\n const brokerProvider = this.createCronBrokerProvider(options);\n const serviceProvider = this.createServiceProvider();\n\n return {\n module: TypeormOutboxModule,\n global: true,\n imports: [\n this.createTypeOrmFeature(),\n ],\n providers: [\n TypeormOutboxCronService,\n configProvider,\n brokerProvider,\n serviceProvider,\n ],\n exports: [configProvider, brokerProvider, serviceProvider],\n };\n }\n}\n"],"mappings":";;;;;;;;;AAEA,MAAa,mCAAmC,OAC9C,mCACD;AACD,MAAa,qCAAqC,OAChD,qCACD;AACD,MAAa,+BAA+B,OAC1C,+BACD;AACD,MAAa,8BAA8B,OACzC,8BACD;AAED,MAAa,iEACJ,iCAAiC;AAC1C,MAAa,mEACJ,mCAAmC;AAC5C,MAAa,8DACJ,6BAA6B;AACtC,MAAa,6DACJ,4BAA4B;;;;;;;;;;;;;;;;;;;;ACb9B,gCAAM,oBAAoB;CAC/B,AACA;CAEA,AACA;CAEA,AACA;CAEA,AACA;CAEA,AACA;CAEA,AACA;CAEA,AACA;;iDAnByB;0CAGP,EAAE,MAAM,cAAc,CAAC;0CAGvB,EAAE,MAAM,cAAc,CAAC;gCAGjC,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;gCAGnD,SAAS,EAAE,UAAU,MAAM,CAAC;gCAG5B,SAAS,EAAE,UAAU,MAAM,CAAC;gCAG5B,QAAQ;sDApBV,SAAS;;;;ACRjB,IAAY,0DAAL;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;ACtDF,IAAa,yCAAb,MAAoD;CAClD,eAA6B,EAAE;CAC/B,wBAAiC;CACjC,iBAA0B,eAAe;;AAe3C,IAAa,6BAAb,MAAwC;CACtC,wBAAiC;;;;;;;;;;;;;;ACb5B,qCAAM,yBAAiD;CAC5D,YACE,AACiB,cACjB,AACiB,cACjB,AAAiB,YACjB;EAJiB;EAEA;EACA;;CAGnB,eAAe;AAIb,EAHgB,IAAIA,aAAQ,KAAK,aAAa,kBAAkB,eAAe,oBAAoB;AACjG,QAAK,gBAAgB;IACrB,CACM,OAAO;;CAGjB,MAAM,iBAAiB;EACrB,MAAM,cAAc,KAAK,WAAW,mBAAmB;AACvD,QAAM,YAAY,SAAS;EAC3B,MAAM,qDAA0B,2BAA2B;AAE3D,MAAI;AAMF,OAAI,EALe,MAAM,YAAY,MACnC,6CACA,CAAC,QAAQ,CACV,EAEe,GAAG,OACjB;AAEF,OAAI;AACF,UAAM,YAAY,iBAAiB,kBAAkB;IAErD,MAAM,WAAW,MAAM,YAAY,QAAQ,KAAK,qBAAqB,EACnE,OAAO,EACL,WAAW,OACZ,EACF,CAAC;AAEF,SAAK,MAAM,UAAU,UAAU;AAC7B,oCACE,KAAK,aAAa,KAAK,OAAO,kBAAkB;MAC9C,KAAK,OAAO;MACZ,OAAO,OAAO;MACd,SAAS,OAAO;MACjB,CAAC,CACH;AACD,WAAM,YAAY,QAAQ,OAAO,qBAAqB,OAAO,GAAG;;AAGlE,UAAM,YAAY,mBAAmB;YAC9B,OAAO;AACd,UAAM,YAAY,qBAAqB;AACvC,UAAM;aACE;AACR,UAAM,YAAY,MAAM,iCAAiC,CAAC,QAAQ,CAAC;;YAE7D;AACR,SAAM,YAAY,SAAS;;;;;iCA3DpB;oBAGR,2BAA2B;oBAE3B,+BAA+B;;;;;;;;;;;ACH7B,iCAAM,qBAAqB;CAChC,YACE,AACiB,kBACjB;EADiB;;CAGnB,MAAM,OAAO,SAA4D;AACvE,SAAO,KAAK,iBAAiB,KAAK;GAChC,kBAAkB,QAAQ;GAC1B,SAAS,QAAQ;GACjB,MAAM,QAAQ;GACd,SAAS,QAAQ;GAClB,CAAC;;;;iCAbO;0DAGS,oBAAoB;;;;;;;ACKnC,uDAAM,oBAAoB;CAC/B,OAAe,wBAAkC;AAC/C,SAAO;GACL,SAAS;GACT,UAAU;GACX;;CAGH,OAAe,qBAAqB,WAAoB,MAAgB;AACtE,SAAO;GACL,SAAS;GACT;GACD;;CAGH,OAAe,qBAAqB,gBAAyB;AAC3D,SAAOC,8BAAc,WACnB,CAAC,oBAAoB,EACrB,kBAAkB,UACnB;;CAGH,OAAe,2BACb,SACU;AACV,SAAO;GACL,SAAS;GACT,UAAU;IACR,GAAG,IAAI,4BAA4B;IACnC,GAAG;IACJ;GACF;;CAGH,OAAe,gCACb,SACU;AACV,SAAO;GACL,SAAS;GACT,YAAY,OAAO,GAAG,SAAoB;IACxC,MAAM,gBAAiB,MAAM,QAAQ,aAAa,GAAG,KAAK;AAG1D,WAAO;KACL,GAAG,IAAI,4BAA4B;KACnC,GAAG;KACJ;;GAEH,QAAQ,QAAQ,UAAU,EAAE;GAC7B;;CAGH,OAAe,yBACb,SACU;AACV,SAAO;GACL,SAAS;GACT,YAAY,OAAO,GAAG,SAAoB;IACxC,MAAM,gBAAgB,MAAM,QAAQ,aAAa,GAAG,KAAK;AACzD,WAAO;KACL,GAAG,IAAI,wCAAwC;KAC/C,GAAG;KACJ;;GAEH,QAAQ,QAAQ,UAAU,EAAE;GAC7B;;CAGH,OAAe,yBACb,SACU;AACV,SAAO;GACL,SAAS;GACT,YAAY,OAAO,GAAG,SAAoB;IACxC,MAAM,gBAAgB,MAAM,QAAQ,aAAa,GAAG,KAAK;IACzD,MAAM,SAAS;KACb,GAAG,IAAI,wCAAwC;KAC/C,GAAG;KACJ;AACD,WAAOC,yCAAmB,OAAO,QAAQ,gBAAgB,EAAE,CAAC;;GAE9D,QAAQ,QAAQ,UAAU,EAAE;GAC7B;;CAGH,OAAO,QAAQ,UAAsC,EAAE,EAAiB;EAItE,MAAM,YAAY;GAHK,KAAK,2BAA2B,QAAQ;GACvC,KAAK,uBAAuB;GAC7B,KAAK,sBAAsB;GACiB;AAEnE,SAAO;GACL;GACA,QAAQ;GACR,SAAS,CAAC,KAAK,qBAAqB,QAAQ,sBAAsB,CAAC;GACnE,WAAW,CAAC,GAAG,UAAU;GACzB,SAAS,CAAC,GAAG,UAAU;GACxB;;CAGH,OAAO,aACL,SACe;EACf,MAAM,iBAAiB,KAAK,gCAAgC,QAAQ;EACpE,MAAM,kBAAkB,KAAK,uBAAuB;EACpD,MAAM,iBAAiB,KAAK,sBAAsB;AAElD,SAAO;GACL;GACA,QAAQ;GACR,SAAS,CAAC,KAAK,sBAAsB,CAAC;GACtC,WAAW;IAAC;IAAgB;IAAiB;IAAe;GAC5D,SAAS;IAAC;IAAgB;IAAiB;IAAe;GAC3D;;CAGH,OAAO,kBACL,SACe;EACf,MAAM,iBAAiB,KAAK,yBAAyB,QAAQ;EAC7D,MAAM,iBAAiB,KAAK,yBAAyB,QAAQ;EAC7D,MAAM,kBAAkB,KAAK,uBAAuB;AAEpD,SAAO;GACL;GACA,QAAQ;GACR,SAAS,CACP,KAAK,sBAAsB,CAC5B;GACD,WAAW;IACT;IACA;IACA;IACA;IACD;GACD,SAAS;IAAC;IAAgB;IAAgB;IAAgB;GAC3D;;;oFAzIG,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["CronJob","Transport","TypeOrmModule","ClientProxyFactory"],"sources":["../src/core/typeorm-outbox.di-tokens.ts","../src/core/typeorm-outbox.entity.ts","../src/core/typeorm-outbox.enums.ts","../src/core/typeorm-outbox.interfaces.ts","../src/core/typeorm-outbox-cron.service.ts","../src/core/typeorm-outbox.service.ts","../src/core/typeorm-outbox.module.ts"],"sourcesContent":["import { Inject } from \"@nestjs/common\";\n\nexport const TYPEORM_OUTBOX_CRON_CONFIG_TOKEN = Symbol(\n \"TYPEORM_OUTBOX_CRON_CONFIG_TOKEN\",\n);\nexport const TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN = Symbol(\n \"TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN\",\n);\nexport const TYPEORM_OUTBOX_SERVICE_TOKEN = Symbol(\n \"TYPEORM_OUTBOX_SERVICE_TOKEN\",\n);\nexport const TYPEORM_OUTBOX_BROKER_TOKEN = Symbol(\n \"TYPEORM_OUTBOX_BROKER_TOKEN\",\n);\n\nexport const InjectTypeormOutboxCronConfig = () =>\n Inject(TYPEORM_OUTBOX_CRON_CONFIG_TOKEN);\nexport const InjectTypeormOutboxModuleConfig = () =>\n Inject(TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN);\nexport const InjectTypeormOutboxService = () =>\n Inject(TYPEORM_OUTBOX_SERVICE_TOKEN);\nexport const InjectTypeormOutboxBroker = () =>\n Inject(TYPEORM_OUTBOX_BROKER_TOKEN);\n","import {\n Column,\n CreateDateColumn,\n Entity,\n PrimaryGeneratedColumn,\n UpdateDateColumn,\n} from \"typeorm\";\n\n@Entity('outbox')\nexport class TypeormOutboxEntity {\n @PrimaryGeneratedColumn()\n id!: number;\n\n @CreateDateColumn({ name: 'created_at' })\n createdAt!: Date;\n\n @UpdateDateColumn({ name: 'updated_at' })\n updatedAt!: Date;\n\n @Column(\"character varying\", { name: 'destination_topic' })\n destinationTopic!: string;\n\n @Column(\"jsonb\", { nullable: true })\n headers!: Record<string, string>;\n\n @Column(\"jsonb\", { nullable: true })\n keys!: Record<string, unknown>;\n\n @Column(\"jsonb\")\n payload!: Record<string, any>;\n}\n","export enum CronExpression {\n EVERY_SECOND = \"* * * * * *\",\n EVERY_2_SECONDS = \"*/2 * * * * *\",\n EVERY_3_SECONDS = \"*/3 * * * * *\",\n EVERY_4_SECONDS = \"*/4 * * * * *\",\n EVERY_5_SECONDS = \"*/5 * * * * *\",\n EVERY_6_SECONDS = \"*/6 * * * * *\",\n EVERY_7_SECONDS = \"*/7 * * * * *\",\n EVERY_8_SECONDS = \"*/8 * * * * *\",\n EVERY_9_SECONDS = \"*/9 * * * * *\",\n EVERY_10_SECONDS = \"*/10 * * * * *\",\n EVERY_11_SECONDS = \"*/11 * * * * *\",\n EVERY_12_SECONDS = \"*/12 * * * * *\",\n EVERY_13_SECONDS = \"*/13 * * * * *\",\n EVERY_14_SECONDS = \"*/14 * * * * *\",\n EVERY_15_SECONDS = \"*/15 * * * * *\",\n EVERY_16_SECONDS = \"*/16 * * * * *\",\n EVERY_17_SECONDS = \"*/17 * * * * *\",\n EVERY_18_SECONDS = \"*/18 * * * * *\",\n EVERY_19_SECONDS = \"*/19 * * * * *\",\n EVERY_20_SECONDS = \"*/20 * * * * *\",\n EVERY_21_SECONDS = \"*/21 * * * * *\",\n EVERY_22_SECONDS = \"*/22 * * * * *\",\n EVERY_23_SECONDS = \"*/23 * * * * *\",\n EVERY_24_SECONDS = \"*/24 * * * * *\",\n EVERY_25_SECONDS = \"*/25 * * * * *\",\n EVERY_26_SECONDS = \"*/26 * * * * *\",\n EVERY_27_SECONDS = \"*/27 * * * * *\",\n EVERY_28_SECONDS = \"*/28 * * * * *\",\n EVERY_29_SECONDS = \"*/29 * * * * *\",\n EVERY_30_SECONDS = \"*/30 * * * * *\",\n EVERY_31_SECONDS = \"*/31 * * * * *\",\n EVERY_32_SECONDS = \"*/32 * * * * *\",\n EVERY_33_SECONDS = \"*/33 * * * * *\",\n EVERY_34_SECONDS = \"*/34 * * * * *\",\n EVERY_35_SECONDS = \"*/35 * * * * *\",\n EVERY_36_SECONDS = \"*/36 * * * * *\",\n EVERY_37_SECONDS = \"*/37 * * * * *\",\n EVERY_38_SECONDS = \"*/38 * * * * *\",\n EVERY_39_SECONDS = \"*/39 * * * * *\",\n EVERY_40_SECONDS = \"*/40 * * * * *\",\n EVERY_41_SECONDS = \"*/41 * * * * *\",\n EVERY_42_SECONDS = \"*/42 * * * * *\",\n EVERY_43_SECONDS = \"*/43 * * * * *\",\n EVERY_44_SECONDS = \"*/44 * * * * *\",\n EVERY_45_SECONDS = \"*/45 * * * * *\",\n EVERY_46_SECONDS = \"*/46 * * * * *\",\n EVERY_47_SECONDS = \"*/47 * * * * *\",\n EVERY_48_SECONDS = \"*/48 * * * * *\",\n EVERY_49_SECONDS = \"*/49 * * * * *\",\n EVERY_50_SECONDS = \"*/50 * * * * *\",\n EVERY_51_SECONDS = \"*/51 * * * * *\",\n EVERY_52_SECONDS = \"*/52 * * * * *\",\n EVERY_53_SECONDS = \"*/53 * * * * *\",\n EVERY_54_SECONDS = \"*/54 * * * * *\",\n EVERY_55_SECONDS = \"*/55 * * * * *\",\n EVERY_56_SECONDS = \"*/56 * * * * *\",\n EVERY_57_SECONDS = \"*/57 * * * * *\",\n EVERY_58_SECONDS = \"*/58 * * * * *\",\n EVERY_59_SECONDS = \"*/59 * * * * *\",\n EVERY_MINUTE = \"0 * * * * *\",\n}","import { KafkaOptions, MqttOptions, NatsOptions } from \"@nestjs/microservices\";\nimport { InjectionToken, ModuleMetadata, Type } from \"@nestjs/common\";\nimport { CronExpression } from \"./typeorm-outbox.enums\";\n\ntype BrokerConfig = MqttOptions | NatsOptions | KafkaOptions;\n\nexport class TypeormOutboxRegisterCronModuleOptions {\n brokerConfig: BrokerConfig = {};\n typeOrmConnectionName?: string = \"default\";\n cronExpression?: string = CronExpression.EVERY_SECOND;\n}\n\nexport interface TypeormOutboxRegisterCronAsyncOptions\n extends Pick<ModuleMetadata, \"imports\"> {\n inject?: InjectionToken[];\n useExisting?: Type<TypeormOutboxRegisterCronModuleOptions>;\n useClass?: Type<TypeormOutboxRegisterCronModuleOptions>;\n useFactory?: (\n ...args: unknown[]\n ) =>\n | Promise<TypeormOutboxRegisterCronModuleOptions>\n | TypeormOutboxRegisterCronModuleOptions;\n}\n\nexport class TypeormOutboxModuleOptions {\n typeOrmConnectionName?: string = \"default\";\n}\n\nexport interface TypeormOutboxModuleAsyncOptions\n extends Pick<ModuleMetadata, \"imports\"> {\n inject?: InjectionToken[];\n useFactory?: (\n ...args: unknown[]\n ) => Promise<TypeormOutboxModuleOptions> | TypeormOutboxModuleOptions;\n}\n","import {\n Injectable,\n OnApplicationBootstrap,\n OnModuleInit,\n} from \"@nestjs/common\";\nimport {\n InjectTypeormOutboxBroker,\n InjectTypeormOutboxCronConfig,\n} from \"./typeorm-outbox.di-tokens\";\nimport { hashStringToInt } from \"@globalart/text-utils\";\nimport { TypeormOutboxEntity } from \"./typeorm-outbox.entity\";\nimport { firstValueFrom } from \"rxjs\";\nimport { ClientProxy, Transport } from \"@nestjs/microservices\";\nimport { CronJob } from \"cron\";\nimport { TypeormOutboxRegisterCronModuleOptions } from \"./typeorm-outbox.interfaces\";\nimport { DataSource } from \"typeorm\";\nimport { CronExpression } from \"./typeorm-outbox.enums\";\n\n@Injectable()\nexport class TypeormOutboxCronService implements OnApplicationBootstrap {\n constructor(\n @InjectTypeormOutboxBroker()\n private readonly brokerClient: ClientProxy,\n @InjectTypeormOutboxCronConfig()\n private readonly moduleConfig: TypeormOutboxRegisterCronModuleOptions,\n private readonly dataSource: DataSource,\n ) {}\n\n onApplicationBootstrap() {\n this.validateBrokerClient();\n const cronJob = new CronJob(\n this.moduleConfig.cronExpression ?? CronExpression.EVERY_SECOND,\n () => {\n this.executeCronJob();\n },\n );\n cronJob.start();\n }\n\n private validateBrokerClient() {\n const brokerConfig = this.moduleConfig.brokerConfig;\n if (\n ![Transport.KAFKA, Transport.NATS, Transport.MQTT].includes(\n brokerConfig?.transport as Transport,\n )\n ) {\n throw new Error(\n `[TypeormOutboxCronService] Broker config must be an instance of KafkaOptions, NatsOptions, or MqttOptions`,\n );\n }\n }\n\n private async executeCronJob() {\n const queryRunner = this.dataSource.createQueryRunner();\n await queryRunner.connect();\n const lockKey = hashStringToInt(\"typeorm-outbox-cron-lock\");\n\n try {\n const lockResult = await queryRunner.query(\n \"SELECT pg_try_advisory_lock($1) as locked\",\n [lockKey],\n );\n\n if (!lockResult[0].locked) {\n return;\n }\n try {\n await queryRunner.startTransaction(\"REPEATABLE READ\");\n\n const entities = await queryRunner.manager.find(TypeormOutboxEntity, {\n order: {\n createdAt: \"ASC\",\n },\n });\n\n for (const entity of entities) {\n await firstValueFrom(\n this.brokerClient.emit(entity.destinationTopic, {\n key: entity.keys,\n value: entity.payload,\n headers: entity.headers,\n }),\n );\n await queryRunner.manager.delete(TypeormOutboxEntity, entity.id);\n }\n\n await queryRunner.commitTransaction();\n } catch (error) {\n await queryRunner.rollbackTransaction();\n throw error;\n } finally {\n await queryRunner.query(\"SELECT pg_advisory_unlock($1)\", [lockKey]);\n }\n } finally {\n await queryRunner.release();\n }\n }\n}\n","import { Injectable } from \"@nestjs/common\";\nimport { InjectRepository } from \"@nestjs/typeorm\";\nimport { TypeormOutboxEntity } from \"./typeorm-outbox.entity\";\nimport { Repository } from \"typeorm\";\n\nexport interface CreateOutboxOptions {\n destinationTopic: string;\n payload: Record<string, unknown>;\n headers?: Record<string, string>;\n keys?: Record<string, unknown>;\n}\n\n@Injectable()\nexport class TypeormOutboxService {\n constructor(\n @InjectRepository(TypeormOutboxEntity)\n private readonly outboxRepository: Repository<TypeormOutboxEntity>,\n ) {}\n\n async create(options: CreateOutboxOptions): Promise<TypeormOutboxEntity> {\n return this.outboxRepository.save({\n destinationTopic: options.destinationTopic,\n headers: options.headers,\n keys: options.keys,\n payload: options.payload,\n });\n }\n}\n","import { TypeOrmModule } from \"@nestjs/typeorm\";\nimport { DynamicModule, Module, Provider } from \"@nestjs/common\";\nimport {\n TypeormOutboxRegisterCronAsyncOptions,\n TypeormOutboxRegisterCronModuleOptions,\n TypeormOutboxModuleOptions,\n TypeormOutboxModuleAsyncOptions,\n} from \"./typeorm-outbox.interfaces\";\nimport {\n TYPEORM_OUTBOX_BROKER_TOKEN,\n TYPEORM_OUTBOX_CRON_CONFIG_TOKEN,\n TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN,\n TYPEORM_OUTBOX_SERVICE_TOKEN,\n} from \"./typeorm-outbox.di-tokens\";\nimport { TypeormOutboxEntity } from \"./typeorm-outbox.entity\";\nimport { TypeormOutboxService } from \"./typeorm-outbox.service\";\nimport { ClientProxyFactory } from \"@nestjs/microservices\";\nimport { TypeormOutboxCronService } from \"./typeorm-outbox-cron.service\";\n\n@Module({})\nexport class TypeormOutboxModule {\n private static createServiceProvider(): Provider {\n return {\n provide: TYPEORM_OUTBOX_SERVICE_TOKEN,\n useClass: TypeormOutboxService,\n };\n }\n\n private static createBrokerProvider(useValue: unknown = null): Provider {\n return {\n provide: TYPEORM_OUTBOX_BROKER_TOKEN,\n useValue,\n };\n }\n\n private static createTypeOrmFeature(connectionName?: string) {\n return TypeOrmModule.forFeature(\n [TypeormOutboxEntity],\n connectionName || \"default\",\n );\n }\n\n private static createModuleConfigProvider(\n options: TypeormOutboxModuleOptions,\n ): Provider {\n return {\n provide: TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN,\n useValue: {\n ...new TypeormOutboxModuleOptions(),\n ...options,\n },\n };\n }\n\n private static createAsyncModuleConfigProvider(\n options: TypeormOutboxModuleAsyncOptions,\n ): Provider {\n return {\n provide: TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN,\n useFactory: async (...args: unknown[]) => {\n const moduleOptions = (await options.useFactory?.(...args)) as\n | TypeormOutboxModuleOptions;\n \n return {\n ...new TypeormOutboxModuleOptions(),\n ...moduleOptions,\n };\n },\n inject: options.inject || [],\n };\n }\n\n private static createCronConfigProvider(\n options: TypeormOutboxRegisterCronAsyncOptions,\n ): Provider {\n return {\n provide: TYPEORM_OUTBOX_CRON_CONFIG_TOKEN,\n useFactory: async (...args: unknown[]) => {\n const moduleOptions = await options.useFactory?.(...args);\n return {\n ...new TypeormOutboxRegisterCronModuleOptions(),\n ...moduleOptions,\n };\n },\n inject: options.inject || [],\n };\n }\n\n private static createCronBrokerProvider(\n options: TypeormOutboxRegisterCronAsyncOptions,\n ): Provider {\n return {\n provide: TYPEORM_OUTBOX_BROKER_TOKEN,\n useFactory: async (...args: unknown[]) => {\n const moduleOptions = await options.useFactory?.(...args);\n const config = {\n ...new TypeormOutboxRegisterCronModuleOptions(),\n ...moduleOptions,\n };\n return ClientProxyFactory.create(config?.brokerConfig ?? {});\n },\n inject: options.inject || [],\n };\n }\n\n static forRoot(options: TypeormOutboxModuleOptions = {}): DynamicModule {\n const configProvider = this.createModuleConfigProvider(options);\n const serviceProvider = this.createServiceProvider();\n const brokerProvider = this.createBrokerProvider();\n const PROVIDERS = [configProvider, serviceProvider, brokerProvider];\n\n return {\n module: TypeormOutboxModule,\n global: true,\n imports: [this.createTypeOrmFeature(options.typeOrmConnectionName)],\n providers: [...PROVIDERS],\n exports: [...PROVIDERS],\n };\n }\n\n static forRootAsync(\n options: TypeormOutboxModuleAsyncOptions,\n ): DynamicModule {\n const configProvider = this.createAsyncModuleConfigProvider(options);\n const serviceProvider = this.createServiceProvider();\n const brokerProvider = this.createBrokerProvider();\n\n return {\n module: TypeormOutboxModule,\n global: true,\n imports: [this.createTypeOrmFeature()],\n providers: [configProvider, serviceProvider, brokerProvider],\n exports: [configProvider, serviceProvider, brokerProvider],\n };\n }\n\n static registerCronAsync(\n options: TypeormOutboxRegisterCronAsyncOptions,\n ): DynamicModule {\n const configProvider = this.createCronConfigProvider(options);\n const brokerProvider = this.createCronBrokerProvider(options);\n const serviceProvider = this.createServiceProvider();\n\n return {\n module: TypeormOutboxModule,\n global: true,\n imports: [\n this.createTypeOrmFeature(),\n ],\n providers: [\n TypeormOutboxCronService,\n configProvider,\n brokerProvider,\n serviceProvider,\n ],\n exports: [configProvider, brokerProvider, serviceProvider],\n };\n }\n}\n"],"mappings":"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"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DynamicModule, InjectionToken, ModuleMetadata,
|
|
1
|
+
import { DynamicModule, InjectionToken, ModuleMetadata, OnApplicationBootstrap, Type } from "@nestjs/common";
|
|
2
2
|
import { ClientProxy, KafkaOptions, MqttOptions, NatsOptions } from "@nestjs/microservices";
|
|
3
3
|
import { DataSource, Repository } from "typeorm";
|
|
4
4
|
|
|
@@ -24,13 +24,14 @@ interface TypeormOutboxModuleAsyncOptions extends Pick<ModuleMetadata, "imports"
|
|
|
24
24
|
}
|
|
25
25
|
//#endregion
|
|
26
26
|
//#region src/core/typeorm-outbox-cron.service.d.ts
|
|
27
|
-
declare class TypeormOutboxCronService implements
|
|
27
|
+
declare class TypeormOutboxCronService implements OnApplicationBootstrap {
|
|
28
28
|
private readonly brokerClient;
|
|
29
29
|
private readonly moduleConfig;
|
|
30
30
|
private readonly dataSource;
|
|
31
31
|
constructor(brokerClient: ClientProxy, moduleConfig: TypeormOutboxRegisterCronModuleOptions, dataSource: DataSource);
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
onApplicationBootstrap(): void;
|
|
33
|
+
private validateBrokerClient;
|
|
34
|
+
private executeCronJob;
|
|
34
35
|
}
|
|
35
36
|
//#endregion
|
|
36
37
|
//#region src/core/typeorm-outbox.di-tokens.d.ts
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DynamicModule, InjectionToken, ModuleMetadata,
|
|
1
|
+
import { DynamicModule, InjectionToken, ModuleMetadata, OnApplicationBootstrap, Type } from "@nestjs/common";
|
|
2
2
|
import { DataSource, Repository } from "typeorm";
|
|
3
3
|
import { ClientProxy, KafkaOptions, MqttOptions, NatsOptions } from "@nestjs/microservices";
|
|
4
4
|
|
|
@@ -24,13 +24,14 @@ interface TypeormOutboxModuleAsyncOptions extends Pick<ModuleMetadata, "imports"
|
|
|
24
24
|
}
|
|
25
25
|
//#endregion
|
|
26
26
|
//#region src/core/typeorm-outbox-cron.service.d.ts
|
|
27
|
-
declare class TypeormOutboxCronService implements
|
|
27
|
+
declare class TypeormOutboxCronService implements OnApplicationBootstrap {
|
|
28
28
|
private readonly brokerClient;
|
|
29
29
|
private readonly moduleConfig;
|
|
30
30
|
private readonly dataSource;
|
|
31
31
|
constructor(brokerClient: ClientProxy, moduleConfig: TypeormOutboxRegisterCronModuleOptions, dataSource: DataSource);
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
onApplicationBootstrap(): void;
|
|
33
|
+
private validateBrokerClient;
|
|
34
|
+
private executeCronJob;
|
|
34
35
|
}
|
|
35
36
|
//#endregion
|
|
36
37
|
//#region src/core/typeorm-outbox.di-tokens.d.ts
|
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { Inject, Injectable, Module } from "@nestjs/common";
|
|
|
2
2
|
import { hashStringToInt } from "@globalart/text-utils";
|
|
3
3
|
import { Column, CreateDateColumn, DataSource, Entity, PrimaryGeneratedColumn, Repository, UpdateDateColumn } from "typeorm";
|
|
4
4
|
import { firstValueFrom } from "rxjs";
|
|
5
|
-
import { ClientProxy, ClientProxyFactory } from "@nestjs/microservices";
|
|
5
|
+
import { ClientProxy, ClientProxyFactory, Transport } from "@nestjs/microservices";
|
|
6
6
|
import { CronJob } from "cron";
|
|
7
7
|
import { InjectRepository, TypeOrmModule } from "@nestjs/typeorm";
|
|
8
8
|
|
|
@@ -17,13 +17,13 @@ const InjectTypeormOutboxService = () => Inject(TYPEORM_OUTBOX_SERVICE_TOKEN);
|
|
|
17
17
|
const InjectTypeormOutboxBroker = () => Inject(TYPEORM_OUTBOX_BROKER_TOKEN);
|
|
18
18
|
|
|
19
19
|
//#endregion
|
|
20
|
-
//#region \0@oxc-project+runtime@0.
|
|
20
|
+
//#region \0@oxc-project+runtime@0.112.0/helpers/decorateMetadata.js
|
|
21
21
|
function __decorateMetadata(k, v) {
|
|
22
22
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
//#endregion
|
|
26
|
-
//#region \0@oxc-project+runtime@0.
|
|
26
|
+
//#region \0@oxc-project+runtime@0.112.0/helpers/decorate.js
|
|
27
27
|
function __decorate(decorators, target, key, desc) {
|
|
28
28
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
29
29
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -130,7 +130,7 @@ var TypeormOutboxModuleOptions = class {
|
|
|
130
130
|
};
|
|
131
131
|
|
|
132
132
|
//#endregion
|
|
133
|
-
//#region \0@oxc-project+runtime@0.
|
|
133
|
+
//#region \0@oxc-project+runtime@0.112.0/helpers/decorateParam.js
|
|
134
134
|
function __decorateParam(paramIndex, decorator) {
|
|
135
135
|
return function(target, key) {
|
|
136
136
|
decorator(target, key, paramIndex);
|
|
@@ -146,11 +146,20 @@ let TypeormOutboxCronService = class TypeormOutboxCronService {
|
|
|
146
146
|
this.moduleConfig = moduleConfig;
|
|
147
147
|
this.dataSource = dataSource;
|
|
148
148
|
}
|
|
149
|
-
|
|
149
|
+
onApplicationBootstrap() {
|
|
150
|
+
this.validateBrokerClient();
|
|
150
151
|
new CronJob(this.moduleConfig.cronExpression ?? CronExpression.EVERY_SECOND, () => {
|
|
151
152
|
this.executeCronJob();
|
|
152
153
|
}).start();
|
|
153
154
|
}
|
|
155
|
+
validateBrokerClient() {
|
|
156
|
+
const brokerConfig = this.moduleConfig.brokerConfig;
|
|
157
|
+
if (![
|
|
158
|
+
Transport.KAFKA,
|
|
159
|
+
Transport.NATS,
|
|
160
|
+
Transport.MQTT
|
|
161
|
+
].includes(brokerConfig?.transport)) throw new Error(`[TypeormOutboxCronService] Broker config must be an instance of KafkaOptions, NatsOptions, or MqttOptions`);
|
|
162
|
+
}
|
|
154
163
|
async executeCronJob() {
|
|
155
164
|
const queryRunner = this.dataSource.createQueryRunner();
|
|
156
165
|
await queryRunner.connect();
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/core/typeorm-outbox.di-tokens.ts","../src/core/typeorm-outbox.entity.ts","../src/core/typeorm-outbox.enums.ts","../src/core/typeorm-outbox.interfaces.ts","../src/core/typeorm-outbox-cron.service.ts","../src/core/typeorm-outbox.service.ts","../src/core/typeorm-outbox.module.ts"],"sourcesContent":["import { Inject } from \"@nestjs/common\";\n\nexport const TYPEORM_OUTBOX_CRON_CONFIG_TOKEN = Symbol(\n \"TYPEORM_OUTBOX_CRON_CONFIG_TOKEN\",\n);\nexport const TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN = Symbol(\n \"TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN\",\n);\nexport const TYPEORM_OUTBOX_SERVICE_TOKEN = Symbol(\n \"TYPEORM_OUTBOX_SERVICE_TOKEN\",\n);\nexport const TYPEORM_OUTBOX_BROKER_TOKEN = Symbol(\n \"TYPEORM_OUTBOX_BROKER_TOKEN\",\n);\n\nexport const InjectTypeormOutboxCronConfig = () =>\n Inject(TYPEORM_OUTBOX_CRON_CONFIG_TOKEN);\nexport const InjectTypeormOutboxModuleConfig = () =>\n Inject(TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN);\nexport const InjectTypeormOutboxService = () =>\n Inject(TYPEORM_OUTBOX_SERVICE_TOKEN);\nexport const InjectTypeormOutboxBroker = () =>\n Inject(TYPEORM_OUTBOX_BROKER_TOKEN);\n","import {\n Column,\n CreateDateColumn,\n Entity,\n PrimaryGeneratedColumn,\n UpdateDateColumn,\n} from \"typeorm\";\n\n@Entity('outbox')\nexport class TypeormOutboxEntity {\n @PrimaryGeneratedColumn()\n id!: number;\n\n @CreateDateColumn({ name: 'created_at' })\n createdAt!: Date;\n\n @UpdateDateColumn({ name: 'updated_at' })\n updatedAt!: Date;\n\n @Column(\"character varying\", { name: 'destination_topic' })\n destinationTopic!: string;\n\n @Column(\"jsonb\", { nullable: true })\n headers!: Record<string, string>;\n\n @Column(\"jsonb\", { nullable: true })\n keys!: Record<string, unknown>;\n\n @Column(\"jsonb\")\n payload!: Record<string, any>;\n}\n","export enum CronExpression {\n EVERY_SECOND = \"* * * * * *\",\n EVERY_2_SECONDS = \"*/2 * * * * *\",\n EVERY_3_SECONDS = \"*/3 * * * * *\",\n EVERY_4_SECONDS = \"*/4 * * * * *\",\n EVERY_5_SECONDS = \"*/5 * * * * *\",\n EVERY_6_SECONDS = \"*/6 * * * * *\",\n EVERY_7_SECONDS = \"*/7 * * * * *\",\n EVERY_8_SECONDS = \"*/8 * * * * *\",\n EVERY_9_SECONDS = \"*/9 * * * * *\",\n EVERY_10_SECONDS = \"*/10 * * * * *\",\n EVERY_11_SECONDS = \"*/11 * * * * *\",\n EVERY_12_SECONDS = \"*/12 * * * * *\",\n EVERY_13_SECONDS = \"*/13 * * * * *\",\n EVERY_14_SECONDS = \"*/14 * * * * *\",\n EVERY_15_SECONDS = \"*/15 * * * * *\",\n EVERY_16_SECONDS = \"*/16 * * * * *\",\n EVERY_17_SECONDS = \"*/17 * * * * *\",\n EVERY_18_SECONDS = \"*/18 * * * * *\",\n EVERY_19_SECONDS = \"*/19 * * * * *\",\n EVERY_20_SECONDS = \"*/20 * * * * *\",\n EVERY_21_SECONDS = \"*/21 * * * * *\",\n EVERY_22_SECONDS = \"*/22 * * * * *\",\n EVERY_23_SECONDS = \"*/23 * * * * *\",\n EVERY_24_SECONDS = \"*/24 * * * * *\",\n EVERY_25_SECONDS = \"*/25 * * * * *\",\n EVERY_26_SECONDS = \"*/26 * * * * *\",\n EVERY_27_SECONDS = \"*/27 * * * * *\",\n EVERY_28_SECONDS = \"*/28 * * * * *\",\n EVERY_29_SECONDS = \"*/29 * * * * *\",\n EVERY_30_SECONDS = \"*/30 * * * * *\",\n EVERY_31_SECONDS = \"*/31 * * * * *\",\n EVERY_32_SECONDS = \"*/32 * * * * *\",\n EVERY_33_SECONDS = \"*/33 * * * * *\",\n EVERY_34_SECONDS = \"*/34 * * * * *\",\n EVERY_35_SECONDS = \"*/35 * * * * *\",\n EVERY_36_SECONDS = \"*/36 * * * * *\",\n EVERY_37_SECONDS = \"*/37 * * * * *\",\n EVERY_38_SECONDS = \"*/38 * * * * *\",\n EVERY_39_SECONDS = \"*/39 * * * * *\",\n EVERY_40_SECONDS = \"*/40 * * * * *\",\n EVERY_41_SECONDS = \"*/41 * * * * *\",\n EVERY_42_SECONDS = \"*/42 * * * * *\",\n EVERY_43_SECONDS = \"*/43 * * * * *\",\n EVERY_44_SECONDS = \"*/44 * * * * *\",\n EVERY_45_SECONDS = \"*/45 * * * * *\",\n EVERY_46_SECONDS = \"*/46 * * * * *\",\n EVERY_47_SECONDS = \"*/47 * * * * *\",\n EVERY_48_SECONDS = \"*/48 * * * * *\",\n EVERY_49_SECONDS = \"*/49 * * * * *\",\n EVERY_50_SECONDS = \"*/50 * * * * *\",\n EVERY_51_SECONDS = \"*/51 * * * * *\",\n EVERY_52_SECONDS = \"*/52 * * * * *\",\n EVERY_53_SECONDS = \"*/53 * * * * *\",\n EVERY_54_SECONDS = \"*/54 * * * * *\",\n EVERY_55_SECONDS = \"*/55 * * * * *\",\n EVERY_56_SECONDS = \"*/56 * * * * *\",\n EVERY_57_SECONDS = \"*/57 * * * * *\",\n EVERY_58_SECONDS = \"*/58 * * * * *\",\n EVERY_59_SECONDS = \"*/59 * * * * *\",\n EVERY_MINUTE = \"0 * * * * *\",\n}","import { KafkaOptions, MqttOptions, NatsOptions } from \"@nestjs/microservices\";\nimport { InjectionToken, ModuleMetadata, Type } from \"@nestjs/common\";\nimport { CronExpression } from \"./typeorm-outbox.enums\";\n\ntype BrokerConfig = MqttOptions | NatsOptions | KafkaOptions;\n\nexport class TypeormOutboxRegisterCronModuleOptions {\n brokerConfig: BrokerConfig = {};\n typeOrmConnectionName?: string = \"default\";\n cronExpression?: string = CronExpression.EVERY_SECOND;\n}\n\nexport interface TypeormOutboxRegisterCronAsyncOptions\n extends Pick<ModuleMetadata, \"imports\"> {\n inject?: InjectionToken[];\n useExisting?: Type<TypeormOutboxRegisterCronModuleOptions>;\n useClass?: Type<TypeormOutboxRegisterCronModuleOptions>;\n useFactory?: (\n ...args: unknown[]\n ) =>\n | Promise<TypeormOutboxRegisterCronModuleOptions>\n | TypeormOutboxRegisterCronModuleOptions;\n}\n\nexport class TypeormOutboxModuleOptions {\n typeOrmConnectionName?: string = \"default\";\n}\n\nexport interface TypeormOutboxModuleAsyncOptions\n extends Pick<ModuleMetadata, \"imports\"> {\n inject?: InjectionToken[];\n useFactory?: (\n ...args: unknown[]\n ) => Promise<TypeormOutboxModuleOptions> | TypeormOutboxModuleOptions;\n}\n","import { Injectable, OnModuleInit } from \"@nestjs/common\";\nimport { InjectTypeormOutboxBroker, InjectTypeormOutboxCronConfig } from \"./typeorm-outbox.di-tokens\";\nimport { hashStringToInt } from \"@globalart/text-utils\";\nimport { TypeormOutboxEntity } from \"./typeorm-outbox.entity\";\nimport { firstValueFrom } from \"rxjs\";\nimport { ClientProxy } from \"@nestjs/microservices\";\nimport { CronJob } from \"cron\";\nimport { TypeormOutboxRegisterCronModuleOptions } from \"./typeorm-outbox.interfaces\";\nimport { DataSource } from \"typeorm\";\nimport { CronExpression } from \"./typeorm-outbox.enums\";\n\n@Injectable()\nexport class TypeormOutboxCronService implements OnModuleInit {\n constructor(\n @InjectTypeormOutboxBroker()\n private readonly brokerClient: ClientProxy,\n @InjectTypeormOutboxCronConfig()\n private readonly moduleConfig: TypeormOutboxRegisterCronModuleOptions,\n private readonly dataSource: DataSource,\n ) { }\n\n onModuleInit() {\n const cronJob = new CronJob(this.moduleConfig.cronExpression ?? CronExpression.EVERY_SECOND, () => {\n this.executeCronJob();\n });\n cronJob.start();\n }\n\n async executeCronJob() {\n const queryRunner = this.dataSource.createQueryRunner();\n await queryRunner.connect();\n const lockKey = hashStringToInt('typeorm-outbox-cron-lock');\n\n try {\n const lockResult = await queryRunner.query(\n 'SELECT pg_try_advisory_lock($1) as locked',\n [lockKey],\n );\n\n if (!lockResult[0].locked) {\n return;\n }\n try {\n await queryRunner.startTransaction('REPEATABLE READ');\n \n const entities = await queryRunner.manager.find(TypeormOutboxEntity, {\n order: {\n createdAt: 'ASC',\n },\n });\n \n for (const entity of entities) {\n await firstValueFrom(\n this.brokerClient.emit(entity.destinationTopic, {\n key: entity.keys,\n value: entity.payload,\n headers: entity.headers,\n }),\n );\n await queryRunner.manager.delete(TypeormOutboxEntity, entity.id);\n }\n\n await queryRunner.commitTransaction();\n } catch (error) {\n await queryRunner.rollbackTransaction();\n throw error;\n } finally {\n await queryRunner.query('SELECT pg_advisory_unlock($1)', [lockKey]);\n }\n } finally {\n await queryRunner.release();\n }\n }\n}\n","import { Injectable } from \"@nestjs/common\";\nimport { InjectRepository } from \"@nestjs/typeorm\";\nimport { TypeormOutboxEntity } from \"./typeorm-outbox.entity\";\nimport { Repository } from \"typeorm\";\n\nexport interface CreateOutboxOptions {\n destinationTopic: string;\n payload: Record<string, unknown>;\n headers?: Record<string, string>;\n keys?: Record<string, unknown>;\n}\n\n@Injectable()\nexport class TypeormOutboxService {\n constructor(\n @InjectRepository(TypeormOutboxEntity)\n private readonly outboxRepository: Repository<TypeormOutboxEntity>,\n ) {}\n\n async create(options: CreateOutboxOptions): Promise<TypeormOutboxEntity> {\n return this.outboxRepository.save({\n destinationTopic: options.destinationTopic,\n headers: options.headers,\n keys: options.keys,\n payload: options.payload,\n });\n }\n}\n","import { TypeOrmModule } from \"@nestjs/typeorm\";\nimport { DynamicModule, Module, Provider } from \"@nestjs/common\";\nimport {\n TypeormOutboxRegisterCronAsyncOptions,\n TypeormOutboxRegisterCronModuleOptions,\n TypeormOutboxModuleOptions,\n TypeormOutboxModuleAsyncOptions,\n} from \"./typeorm-outbox.interfaces\";\nimport {\n TYPEORM_OUTBOX_BROKER_TOKEN,\n TYPEORM_OUTBOX_CRON_CONFIG_TOKEN,\n TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN,\n TYPEORM_OUTBOX_SERVICE_TOKEN,\n} from \"./typeorm-outbox.di-tokens\";\nimport { TypeormOutboxEntity } from \"./typeorm-outbox.entity\";\nimport { TypeormOutboxService } from \"./typeorm-outbox.service\";\nimport { ClientProxyFactory } from \"@nestjs/microservices\";\nimport { TypeormOutboxCronService } from \"./typeorm-outbox-cron.service\";\n\n@Module({})\nexport class TypeormOutboxModule {\n private static createServiceProvider(): Provider {\n return {\n provide: TYPEORM_OUTBOX_SERVICE_TOKEN,\n useClass: TypeormOutboxService,\n };\n }\n\n private static createBrokerProvider(useValue: unknown = null): Provider {\n return {\n provide: TYPEORM_OUTBOX_BROKER_TOKEN,\n useValue,\n };\n }\n\n private static createTypeOrmFeature(connectionName?: string) {\n return TypeOrmModule.forFeature(\n [TypeormOutboxEntity],\n connectionName || \"default\",\n );\n }\n\n private static createModuleConfigProvider(\n options: TypeormOutboxModuleOptions,\n ): Provider {\n return {\n provide: TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN,\n useValue: {\n ...new TypeormOutboxModuleOptions(),\n ...options,\n },\n };\n }\n\n private static createAsyncModuleConfigProvider(\n options: TypeormOutboxModuleAsyncOptions,\n ): Provider {\n return {\n provide: TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN,\n useFactory: async (...args: unknown[]) => {\n const moduleOptions = (await options.useFactory?.(...args)) as\n | TypeormOutboxModuleOptions;\n \n return {\n ...new TypeormOutboxModuleOptions(),\n ...moduleOptions,\n };\n },\n inject: options.inject || [],\n };\n }\n\n private static createCronConfigProvider(\n options: TypeormOutboxRegisterCronAsyncOptions,\n ): Provider {\n return {\n provide: TYPEORM_OUTBOX_CRON_CONFIG_TOKEN,\n useFactory: async (...args: unknown[]) => {\n const moduleOptions = await options.useFactory?.(...args);\n return {\n ...new TypeormOutboxRegisterCronModuleOptions(),\n ...moduleOptions,\n };\n },\n inject: options.inject || [],\n };\n }\n\n private static createCronBrokerProvider(\n options: TypeormOutboxRegisterCronAsyncOptions,\n ): Provider {\n return {\n provide: TYPEORM_OUTBOX_BROKER_TOKEN,\n useFactory: async (...args: unknown[]) => {\n const moduleOptions = await options.useFactory?.(...args);\n const config = {\n ...new TypeormOutboxRegisterCronModuleOptions(),\n ...moduleOptions,\n };\n return ClientProxyFactory.create(config?.brokerConfig ?? {});\n },\n inject: options.inject || [],\n };\n }\n\n static forRoot(options: TypeormOutboxModuleOptions = {}): DynamicModule {\n const configProvider = this.createModuleConfigProvider(options);\n const serviceProvider = this.createServiceProvider();\n const brokerProvider = this.createBrokerProvider();\n const PROVIDERS = [configProvider, serviceProvider, brokerProvider];\n\n return {\n module: TypeormOutboxModule,\n global: true,\n imports: [this.createTypeOrmFeature(options.typeOrmConnectionName)],\n providers: [...PROVIDERS],\n exports: [...PROVIDERS],\n };\n }\n\n static forRootAsync(\n options: TypeormOutboxModuleAsyncOptions,\n ): DynamicModule {\n const configProvider = this.createAsyncModuleConfigProvider(options);\n const serviceProvider = this.createServiceProvider();\n const brokerProvider = this.createBrokerProvider();\n\n return {\n module: TypeormOutboxModule,\n global: true,\n imports: [this.createTypeOrmFeature()],\n providers: [configProvider, serviceProvider, brokerProvider],\n exports: [configProvider, serviceProvider, brokerProvider],\n };\n }\n\n static registerCronAsync(\n options: TypeormOutboxRegisterCronAsyncOptions,\n ): DynamicModule {\n const configProvider = this.createCronConfigProvider(options);\n const brokerProvider = this.createCronBrokerProvider(options);\n const serviceProvider = this.createServiceProvider();\n\n return {\n module: TypeormOutboxModule,\n global: true,\n imports: [\n this.createTypeOrmFeature(),\n ],\n providers: [\n TypeormOutboxCronService,\n configProvider,\n brokerProvider,\n serviceProvider,\n ],\n exports: [configProvider, brokerProvider, serviceProvider],\n };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/core/typeorm-outbox.di-tokens.ts","../src/core/typeorm-outbox.entity.ts","../src/core/typeorm-outbox.enums.ts","../src/core/typeorm-outbox.interfaces.ts","../src/core/typeorm-outbox-cron.service.ts","../src/core/typeorm-outbox.service.ts","../src/core/typeorm-outbox.module.ts"],"sourcesContent":["import { Inject } from \"@nestjs/common\";\n\nexport const TYPEORM_OUTBOX_CRON_CONFIG_TOKEN = Symbol(\n \"TYPEORM_OUTBOX_CRON_CONFIG_TOKEN\",\n);\nexport const TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN = Symbol(\n \"TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN\",\n);\nexport const TYPEORM_OUTBOX_SERVICE_TOKEN = Symbol(\n \"TYPEORM_OUTBOX_SERVICE_TOKEN\",\n);\nexport const TYPEORM_OUTBOX_BROKER_TOKEN = Symbol(\n \"TYPEORM_OUTBOX_BROKER_TOKEN\",\n);\n\nexport const InjectTypeormOutboxCronConfig = () =>\n Inject(TYPEORM_OUTBOX_CRON_CONFIG_TOKEN);\nexport const InjectTypeormOutboxModuleConfig = () =>\n Inject(TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN);\nexport const InjectTypeormOutboxService = () =>\n Inject(TYPEORM_OUTBOX_SERVICE_TOKEN);\nexport const InjectTypeormOutboxBroker = () =>\n Inject(TYPEORM_OUTBOX_BROKER_TOKEN);\n","import {\n Column,\n CreateDateColumn,\n Entity,\n PrimaryGeneratedColumn,\n UpdateDateColumn,\n} from \"typeorm\";\n\n@Entity('outbox')\nexport class TypeormOutboxEntity {\n @PrimaryGeneratedColumn()\n id!: number;\n\n @CreateDateColumn({ name: 'created_at' })\n createdAt!: Date;\n\n @UpdateDateColumn({ name: 'updated_at' })\n updatedAt!: Date;\n\n @Column(\"character varying\", { name: 'destination_topic' })\n destinationTopic!: string;\n\n @Column(\"jsonb\", { nullable: true })\n headers!: Record<string, string>;\n\n @Column(\"jsonb\", { nullable: true })\n keys!: Record<string, unknown>;\n\n @Column(\"jsonb\")\n payload!: Record<string, any>;\n}\n","export enum CronExpression {\n EVERY_SECOND = \"* * * * * *\",\n EVERY_2_SECONDS = \"*/2 * * * * *\",\n EVERY_3_SECONDS = \"*/3 * * * * *\",\n EVERY_4_SECONDS = \"*/4 * * * * *\",\n EVERY_5_SECONDS = \"*/5 * * * * *\",\n EVERY_6_SECONDS = \"*/6 * * * * *\",\n EVERY_7_SECONDS = \"*/7 * * * * *\",\n EVERY_8_SECONDS = \"*/8 * * * * *\",\n EVERY_9_SECONDS = \"*/9 * * * * *\",\n EVERY_10_SECONDS = \"*/10 * * * * *\",\n EVERY_11_SECONDS = \"*/11 * * * * *\",\n EVERY_12_SECONDS = \"*/12 * * * * *\",\n EVERY_13_SECONDS = \"*/13 * * * * *\",\n EVERY_14_SECONDS = \"*/14 * * * * *\",\n EVERY_15_SECONDS = \"*/15 * * * * *\",\n EVERY_16_SECONDS = \"*/16 * * * * *\",\n EVERY_17_SECONDS = \"*/17 * * * * *\",\n EVERY_18_SECONDS = \"*/18 * * * * *\",\n EVERY_19_SECONDS = \"*/19 * * * * *\",\n EVERY_20_SECONDS = \"*/20 * * * * *\",\n EVERY_21_SECONDS = \"*/21 * * * * *\",\n EVERY_22_SECONDS = \"*/22 * * * * *\",\n EVERY_23_SECONDS = \"*/23 * * * * *\",\n EVERY_24_SECONDS = \"*/24 * * * * *\",\n EVERY_25_SECONDS = \"*/25 * * * * *\",\n EVERY_26_SECONDS = \"*/26 * * * * *\",\n EVERY_27_SECONDS = \"*/27 * * * * *\",\n EVERY_28_SECONDS = \"*/28 * * * * *\",\n EVERY_29_SECONDS = \"*/29 * * * * *\",\n EVERY_30_SECONDS = \"*/30 * * * * *\",\n EVERY_31_SECONDS = \"*/31 * * * * *\",\n EVERY_32_SECONDS = \"*/32 * * * * *\",\n EVERY_33_SECONDS = \"*/33 * * * * *\",\n EVERY_34_SECONDS = \"*/34 * * * * *\",\n EVERY_35_SECONDS = \"*/35 * * * * *\",\n EVERY_36_SECONDS = \"*/36 * * * * *\",\n EVERY_37_SECONDS = \"*/37 * * * * *\",\n EVERY_38_SECONDS = \"*/38 * * * * *\",\n EVERY_39_SECONDS = \"*/39 * * * * *\",\n EVERY_40_SECONDS = \"*/40 * * * * *\",\n EVERY_41_SECONDS = \"*/41 * * * * *\",\n EVERY_42_SECONDS = \"*/42 * * * * *\",\n EVERY_43_SECONDS = \"*/43 * * * * *\",\n EVERY_44_SECONDS = \"*/44 * * * * *\",\n EVERY_45_SECONDS = \"*/45 * * * * *\",\n EVERY_46_SECONDS = \"*/46 * * * * *\",\n EVERY_47_SECONDS = \"*/47 * * * * *\",\n EVERY_48_SECONDS = \"*/48 * * * * *\",\n EVERY_49_SECONDS = \"*/49 * * * * *\",\n EVERY_50_SECONDS = \"*/50 * * * * *\",\n EVERY_51_SECONDS = \"*/51 * * * * *\",\n EVERY_52_SECONDS = \"*/52 * * * * *\",\n EVERY_53_SECONDS = \"*/53 * * * * *\",\n EVERY_54_SECONDS = \"*/54 * * * * *\",\n EVERY_55_SECONDS = \"*/55 * * * * *\",\n EVERY_56_SECONDS = \"*/56 * * * * *\",\n EVERY_57_SECONDS = \"*/57 * * * * *\",\n EVERY_58_SECONDS = \"*/58 * * * * *\",\n EVERY_59_SECONDS = \"*/59 * * * * *\",\n EVERY_MINUTE = \"0 * * * * *\",\n}","import { KafkaOptions, MqttOptions, NatsOptions } from \"@nestjs/microservices\";\nimport { InjectionToken, ModuleMetadata, Type } from \"@nestjs/common\";\nimport { CronExpression } from \"./typeorm-outbox.enums\";\n\ntype BrokerConfig = MqttOptions | NatsOptions | KafkaOptions;\n\nexport class TypeormOutboxRegisterCronModuleOptions {\n brokerConfig: BrokerConfig = {};\n typeOrmConnectionName?: string = \"default\";\n cronExpression?: string = CronExpression.EVERY_SECOND;\n}\n\nexport interface TypeormOutboxRegisterCronAsyncOptions\n extends Pick<ModuleMetadata, \"imports\"> {\n inject?: InjectionToken[];\n useExisting?: Type<TypeormOutboxRegisterCronModuleOptions>;\n useClass?: Type<TypeormOutboxRegisterCronModuleOptions>;\n useFactory?: (\n ...args: unknown[]\n ) =>\n | Promise<TypeormOutboxRegisterCronModuleOptions>\n | TypeormOutboxRegisterCronModuleOptions;\n}\n\nexport class TypeormOutboxModuleOptions {\n typeOrmConnectionName?: string = \"default\";\n}\n\nexport interface TypeormOutboxModuleAsyncOptions\n extends Pick<ModuleMetadata, \"imports\"> {\n inject?: InjectionToken[];\n useFactory?: (\n ...args: unknown[]\n ) => Promise<TypeormOutboxModuleOptions> | TypeormOutboxModuleOptions;\n}\n","import {\n Injectable,\n OnApplicationBootstrap,\n OnModuleInit,\n} from \"@nestjs/common\";\nimport {\n InjectTypeormOutboxBroker,\n InjectTypeormOutboxCronConfig,\n} from \"./typeorm-outbox.di-tokens\";\nimport { hashStringToInt } from \"@globalart/text-utils\";\nimport { TypeormOutboxEntity } from \"./typeorm-outbox.entity\";\nimport { firstValueFrom } from \"rxjs\";\nimport { ClientProxy, Transport } from \"@nestjs/microservices\";\nimport { CronJob } from \"cron\";\nimport { TypeormOutboxRegisterCronModuleOptions } from \"./typeorm-outbox.interfaces\";\nimport { DataSource } from \"typeorm\";\nimport { CronExpression } from \"./typeorm-outbox.enums\";\n\n@Injectable()\nexport class TypeormOutboxCronService implements OnApplicationBootstrap {\n constructor(\n @InjectTypeormOutboxBroker()\n private readonly brokerClient: ClientProxy,\n @InjectTypeormOutboxCronConfig()\n private readonly moduleConfig: TypeormOutboxRegisterCronModuleOptions,\n private readonly dataSource: DataSource,\n ) {}\n\n onApplicationBootstrap() {\n this.validateBrokerClient();\n const cronJob = new CronJob(\n this.moduleConfig.cronExpression ?? CronExpression.EVERY_SECOND,\n () => {\n this.executeCronJob();\n },\n );\n cronJob.start();\n }\n\n private validateBrokerClient() {\n const brokerConfig = this.moduleConfig.brokerConfig;\n if (\n ![Transport.KAFKA, Transport.NATS, Transport.MQTT].includes(\n brokerConfig?.transport as Transport,\n )\n ) {\n throw new Error(\n `[TypeormOutboxCronService] Broker config must be an instance of KafkaOptions, NatsOptions, or MqttOptions`,\n );\n }\n }\n\n private async executeCronJob() {\n const queryRunner = this.dataSource.createQueryRunner();\n await queryRunner.connect();\n const lockKey = hashStringToInt(\"typeorm-outbox-cron-lock\");\n\n try {\n const lockResult = await queryRunner.query(\n \"SELECT pg_try_advisory_lock($1) as locked\",\n [lockKey],\n );\n\n if (!lockResult[0].locked) {\n return;\n }\n try {\n await queryRunner.startTransaction(\"REPEATABLE READ\");\n\n const entities = await queryRunner.manager.find(TypeormOutboxEntity, {\n order: {\n createdAt: \"ASC\",\n },\n });\n\n for (const entity of entities) {\n await firstValueFrom(\n this.brokerClient.emit(entity.destinationTopic, {\n key: entity.keys,\n value: entity.payload,\n headers: entity.headers,\n }),\n );\n await queryRunner.manager.delete(TypeormOutboxEntity, entity.id);\n }\n\n await queryRunner.commitTransaction();\n } catch (error) {\n await queryRunner.rollbackTransaction();\n throw error;\n } finally {\n await queryRunner.query(\"SELECT pg_advisory_unlock($1)\", [lockKey]);\n }\n } finally {\n await queryRunner.release();\n }\n }\n}\n","import { Injectable } from \"@nestjs/common\";\nimport { InjectRepository } from \"@nestjs/typeorm\";\nimport { TypeormOutboxEntity } from \"./typeorm-outbox.entity\";\nimport { Repository } from \"typeorm\";\n\nexport interface CreateOutboxOptions {\n destinationTopic: string;\n payload: Record<string, unknown>;\n headers?: Record<string, string>;\n keys?: Record<string, unknown>;\n}\n\n@Injectable()\nexport class TypeormOutboxService {\n constructor(\n @InjectRepository(TypeormOutboxEntity)\n private readonly outboxRepository: Repository<TypeormOutboxEntity>,\n ) {}\n\n async create(options: CreateOutboxOptions): Promise<TypeormOutboxEntity> {\n return this.outboxRepository.save({\n destinationTopic: options.destinationTopic,\n headers: options.headers,\n keys: options.keys,\n payload: options.payload,\n });\n }\n}\n","import { TypeOrmModule } from \"@nestjs/typeorm\";\nimport { DynamicModule, Module, Provider } from \"@nestjs/common\";\nimport {\n TypeormOutboxRegisterCronAsyncOptions,\n TypeormOutboxRegisterCronModuleOptions,\n TypeormOutboxModuleOptions,\n TypeormOutboxModuleAsyncOptions,\n} from \"./typeorm-outbox.interfaces\";\nimport {\n TYPEORM_OUTBOX_BROKER_TOKEN,\n TYPEORM_OUTBOX_CRON_CONFIG_TOKEN,\n TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN,\n TYPEORM_OUTBOX_SERVICE_TOKEN,\n} from \"./typeorm-outbox.di-tokens\";\nimport { TypeormOutboxEntity } from \"./typeorm-outbox.entity\";\nimport { TypeormOutboxService } from \"./typeorm-outbox.service\";\nimport { ClientProxyFactory } from \"@nestjs/microservices\";\nimport { TypeormOutboxCronService } from \"./typeorm-outbox-cron.service\";\n\n@Module({})\nexport class TypeormOutboxModule {\n private static createServiceProvider(): Provider {\n return {\n provide: TYPEORM_OUTBOX_SERVICE_TOKEN,\n useClass: TypeormOutboxService,\n };\n }\n\n private static createBrokerProvider(useValue: unknown = null): Provider {\n return {\n provide: TYPEORM_OUTBOX_BROKER_TOKEN,\n useValue,\n };\n }\n\n private static createTypeOrmFeature(connectionName?: string) {\n return TypeOrmModule.forFeature(\n [TypeormOutboxEntity],\n connectionName || \"default\",\n );\n }\n\n private static createModuleConfigProvider(\n options: TypeormOutboxModuleOptions,\n ): Provider {\n return {\n provide: TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN,\n useValue: {\n ...new TypeormOutboxModuleOptions(),\n ...options,\n },\n };\n }\n\n private static createAsyncModuleConfigProvider(\n options: TypeormOutboxModuleAsyncOptions,\n ): Provider {\n return {\n provide: TYPEORM_OUTBOX_MODULE_CONFIG_TOKEN,\n useFactory: async (...args: unknown[]) => {\n const moduleOptions = (await options.useFactory?.(...args)) as\n | TypeormOutboxModuleOptions;\n \n return {\n ...new TypeormOutboxModuleOptions(),\n ...moduleOptions,\n };\n },\n inject: options.inject || [],\n };\n }\n\n private static createCronConfigProvider(\n options: TypeormOutboxRegisterCronAsyncOptions,\n ): Provider {\n return {\n provide: TYPEORM_OUTBOX_CRON_CONFIG_TOKEN,\n useFactory: async (...args: unknown[]) => {\n const moduleOptions = await options.useFactory?.(...args);\n return {\n ...new TypeormOutboxRegisterCronModuleOptions(),\n ...moduleOptions,\n };\n },\n inject: options.inject || [],\n };\n }\n\n private static createCronBrokerProvider(\n options: TypeormOutboxRegisterCronAsyncOptions,\n ): Provider {\n return {\n provide: TYPEORM_OUTBOX_BROKER_TOKEN,\n useFactory: async (...args: unknown[]) => {\n const moduleOptions = await options.useFactory?.(...args);\n const config = {\n ...new TypeormOutboxRegisterCronModuleOptions(),\n ...moduleOptions,\n };\n return ClientProxyFactory.create(config?.brokerConfig ?? {});\n },\n inject: options.inject || [],\n };\n }\n\n static forRoot(options: TypeormOutboxModuleOptions = {}): DynamicModule {\n const configProvider = this.createModuleConfigProvider(options);\n const serviceProvider = this.createServiceProvider();\n const brokerProvider = this.createBrokerProvider();\n const PROVIDERS = [configProvider, serviceProvider, brokerProvider];\n\n return {\n module: TypeormOutboxModule,\n global: true,\n imports: [this.createTypeOrmFeature(options.typeOrmConnectionName)],\n providers: [...PROVIDERS],\n exports: [...PROVIDERS],\n };\n }\n\n static forRootAsync(\n options: TypeormOutboxModuleAsyncOptions,\n ): DynamicModule {\n const configProvider = this.createAsyncModuleConfigProvider(options);\n const serviceProvider = this.createServiceProvider();\n const brokerProvider = this.createBrokerProvider();\n\n return {\n module: TypeormOutboxModule,\n global: true,\n imports: [this.createTypeOrmFeature()],\n providers: [configProvider, serviceProvider, brokerProvider],\n exports: [configProvider, serviceProvider, brokerProvider],\n };\n }\n\n static registerCronAsync(\n options: TypeormOutboxRegisterCronAsyncOptions,\n ): DynamicModule {\n const configProvider = this.createCronConfigProvider(options);\n const brokerProvider = this.createCronBrokerProvider(options);\n const serviceProvider = this.createServiceProvider();\n\n return {\n module: TypeormOutboxModule,\n global: true,\n imports: [\n this.createTypeOrmFeature(),\n ],\n providers: [\n TypeormOutboxCronService,\n configProvider,\n brokerProvider,\n serviceProvider,\n ],\n exports: [configProvider, brokerProvider, serviceProvider],\n };\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@globalart/nestjs-typeorm-outbox",
|
|
3
3
|
"description": "TypeORM Outbox integration for NestJS",
|
|
4
|
-
"version": "1.1
|
|
4
|
+
"version": "1.2.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
7
7
|
"module": "dist/index.mjs",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@globalart/text-utils": "^1.0.5",
|
|
49
|
-
"@nestjs/common": "11.1.
|
|
50
|
-
"@nestjs/core": "11.1.
|
|
49
|
+
"@nestjs/common": "11.1.13",
|
|
50
|
+
"@nestjs/core": "11.1.13",
|
|
51
51
|
"@nestjs/microservices": "^11.1.12",
|
|
52
52
|
"@nestjs/typeorm": "^11.0.0",
|
|
53
53
|
"cron": "^4.4.0",
|
|
@@ -57,11 +57,11 @@
|
|
|
57
57
|
"typeorm": "^0.3.28"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@types/node": "25.
|
|
60
|
+
"@types/node": "25.2.3",
|
|
61
61
|
"prettier": "^3.8.1",
|
|
62
62
|
"reflect-metadata": "^0.2.2",
|
|
63
63
|
"release-it": "19.2.4",
|
|
64
|
-
"tsdown": "0.20.
|
|
64
|
+
"tsdown": "0.20.3",
|
|
65
65
|
"typescript": "^5.9.3"
|
|
66
66
|
}
|
|
67
67
|
}
|