@nest-boot/mikro-orm 7.7.1 → 7.7.2
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/mikro-orm.module.d.ts +3 -0
- package/dist/mikro-orm.module.js +20 -1
- package/dist/mikro-orm.module.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/load-config-from-env.util.d.ts +16 -6
- package/dist/utils/load-config-from-env.util.js +196 -53
- package/dist/utils/load-config-from-env.util.js.map +1 -1
- package/dist/utils/load-config-from-env.util.spec.js +244 -17
- package/dist/utils/load-config-from-env.util.spec.js.map +1 -1
- package/dist/utils/load-default-config.util.d.ts +23 -0
- package/dist/utils/load-default-config.util.js +29 -0
- package/dist/utils/load-default-config.util.js.map +1 -0
- package/package.json +6 -5
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Configuration, IDatabaseDriver } from "@mikro-orm/core";
|
|
1
|
+
import { Configuration, IDatabaseDriver, type Options } from "@mikro-orm/core";
|
|
2
2
|
/** Constructor type for a MikroORM database driver. */
|
|
3
3
|
export type DatabaseDriverConstructor = new (config: Configuration) => IDatabaseDriver;
|
|
4
4
|
/** Database driver configuration for MikroORM. */
|
|
@@ -6,7 +6,7 @@ export interface DriverConfig {
|
|
|
6
6
|
/** Database driver class constructor. */
|
|
7
7
|
driver?: DatabaseDriverConstructor;
|
|
8
8
|
}
|
|
9
|
-
/** URL-based database connection configuration. */
|
|
9
|
+
/** URL-based database connection configuration for explicit module options. */
|
|
10
10
|
export interface UrlConfig {
|
|
11
11
|
/** Database connection URL. */
|
|
12
12
|
clientUrl?: string;
|
|
@@ -23,15 +23,25 @@ export interface HostConfig {
|
|
|
23
23
|
user?: string;
|
|
24
24
|
/** Database password. */
|
|
25
25
|
password?: string;
|
|
26
|
+
/** Default database schema. */
|
|
27
|
+
schema?: string;
|
|
28
|
+
/** Driver connection options parsed from URL query parameters. */
|
|
29
|
+
driverOptions?: Options["driverOptions"];
|
|
26
30
|
}
|
|
27
31
|
/**
|
|
28
32
|
* Loads MikroORM configuration from environment variables.
|
|
29
33
|
*
|
|
30
34
|
* @remarks
|
|
31
|
-
* Supports
|
|
32
|
-
*
|
|
33
|
-
*
|
|
35
|
+
* Supports `DATABASE_URL`, which is parsed into individual connection options,
|
|
36
|
+
* including structured query options. The `postgresql:` and `postgres:`
|
|
37
|
+
* protocols select PostgreSQL, `mysql:` selects MySQL, and `file:` selects
|
|
38
|
+
* SQLite. Only the URL forms documented by those databases are accepted;
|
|
39
|
+
* other protocol names and driver-specific compatibility forms are rejected.
|
|
40
|
+
* PostgreSQL supports `sslmode=disable`, `require`, `verify-ca`, and
|
|
41
|
+
* `verify-full`; MySQL supports `ssl-mode=DISABLED`, `REQUIRED`, `VERIFY_CA`,
|
|
42
|
+
* and `VERIFY_IDENTITY`. Modes that require a plaintext fallback are rejected
|
|
43
|
+
* because one structured driver configuration cannot preserve that behavior.
|
|
34
44
|
*
|
|
35
45
|
* @returns MikroORM options derived from environment variables
|
|
36
46
|
*/
|
|
37
|
-
export declare function loadConfigFromEnv(): Promise<DriverConfig &
|
|
47
|
+
export declare function loadConfigFromEnv(): Promise<DriverConfig & HostConfig>;
|
|
@@ -34,77 +34,220 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.loadConfigFromEnv = loadConfigFromEnv;
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
const promises_1 = require("node:fs/promises");
|
|
38
|
+
const node_url_1 = require("node:url");
|
|
39
|
+
const load_default_config_util_1 = require("./load-default-config.util");
|
|
40
|
+
async function getDriver(protocol) {
|
|
41
|
+
switch (protocol) {
|
|
42
|
+
case "file:":
|
|
43
|
+
return (await Promise.resolve().then(() => __importStar(require("@mikro-orm/better-sqlite")))).BetterSqliteDriver;
|
|
44
|
+
case "mysql:":
|
|
42
45
|
return (await Promise.resolve().then(() => __importStar(require("@mikro-orm/mysql")))).MySqlDriver;
|
|
43
|
-
case "postgres":
|
|
44
|
-
case "postgresql":
|
|
46
|
+
case "postgres:":
|
|
47
|
+
case "postgresql:":
|
|
45
48
|
return (await Promise.resolve().then(() => __importStar(require("@mikro-orm/postgresql")))).PostgreSqlDriver;
|
|
49
|
+
default:
|
|
50
|
+
throw new TypeError(`Unsupported DATABASE_URL protocol: ${protocol}`);
|
|
46
51
|
}
|
|
47
52
|
}
|
|
53
|
+
function normalizeHostname(hostname) {
|
|
54
|
+
if (hostname.startsWith("[") && hostname.endsWith("]")) {
|
|
55
|
+
return hostname.slice(1, -1);
|
|
56
|
+
}
|
|
57
|
+
return hostname;
|
|
58
|
+
}
|
|
59
|
+
async function loadTlsFiles(files) {
|
|
60
|
+
const ssl = {};
|
|
61
|
+
let hasTlsFile = false;
|
|
62
|
+
for (const [path, sslKey] of files) {
|
|
63
|
+
if (typeof path === "string" && path) {
|
|
64
|
+
ssl[sslKey] = await (0, promises_1.readFile)(path, "utf8");
|
|
65
|
+
hasTlsFile = true;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return hasTlsFile ? ssl : undefined;
|
|
69
|
+
}
|
|
70
|
+
async function loadPostgreSqlTlsFiles(connection) {
|
|
71
|
+
const ssl = await loadTlsFiles([
|
|
72
|
+
[connection.sslrootcert, "ca"],
|
|
73
|
+
[connection.sslcert, "cert"],
|
|
74
|
+
[connection.sslkey, "key"],
|
|
75
|
+
]);
|
|
76
|
+
delete connection.sslrootcert;
|
|
77
|
+
delete connection.sslcert;
|
|
78
|
+
delete connection.sslkey;
|
|
79
|
+
return ssl;
|
|
80
|
+
}
|
|
81
|
+
async function loadMySqlTlsConfig(connection) {
|
|
82
|
+
const supportedParameters = ["ssl-mode", "ssl-ca", "ssl-cert", "ssl-key"];
|
|
83
|
+
for (const parameter of Object.keys(connection)) {
|
|
84
|
+
if (!supportedParameters.includes(parameter)) {
|
|
85
|
+
throw new TypeError(`Unsupported MySQL DATABASE_URL parameter: ${parameter}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const sslMode = connection["ssl-mode"];
|
|
89
|
+
const tlsFiles = [
|
|
90
|
+
[connection["ssl-ca"], "ca"],
|
|
91
|
+
[connection["ssl-cert"], "cert"],
|
|
92
|
+
[connection["ssl-key"], "key"],
|
|
93
|
+
];
|
|
94
|
+
delete connection["ssl-ca"];
|
|
95
|
+
delete connection["ssl-cert"];
|
|
96
|
+
delete connection["ssl-key"];
|
|
97
|
+
delete connection["ssl-mode"];
|
|
98
|
+
const normalizedSslMode = typeof sslMode === "string" ? sslMode.toUpperCase() : sslMode;
|
|
99
|
+
if (normalizedSslMode === "DISABLED") {
|
|
100
|
+
connection.ssl = false;
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (normalizedSslMode === "PREFERRED") {
|
|
104
|
+
throw new TypeError("Unsupported MySQL ssl-mode: PREFERRED");
|
|
105
|
+
}
|
|
106
|
+
const ssl = await loadTlsFiles(tlsFiles);
|
|
107
|
+
switch (normalizedSslMode) {
|
|
108
|
+
case "REQUIRED":
|
|
109
|
+
connection.ssl = { ...ssl, rejectUnauthorized: false };
|
|
110
|
+
break;
|
|
111
|
+
case "VERIFY_CA":
|
|
112
|
+
if (!ssl?.ca) {
|
|
113
|
+
throw new TypeError("MySQL ssl-mode=VERIFY_CA requires ssl-ca");
|
|
114
|
+
}
|
|
115
|
+
connection.ssl = {
|
|
116
|
+
...ssl,
|
|
117
|
+
rejectUnauthorized: true,
|
|
118
|
+
verifyIdentity: false,
|
|
119
|
+
};
|
|
120
|
+
break;
|
|
121
|
+
case "VERIFY_IDENTITY":
|
|
122
|
+
if (!ssl?.ca) {
|
|
123
|
+
throw new TypeError("MySQL ssl-mode=VERIFY_IDENTITY requires ssl-ca");
|
|
124
|
+
}
|
|
125
|
+
connection.ssl = {
|
|
126
|
+
...ssl,
|
|
127
|
+
rejectUnauthorized: true,
|
|
128
|
+
verifyIdentity: true,
|
|
129
|
+
};
|
|
130
|
+
break;
|
|
131
|
+
case undefined:
|
|
132
|
+
if (ssl) {
|
|
133
|
+
connection.ssl = {
|
|
134
|
+
...ssl,
|
|
135
|
+
rejectUnauthorized: true,
|
|
136
|
+
verifyIdentity: false,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
break;
|
|
140
|
+
default:
|
|
141
|
+
throw new TypeError(`Unsupported MySQL ssl-mode: ${String(sslMode)}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
async function loadQueryConfig(url, protocol) {
|
|
145
|
+
const connection = Object.fromEntries(url.searchParams);
|
|
146
|
+
const schema = url.searchParams.get("schema") ?? undefined;
|
|
147
|
+
delete connection.schema;
|
|
148
|
+
if (protocol === "mysql:") {
|
|
149
|
+
await loadMySqlTlsConfig(connection);
|
|
150
|
+
}
|
|
151
|
+
if (protocol === "postgres:" || protocol === "postgresql:") {
|
|
152
|
+
if (connection.ssl !== undefined) {
|
|
153
|
+
throw new TypeError("Unsupported PostgreSQL DATABASE_URL parameter: ssl");
|
|
154
|
+
}
|
|
155
|
+
if (connection.uselibpqcompat !== undefined) {
|
|
156
|
+
throw new TypeError("Unsupported PostgreSQL DATABASE_URL parameter: uselibpqcompat");
|
|
157
|
+
}
|
|
158
|
+
const sslMode = connection.sslmode;
|
|
159
|
+
delete connection.uselibpqcompat;
|
|
160
|
+
delete connection.sslmode;
|
|
161
|
+
if (sslMode === "disable") {
|
|
162
|
+
delete connection.sslrootcert;
|
|
163
|
+
delete connection.sslcert;
|
|
164
|
+
delete connection.sslkey;
|
|
165
|
+
connection.ssl = false;
|
|
166
|
+
}
|
|
167
|
+
else if (sslMode === "allow" || sslMode === "prefer") {
|
|
168
|
+
throw new TypeError(`Unsupported PostgreSQL sslmode: ${sslMode}`);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
const tls = await loadPostgreSqlTlsFiles(connection);
|
|
172
|
+
if (tls) {
|
|
173
|
+
connection.ssl = tls;
|
|
174
|
+
}
|
|
175
|
+
switch (sslMode) {
|
|
176
|
+
case "require":
|
|
177
|
+
connection.ssl = tls?.ca
|
|
178
|
+
? { ...tls, checkServerIdentity: () => undefined }
|
|
179
|
+
: { ...tls, rejectUnauthorized: false };
|
|
180
|
+
break;
|
|
181
|
+
case "verify-ca":
|
|
182
|
+
if (!tls?.ca) {
|
|
183
|
+
throw new TypeError("PostgreSQL sslmode=verify-ca requires sslrootcert");
|
|
184
|
+
}
|
|
185
|
+
connection.ssl = { ...tls, checkServerIdentity: () => undefined };
|
|
186
|
+
break;
|
|
187
|
+
case "verify-full":
|
|
188
|
+
connection.ssl = tls ?? {};
|
|
189
|
+
break;
|
|
190
|
+
case undefined:
|
|
191
|
+
break;
|
|
192
|
+
default:
|
|
193
|
+
throw new TypeError(`Unsupported PostgreSQL sslmode: ${String(sslMode)}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
schema,
|
|
199
|
+
driverOptions: Object.keys(connection).length ? { connection } : undefined,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
48
202
|
/**
|
|
49
203
|
* Loads MikroORM configuration from environment variables.
|
|
50
204
|
*
|
|
51
205
|
* @remarks
|
|
52
|
-
* Supports
|
|
53
|
-
*
|
|
54
|
-
*
|
|
206
|
+
* Supports `DATABASE_URL`, which is parsed into individual connection options,
|
|
207
|
+
* including structured query options. The `postgresql:` and `postgres:`
|
|
208
|
+
* protocols select PostgreSQL, `mysql:` selects MySQL, and `file:` selects
|
|
209
|
+
* SQLite. Only the URL forms documented by those databases are accepted;
|
|
210
|
+
* other protocol names and driver-specific compatibility forms are rejected.
|
|
211
|
+
* PostgreSQL supports `sslmode=disable`, `require`, `verify-ca`, and
|
|
212
|
+
* `verify-full`; MySQL supports `ssl-mode=DISABLED`, `REQUIRED`, `VERIFY_CA`,
|
|
213
|
+
* and `VERIFY_IDENTITY`. Modes that require a plaintext fallback are rejected
|
|
214
|
+
* because one structured driver configuration cannot preserve that behavior.
|
|
55
215
|
*
|
|
56
216
|
* @returns MikroORM options derived from environment variables
|
|
57
217
|
*/
|
|
58
218
|
async function loadConfigFromEnv() {
|
|
59
|
-
const baseConfig =
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
seeder: {
|
|
73
|
-
path: "dist/database/seeders",
|
|
74
|
-
pathTs: "src/database/seeders",
|
|
75
|
-
defaultSeeder: "DatabaseSeeder",
|
|
76
|
-
fileName: (className) => className,
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
const dbUrl = process.env.DB_URL ?? process.env.DATABASE_URL;
|
|
80
|
-
if (dbUrl) {
|
|
81
|
-
const dbType = new URL(dbUrl).protocol.replace(":", "");
|
|
219
|
+
const baseConfig = (0, load_default_config_util_1.loadDefaultConfig)();
|
|
220
|
+
const databaseUrl = process.env.DATABASE_URL;
|
|
221
|
+
if (databaseUrl) {
|
|
222
|
+
const url = new URL(databaseUrl);
|
|
223
|
+
const driver = await getDriver(url.protocol);
|
|
224
|
+
if (url.protocol === "file:") {
|
|
225
|
+
return {
|
|
226
|
+
...baseConfig,
|
|
227
|
+
driver,
|
|
228
|
+
dbName: (0, node_url_1.fileURLToPath)(url),
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
const dbName = url.pathname.slice(1);
|
|
82
232
|
return {
|
|
83
233
|
...baseConfig,
|
|
84
|
-
driver
|
|
85
|
-
|
|
234
|
+
driver,
|
|
235
|
+
host: normalizeHostname(url.hostname),
|
|
236
|
+
port: +url.port,
|
|
237
|
+
dbName: dbName ? decodeURIComponent(dbName) : undefined,
|
|
238
|
+
user: decodeURIComponent(url.username),
|
|
239
|
+
password: decodeURIComponent(url.password),
|
|
240
|
+
...(await loadQueryConfig(url, url.protocol)),
|
|
86
241
|
};
|
|
87
242
|
}
|
|
88
|
-
const dbType = process.env.DB_TYPE ?? process.env.DATABASE_TYPE;
|
|
89
|
-
const dbHost = process.env.DB_HOST ?? process.env.DATABASE_HOST;
|
|
90
|
-
const dbPort = process.env.DB_PORT ?? process.env.DATABASE_PORT;
|
|
91
|
-
const dbName = process.env.DB_NAME ?? process.env.DB_DATABASE ?? process.env.DATABASE_NAME;
|
|
92
|
-
const dbUsername = process.env.DB_USER ??
|
|
93
|
-
process.env.DB_USERNAME ??
|
|
94
|
-
process.env.DATABASE_USER ??
|
|
95
|
-
process.env.DATABASE_USERNAME;
|
|
96
|
-
const dbPassword = process.env.DB_PASS ??
|
|
97
|
-
process.env.DB_PASSWORD ??
|
|
98
|
-
process.env.DATABASE_PASS ??
|
|
99
|
-
process.env.DATABASE_PASSWORD;
|
|
100
243
|
return {
|
|
101
244
|
...baseConfig,
|
|
102
|
-
driver:
|
|
103
|
-
host:
|
|
104
|
-
port:
|
|
105
|
-
dbName,
|
|
106
|
-
user:
|
|
107
|
-
password:
|
|
245
|
+
driver: undefined,
|
|
246
|
+
host: undefined,
|
|
247
|
+
port: undefined,
|
|
248
|
+
dbName: undefined,
|
|
249
|
+
user: undefined,
|
|
250
|
+
password: undefined,
|
|
108
251
|
};
|
|
109
252
|
}
|
|
110
253
|
//# sourceMappingURL=load-config-from-env.util.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-config-from-env.util.js","sourceRoot":"","sources":["../../src/utils/load-config-from-env.util.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"load-config-from-env.util.js","sourceRoot":"","sources":["../../src/utils/load-config-from-env.util.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,29 +1,55 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const promises_1 = require("node:fs/promises");
|
|
4
|
+
const node_os_1 = require("node:os");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const better_sqlite_1 = require("@mikro-orm/better-sqlite");
|
|
3
7
|
const core_1 = require("@mikro-orm/core");
|
|
4
8
|
const mysql_1 = require("@mikro-orm/mysql");
|
|
5
9
|
const postgresql_1 = require("@mikro-orm/postgresql");
|
|
6
10
|
const reflection_1 = require("@mikro-orm/reflection");
|
|
7
11
|
const load_config_from_env_util_1 = require("./load-config-from-env.util");
|
|
8
12
|
const ORIGINAL_ENV = process.env;
|
|
13
|
+
async function withTlsFiles(callback) {
|
|
14
|
+
const directory = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "nest-boot-mikro-orm-"));
|
|
15
|
+
const paths = {
|
|
16
|
+
clientCert: (0, node_path_1.join)(directory, "client.crt"),
|
|
17
|
+
clientKey: (0, node_path_1.join)(directory, "client.key"),
|
|
18
|
+
rootCert: (0, node_path_1.join)(directory, "root.crt"),
|
|
19
|
+
};
|
|
20
|
+
try {
|
|
21
|
+
await Promise.all([
|
|
22
|
+
(0, promises_1.writeFile)(paths.rootCert, "root certificate"),
|
|
23
|
+
(0, promises_1.writeFile)(paths.clientCert, "client certificate"),
|
|
24
|
+
(0, promises_1.writeFile)(paths.clientKey, "client key"),
|
|
25
|
+
]);
|
|
26
|
+
await callback(paths);
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
await (0, promises_1.rm)(directory, { force: true, recursive: true });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
9
32
|
describe("loadConfigFromEnv", () => {
|
|
10
33
|
beforeEach(() => {
|
|
11
|
-
process.env =
|
|
34
|
+
process.env = { ...ORIGINAL_ENV };
|
|
35
|
+
delete process.env.DATABASE_URL;
|
|
12
36
|
});
|
|
13
37
|
afterAll(() => {
|
|
14
38
|
process.env = ORIGINAL_ENV;
|
|
15
39
|
});
|
|
16
40
|
it("should load URL-based MySQL config", async () => {
|
|
17
|
-
process.env.
|
|
18
|
-
|
|
19
|
-
await
|
|
20
|
-
|
|
41
|
+
process.env.DATABASE_URL =
|
|
42
|
+
"mysql://user%40example.com:p%40ss%2Fword@localhost:3306/app";
|
|
43
|
+
const config = await (0, load_config_from_env_util_1.loadConfigFromEnv)();
|
|
44
|
+
expect(config).toMatchObject({
|
|
21
45
|
colors: false,
|
|
22
46
|
dataloader: core_1.DataloaderType.ALL,
|
|
23
|
-
|
|
47
|
+
dbName: "app",
|
|
48
|
+
debug: false,
|
|
24
49
|
driver: mysql_1.MySqlDriver,
|
|
25
50
|
entities: ["dist/**/*.entity.js"],
|
|
26
51
|
entitiesTs: ["src/**/*.entity.ts"],
|
|
52
|
+
host: "localhost",
|
|
27
53
|
metadataProvider: reflection_1.TsMorphMetadataProvider,
|
|
28
54
|
migrations: {
|
|
29
55
|
path: "dist/database/migrations",
|
|
@@ -35,33 +61,234 @@ describe("loadConfigFromEnv", () => {
|
|
|
35
61
|
path: "dist/database/seeders",
|
|
36
62
|
pathTs: "src/database/seeders",
|
|
37
63
|
},
|
|
64
|
+
password: "p@ss/word",
|
|
65
|
+
port: 3306,
|
|
38
66
|
timezone: "UTC",
|
|
67
|
+
user: "user@example.com",
|
|
39
68
|
});
|
|
69
|
+
expect(config).not.toHaveProperty("clientUrl");
|
|
70
|
+
expect(config.seeder?.fileName?.("CustomSeeder")).toBe("CustomSeeder");
|
|
40
71
|
});
|
|
41
72
|
it("should load URL-based PostgreSQL config", async () => {
|
|
42
|
-
process.env.DATABASE_URL =
|
|
73
|
+
process.env.DATABASE_URL =
|
|
74
|
+
"postgresql://user:pass@[2001:db8::1]:5432/app?schema=tenant&sslmode=require&application_name=nest-boot";
|
|
43
75
|
await expect((0, load_config_from_env_util_1.loadConfigFromEnv)()).resolves.toMatchObject({
|
|
44
|
-
|
|
76
|
+
dbName: "app",
|
|
45
77
|
driver: postgresql_1.PostgreSqlDriver,
|
|
78
|
+
driverOptions: {
|
|
79
|
+
connection: {
|
|
80
|
+
application_name: "nest-boot",
|
|
81
|
+
ssl: {},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
host: "2001:db8::1",
|
|
85
|
+
password: "pass",
|
|
86
|
+
port: 5432,
|
|
87
|
+
schema: "tenant",
|
|
88
|
+
user: "user",
|
|
46
89
|
});
|
|
47
90
|
});
|
|
48
|
-
it("should load
|
|
49
|
-
process.env.
|
|
50
|
-
process.env.DATABASE_HOST = "localhost";
|
|
51
|
-
process.env.DATABASE_PORT = "5432";
|
|
52
|
-
process.env.DATABASE_NAME = "app";
|
|
53
|
-
process.env.DATABASE_USERNAME = "user";
|
|
54
|
-
process.env.DATABASE_PASSWORD = "pass";
|
|
91
|
+
it("should load the postgres PostgreSQL URI form", async () => {
|
|
92
|
+
process.env.DATABASE_URL = "postgres://user:pass@localhost/app";
|
|
55
93
|
await expect((0, load_config_from_env_util_1.loadConfigFromEnv)()).resolves.toMatchObject({
|
|
56
94
|
dbName: "app",
|
|
57
95
|
driver: postgresql_1.PostgreSqlDriver,
|
|
58
96
|
host: "localhost",
|
|
59
97
|
password: "pass",
|
|
60
|
-
port: 5432,
|
|
61
98
|
user: "user",
|
|
62
99
|
});
|
|
63
100
|
});
|
|
64
|
-
it("should
|
|
101
|
+
it("should load a file URL as SQLite config", async () => {
|
|
102
|
+
process.env.DATABASE_URL = "file:///var/lib/nest-boot/app%20data.db";
|
|
103
|
+
await expect((0, load_config_from_env_util_1.loadConfigFromEnv)()).resolves.toMatchObject({
|
|
104
|
+
dbName: "/var/lib/nest-boot/app data.db",
|
|
105
|
+
driver: better_sqlite_1.BetterSqliteDriver,
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
it.each([
|
|
109
|
+
["mysql", "ssl-mode=DISABLED", { ssl: false }],
|
|
110
|
+
["mysql", "ssl-mode=REQUIRED", { ssl: { rejectUnauthorized: false } }],
|
|
111
|
+
["postgresql", "sslmode=disable", { ssl: false }],
|
|
112
|
+
["postgresql", "sslmode=require", { ssl: { rejectUnauthorized: false } }],
|
|
113
|
+
["postgresql", "sslmode=verify-full", { ssl: {} }],
|
|
114
|
+
])("should parse %s driver query option %s", async (protocol, query, expected) => {
|
|
115
|
+
process.env.DATABASE_URL = `${protocol}://user:pass@localhost/app?${query}`;
|
|
116
|
+
await expect((0, load_config_from_env_util_1.loadConfigFromEnv)()).resolves.toMatchObject({
|
|
117
|
+
driverOptions: {
|
|
118
|
+
connection: expected,
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
it("should preserve omitted URL credentials and port", async () => {
|
|
123
|
+
process.env.DATABASE_URL = "postgresql://db.internal";
|
|
124
|
+
const config = await (0, load_config_from_env_util_1.loadConfigFromEnv)();
|
|
125
|
+
expect(config).toMatchObject({
|
|
126
|
+
dbName: undefined,
|
|
127
|
+
host: "db.internal",
|
|
128
|
+
password: "",
|
|
129
|
+
port: 0,
|
|
130
|
+
user: "",
|
|
131
|
+
});
|
|
132
|
+
const mikroOrmConfig = new core_1.Configuration(config, false);
|
|
133
|
+
expect(mikroOrmConfig.getDriver().getConnection().getConnectionOptions()).toMatchObject({
|
|
134
|
+
host: "db.internal",
|
|
135
|
+
password: "",
|
|
136
|
+
port: 0,
|
|
137
|
+
user: "",
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
it("should load PostgreSQL TLS files into structured SSL options", async () => {
|
|
141
|
+
await withTlsFiles(async ({ clientCert, clientKey, rootCert }) => {
|
|
142
|
+
const databaseUrl = new URL("postgresql://user:pass@localhost/app");
|
|
143
|
+
databaseUrl.searchParams.set("sslmode", "verify-full");
|
|
144
|
+
databaseUrl.searchParams.set("sslrootcert", rootCert);
|
|
145
|
+
databaseUrl.searchParams.set("sslcert", clientCert);
|
|
146
|
+
databaseUrl.searchParams.set("sslkey", clientKey);
|
|
147
|
+
process.env.DATABASE_URL = databaseUrl.href;
|
|
148
|
+
await expect((0, load_config_from_env_util_1.loadConfigFromEnv)()).resolves.toMatchObject({
|
|
149
|
+
driverOptions: {
|
|
150
|
+
connection: {
|
|
151
|
+
ssl: {
|
|
152
|
+
ca: "root certificate",
|
|
153
|
+
cert: "client certificate",
|
|
154
|
+
key: "client key",
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
it.each(["require", "verify-ca"])("should map PostgreSQL sslmode=%s with a root certificate", async (sslMode) => {
|
|
162
|
+
await withTlsFiles(async ({ rootCert }) => {
|
|
163
|
+
const databaseUrl = new URL("postgresql://user:pass@localhost/app");
|
|
164
|
+
databaseUrl.searchParams.set("sslmode", sslMode);
|
|
165
|
+
databaseUrl.searchParams.set("sslrootcert", rootCert);
|
|
166
|
+
process.env.DATABASE_URL = databaseUrl.href;
|
|
167
|
+
const config = await (0, load_config_from_env_util_1.loadConfigFromEnv)();
|
|
168
|
+
const connection = config.driverOptions?.connection;
|
|
169
|
+
const ssl = connection.ssl;
|
|
170
|
+
expect(ssl).toMatchObject({
|
|
171
|
+
ca: "root certificate",
|
|
172
|
+
checkServerIdentity: expect.any(Function),
|
|
173
|
+
});
|
|
174
|
+
const checkServerIdentity = ssl.checkServerIdentity;
|
|
175
|
+
checkServerIdentity();
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
it("should load MySQL TLS files into structured SSL options", async () => {
|
|
179
|
+
await withTlsFiles(async ({ clientCert, clientKey, rootCert }) => {
|
|
180
|
+
const databaseUrl = new URL("mysql://user:pass@localhost/app");
|
|
181
|
+
databaseUrl.searchParams.set("ssl-ca", rootCert);
|
|
182
|
+
databaseUrl.searchParams.set("ssl-cert", clientCert);
|
|
183
|
+
databaseUrl.searchParams.set("ssl-key", clientKey);
|
|
184
|
+
process.env.DATABASE_URL = databaseUrl.href;
|
|
185
|
+
const config = await (0, load_config_from_env_util_1.loadConfigFromEnv)();
|
|
186
|
+
expect(config.driverOptions).toEqual({
|
|
187
|
+
connection: {
|
|
188
|
+
ssl: {
|
|
189
|
+
ca: "root certificate",
|
|
190
|
+
cert: "client certificate",
|
|
191
|
+
key: "client key",
|
|
192
|
+
rejectUnauthorized: true,
|
|
193
|
+
verifyIdentity: false,
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
it.each([
|
|
200
|
+
["VERIFY_CA", false],
|
|
201
|
+
["VERIFY_IDENTITY", true],
|
|
202
|
+
])("should map MySQL ssl-mode=%s with a CA certificate", async (sslMode, verifyIdentity) => {
|
|
203
|
+
await withTlsFiles(async ({ rootCert }) => {
|
|
204
|
+
const databaseUrl = new URL("mysql://user:pass@localhost/app");
|
|
205
|
+
databaseUrl.searchParams.set("ssl-mode", sslMode);
|
|
206
|
+
databaseUrl.searchParams.set("ssl-ca", rootCert);
|
|
207
|
+
process.env.DATABASE_URL = databaseUrl.href;
|
|
208
|
+
await expect((0, load_config_from_env_util_1.loadConfigFromEnv)()).resolves.toMatchObject({
|
|
209
|
+
driverOptions: {
|
|
210
|
+
connection: {
|
|
211
|
+
ssl: {
|
|
212
|
+
ca: "root certificate",
|
|
213
|
+
rejectUnauthorized: true,
|
|
214
|
+
verifyIdentity,
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
it("should not read MySQL TLS files when SSL is disabled", async () => {
|
|
222
|
+
process.env.DATABASE_URL =
|
|
223
|
+
"mysql://user:pass@localhost/app?ssl-mode=DISABLED&ssl-ca=/missing/ca.pem";
|
|
224
|
+
await expect((0, load_config_from_env_util_1.loadConfigFromEnv)()).resolves.toMatchObject({
|
|
225
|
+
driverOptions: {
|
|
226
|
+
connection: {
|
|
227
|
+
ssl: false,
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
it("should reject unsupported MySQL SSL modes", async () => {
|
|
233
|
+
process.env.DATABASE_URL =
|
|
234
|
+
"mysql://user:pass@localhost/app?ssl-mode=VERIFY_HOSTNAME";
|
|
235
|
+
await expect((0, load_config_from_env_util_1.loadConfigFromEnv)()).rejects.toThrow("Unsupported MySQL ssl-mode: VERIFY_HOSTNAME");
|
|
236
|
+
});
|
|
237
|
+
it.each([
|
|
238
|
+
["mysql://user:pass@localhost/app?ssl-mode=PREFERRED", "PREFERRED"],
|
|
239
|
+
["postgresql://user:pass@localhost/app?sslmode=allow", "allow"],
|
|
240
|
+
["postgresql://user:pass@localhost/app?sslmode=prefer", "prefer"],
|
|
241
|
+
])("should reject SSL fallback mode %s that structured options cannot express", async (databaseUrl, sslMode) => {
|
|
242
|
+
process.env.DATABASE_URL = databaseUrl;
|
|
243
|
+
await expect((0, load_config_from_env_util_1.loadConfigFromEnv)()).rejects.toThrow(`Unsupported ${databaseUrl.startsWith("mysql:") ? "MySQL ssl-mode" : "PostgreSQL sslmode"}: ${sslMode}`);
|
|
244
|
+
});
|
|
245
|
+
it.each(["VERIFY_CA", "VERIFY_IDENTITY"])("should require ssl-ca for MySQL ssl-mode=%s", async (sslMode) => {
|
|
246
|
+
process.env.DATABASE_URL = `mysql://user:pass@localhost/app?ssl-mode=${sslMode}`;
|
|
247
|
+
await expect((0, load_config_from_env_util_1.loadConfigFromEnv)()).rejects.toThrow(`MySQL ssl-mode=${sslMode} requires ssl-ca`);
|
|
248
|
+
});
|
|
249
|
+
it("should require sslrootcert for PostgreSQL verify-ca", async () => {
|
|
250
|
+
process.env.DATABASE_URL =
|
|
251
|
+
"postgresql://user:pass@localhost/app?sslmode=verify-ca";
|
|
252
|
+
await expect((0, load_config_from_env_util_1.loadConfigFromEnv)()).rejects.toThrow("PostgreSQL sslmode=verify-ca requires sslrootcert");
|
|
253
|
+
});
|
|
254
|
+
it.each([
|
|
255
|
+
[
|
|
256
|
+
"mysql://user:pass@localhost/app?ssl=true",
|
|
257
|
+
"Unsupported MySQL DATABASE_URL parameter: ssl",
|
|
258
|
+
],
|
|
259
|
+
[
|
|
260
|
+
"mysql://user:pass@localhost/app?multipleStatements=false",
|
|
261
|
+
"Unsupported MySQL DATABASE_URL parameter: multipleStatements",
|
|
262
|
+
],
|
|
263
|
+
[
|
|
264
|
+
"postgresql://user:pass@localhost/app?ssl=true",
|
|
265
|
+
"Unsupported PostgreSQL DATABASE_URL parameter: ssl",
|
|
266
|
+
],
|
|
267
|
+
[
|
|
268
|
+
"postgresql://user:pass@localhost/app?ssl=1",
|
|
269
|
+
"Unsupported PostgreSQL DATABASE_URL parameter: ssl",
|
|
270
|
+
],
|
|
271
|
+
[
|
|
272
|
+
"postgresql://user:pass@localhost/app?uselibpqcompat=true",
|
|
273
|
+
"Unsupported PostgreSQL DATABASE_URL parameter: uselibpqcompat",
|
|
274
|
+
],
|
|
275
|
+
[
|
|
276
|
+
"postgresql://user:pass@localhost/app?sslmode=no-verify",
|
|
277
|
+
"Unsupported PostgreSQL sslmode: no-verify",
|
|
278
|
+
],
|
|
279
|
+
])("should reject non-standard database URL options", async (url, error) => {
|
|
280
|
+
process.env.DATABASE_URL = url;
|
|
281
|
+
await expect((0, load_config_from_env_util_1.loadConfigFromEnv)()).rejects.toThrow(error);
|
|
282
|
+
});
|
|
283
|
+
it.each(["mysql2://localhost/app", "sqlite:///var/lib/app.db"])("should reject non-standard database URL %s", async (databaseUrl) => {
|
|
284
|
+
process.env.DATABASE_URL = databaseUrl;
|
|
285
|
+
await expect((0, load_config_from_env_util_1.loadConfigFromEnv)()).rejects.toThrow(`Unsupported DATABASE_URL protocol: ${new URL(databaseUrl).protocol}`);
|
|
286
|
+
});
|
|
287
|
+
it("should reject unsupported database URL protocols", async () => {
|
|
288
|
+
process.env.DATABASE_URL = "mongodb://localhost/app";
|
|
289
|
+
await expect((0, load_config_from_env_util_1.loadConfigFromEnv)()).rejects.toThrow("Unsupported DATABASE_URL protocol: mongodb:");
|
|
290
|
+
});
|
|
291
|
+
it("should return undefined connection fields when DATABASE_URL is absent", async () => {
|
|
65
292
|
await expect((0, load_config_from_env_util_1.loadConfigFromEnv)()).resolves.toMatchObject({
|
|
66
293
|
dbName: undefined,
|
|
67
294
|
driver: undefined,
|