@rsdk/db.typeorm 5.12.0-next.6 → 5.12.0-next.8

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.d.ts CHANGED
@@ -5,6 +5,7 @@ export { IsolationLevel } from './types';
5
5
  export { OverrideEntity } from './metadata/override-entity.decorator';
6
6
  export { TypeOrmEntity } from './metadata/typeorm-entity.decorator';
7
7
  export { flatOrder } from './flat-order';
8
+ export { TypeOrmPluginConfig } from './providers/typeorm.config';
8
9
  export declare const Runner: TransactionRunner<import("./types").IsolationLevel, import("./internal/context").TypeOrmContext>;
9
10
  export declare const Transactional: (payload?: {
10
11
  isolation?: import("./types").IsolationLevel;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Transactional = exports.Runner = exports.flatOrder = exports.TypeOrmEntity = exports.OverrideEntity = exports.IsolationLevel = exports.TypeOrmPlugin = exports.DataSourceExtractor = void 0;
3
+ exports.Transactional = exports.Runner = exports.TypeOrmPluginConfig = exports.flatOrder = exports.TypeOrmEntity = exports.OverrideEntity = exports.IsolationLevel = exports.TypeOrmPlugin = exports.DataSourceExtractor = void 0;
4
4
  const db_1 = require("@rsdk/db");
5
5
  const strategy_1 = require("./internal/strategy");
6
6
  var data_source_extractor_1 = require("./data-source-extractor");
@@ -15,6 +15,8 @@ var typeorm_entity_decorator_1 = require("./metadata/typeorm-entity.decorator");
15
15
  Object.defineProperty(exports, "TypeOrmEntity", { enumerable: true, get: function () { return typeorm_entity_decorator_1.TypeOrmEntity; } });
16
16
  var flat_order_1 = require("./flat-order");
17
17
  Object.defineProperty(exports, "flatOrder", { enumerable: true, get: function () { return flat_order_1.flatOrder; } });
18
+ var typeorm_config_1 = require("./providers/typeorm.config");
19
+ Object.defineProperty(exports, "TypeOrmPluginConfig", { enumerable: true, get: function () { return typeorm_config_1.TypeOrmPluginConfig; } });
18
20
  exports.Runner = new db_1.TransactionRunner(new strategy_1.TypeOrmTransactionalStrategy());
19
21
  exports.Transactional = exports.Runner.Transactional.bind(exports.Runner);
20
22
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,iCAA6C;AAE7C,kDAAmE;AAEnE,iEAA8D;AAArD,4HAAA,mBAAmB,OAAA;AAE5B,mDAAiD;AAAxC,+GAAA,aAAa,OAAA;AACtB,iCAAyC;AAAhC,uGAAA,cAAc,OAAA;AACvB,kFAAsE;AAA7D,2HAAA,cAAc,OAAA;AACvB,gFAAoE;AAA3D,yHAAA,aAAa,OAAA;AACtB,2CAAyC;AAAhC,uGAAA,SAAS,OAAA;AAEL,QAAA,MAAM,GAAG,IAAI,sBAAiB,CAAC,IAAI,uCAA4B,EAAE,CAAC,CAAC;AACnE,QAAA,aAAa,GAAG,cAAM,CAAC,aAAa,CAAC,IAAI,CAAC,cAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,iCAA6C;AAE7C,kDAAmE;AAEnE,iEAA8D;AAArD,4HAAA,mBAAmB,OAAA;AAE5B,mDAAiD;AAAxC,+GAAA,aAAa,OAAA;AACtB,iCAAyC;AAAhC,uGAAA,cAAc,OAAA;AACvB,kFAAsE;AAA7D,2HAAA,cAAc,OAAA;AACvB,gFAAoE;AAA3D,yHAAA,aAAa,OAAA;AACtB,2CAAyC;AAAhC,uGAAA,SAAS,OAAA;AAClB,6DAAiE;AAAxD,qHAAA,mBAAmB,OAAA;AAEf,QAAA,MAAM,GAAG,IAAI,sBAAiB,CAAC,IAAI,uCAA4B,EAAE,CAAC,CAAC;AACnE,QAAA,aAAa,GAAG,cAAM,CAAC,aAAa,CAAC,IAAI,CAAC,cAAM,CAAC,CAAC"}
@@ -1,8 +1,9 @@
1
1
  import { Timespan } from '@rsdk/common';
2
2
  import { Config } from '@rsdk/core';
3
- import { SslModeEnum } from '@rsdk/db';
3
+ import { MultiHostUrl, SslModeEnum } from '@rsdk/db';
4
4
  export declare class TypeOrmPluginConfig extends Config {
5
- url: URL;
5
+ url: MultiHostUrl;
6
+ multiHostBootstrapFallback: boolean;
6
7
  schema: string;
7
8
  poolMin: number;
8
9
  poolMax: number;
@@ -15,6 +15,7 @@ const core_1 = require("@rsdk/core");
15
15
  const db_1 = require("@rsdk/db");
16
16
  let TypeOrmPluginConfig = class TypeOrmPluginConfig extends core_1.Config {
17
17
  url;
18
+ multiHostBootstrapFallback;
18
19
  schema;
19
20
  poolMin;
20
21
  poolMax;
@@ -30,11 +31,28 @@ let TypeOrmPluginConfig = class TypeOrmPluginConfig extends core_1.Config {
30
31
  };
31
32
  exports.TypeOrmPluginConfig = TypeOrmPluginConfig;
32
33
  __decorate([
33
- (0, core_1.Property)('URL', new core_1.UrlParser(), {
34
- description: 'Database server url',
34
+ (0, core_1.Property)('URL', new db_1.MultiHostUrlParser(), {
35
+ description: (0, common_1.text) `
36
+ Database server url. Supports multi-host syntax for Postgres:
37
+ \`postgres://user:pass@host1:5432,host2:5432/db\`. Port is optional (driver default, e.g. 5432 for PostgreSQL).
38
+ With \`pg-native\` installed RSDK uses libpq runtime failover. Without \`pg-native\`
39
+ the app fails fast at startup unless DB_MULTIHOST_BOOTSTRAP_FALLBACK=true is set.
40
+ See docs/md/DATABASES.md for details.
41
+ `,
35
42
  }),
36
- __metadata("design:type", URL)
43
+ __metadata("design:type", db_1.MultiHostUrl)
37
44
  ], TypeOrmPluginConfig.prototype, "url", void 0);
45
+ __decorate([
46
+ (0, core_1.Property)('MULTIHOST_BOOTSTRAP_FALLBACK', new core_1.BoolParser(), {
47
+ defaultValue: false,
48
+ description: (0, common_1.text) `
49
+ Allows silent fallback to bootstrap-resolve when DB_URL has multiple
50
+ hosts but \`pg-native\` is not installed. When false (default) the app
51
+ fails fast at startup so that runtime failover is never quietly downgraded.
52
+ `,
53
+ }),
54
+ __metadata("design:type", Boolean)
55
+ ], TypeOrmPluginConfig.prototype, "multiHostBootstrapFallback", void 0);
38
56
  __decorate([
39
57
  (0, core_1.Property)('SCHEMA', new core_1.StringParser(), {
40
58
  description: (0, common_1.text) `
@@ -1 +1 @@
1
- {"version":3,"file":"typeorm.config.js","sourceRoot":"","sources":["../../src/providers/typeorm.config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"typeorm.config.js","sourceRoot":"","sources":["../../src/providers/typeorm.config.ts"],"names":[],"mappings":"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"}
@@ -46,34 +46,78 @@ class TypeOrmPlugin {
46
46
  },
47
47
  ],
48
48
  inject: [providers_1.TypeOrmPluginConfig, providers_1.TypeOrmLoggerAdapter, core_1.APP_NAME],
49
- useFactory: (config, logger, appName) => ({
49
+ useFactory: async (config, logger, appName) => {
50
+ const ssl = (0, db_1.getSecureContextOptions)(config);
50
51
  /**
51
- * Так как typeorm поддерживает целый зоопарк не совместимых друг с другом СУБД, для всего нужны разные опции
52
- * И он начинает ругаться на то что какие-то поля должны быть, каких то не должно быть
53
- * Принято волевое решение пока остановиться на нашей основной СУБД, а именно `postgres`
52
+ * libpq-режим имеет смысл только для wire-совместимых с PostgreSQL
53
+ * драйверов. Для mysql/mariadb/mssql/etc multi-host обслуживается
54
+ * resolver-ом (bootstrap-only) у их драйверов своё API failover.
54
55
  */
55
- type: this.options.type,
56
- url: config.url.toString(),
57
- ...(config.schema && {
58
- schema: config.schema,
59
- }),
60
- logger,
61
- ...(this.entities && { entities: this.entities }),
62
- autoLoadEntities: !this.entities,
63
- retryDelay: config.reconnectInterval.millis(),
64
- retryAttempts: config.reconnectAttempts,
65
- applicationName: appName + ':typeorm',
66
- extra: {
67
- min: config.poolMin,
68
- max: config.poolMax,
69
- keepAlive: config.keepAlive,
70
- keepAliveInitialDelay: config.keepAliveInitialDelay,
71
- ssl: (0, db_1.getSecureContextOptions)(config),
72
- },
73
- migrations,
74
- migrationsTableName: 'typeorm_migrations',
75
- ...this.options.overrideConfig,
76
- }),
56
+ const isPostgresFamily = this.options.type === 'postgres' ||
57
+ this.options.type === 'aurora-postgres';
58
+ /**
59
+ * Probe передаётся только если фолбэк явно разрешён через env.
60
+ * Иначе resolveDbConnection упадёт с MultiHostNativeRequired при
61
+ * отсутствии pg-native — runtime failover не будет тихо потерян.
62
+ */
63
+ const resolved = await (0, db_1.resolveDbConnection)({
64
+ url: config.url,
65
+ logger: TypeOrmPlugin.logger,
66
+ isPostgresFamily,
67
+ ...(config.multiHostBootstrapFallback && {
68
+ bootstrapProbe: (candidate) => (0, db_1.pgProbe)(candidate, ssl),
69
+ }),
70
+ });
71
+ let nativeDriver;
72
+ let connection;
73
+ let extraConnection;
74
+ if (resolved.kind === 'native-libpq') {
75
+ nativeDriver = resolved.driver;
76
+ connection = {
77
+ host: resolved.firstHostEntry.host,
78
+ port: resolved.firstHostEntry.port,
79
+ ...(resolved.username && { username: resolved.username }),
80
+ ...(resolved.password && { password: resolved.password }),
81
+ ...(resolved.database && { database: resolved.database }),
82
+ };
83
+ extraConnection = {
84
+ nativeConnectionString: resolved.multiHostUrl,
85
+ };
86
+ }
87
+ else {
88
+ connection = { url: resolved.url.toString() };
89
+ extraConnection = {};
90
+ }
91
+ const userOverride = (this.options.overrideConfig ?? {});
92
+ const driverOverride = nativeDriver !== undefined && userOverride.driver === undefined
93
+ ? { driver: nativeDriver }
94
+ : {};
95
+ return {
96
+ type: this.options.type,
97
+ ...connection,
98
+ ...(config.schema && {
99
+ schema: config.schema,
100
+ }),
101
+ logger,
102
+ ...(this.entities && { entities: this.entities }),
103
+ autoLoadEntities: !this.entities,
104
+ retryDelay: config.reconnectInterval.millis(),
105
+ retryAttempts: config.reconnectAttempts,
106
+ applicationName: appName + ':typeorm',
107
+ extra: {
108
+ min: config.poolMin,
109
+ max: config.poolMax,
110
+ keepAlive: config.keepAlive,
111
+ keepAliveInitialDelay: config.keepAliveInitialDelay,
112
+ ssl,
113
+ ...extraConnection,
114
+ },
115
+ migrations,
116
+ migrationsTableName: 'typeorm_migrations',
117
+ ...userOverride,
118
+ ...driverOverride,
119
+ };
120
+ },
77
121
  dataSourceFactory: (options) => {
78
122
  if (!options) {
79
123
  throw new exceptions_1.DatasourceOptionsNotSet();
@@ -1 +1 @@
1
- {"version":3,"file":"typeorm.plugin.js","sourceRoot":"","sources":["../src/typeorm.plugin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"typeorm.plugin.js","sourceRoot":"","sources":["../src/typeorm.plugin.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rsdk/db.typeorm",
3
- "version": "5.12.0-next.6",
3
+ "version": "5.12.0-next.8",
4
4
  "description": "TypeOrm module for platform",
5
5
  "license": "Apache License 2.0",
6
6
  "publishConfig": {
@@ -28,5 +28,5 @@
28
28
  "rxjs": "^7.1.0",
29
29
  "typeorm": "^0.3.12"
30
30
  },
31
- "gitHead": "32103725bddbe5e7e99074ba40b5032dc14cf60c"
31
+ "gitHead": "ce0adb86b9bafb8df462e4eb47600c8bb08cc7df"
32
32
  }
package/src/index.ts CHANGED
@@ -9,6 +9,7 @@ export { IsolationLevel } from './types';
9
9
  export { OverrideEntity } from './metadata/override-entity.decorator';
10
10
  export { TypeOrmEntity } from './metadata/typeorm-entity.decorator';
11
11
  export { flatOrder } from './flat-order';
12
+ export { TypeOrmPluginConfig } from './providers/typeorm.config';
12
13
 
13
14
  export const Runner = new TransactionRunner(new TypeOrmTransactionalStrategy());
14
15
  export const Transactional = Runner.Transactional.bind(Runner);
@@ -9,9 +9,8 @@ import {
9
9
  Property,
10
10
  StringParser,
11
11
  TimespanParser,
12
- UrlParser,
13
12
  } from '@rsdk/core';
14
- import { SslModeEnum } from '@rsdk/db';
13
+ import { MultiHostUrl, MultiHostUrlParser, SslModeEnum } from '@rsdk/db';
15
14
 
16
15
  @ConfigSection({
17
16
  name: 'typeorm database config',
@@ -19,10 +18,26 @@ import { SslModeEnum } from '@rsdk/db';
19
18
  prefix: 'DB',
20
19
  })
21
20
  export class TypeOrmPluginConfig extends Config {
22
- @Property('URL', new UrlParser(), {
23
- description: 'Database server url',
21
+ @Property('URL', new MultiHostUrlParser(), {
22
+ description: text`
23
+ Database server url. Supports multi-host syntax for Postgres:
24
+ \`postgres://user:pass@host1:5432,host2:5432/db\`. Port is optional (driver default, e.g. 5432 for PostgreSQL).
25
+ With \`pg-native\` installed RSDK uses libpq runtime failover. Without \`pg-native\`
26
+ the app fails fast at startup unless DB_MULTIHOST_BOOTSTRAP_FALLBACK=true is set.
27
+ See docs/md/DATABASES.md for details.
28
+ `,
29
+ })
30
+ url!: MultiHostUrl;
31
+
32
+ @Property('MULTIHOST_BOOTSTRAP_FALLBACK', new BoolParser(), {
33
+ defaultValue: false,
34
+ description: text`
35
+ Allows silent fallback to bootstrap-resolve when DB_URL has multiple
36
+ hosts but \`pg-native\` is not installed. When false (default) the app
37
+ fails fast at startup so that runtime failover is never quietly downgraded.
38
+ `,
24
39
  })
25
- url!: URL;
40
+ multiHostBootstrapFallback!: boolean;
26
41
 
27
42
  @Property('SCHEMA', new StringParser(), {
28
43
  description: text`
@@ -8,7 +8,11 @@ import type {
8
8
  PlatformAppPlugin,
9
9
  } from '@rsdk/core';
10
10
  import { APP_NAME } from '@rsdk/core';
11
- import { getSecureContextOptions } from '@rsdk/db';
11
+ import {
12
+ getSecureContextOptions,
13
+ pgProbe,
14
+ resolveDbConnection,
15
+ } from '@rsdk/db';
12
16
  import { LoggerFactory } from '@rsdk/logging';
13
17
  import path from 'node:path';
14
18
  import type { DataSourceOptions } from 'typeorm';
@@ -59,38 +63,93 @@ export class TypeOrmPlugin implements PlatformAppPlugin {
59
63
  },
60
64
  ],
61
65
  inject: [TypeOrmPluginConfig, TypeOrmLoggerAdapter, APP_NAME],
62
- useFactory: (
66
+ useFactory: async (
63
67
  config: TypeOrmPluginConfig,
64
68
  logger: TypeOrmLoggerAdapter,
65
69
  appName: string,
66
- ): TypeOrmModuleOptions => ({
70
+ ): Promise<TypeOrmModuleOptions> => {
71
+ const ssl = getSecureContextOptions(config);
72
+
67
73
  /**
68
- * Так как typeorm поддерживает целый зоопарк не совместимых друг с другом СУБД, для всего нужны разные опции
69
- * И он начинает ругаться на то что какие-то поля должны быть, каких то не должно быть
70
- * Принято волевое решение пока остановиться на нашей основной СУБД, а именно `postgres`
74
+ * libpq-режим имеет смысл только для wire-совместимых с PostgreSQL
75
+ * драйверов. Для mysql/mariadb/mssql/etc multi-host обслуживается
76
+ * resolver-ом (bootstrap-only) у их драйверов своё API failover.
71
77
  */
72
- type: this.options.type,
73
- url: config.url.toString(),
74
- ...(config.schema && {
75
- schema: config.schema,
76
- }),
77
- logger,
78
- ...(this.entities && { entities: this.entities }),
79
- autoLoadEntities: !this.entities,
80
- retryDelay: config.reconnectInterval.millis(),
81
- retryAttempts: config.reconnectAttempts,
82
- applicationName: appName + ':typeorm',
83
- extra: {
84
- min: config.poolMin,
85
- max: config.poolMax,
86
- keepAlive: config.keepAlive,
87
- keepAliveInitialDelay: config.keepAliveInitialDelay,
88
- ssl: getSecureContextOptions(config),
89
- },
90
- migrations,
91
- migrationsTableName: 'typeorm_migrations',
92
- ...(this.options.overrideConfig as any),
93
- }),
78
+ const isPostgresFamily =
79
+ this.options.type === 'postgres' ||
80
+ this.options.type === 'aurora-postgres';
81
+
82
+ /**
83
+ * Probe передаётся только если фолбэк явно разрешён через env.
84
+ * Иначе resolveDbConnection упадёт с MultiHostNativeRequired при
85
+ * отсутствии pg-native — runtime failover не будет тихо потерян.
86
+ */
87
+ const resolved = await resolveDbConnection({
88
+ url: config.url,
89
+ logger: TypeOrmPlugin.logger,
90
+ isPostgresFamily,
91
+ ...(config.multiHostBootstrapFallback && {
92
+ bootstrapProbe: (candidate: URL): Promise<void> =>
93
+ pgProbe(candidate, ssl),
94
+ }),
95
+ });
96
+
97
+ let nativeDriver: unknown;
98
+ let connection: Record<string, unknown>;
99
+ let extraConnection: Record<string, unknown>;
100
+
101
+ if (resolved.kind === 'native-libpq') {
102
+ nativeDriver = resolved.driver;
103
+ connection = {
104
+ host: resolved.firstHostEntry.host,
105
+ port: resolved.firstHostEntry.port,
106
+ ...(resolved.username && { username: resolved.username }),
107
+ ...(resolved.password && { password: resolved.password }),
108
+ ...(resolved.database && { database: resolved.database }),
109
+ };
110
+ extraConnection = {
111
+ nativeConnectionString: resolved.multiHostUrl,
112
+ };
113
+ } else {
114
+ connection = { url: resolved.url.toString() };
115
+ extraConnection = {};
116
+ }
117
+
118
+ const userOverride = (this.options.overrideConfig ?? {}) as Record<
119
+ string,
120
+ unknown
121
+ >;
122
+ const driverOverride =
123
+ nativeDriver !== undefined && userOverride.driver === undefined
124
+ ? { driver: nativeDriver }
125
+ : {};
126
+
127
+ return {
128
+ type: this.options.type,
129
+ ...connection,
130
+ ...(config.schema && {
131
+ schema: config.schema,
132
+ }),
133
+ logger,
134
+ ...(this.entities && { entities: this.entities }),
135
+ autoLoadEntities: !this.entities,
136
+ retryDelay: config.reconnectInterval.millis(),
137
+ retryAttempts: config.reconnectAttempts,
138
+ applicationName: appName + ':typeorm',
139
+ extra: {
140
+ min: config.poolMin,
141
+ max: config.poolMax,
142
+ keepAlive: config.keepAlive,
143
+ keepAliveInitialDelay: config.keepAliveInitialDelay,
144
+ ssl,
145
+ ...extraConnection,
146
+ },
147
+ migrations,
148
+ migrationsTableName: 'typeorm_migrations',
149
+ ...(userOverride as any),
150
+ ...driverOverride,
151
+ };
152
+ },
94
153
  dataSourceFactory: (options?: DataSourceOptions) => {
95
154
  if (!options) {
96
155
  throw new DatasourceOptionsNotSet();