@rsdk/kafka.producer.outbox.typeorm 1.0.13

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/CHANGELOG.md ADDED
@@ -0,0 +1,24 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ ## 1.0.13 (2023-06-06)
7
+
8
+ **Note:** Version bump only for package @rsdk/kafka.producer.outbox.typeorm
9
+
10
+ ## 1.0.12 (2023-05-23)
11
+
12
+ ### Bug Fixes
13
+
14
+ * remove private dependencies from `peerDependencies` section ([0bce6ff](https://github.com/R-Vision/rsdk/commit/0bce6ffb5b699e2ed1dc9aca77cbdbf085267ff7))
15
+
16
+ ## 1.0.11 (2023-05-23)
17
+
18
+ **Note:** Version bump only for package @rsdk/kafka.producer.outbox.typeorm
19
+
20
+ ## 1.0.10 (2023-05-22)
21
+
22
+ ### Bug Fixes
23
+
24
+ * add "access: public" to new packages ([04d5983](https://github.com/R-Vision/rsdk/commit/04d5983cfa3e97c5d8219e07208a0499a8c6bc83))
@@ -0,0 +1,2 @@
1
+ export { Outbox } from './outbox.entity';
2
+ export { TypeormOutboxProducer } from './typeorm-outbox.producer';
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TypeormOutboxProducer = exports.Outbox = void 0;
4
+ var outbox_entity_1 = require("./outbox.entity");
5
+ Object.defineProperty(exports, "Outbox", { enumerable: true, get: function () { return outbox_entity_1.Outbox; } });
6
+ var typeorm_outbox_producer_1 = require("./typeorm-outbox.producer");
7
+ Object.defineProperty(exports, "TypeormOutboxProducer", { enumerable: true, get: function () { return typeorm_outbox_producer_1.TypeormOutboxProducer; } });
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,iDAAyC;AAAhC,uGAAA,MAAM,OAAA;AACf,qEAAkE;AAAzD,gIAAA,qBAAqB,OAAA"}
@@ -0,0 +1,7 @@
1
+ import type { DocumentResolver } from '@rsdk/autodoc.protocol';
2
+ import { Composite } from '@rsdk/autodoc.protocol';
3
+ import type { RsdkMetadataProvider } from '@rsdk/metadata';
4
+ export declare class TypeormOutboxAutodocResolver implements DocumentResolver {
5
+ getNode(rsdkMetadataProvider: RsdkMetadataProvider): Composite | null;
6
+ }
7
+ export declare const typeormOutboxAutodocResolver: TypeormOutboxAutodocResolver;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.typeormOutboxAutodocResolver = exports.TypeormOutboxAutodocResolver = void 0;
4
+ const autodoc_protocol_1 = require("@rsdk/autodoc.protocol");
5
+ const constants_1 = require("./constants");
6
+ class TypeormOutboxAutodocResolver {
7
+ getNode(rsdkMetadataProvider) {
8
+ const resources = rsdkMetadataProvider.get(constants_1.TYPEORM_OUTBOX_RSDK_METADATA_SCOPE);
9
+ if (!resources) {
10
+ return null;
11
+ }
12
+ return new autodoc_protocol_1.Composite(new autodoc_protocol_1.Table(resources.map((resource) => {
13
+ const { $type, $group, $partitionKeyField } = resource.value.eventType;
14
+ return {
15
+ Type: $type,
16
+ Group: $group,
17
+ PartitionKeyField: $partitionKeyField ?? '-',
18
+ };
19
+ })), 'Kafka typeorm outbox');
20
+ }
21
+ }
22
+ exports.TypeormOutboxAutodocResolver = TypeormOutboxAutodocResolver;
23
+ exports.typeormOutboxAutodocResolver = new TypeormOutboxAutodocResolver();
24
+ //# sourceMappingURL=autodoc.resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autodoc.resolver.js","sourceRoot":"","sources":["../../src/metadata/autodoc.resolver.ts"],"names":[],"mappings":";;;AACA,6DAA0D;AAG1D,2CAAiE;AAGjE,MAAa,4BAA4B;IACvC,OAAO,CAAC,oBAA0C;QAChD,MAAM,SAAS,GAAG,oBAAoB,CAAC,GAAG,CACxC,8CAAkC,CACnC,CAAC;QAEF,IAAI,CAAC,SAAS,EAAE;YACd,OAAO,IAAI,CAAC;SACb;QAED,OAAO,IAAI,4BAAS,CAClB,IAAI,wBAAK,CACP,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;YACzB,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,GACzC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC;YAE3B,OAAO;gBACL,IAAI,EAAE,KAAK;gBACX,KAAK,EAAE,MAAM;gBACb,iBAAiB,EAAE,kBAAkB,IAAI,GAAG;aAC7C,CAAC;QACJ,CAAC,CAAC,CACH,EACD,sBAAsB,CACvB,CAAC;IACJ,CAAC;CACF;AA1BD,oEA0BC;AAEY,QAAA,4BAA4B,GAAG,IAAI,4BAA4B,EAAE,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const TYPEORM_OUTBOX_RSDK_METADATA_SCOPE = "kafka-producer-direct";
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TYPEORM_OUTBOX_RSDK_METADATA_SCOPE = void 0;
4
+ exports.TYPEORM_OUTBOX_RSDK_METADATA_SCOPE = 'kafka-producer-direct';
5
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/metadata/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,kCAAkC,GAAG,uBAAuB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { EventType } from '@rsdk/kafka.common';
2
+ export type RsdkTypeormOutboxMetadata = {
3
+ eventType: EventType;
4
+ eventData: Omit<EventType, 'toJSON'>;
5
+ };
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/metadata/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ /// <reference types="node" />
2
+ import type { OutboxTable } from '@rsdk/kafka.producer';
3
+ export declare class Outbox implements OutboxTable {
4
+ id: string;
5
+ type: string;
6
+ group: string;
7
+ partition_key: string;
8
+ metadata: Record<string, any> | null;
9
+ payload: Buffer;
10
+ }
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.Outbox = void 0;
13
+ const typeorm_1 = require("typeorm");
14
+ let Outbox = class Outbox {
15
+ id;
16
+ type;
17
+ group;
18
+ partition_key;
19
+ metadata;
20
+ payload;
21
+ };
22
+ __decorate([
23
+ (0, typeorm_1.PrimaryColumn)('uuid'),
24
+ __metadata("design:type", String)
25
+ ], Outbox.prototype, "id", void 0);
26
+ __decorate([
27
+ (0, typeorm_1.Column)({ nullable: false }),
28
+ __metadata("design:type", String)
29
+ ], Outbox.prototype, "type", void 0);
30
+ __decorate([
31
+ (0, typeorm_1.Column)({ nullable: false }),
32
+ __metadata("design:type", String)
33
+ ], Outbox.prototype, "group", void 0);
34
+ __decorate([
35
+ (0, typeorm_1.Column)({ nullable: false }),
36
+ __metadata("design:type", String)
37
+ ], Outbox.prototype, "partition_key", void 0);
38
+ __decorate([
39
+ (0, typeorm_1.Column)({ nullable: true, type: 'jsonb' }),
40
+ __metadata("design:type", Object)
41
+ ], Outbox.prototype, "metadata", void 0);
42
+ __decorate([
43
+ (0, typeorm_1.Column)({ nullable: false, type: 'bytea' }),
44
+ __metadata("design:type", Buffer)
45
+ ], Outbox.prototype, "payload", void 0);
46
+ Outbox = __decorate([
47
+ (0, typeorm_1.Entity)('outbox')
48
+ ], Outbox);
49
+ exports.Outbox = Outbox;
50
+ //# sourceMappingURL=outbox.entity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox.entity.js","sourceRoot":"","sources":["../src/outbox.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,qCAAwD;AAGxD,IAAa,MAAM,GAAnB,MAAa,MAAM;IAEjB,EAAE,CAAU;IAGZ,IAAI,CAAU;IAGd,KAAK,CAAU;IAGf,aAAa,CAAU;IAGvB,QAAQ,CAA8B;IAGtC,OAAO,CAAU;CAClB,CAAA;AAhBC;IADC,IAAA,uBAAa,EAAC,MAAM,CAAC;;kCACV;AAGZ;IADC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;;oCACd;AAGd;IADC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;;qCACb;AAGf;IADC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;;6CACL;AAGvB;IADC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;;wCACJ;AAGtC;IADC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;8BACjC,MAAM;uCAAC;AAjBN,MAAM;IADlB,IAAA,gBAAM,EAAC,QAAQ,CAAC;GACJ,MAAM,CAkBlB;AAlBY,wBAAM"}
@@ -0,0 +1,5 @@
1
+ import type { DynamicModule } from '@nestjs/common';
2
+ import type { EventType } from '@rsdk/kafka.common';
3
+ export declare class TypeormOutboxProducer {
4
+ static forEvent(eventType: EventType | EventType[]): DynamicModule;
5
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.TypeormOutboxProducer = void 0;
7
+ const typeorm_1 = require("@nestjs/typeorm");
8
+ const autodoc_protocol_1 = require("@rsdk/autodoc.protocol");
9
+ const metadata_1 = require("@rsdk/metadata");
10
+ const omit_1 = __importDefault(require("lodash/omit"));
11
+ const autodoc_resolver_1 = require("./metadata/autodoc.resolver");
12
+ const constants_1 = require("./metadata/constants");
13
+ const outbox_entity_1 = require("./outbox.entity");
14
+ const typeorm_producer_1 = require("./typeorm.producer");
15
+ class TypeormOutboxProducer {
16
+ static forEvent(eventType) {
17
+ const eventTypes = Array.isArray(eventType) ? eventType : [eventType];
18
+ const providers = eventTypes.map((eventType) => ({
19
+ inject: [(0, typeorm_1.getRepositoryToken)(outbox_entity_1.Outbox)],
20
+ provide: eventType.$type,
21
+ useFactory: (repository) => new typeorm_producer_1.TypeOrmProducer(eventType, repository),
22
+ }));
23
+ const moduleDef = {
24
+ imports: [typeorm_1.TypeOrmModule.forFeature([outbox_entity_1.Outbox])],
25
+ module: TypeormOutboxProducer,
26
+ providers,
27
+ exports: providers,
28
+ };
29
+ const rsdkMetadata = new metadata_1.RsdkMetadata(moduleDef, constants_1.TYPEORM_OUTBOX_RSDK_METADATA_SCOPE);
30
+ for (const eventType of eventTypes) {
31
+ rsdkMetadata.add({
32
+ eventType,
33
+ // Потому что https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#:~:text=If%20the%20value%20has%20a%20toJSON()%20method%2C%20it%27s%20responsible%20to%20define%20what%20data%20will%20be%20serialized.
34
+ eventData: (0, omit_1.default)(eventType, 'toJSON'),
35
+ });
36
+ }
37
+ autodoc_protocol_1.AutodocMetadata.defineResolver(moduleDef, constants_1.TYPEORM_OUTBOX_RSDK_METADATA_SCOPE, autodoc_resolver_1.typeormOutboxAutodocResolver);
38
+ return moduleDef;
39
+ }
40
+ }
41
+ exports.TypeormOutboxProducer = TypeormOutboxProducer;
42
+ //# sourceMappingURL=typeorm-outbox.producer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typeorm-outbox.producer.js","sourceRoot":"","sources":["../src/typeorm-outbox.producer.ts"],"names":[],"mappings":";;;;;;AACA,6CAAoE;AACpE,6DAAyD;AAEzD,6CAA8C;AAC9C,uDAA+B;AAG/B,kEAA2E;AAC3E,oDAA0E;AAE1E,mDAAyC;AACzC,yDAAqD;AAErD,MAAa,qBAAqB;IAChC,MAAM,CAAC,QAAQ,CAAC,SAAkC;QAChD,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAEtE,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YAC/C,MAAM,EAAE,CAAC,IAAA,4BAAkB,EAAC,sBAAM,CAAC,CAAC;YACpC,OAAO,EAAE,SAAS,CAAC,KAAK;YACxB,UAAU,EAAE,CACV,UAA8B,EACF,EAAE,CAC9B,IAAI,kCAAe,CAAC,SAAS,EAAE,UAAU,CAAC;SAC7C,CAAC,CAAC,CAAC;QAEJ,MAAM,SAAS,GAAG;YAChB,OAAO,EAAE,CAAC,uBAAa,CAAC,UAAU,CAAC,CAAC,sBAAM,CAAC,CAAC,CAAC;YAC7C,MAAM,EAAE,qBAAqB;YAC7B,SAAS;YACT,OAAO,EAAE,SAAS;SACnB,CAAC;QACF,MAAM,YAAY,GAAG,IAAI,uBAAY,CACnC,SAAS,EACT,8CAAkC,CACnC,CAAC;QAEF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE;YAClC,YAAY,CAAC,GAAG,CAAC;gBACf,SAAS;gBACT,oPAAoP;gBACpP,SAAS,EAAE,IAAA,cAAI,EAAC,SAAS,EAAE,QAAQ,CAAC;aACrC,CAAC,CAAC;SACJ;QAED,kCAAe,CAAC,cAAc,CAC5B,SAAS,EACT,8CAAkC,EAClC,+CAA4B,CAC7B,CAAC;QAEF,OAAO,SAAS,CAAC;IACnB,CAAC;CACF;AAxCD,sDAwCC"}
@@ -0,0 +1,11 @@
1
+ import type { EventType } from '@rsdk/kafka.common';
2
+ import type { PublishOptions } from '@rsdk/kafka.producer';
3
+ import { BaseProducer } from '@rsdk/kafka.producer';
4
+ import type { Repository } from 'typeorm';
5
+ import type { Outbox } from './outbox.entity';
6
+ export declare class TypeOrmProducer<T extends EventType> extends BaseProducer<T> {
7
+ readonly protoType: T;
8
+ private readonly outbox;
9
+ constructor(protoType: T, outbox: Repository<Outbox>);
10
+ publish(payload: T, options?: PublishOptions): Promise<void>;
11
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.TypeOrmProducer = void 0;
27
+ const crypto = __importStar(require("crypto"));
28
+ const kafka_producer_1 = require("@rsdk/kafka.producer");
29
+ class TypeOrmProducer extends kafka_producer_1.BaseProducer {
30
+ protoType;
31
+ outbox;
32
+ constructor(protoType, outbox) {
33
+ super(protoType);
34
+ this.protoType = protoType;
35
+ this.outbox = outbox;
36
+ }
37
+ async publish(payload, options) {
38
+ const value = this.parsePayload(payload, options);
39
+ await this.outbox.insert({ ...value, id: crypto.randomUUID() });
40
+ }
41
+ }
42
+ exports.TypeOrmProducer = TypeOrmProducer;
43
+ //# sourceMappingURL=typeorm.producer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typeorm.producer.js","sourceRoot":"","sources":["../src/typeorm.producer.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAiC;AAIjC,yDAAoD;AAKpD,MAAa,eAAqC,SAAQ,6BAAe;IAE5D;IACQ;IAFnB,YACW,SAAY,EACJ,MAA0B;QAE3C,KAAK,CAAC,SAAS,CAAC,CAAC;QAHR,cAAS,GAAT,SAAS,CAAG;QACJ,WAAM,GAAN,MAAM,CAAoB;IAG7C,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAU,EAAE,OAAwB;QAChD,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAElD,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAClE,CAAC;CACF;AAbD,0CAaC"}
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@rsdk/kafka.producer.outbox.typeorm",
3
+ "version": "1.0.13",
4
+ "description": "Producing messages to outbox table (on top of typeorm 0.3.*)",
5
+ "license": "Apache License 2.0",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "repository": {
10
+ "url": "https://github.com/R-Vision/rsdk"
11
+ },
12
+ "main": "dist/index.js",
13
+ "peerDependencies": {
14
+ "@nestjs/common": "^9.0.0",
15
+ "@nestjs/microservices": "^9.0.0",
16
+ "@nestjs/typeorm": "^9.0.0",
17
+ "@rsdk/autodoc.protocol": "^1.0.13",
18
+ "@rsdk/common": "^1.0.13",
19
+ "@rsdk/core": "^1.0.13",
20
+ "@rsdk/kafka.common": "^1.0.13",
21
+ "@rsdk/kafka.producer": "^1.0.13",
22
+ "@rsdk/logging": "^1.0.13",
23
+ "@rsdk/metadata": "^1.0.13",
24
+ "typeorm": "^0.3.12"
25
+ },
26
+ "dependencies": {
27
+ "lodash": "^4.17.21"
28
+ },
29
+ "gitHead": "1f40e539993d341b239f78bf2f8b29b44fae9c1e"
30
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { Outbox } from './outbox.entity';
2
+ export { TypeormOutboxProducer } from './typeorm-outbox.producer';
@@ -0,0 +1,36 @@
1
+ import type { DocumentResolver } from '@rsdk/autodoc.protocol';
2
+ import { Composite, Table } from '@rsdk/autodoc.protocol';
3
+ import type { RsdkMetadataProvider } from '@rsdk/metadata';
4
+
5
+ import { TYPEORM_OUTBOX_RSDK_METADATA_SCOPE } from './constants';
6
+ import type { RsdkTypeormOutboxMetadata } from './types';
7
+
8
+ export class TypeormOutboxAutodocResolver implements DocumentResolver {
9
+ getNode(rsdkMetadataProvider: RsdkMetadataProvider): Composite | null {
10
+ const resources = rsdkMetadataProvider.get<RsdkTypeormOutboxMetadata>(
11
+ TYPEORM_OUTBOX_RSDK_METADATA_SCOPE,
12
+ );
13
+
14
+ if (!resources) {
15
+ return null;
16
+ }
17
+
18
+ return new Composite(
19
+ new Table(
20
+ resources.map((resource) => {
21
+ const { $type, $group, $partitionKeyField } =
22
+ resource.value.eventType;
23
+
24
+ return {
25
+ Type: $type,
26
+ Group: $group,
27
+ PartitionKeyField: $partitionKeyField ?? '-',
28
+ };
29
+ }),
30
+ ),
31
+ 'Kafka typeorm outbox',
32
+ );
33
+ }
34
+ }
35
+
36
+ export const typeormOutboxAutodocResolver = new TypeormOutboxAutodocResolver();
@@ -0,0 +1 @@
1
+ export const TYPEORM_OUTBOX_RSDK_METADATA_SCOPE = 'kafka-producer-direct';
@@ -0,0 +1,6 @@
1
+ import type { EventType } from '@rsdk/kafka.common';
2
+
3
+ export type RsdkTypeormOutboxMetadata = {
4
+ eventType: EventType;
5
+ eventData: Omit<EventType, 'toJSON'>;
6
+ };
@@ -0,0 +1,23 @@
1
+ import type { OutboxTable } from '@rsdk/kafka.producer';
2
+ import { Column, Entity, PrimaryColumn } from 'typeorm';
3
+
4
+ @Entity('outbox')
5
+ export class Outbox implements OutboxTable {
6
+ @PrimaryColumn('uuid')
7
+ id!: string;
8
+
9
+ @Column({ nullable: false })
10
+ type!: string;
11
+
12
+ @Column({ nullable: false })
13
+ group!: string;
14
+
15
+ @Column({ nullable: false })
16
+ partition_key!: string;
17
+
18
+ @Column({ nullable: true, type: 'jsonb' })
19
+ metadata!: Record<string, any> | null;
20
+
21
+ @Column({ nullable: false, type: 'bytea' })
22
+ payload!: Buffer;
23
+ }
@@ -0,0 +1,55 @@
1
+ import type { DynamicModule } from '@nestjs/common';
2
+ import { getRepositoryToken, TypeOrmModule } from '@nestjs/typeorm';
3
+ import { AutodocMetadata } from '@rsdk/autodoc.protocol';
4
+ import type { EventType } from '@rsdk/kafka.common';
5
+ import { RsdkMetadata } from '@rsdk/metadata';
6
+ import omit from 'lodash/omit';
7
+ import type { Repository } from 'typeorm';
8
+
9
+ import { typeormOutboxAutodocResolver } from './metadata/autodoc.resolver';
10
+ import { TYPEORM_OUTBOX_RSDK_METADATA_SCOPE } from './metadata/constants';
11
+ import type { RsdkTypeormOutboxMetadata } from './metadata/types';
12
+ import { Outbox } from './outbox.entity';
13
+ import { TypeOrmProducer } from './typeorm.producer';
14
+
15
+ export class TypeormOutboxProducer {
16
+ static forEvent(eventType: EventType | EventType[]): DynamicModule {
17
+ const eventTypes = Array.isArray(eventType) ? eventType : [eventType];
18
+
19
+ const providers = eventTypes.map((eventType) => ({
20
+ inject: [getRepositoryToken(Outbox)],
21
+ provide: eventType.$type,
22
+ useFactory: (
23
+ repository: Repository<Outbox>,
24
+ ): TypeOrmProducer<EventType> =>
25
+ new TypeOrmProducer(eventType, repository),
26
+ }));
27
+
28
+ const moduleDef = {
29
+ imports: [TypeOrmModule.forFeature([Outbox])],
30
+ module: TypeormOutboxProducer,
31
+ providers,
32
+ exports: providers,
33
+ };
34
+ const rsdkMetadata = new RsdkMetadata<RsdkTypeormOutboxMetadata>(
35
+ moduleDef,
36
+ TYPEORM_OUTBOX_RSDK_METADATA_SCOPE,
37
+ );
38
+
39
+ for (const eventType of eventTypes) {
40
+ rsdkMetadata.add({
41
+ eventType,
42
+ // Потому что https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#:~:text=If%20the%20value%20has%20a%20toJSON()%20method%2C%20it%27s%20responsible%20to%20define%20what%20data%20will%20be%20serialized.
43
+ eventData: omit(eventType, 'toJSON'),
44
+ });
45
+ }
46
+
47
+ AutodocMetadata.defineResolver(
48
+ moduleDef,
49
+ TYPEORM_OUTBOX_RSDK_METADATA_SCOPE,
50
+ typeormOutboxAutodocResolver,
51
+ );
52
+
53
+ return moduleDef;
54
+ }
55
+ }
@@ -0,0 +1,23 @@
1
+ import * as crypto from 'crypto';
2
+
3
+ import type { EventType } from '@rsdk/kafka.common';
4
+ import type { PublishOptions } from '@rsdk/kafka.producer';
5
+ import { BaseProducer } from '@rsdk/kafka.producer';
6
+ import type { Repository } from 'typeorm';
7
+
8
+ import type { Outbox } from './outbox.entity';
9
+
10
+ export class TypeOrmProducer<T extends EventType> extends BaseProducer<T> {
11
+ constructor(
12
+ readonly protoType: T,
13
+ private readonly outbox: Repository<Outbox>,
14
+ ) {
15
+ super(protoType);
16
+ }
17
+
18
+ async publish(payload: T, options?: PublishOptions): Promise<void> {
19
+ const value = this.parsePayload(payload, options);
20
+
21
+ await this.outbox.insert({ ...value, id: crypto.randomUUID() });
22
+ }
23
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "@rsdk/tsconfig/base.json",
3
+ "compilerOptions": {
4
+ "declaration": true,
5
+ "outDir": "dist"
6
+ },
7
+ "include": ["src/**/*"],
8
+ "exclude": ["node_modules", "dist", "test", "**/*spec.ts"]
9
+ }