@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 +1 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/providers/typeorm.config.d.ts +3 -2
- package/dist/providers/typeorm.config.js +21 -3
- package/dist/providers/typeorm.config.js.map +1 -1
- package/dist/typeorm.plugin.js +70 -26
- package/dist/typeorm.plugin.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +1 -0
- package/src/providers/typeorm.config.ts +20 -5
- package/src/typeorm.plugin.ts +87 -28
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;
|
|
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:
|
|
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
|
|
34
|
-
description:
|
|
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",
|
|
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":";;;;;;;;;;;;AAAA,yCAA8C;AAC9C,
|
|
1
|
+
{"version":3,"file":"typeorm.config.js","sourceRoot":"","sources":["../../src/providers/typeorm.config.ts"],"names":[],"mappings":"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"}
|
package/dist/typeorm.plugin.js
CHANGED
|
@@ -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
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
52
|
+
* libpq-режим имеет смысл только для wire-совместимых с PostgreSQL
|
|
53
|
+
* драйверов. Для mysql/mariadb/mssql/etc multi-host обслуживается
|
|
54
|
+
* resolver-ом (bootstrap-only) — у их драйверов своё API failover.
|
|
54
55
|
*/
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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":";;;;;;AAEA,6CAAgD;AAOhD,qCAAsC;AACtC,
|
|
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.
|
|
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": "
|
|
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
|
|
23
|
-
description:
|
|
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
|
-
|
|
40
|
+
multiHostBootstrapFallback!: boolean;
|
|
26
41
|
|
|
27
42
|
@Property('SCHEMA', new StringParser(), {
|
|
28
43
|
description: text`
|
package/src/typeorm.plugin.ts
CHANGED
|
@@ -8,7 +8,11 @@ import type {
|
|
|
8
8
|
PlatformAppPlugin,
|
|
9
9
|
} from '@rsdk/core';
|
|
10
10
|
import { APP_NAME } from '@rsdk/core';
|
|
11
|
-
import {
|
|
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
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
74
|
+
* libpq-режим имеет смысл только для wire-совместимых с PostgreSQL
|
|
75
|
+
* драйверов. Для mysql/mariadb/mssql/etc multi-host обслуживается
|
|
76
|
+
* resolver-ом (bootstrap-only) — у их драйверов своё API failover.
|
|
71
77
|
*/
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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();
|