@privateaim/server-db-kit 0.8.26 → 0.8.28

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 CHANGED
@@ -1,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.8.28](https://github.com/PrivateAIM/hub/compare/v0.8.27...v0.8.28) (2026-02-26)
4
+
5
+
6
+ ### Features
7
+
8
+ * database migration capabilities ([#1437](https://github.com/PrivateAIM/hub/issues/1437)) ([ada0c8c](https://github.com/PrivateAIM/hub/commit/ada0c8c82c50d7ff999c60d7d6b8a6aea10064f0))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @privateaim/kit bumped from ^0.8.27 to ^0.8.28
16
+ * @privateaim/server-kit bumped from ^0.8.27 to ^0.8.28
17
+
18
+ ## [0.8.27](https://github.com/PrivateAIM/hub/compare/v0.8.26...v0.8.27) (2026-02-12)
19
+
20
+
21
+ ### Dependencies
22
+
23
+ * The following workspace dependencies were updated
24
+ * dependencies
25
+ * @privateaim/kit bumped from ^0.8.26 to ^0.8.27
26
+ * @privateaim/server-kit bumped from ^0.8.26 to ^0.8.27
27
+
3
28
  ## [0.8.26](https://github.com/PrivateAIM/hub/compare/v0.8.25...v0.8.26) (2026-02-11)
4
29
 
5
30
 
@@ -0,0 +1,2 @@
1
+ export * from './options.ts';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/data-source/index.ts"],"names":[],"mappings":"AAOA,cAAc,cAAc,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { DataSourceOptions } from 'typeorm';
2
+ export type DataSourceOptionsEntities = DataSourceOptions['entities'];
3
+ export type DataSourceOptionsSubscribers = DataSourceOptions['subscribers'];
4
+ export declare class DataSourceOptionsBuilder {
5
+ protected entities: DataSourceOptionsEntities;
6
+ protected subscribers: DataSourceOptionsSubscribers;
7
+ constructor();
8
+ buildWithEnv(): DataSourceOptions;
9
+ buildWith(options: DataSourceOptions): DataSourceOptions;
10
+ setEntities(entities: DataSourceOptionsEntities): void;
11
+ setSubscribers(subscribers: DataSourceOptionsSubscribers): void;
12
+ protected normalize(options: DataSourceOptions): DataSourceOptions;
13
+ }
14
+ //# sourceMappingURL=options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/data-source/options.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAQjD,MAAM,MAAM,yBAAyB,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;AACtE,MAAM,MAAM,4BAA4B,GAAG,iBAAiB,CAAC,aAAa,CAAC,CAAC;AAE5E,qBAAa,wBAAwB;IACjC,SAAS,CAAC,QAAQ,EAAG,yBAAyB,CAAC;IAE/C,SAAS,CAAC,WAAW,EAAG,4BAA4B,CAAC;;IAWrD,YAAY;IAUZ,SAAS,CAAC,OAAO,EAAE,iBAAiB;IAMpC,WAAW,CAAC,QAAQ,EAAE,yBAAyB;IAI/C,cAAc,CAAC,WAAW,EAAE,4BAA4B;IAMxD,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,iBAAiB,GAAI,iBAAiB;CA4CtE"}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
- export * from './subscriber';
1
+ export * from './data-source/index.ts';
2
+ export * from './subscriber/index.ts';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC"}
package/dist/index.mjs CHANGED
@@ -1,5 +1,72 @@
1
+ import { readDataSourceOptionsFromEnv, isCodeTransformation, CodeTransformation, transformFilePath } from 'typeorm-extension';
1
2
  import { DomainEventName } from '@privateaim/kit';
2
- import { useEntityEventPublisher } from '@privateaim/server-kit';
3
+ import { isEntityEventPublisherUsable, useEntityEventPublisher } from '@privateaim/server-kit';
4
+
5
+ class DataSourceOptionsBuilder {
6
+ entities;
7
+ subscribers;
8
+ // ------------------------------------------------------------------
9
+ constructor(){
10
+ this.entities = [];
11
+ this.subscribers = [];
12
+ }
13
+ // ------------------------------------------------------------------
14
+ buildWithEnv() {
15
+ const options = readDataSourceOptionsFromEnv();
16
+ if (!options) {
17
+ throw new Error('The database configuration could not be read from env variables.');
18
+ }
19
+ return this.normalize(options);
20
+ }
21
+ buildWith(options) {
22
+ return this.normalize(options);
23
+ }
24
+ // ------------------------------------------------------------------
25
+ setEntities(entities) {
26
+ this.entities = entities;
27
+ }
28
+ setSubscribers(subscribers) {
29
+ this.subscribers = subscribers;
30
+ }
31
+ // ------------------------------------------------------------------
32
+ normalize(options) {
33
+ if (options.type !== 'mysql' && options.type !== 'postgres' && options.type !== 'better-sqlite3') {
34
+ throw new Error(`The database type ${options.type} is not supported.`);
35
+ }
36
+ options = {
37
+ ...options,
38
+ logging: false,
39
+ entities: [
40
+ ...options.entities ? options.entities : [],
41
+ ...this.entities
42
+ ],
43
+ migrations: [],
44
+ migrationsTransactionMode: 'each',
45
+ subscribers: [
46
+ ...options.subscribers || [],
47
+ ...this.subscribers
48
+ ]
49
+ };
50
+ if (options.type === 'mysql' || options.type === 'postgres') {
51
+ let migrationPath = `src/database/migrations/${options.type}/*.{ts,js}`;
52
+ if (!isCodeTransformation(CodeTransformation.JUST_IN_TIME)) {
53
+ migrationPath = transformFilePath(migrationPath, './dist', './src');
54
+ }
55
+ Object.assign(options, {
56
+ migrations: [
57
+ migrationPath
58
+ ],
59
+ migrationsTransactionMode: 'all'
60
+ });
61
+ }
62
+ if (options.type === 'mysql') {
63
+ Object.assign(options, {
64
+ connectorPackage: 'mysql2'
65
+ });
66
+ }
67
+ return options;
68
+ }
69
+ }
3
70
 
4
71
  class BaseSubscriber {
5
72
  publisher;
@@ -7,7 +74,9 @@ class BaseSubscriber {
7
74
  refType;
8
75
  constructor(ctx){
9
76
  this.refType = ctx.refType;
10
- this.publisher = useEntityEventPublisher();
77
+ if (isEntityEventPublisherUsable()) {
78
+ this.publisher = useEntityEventPublisher();
79
+ }
11
80
  this.destinations = ctx.destinations;
12
81
  }
13
82
  async afterInsert(event) {
@@ -35,6 +104,9 @@ class BaseSubscriber {
35
104
  }
36
105
  }
37
106
  async publish(payload) {
107
+ if (!this.publisher) {
108
+ return;
109
+ }
38
110
  await this.publisher.safePublish({
39
111
  data: payload.data,
40
112
  dataPrevious: payload.dataPrevious,
@@ -49,5 +121,5 @@ class BaseSubscriber {
49
121
  }
50
122
  }
51
123
 
52
- export { BaseSubscriber };
124
+ export { BaseSubscriber, DataSourceOptionsBuilder };
53
125
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/subscriber/base.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { ObjectLiteral } from '@privateaim/kit';\nimport { DomainEventName } from '@privateaim/kit';\nimport type {\n EntityEventDestinations, EntityEventDestinationsFn,\n EntityEventPublisher,\n} from '@privateaim/server-kit';\nimport { useEntityEventPublisher } from '@privateaim/server-kit';\nimport type {\n EntitySubscriberInterface, InsertEvent, RemoveEvent, UpdateEvent,\n} from 'typeorm';\nimport type { BaseSubscriberContext, SubscriberPublishPayload } from './types';\n\nexport class BaseSubscriber<\n RECORD extends ObjectLiteral,\n> implements EntitySubscriberInterface<RECORD> {\n private readonly publisher: EntityEventPublisher;\n\n private readonly destinations : EntityEventDestinations | EntityEventDestinationsFn<RECORD>;\n\n private readonly refType: string;\n\n constructor(ctx: BaseSubscriberContext<RECORD>) {\n this.refType = ctx.refType;\n this.publisher = useEntityEventPublisher();\n this.destinations = ctx.destinations;\n }\n\n async afterInsert(event: InsertEvent<RECORD>): Promise<any> {\n await this.publish({\n data: event.entity,\n type: DomainEventName.CREATED,\n metadata: event.queryRunner.data,\n });\n }\n\n async afterUpdate(event: UpdateEvent<RECORD>): Promise<any> {\n await this.publish({\n type: DomainEventName.UPDATED,\n data: event.entity as RECORD,\n dataPrevious: event.databaseEntity,\n metadata: event.queryRunner.data,\n });\n }\n\n async beforeRemove(event: RemoveEvent<RECORD>): Promise<any> {\n if (event.entity) {\n await this.publish({\n type: DomainEventName.DELETED,\n data: event.entity as RECORD,\n metadata: event.queryRunner.data,\n });\n }\n }\n\n async publish(payload: SubscriberPublishPayload<RECORD>) {\n await this.publisher.safePublish({\n data: payload.data,\n dataPrevious: payload.dataPrevious,\n metadata: {\n ref_type: this.refType,\n ref_id: payload.data.id,\n\n event: payload.type,\n ...(payload.metadata ? payload.metadata : {}),\n },\n destinations: this.destinations,\n });\n }\n}\n"],"names":["BaseSubscriber","publisher","destinations","refType","ctx","useEntityEventPublisher","afterInsert","event","publish","data","entity","type","DomainEventName","CREATED","metadata","queryRunner","afterUpdate","UPDATED","dataPrevious","databaseEntity","beforeRemove","DELETED","payload","safePublish","ref_type","ref_id","id"],"mappings":";;;AAmBO,MAAMA,cAAAA,CAAAA;IAGQC,SAAAA;IAEAC,YAAAA;IAEAC,OAAAA;AAEjB,IAAA,WAAA,CAAYC,GAAkC,CAAE;AAC5C,QAAA,IAAI,CAACD,OAAO,GAAGC,GAAAA,CAAID,OAAO;QAC1B,IAAI,CAACF,SAAS,GAAGI,uBAAAA,EAAAA;AACjB,QAAA,IAAI,CAACH,YAAY,GAAGE,GAAAA,CAAIF,YAAY;AACxC,IAAA;IAEA,MAAMI,WAAAA,CAAYC,KAA0B,EAAgB;QACxD,MAAM,IAAI,CAACC,OAAO,CAAC;AACfC,YAAAA,IAAAA,EAAMF,MAAMG,MAAM;AAClBC,YAAAA,IAAAA,EAAMC,gBAAgBC,OAAO;YAC7BC,QAAAA,EAAUP,KAAAA,CAAMQ,WAAW,CAACN;AAChC,SAAA,CAAA;AACJ,IAAA;IAEA,MAAMO,WAAAA,CAAYT,KAA0B,EAAgB;QACxD,MAAM,IAAI,CAACC,OAAO,CAAC;AACfG,YAAAA,IAAAA,EAAMC,gBAAgBK,OAAO;AAC7BR,YAAAA,IAAAA,EAAMF,MAAMG,MAAM;AAClBQ,YAAAA,YAAAA,EAAcX,MAAMY,cAAc;YAClCL,QAAAA,EAAUP,KAAAA,CAAMQ,WAAW,CAACN;AAChC,SAAA,CAAA;AACJ,IAAA;IAEA,MAAMW,YAAAA,CAAab,KAA0B,EAAgB;QACzD,IAAIA,KAAAA,CAAMG,MAAM,EAAE;YACd,MAAM,IAAI,CAACF,OAAO,CAAC;AACfG,gBAAAA,IAAAA,EAAMC,gBAAgBS,OAAO;AAC7BZ,gBAAAA,IAAAA,EAAMF,MAAMG,MAAM;gBAClBI,QAAAA,EAAUP,KAAAA,CAAMQ,WAAW,CAACN;AAChC,aAAA,CAAA;AACJ,QAAA;AACJ,IAAA;IAEA,MAAMD,OAAAA,CAAQc,OAAyC,EAAE;AACrD,QAAA,MAAM,IAAI,CAACrB,SAAS,CAACsB,WAAW,CAAC;AAC7Bd,YAAAA,IAAAA,EAAMa,QAAQb,IAAI;AAClBS,YAAAA,YAAAA,EAAcI,QAAQJ,YAAY;YAClCJ,QAAAA,EAAU;gBACNU,QAAAA,EAAU,IAAI,CAACrB,OAAO;gBACtBsB,MAAAA,EAAQH,OAAAA,CAAQb,IAAI,CAACiB,EAAE;AAEvBnB,gBAAAA,KAAAA,EAAOe,QAAQX,IAAI;AACnB,gBAAA,GAAIW,QAAQR,QAAQ,GAAGQ,QAAQR,QAAQ,GAAG;AAC9C,aAAA;YACAZ,YAAAA,EAAc,IAAI,CAACA;AACvB,SAAA,CAAA;AACJ,IAAA;AACJ;;;;"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/data-source/options.ts","../src/subscriber/base.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { DataSourceOptions } from 'typeorm';\nimport {\n CodeTransformation,\n isCodeTransformation,\n readDataSourceOptionsFromEnv,\n transformFilePath,\n} from 'typeorm-extension';\n\nexport type DataSourceOptionsEntities = DataSourceOptions['entities'];\nexport type DataSourceOptionsSubscribers = DataSourceOptions['subscribers'];\n\nexport class DataSourceOptionsBuilder {\n protected entities : DataSourceOptionsEntities;\n\n protected subscribers : DataSourceOptionsSubscribers;\n\n // ------------------------------------------------------------------\n\n constructor() {\n this.entities = [];\n this.subscribers = [];\n }\n\n // ------------------------------------------------------------------\n\n buildWithEnv() {\n const options = readDataSourceOptionsFromEnv();\n\n if (!options) {\n throw new Error('The database configuration could not be read from env variables.');\n }\n\n return this.normalize(options);\n }\n\n buildWith(options: DataSourceOptions) {\n return this.normalize(options);\n }\n\n // ------------------------------------------------------------------\n\n setEntities(entities: DataSourceOptionsEntities) {\n this.entities = entities;\n }\n\n setSubscribers(subscribers: DataSourceOptionsSubscribers) {\n this.subscribers = subscribers;\n }\n\n // ------------------------------------------------------------------\n\n protected normalize(options: DataSourceOptions) : DataSourceOptions {\n if (\n options.type !== 'mysql' &&\n options.type !== 'postgres' &&\n options.type !== 'better-sqlite3'\n ) {\n throw new Error(`The database type ${options.type} is not supported.`);\n }\n\n options = {\n ...options,\n logging: false,\n entities: [\n ...(options.entities ? options.entities : []) as string[],\n ...(this.entities) as string[],\n ],\n migrations: [],\n migrationsTransactionMode: 'each',\n subscribers: [\n ...(options.subscribers || []) as string[],\n ...this.subscribers as string[],\n ],\n };\n\n if (options.type === 'mysql' || options.type === 'postgres') {\n let migrationPath = `src/database/migrations/${options.type}/*.{ts,js}`;\n if (!isCodeTransformation(CodeTransformation.JUST_IN_TIME)) {\n migrationPath = transformFilePath(migrationPath, './dist', './src');\n }\n\n Object.assign(options, {\n migrations: [migrationPath],\n migrationsTransactionMode: 'all',\n } as DataSourceOptions);\n }\n\n if (options.type === 'mysql') {\n Object.assign(options, {\n connectorPackage: 'mysql2',\n } satisfies Partial<DataSourceOptions>);\n }\n\n return options;\n }\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { ObjectLiteral } from '@privateaim/kit';\nimport { DomainEventName } from '@privateaim/kit';\nimport type {\n EntityEventDestinations, EntityEventDestinationsFn,\n EntityEventPublisher,\n} from '@privateaim/server-kit';\nimport {\n isEntityEventPublisherUsable,\n useEntityEventPublisher,\n} from '@privateaim/server-kit';\nimport type {\n EntitySubscriberInterface, InsertEvent, RemoveEvent, UpdateEvent,\n} from 'typeorm';\nimport type { BaseSubscriberContext, SubscriberPublishPayload } from './types';\n\nexport class BaseSubscriber<\n RECORD extends ObjectLiteral,\n> implements EntitySubscriberInterface<RECORD> {\n private readonly publisher: EntityEventPublisher | undefined;\n\n private readonly destinations : EntityEventDestinations | EntityEventDestinationsFn<RECORD>;\n\n private readonly refType: string;\n\n constructor(ctx: BaseSubscriberContext<RECORD>) {\n this.refType = ctx.refType;\n if (isEntityEventPublisherUsable()) {\n this.publisher = useEntityEventPublisher();\n }\n\n this.destinations = ctx.destinations;\n }\n\n async afterInsert(event: InsertEvent<RECORD>): Promise<any> {\n await this.publish({\n data: event.entity,\n type: DomainEventName.CREATED,\n metadata: event.queryRunner.data,\n });\n }\n\n async afterUpdate(event: UpdateEvent<RECORD>): Promise<any> {\n await this.publish({\n type: DomainEventName.UPDATED,\n data: event.entity as RECORD,\n dataPrevious: event.databaseEntity,\n metadata: event.queryRunner.data,\n });\n }\n\n async beforeRemove(event: RemoveEvent<RECORD>): Promise<any> {\n if (event.entity) {\n await this.publish({\n type: DomainEventName.DELETED,\n data: event.entity as RECORD,\n metadata: event.queryRunner.data,\n });\n }\n }\n\n async publish(payload: SubscriberPublishPayload<RECORD>) {\n if (!this.publisher) {\n return;\n }\n\n await this.publisher.safePublish({\n data: payload.data,\n dataPrevious: payload.dataPrevious,\n metadata: {\n ref_type: this.refType,\n ref_id: payload.data.id,\n\n event: payload.type,\n ...(payload.metadata ? payload.metadata : {}),\n },\n destinations: this.destinations,\n });\n }\n}\n"],"names":["DataSourceOptionsBuilder","entities","subscribers","buildWithEnv","options","readDataSourceOptionsFromEnv","Error","normalize","buildWith","setEntities","setSubscribers","type","logging","migrations","migrationsTransactionMode","migrationPath","isCodeTransformation","CodeTransformation","JUST_IN_TIME","transformFilePath","Object","assign","connectorPackage","BaseSubscriber","publisher","destinations","refType","ctx","isEntityEventPublisherUsable","useEntityEventPublisher","afterInsert","event","publish","data","entity","DomainEventName","CREATED","metadata","queryRunner","afterUpdate","UPDATED","dataPrevious","databaseEntity","beforeRemove","DELETED","payload","safePublish","ref_type","ref_id","id"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/subscriber/base.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAOrD,OAAO,KAAK,EACR,yBAAyB,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EACnE,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAE/E,qBAAa,cAAc,CACvB,MAAM,SAAS,aAAa,CAC9B,YAAW,yBAAyB,CAAC,MAAM,CAAC;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuB;IAEjD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA+D;IAE5F,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,GAAG,EAAE,qBAAqB,CAAC,MAAM,CAAC;IAMxC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IAQrD,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IASrD,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IAUtD,OAAO,CAAC,OAAO,EAAE,wBAAwB,CAAC,MAAM,CAAC;CAc1D"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/subscriber/base.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAUrD,OAAO,KAAK,EACR,yBAAyB,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EACnE,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAE/E,qBAAa,cAAc,CACvB,MAAM,SAAS,aAAa,CAC9B,YAAW,yBAAyB,CAAC,MAAM,CAAC;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmC;IAE7D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA+D;IAE5F,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,GAAG,EAAE,qBAAqB,CAAC,MAAM,CAAC;IASxC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IAQrD,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IASrD,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IAUtD,OAAO,CAAC,OAAO,EAAE,wBAAwB,CAAC,MAAM,CAAC;CAkB1D"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@privateaim/server-db-kit",
3
3
  "type": "module",
4
- "version": "0.8.26",
4
+ "version": "0.8.28",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
7
7
  "exports": {
@@ -19,16 +19,16 @@
19
19
  "license": "Apache-2.0",
20
20
  "description": "This package contains server side db helpers & utilities.",
21
21
  "dependencies": {
22
- "@privateaim/kit": "^0.8.26",
23
- "@privateaim/server-kit": "^0.8.26"
22
+ "@privateaim/kit": "^0.8.28",
23
+ "@privateaim/server-kit": "^0.8.28"
24
24
  },
25
25
  "devDependencies": {
26
26
  "typeorm": "^0.3.28",
27
- "typeorm-extension": "^3.8.0"
27
+ "typeorm-extension": "^3.9.0"
28
28
  },
29
29
  "peerDependencies": {
30
30
  "typeorm": "^0.3.28",
31
- "typeorm-extension": "^3.8.0"
31
+ "typeorm-extension": "^3.9.0"
32
32
  },
33
33
  "scripts": {
34
34
  "build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json",
@@ -0,0 +1,8 @@
1
+ /*
2
+ * Copyright (c) 2026.
3
+ * Author Peter Placzek (tada5hi)
4
+ * For the full copyright and license information,
5
+ * view the LICENSE file that was distributed with this source code.
6
+ */
7
+
8
+ export * from './options.ts';
@@ -0,0 +1,103 @@
1
+ /*
2
+ * Copyright (c) 2026.
3
+ * Author Peter Placzek (tada5hi)
4
+ * For the full copyright and license information,
5
+ * view the LICENSE file that was distributed with this source code.
6
+ */
7
+
8
+ import type { DataSourceOptions } from 'typeorm';
9
+ import {
10
+ CodeTransformation,
11
+ isCodeTransformation,
12
+ readDataSourceOptionsFromEnv,
13
+ transformFilePath,
14
+ } from 'typeorm-extension';
15
+
16
+ export type DataSourceOptionsEntities = DataSourceOptions['entities'];
17
+ export type DataSourceOptionsSubscribers = DataSourceOptions['subscribers'];
18
+
19
+ export class DataSourceOptionsBuilder {
20
+ protected entities : DataSourceOptionsEntities;
21
+
22
+ protected subscribers : DataSourceOptionsSubscribers;
23
+
24
+ // ------------------------------------------------------------------
25
+
26
+ constructor() {
27
+ this.entities = [];
28
+ this.subscribers = [];
29
+ }
30
+
31
+ // ------------------------------------------------------------------
32
+
33
+ buildWithEnv() {
34
+ const options = readDataSourceOptionsFromEnv();
35
+
36
+ if (!options) {
37
+ throw new Error('The database configuration could not be read from env variables.');
38
+ }
39
+
40
+ return this.normalize(options);
41
+ }
42
+
43
+ buildWith(options: DataSourceOptions) {
44
+ return this.normalize(options);
45
+ }
46
+
47
+ // ------------------------------------------------------------------
48
+
49
+ setEntities(entities: DataSourceOptionsEntities) {
50
+ this.entities = entities;
51
+ }
52
+
53
+ setSubscribers(subscribers: DataSourceOptionsSubscribers) {
54
+ this.subscribers = subscribers;
55
+ }
56
+
57
+ // ------------------------------------------------------------------
58
+
59
+ protected normalize(options: DataSourceOptions) : DataSourceOptions {
60
+ if (
61
+ options.type !== 'mysql' &&
62
+ options.type !== 'postgres' &&
63
+ options.type !== 'better-sqlite3'
64
+ ) {
65
+ throw new Error(`The database type ${options.type} is not supported.`);
66
+ }
67
+
68
+ options = {
69
+ ...options,
70
+ logging: false,
71
+ entities: [
72
+ ...(options.entities ? options.entities : []) as string[],
73
+ ...(this.entities) as string[],
74
+ ],
75
+ migrations: [],
76
+ migrationsTransactionMode: 'each',
77
+ subscribers: [
78
+ ...(options.subscribers || []) as string[],
79
+ ...this.subscribers as string[],
80
+ ],
81
+ };
82
+
83
+ if (options.type === 'mysql' || options.type === 'postgres') {
84
+ let migrationPath = `src/database/migrations/${options.type}/*.{ts,js}`;
85
+ if (!isCodeTransformation(CodeTransformation.JUST_IN_TIME)) {
86
+ migrationPath = transformFilePath(migrationPath, './dist', './src');
87
+ }
88
+
89
+ Object.assign(options, {
90
+ migrations: [migrationPath],
91
+ migrationsTransactionMode: 'all',
92
+ } as DataSourceOptions);
93
+ }
94
+
95
+ if (options.type === 'mysql') {
96
+ Object.assign(options, {
97
+ connectorPackage: 'mysql2',
98
+ } satisfies Partial<DataSourceOptions>);
99
+ }
100
+
101
+ return options;
102
+ }
103
+ }
package/src/index.ts CHANGED
@@ -5,4 +5,5 @@
5
5
  * view the LICENSE file that was distributed with this source code.
6
6
  */
7
7
 
8
- export * from './subscriber';
8
+ export * from './data-source/index.ts';
9
+ export * from './subscriber/index.ts';
@@ -11,7 +11,10 @@ import type {
11
11
  EntityEventDestinations, EntityEventDestinationsFn,
12
12
  EntityEventPublisher,
13
13
  } from '@privateaim/server-kit';
14
- import { useEntityEventPublisher } from '@privateaim/server-kit';
14
+ import {
15
+ isEntityEventPublisherUsable,
16
+ useEntityEventPublisher,
17
+ } from '@privateaim/server-kit';
15
18
  import type {
16
19
  EntitySubscriberInterface, InsertEvent, RemoveEvent, UpdateEvent,
17
20
  } from 'typeorm';
@@ -20,7 +23,7 @@ import type { BaseSubscriberContext, SubscriberPublishPayload } from './types';
20
23
  export class BaseSubscriber<
21
24
  RECORD extends ObjectLiteral,
22
25
  > implements EntitySubscriberInterface<RECORD> {
23
- private readonly publisher: EntityEventPublisher;
26
+ private readonly publisher: EntityEventPublisher | undefined;
24
27
 
25
28
  private readonly destinations : EntityEventDestinations | EntityEventDestinationsFn<RECORD>;
26
29
 
@@ -28,7 +31,10 @@ export class BaseSubscriber<
28
31
 
29
32
  constructor(ctx: BaseSubscriberContext<RECORD>) {
30
33
  this.refType = ctx.refType;
31
- this.publisher = useEntityEventPublisher();
34
+ if (isEntityEventPublisherUsable()) {
35
+ this.publisher = useEntityEventPublisher();
36
+ }
37
+
32
38
  this.destinations = ctx.destinations;
33
39
  }
34
40
 
@@ -60,6 +66,10 @@ export class BaseSubscriber<
60
66
  }
61
67
 
62
68
  async publish(payload: SubscriberPublishPayload<RECORD>) {
69
+ if (!this.publisher) {
70
+ return;
71
+ }
72
+
63
73
  await this.publisher.safePublish({
64
74
  data: payload.data,
65
75
  dataPrevious: payload.dataPrevious,