@jongodb/memory-server 0.1.1 → 0.1.3
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/README.md +123 -134
- package/dist/cjs/index.js +588 -0
- package/dist/cjs/jest.js +172 -0
- package/dist/cjs/nestjs.js +10 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/runtime.js +100 -0
- package/dist/cjs/vitest.js +18 -0
- package/dist/{index.d.ts → esm/index.d.ts} +3 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/{index.js → esm/index.js} +52 -6
- package/dist/{jest.d.ts → esm/jest.d.ts} +1 -0
- package/dist/esm/jest.d.ts.map +1 -0
- package/dist/esm/nestjs.d.ts.map +1 -0
- package/dist/{runtime.d.ts → esm/runtime.d.ts} +2 -0
- package/dist/esm/runtime.d.ts.map +1 -0
- package/dist/esm/runtime.js +97 -0
- package/dist/{vitest.d.ts → esm/vitest.d.ts} +1 -0
- package/dist/esm/vitest.d.ts.map +1 -0
- package/package.json +41 -24
- package/dist/index.d.ts.map +0 -1
- package/dist/jest.d.ts.map +0 -1
- package/dist/nestjs.d.ts.map +0 -1
- package/dist/runtime.d.ts.map +0 -1
- package/dist/runtime.js +0 -55
- package/dist/vitest.d.ts.map +0 -1
- /package/dist/{jest.js → esm/jest.js} +0 -0
- /package/dist/{nestjs.d.ts → esm/nestjs.d.ts} +0 -0
- /package/dist/{nestjs.js → esm/nestjs.js} +0 -0
- /package/dist/{vitest.js → esm/vitest.js} +0 -0
package/dist/cjs/jest.js
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
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.registerJongodbForJest = registerJongodbForJest;
|
|
7
|
+
exports.createJestGlobalSetup = createJestGlobalSetup;
|
|
8
|
+
exports.createJestGlobalTeardown = createJestGlobalTeardown;
|
|
9
|
+
exports.readJestGlobalState = readJestGlobalState;
|
|
10
|
+
exports.readJestGlobalUri = readJestGlobalUri;
|
|
11
|
+
const promises_1 = require("node:fs/promises");
|
|
12
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
13
|
+
const index_js_1 = require("./index.js");
|
|
14
|
+
const runtime_js_1 = require("./runtime.js");
|
|
15
|
+
const DEFAULT_ENV_VAR_NAME = "MONGODB_URI";
|
|
16
|
+
const DEFAULT_STATE_FILE = node_path_1.default.join(process.cwd(), ".jongodb", "jest-memory-server.json");
|
|
17
|
+
const DEFAULT_STOP_TIMEOUT_MS = 5_000;
|
|
18
|
+
function registerJongodbForJest(hooks, options = {}) {
|
|
19
|
+
const runtime = (0, runtime_js_1.createJongodbEnvRuntime)(options);
|
|
20
|
+
hooks.beforeAll(async () => {
|
|
21
|
+
await runtime.setup();
|
|
22
|
+
});
|
|
23
|
+
hooks.afterAll(async () => {
|
|
24
|
+
await runtime.teardown();
|
|
25
|
+
});
|
|
26
|
+
return {
|
|
27
|
+
get uri() {
|
|
28
|
+
return runtime.uri;
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function createJestGlobalSetup(options = {}) {
|
|
33
|
+
return async () => {
|
|
34
|
+
const { envVarName, stateFile, runtimeOptions } = splitLifecycleOptions(options);
|
|
35
|
+
const server = await (0, index_js_1.startJongodbMemoryServer)(runtimeOptions);
|
|
36
|
+
process.env[envVarName] = server.uri;
|
|
37
|
+
await (0, promises_1.mkdir)(node_path_1.default.dirname(stateFile), { recursive: true });
|
|
38
|
+
const state = {
|
|
39
|
+
uri: server.uri,
|
|
40
|
+
pid: server.pid,
|
|
41
|
+
envVarName,
|
|
42
|
+
};
|
|
43
|
+
await (0, promises_1.writeFile)(stateFile, JSON.stringify(state, null, 2), "utf8");
|
|
44
|
+
server.detach();
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function createJestGlobalTeardown(options = {}) {
|
|
48
|
+
return async () => {
|
|
49
|
+
const { stateFile } = splitLifecycleOptions(options);
|
|
50
|
+
const state = await readJestGlobalState({ stateFile });
|
|
51
|
+
if (state === null) {
|
|
52
|
+
await (0, promises_1.rm)(stateFile, { force: true });
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
await terminatePid(state.pid, options.killTimeoutMs ?? DEFAULT_STOP_TIMEOUT_MS);
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
await (0, promises_1.rm)(stateFile, { force: true });
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
async function readJestGlobalState(options = {}) {
|
|
64
|
+
const stateFile = normalizeStateFile(options.stateFile);
|
|
65
|
+
try {
|
|
66
|
+
const raw = await (0, promises_1.readFile)(stateFile, "utf8");
|
|
67
|
+
const parsed = JSON.parse(raw);
|
|
68
|
+
if (typeof parsed.uri !== "string" ||
|
|
69
|
+
typeof parsed.pid !== "number" ||
|
|
70
|
+
typeof parsed.envVarName !== "string") {
|
|
71
|
+
throw new Error("Jest global state file has invalid schema.");
|
|
72
|
+
}
|
|
73
|
+
return parsed;
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (isMissingFileError(error)) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async function readJestGlobalUri(options = {}) {
|
|
83
|
+
const state = await readJestGlobalState(options);
|
|
84
|
+
if (state === null) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
return state.uri;
|
|
88
|
+
}
|
|
89
|
+
function splitLifecycleOptions(options) {
|
|
90
|
+
const { envVarName, stateFile, killTimeoutMs: _killTimeoutMs, ...runtimeOptions } = options;
|
|
91
|
+
return {
|
|
92
|
+
envVarName: normalizeEnvVarName(envVarName),
|
|
93
|
+
stateFile: normalizeStateFile(stateFile),
|
|
94
|
+
runtimeOptions,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function normalizeEnvVarName(name) {
|
|
98
|
+
const normalized = name?.trim() || DEFAULT_ENV_VAR_NAME;
|
|
99
|
+
if (normalized.length === 0) {
|
|
100
|
+
throw new Error("envVarName must not be empty.");
|
|
101
|
+
}
|
|
102
|
+
return normalized;
|
|
103
|
+
}
|
|
104
|
+
function normalizeStateFile(stateFile) {
|
|
105
|
+
const normalized = stateFile?.trim() || DEFAULT_STATE_FILE;
|
|
106
|
+
if (normalized.length === 0) {
|
|
107
|
+
throw new Error("stateFile must not be empty.");
|
|
108
|
+
}
|
|
109
|
+
return normalized;
|
|
110
|
+
}
|
|
111
|
+
async function terminatePid(pid, timeoutMs) {
|
|
112
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
113
|
+
throw new Error(`Invalid PID in Jest global state: ${pid}`);
|
|
114
|
+
}
|
|
115
|
+
if (!isProcessRunning(pid)) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
process.kill(pid, "SIGTERM");
|
|
119
|
+
const deadline = Date.now() + timeoutMs;
|
|
120
|
+
while (Date.now() < deadline) {
|
|
121
|
+
if (!isProcessRunning(pid)) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
await sleep(50);
|
|
125
|
+
}
|
|
126
|
+
if (!isProcessRunning(pid)) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
process.kill(pid, "SIGKILL");
|
|
130
|
+
await waitForProcessExit(pid, timeoutMs);
|
|
131
|
+
if (isProcessRunning(pid)) {
|
|
132
|
+
throw new Error(`Unable to stop detached Jest process pid=${pid} after SIGKILL.`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function isProcessRunning(pid) {
|
|
136
|
+
try {
|
|
137
|
+
process.kill(pid, 0);
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
if (isNoSuchProcessError(error)) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function isNoSuchProcessError(error) {
|
|
148
|
+
return (typeof error === "object" &&
|
|
149
|
+
error !== null &&
|
|
150
|
+
"code" in error &&
|
|
151
|
+
error.code === "ESRCH");
|
|
152
|
+
}
|
|
153
|
+
function isMissingFileError(error) {
|
|
154
|
+
return (typeof error === "object" &&
|
|
155
|
+
error !== null &&
|
|
156
|
+
"code" in error &&
|
|
157
|
+
error.code === "ENOENT");
|
|
158
|
+
}
|
|
159
|
+
function sleep(ms) {
|
|
160
|
+
return new Promise((resolve) => {
|
|
161
|
+
setTimeout(resolve, ms);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
async function waitForProcessExit(pid, timeoutMs) {
|
|
165
|
+
const deadline = Date.now() + timeoutMs;
|
|
166
|
+
while (Date.now() < deadline) {
|
|
167
|
+
if (!isProcessRunning(pid)) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
await sleep(50);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerJongodbForNestJest = registerJongodbForNestJest;
|
|
4
|
+
const jest_js_1 = require("./jest.js");
|
|
5
|
+
/**
|
|
6
|
+
* Convenience wrapper for NestJS E2E tests that run on Jest.
|
|
7
|
+
*/
|
|
8
|
+
function registerJongodbForNestJest(hooks, options = {}) {
|
|
9
|
+
return (0, jest_js_1.registerJongodbForJest)(hooks, options);
|
|
10
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createJongodbEnvRuntime = createJongodbEnvRuntime;
|
|
4
|
+
const index_js_1 = require("./index.js");
|
|
5
|
+
const DEFAULT_ENV_VAR_NAME = "MONGODB_URI";
|
|
6
|
+
function createJongodbEnvRuntime(options = {}) {
|
|
7
|
+
const envVarNames = resolveEnvVarNames(options);
|
|
8
|
+
const envVarName = envVarNames[0];
|
|
9
|
+
const { envVarName: _envVarName, envVarNames: _envVarNames, ...serverOptions } = options;
|
|
10
|
+
let runtimeServer = null;
|
|
11
|
+
let uri = null;
|
|
12
|
+
let previousEnvState = captureEnvState(envVarNames);
|
|
13
|
+
return {
|
|
14
|
+
envVarName,
|
|
15
|
+
envVarNames,
|
|
16
|
+
get running() {
|
|
17
|
+
return runtimeServer !== null;
|
|
18
|
+
},
|
|
19
|
+
get uri() {
|
|
20
|
+
if (uri === null) {
|
|
21
|
+
throw new Error("Jongodb URI is not available before setup completes.");
|
|
22
|
+
}
|
|
23
|
+
return uri;
|
|
24
|
+
},
|
|
25
|
+
async setup() {
|
|
26
|
+
if (runtimeServer !== null && uri !== null) {
|
|
27
|
+
return uri;
|
|
28
|
+
}
|
|
29
|
+
previousEnvState = captureEnvState(envVarNames);
|
|
30
|
+
runtimeServer = await (0, index_js_1.startJongodbMemoryServer)(serverOptions);
|
|
31
|
+
uri = runtimeServer.uri;
|
|
32
|
+
for (const candidate of envVarNames) {
|
|
33
|
+
process.env[candidate] = uri;
|
|
34
|
+
}
|
|
35
|
+
return uri;
|
|
36
|
+
},
|
|
37
|
+
async teardown() {
|
|
38
|
+
if (runtimeServer !== null) {
|
|
39
|
+
await runtimeServer.stop();
|
|
40
|
+
runtimeServer = null;
|
|
41
|
+
}
|
|
42
|
+
restoreEnvState(previousEnvState);
|
|
43
|
+
uri = null;
|
|
44
|
+
previousEnvState = captureEnvState(envVarNames);
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function resolveEnvVarNames(options) {
|
|
49
|
+
const explicitCandidates = [];
|
|
50
|
+
if (options.envVarName !== undefined) {
|
|
51
|
+
explicitCandidates.push(options.envVarName);
|
|
52
|
+
}
|
|
53
|
+
if (options.envVarNames !== undefined) {
|
|
54
|
+
explicitCandidates.push(...options.envVarNames);
|
|
55
|
+
}
|
|
56
|
+
if (explicitCandidates.length === 0) {
|
|
57
|
+
return [DEFAULT_ENV_VAR_NAME];
|
|
58
|
+
}
|
|
59
|
+
const resolved = [];
|
|
60
|
+
const seen = new Set();
|
|
61
|
+
for (const candidate of explicitCandidates) {
|
|
62
|
+
const normalized = normalizeEnvVarName(candidate);
|
|
63
|
+
if (seen.has(normalized)) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
seen.add(normalized);
|
|
67
|
+
resolved.push(normalized);
|
|
68
|
+
}
|
|
69
|
+
if (resolved.length === 0) {
|
|
70
|
+
return [DEFAULT_ENV_VAR_NAME];
|
|
71
|
+
}
|
|
72
|
+
return resolved;
|
|
73
|
+
}
|
|
74
|
+
function normalizeEnvVarName(name) {
|
|
75
|
+
const normalized = name.trim();
|
|
76
|
+
if (normalized.length === 0) {
|
|
77
|
+
throw new Error("envVarName/envVarNames entries must not be empty.");
|
|
78
|
+
}
|
|
79
|
+
return normalized;
|
|
80
|
+
}
|
|
81
|
+
function captureEnvState(envVarNames) {
|
|
82
|
+
const state = new Map();
|
|
83
|
+
for (const envVarName of envVarNames) {
|
|
84
|
+
state.set(envVarName, {
|
|
85
|
+
hadPrevious: Object.prototype.hasOwnProperty.call(process.env, envVarName),
|
|
86
|
+
previousValue: process.env[envVarName],
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return state;
|
|
90
|
+
}
|
|
91
|
+
function restoreEnvState(state) {
|
|
92
|
+
for (const [envVarName, previous] of state.entries()) {
|
|
93
|
+
if (previous.hadPrevious) {
|
|
94
|
+
process.env[envVarName] = previous.previousValue;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
delete process.env[envVarName];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerJongodbForVitest = registerJongodbForVitest;
|
|
4
|
+
const runtime_js_1 = require("./runtime.js");
|
|
5
|
+
function registerJongodbForVitest(hooks, options = {}) {
|
|
6
|
+
const runtime = (0, runtime_js_1.createJongodbEnvRuntime)(options);
|
|
7
|
+
hooks.beforeAll(async () => {
|
|
8
|
+
await runtime.setup();
|
|
9
|
+
});
|
|
10
|
+
hooks.afterAll(async () => {
|
|
11
|
+
await runtime.teardown();
|
|
12
|
+
});
|
|
13
|
+
return {
|
|
14
|
+
get uri() {
|
|
15
|
+
return runtime.uri;
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
type LogLevel = "silent" | "info" | "debug";
|
|
2
2
|
type LaunchMode = "auto" | "binary" | "java";
|
|
3
|
+
type DatabaseNameStrategy = "static" | "worker";
|
|
3
4
|
export interface JongodbMemoryServerOptions {
|
|
4
5
|
host?: string;
|
|
5
6
|
port?: number;
|
|
6
7
|
databaseName?: string;
|
|
8
|
+
databaseNameSuffix?: string;
|
|
9
|
+
databaseNameStrategy?: DatabaseNameStrategy;
|
|
7
10
|
startupTimeoutMs?: number;
|
|
8
11
|
stopTimeoutMs?: number;
|
|
9
12
|
javaPath?: string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAqBA,KAAK,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAC5C,KAAK,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AAC7C,KAAK,oBAAoB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEhD,MAAM,WAAW,0BAA0B;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,MAAM,IAAI,IAAI,CAAC;IACf,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAcD,wBAAsB,wBAAwB,CAC5C,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,mBAAmB,CAAC,CA6C9B"}
|
|
@@ -3,7 +3,7 @@ import { readFileSync } from "node:fs";
|
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { delimiter, dirname, resolve } from "node:path";
|
|
5
5
|
import { createInterface } from "node:readline";
|
|
6
|
-
const
|
|
6
|
+
const moduleRequire = createRequire(resolve(process.cwd(), "__jongodb_module_resolver__.js"));
|
|
7
7
|
const READY_PREFIX = "JONGODB_URI=";
|
|
8
8
|
const FAILURE_PREFIX = "JONGODB_START_FAILURE=";
|
|
9
9
|
const DEFAULT_HOST = "127.0.0.1";
|
|
@@ -18,7 +18,7 @@ export async function startJongodbMemoryServer(options = {}) {
|
|
|
18
18
|
const stopTimeoutMs = normalizeTimeout(options.stopTimeoutMs, DEFAULT_STOP_TIMEOUT_MS, "stopTimeoutMs");
|
|
19
19
|
const host = normalizeHost(options.host);
|
|
20
20
|
const port = normalizePort(options.port);
|
|
21
|
-
const databaseName =
|
|
21
|
+
const databaseName = resolveDatabaseName(options);
|
|
22
22
|
const logLevel = options.logLevel ?? "silent";
|
|
23
23
|
const launchConfigs = resolveLaunchConfigs(options, {
|
|
24
24
|
host,
|
|
@@ -264,7 +264,7 @@ function detectLinuxLibcVariant() {
|
|
|
264
264
|
}
|
|
265
265
|
function resolveBinaryPathFromPackage(packageName) {
|
|
266
266
|
try {
|
|
267
|
-
const packageJsonPath =
|
|
267
|
+
const packageJsonPath = moduleRequire.resolve(`${packageName}/package.json`);
|
|
268
268
|
const packageDir = dirname(packageJsonPath);
|
|
269
269
|
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
270
270
|
const binaryRelativePath = readJongodbBinaryPath(packageJson) ??
|
|
@@ -344,13 +344,59 @@ function normalizePort(port) {
|
|
|
344
344
|
}
|
|
345
345
|
return normalized;
|
|
346
346
|
}
|
|
347
|
-
function
|
|
348
|
-
const
|
|
347
|
+
function resolveDatabaseName(options) {
|
|
348
|
+
const base = normalizeDatabaseNameBase(options.databaseName);
|
|
349
|
+
const explicitSuffix = normalizeDatabaseNameSuffix(options.databaseNameSuffix);
|
|
350
|
+
const workerSuffix = resolveWorkerDatabaseNameSuffix(options.databaseNameStrategy);
|
|
351
|
+
return `${base}${explicitSuffix}${workerSuffix}`;
|
|
352
|
+
}
|
|
353
|
+
function normalizeDatabaseNameBase(databaseName) {
|
|
354
|
+
return databaseName?.trim() || DEFAULT_DATABASE;
|
|
355
|
+
}
|
|
356
|
+
function normalizeDatabaseNameSuffix(databaseNameSuffix) {
|
|
357
|
+
if (databaseNameSuffix === undefined) {
|
|
358
|
+
return "";
|
|
359
|
+
}
|
|
360
|
+
const normalized = databaseNameSuffix.trim();
|
|
349
361
|
if (normalized.length === 0) {
|
|
350
|
-
throw new Error("
|
|
362
|
+
throw new Error("databaseNameSuffix must not be empty when provided.");
|
|
351
363
|
}
|
|
352
364
|
return normalized;
|
|
353
365
|
}
|
|
366
|
+
function resolveWorkerDatabaseNameSuffix(strategy) {
|
|
367
|
+
const resolvedStrategy = strategy ?? "static";
|
|
368
|
+
if (resolvedStrategy !== "static" && resolvedStrategy !== "worker") {
|
|
369
|
+
throw new Error(`databaseNameStrategy must be one of: static, worker (got: ${String(strategy)}).`);
|
|
370
|
+
}
|
|
371
|
+
if (resolvedStrategy === "static") {
|
|
372
|
+
return "";
|
|
373
|
+
}
|
|
374
|
+
const workerToken = resolveWorkerToken();
|
|
375
|
+
return `_w${sanitizeDatabaseNameToken(workerToken)}`;
|
|
376
|
+
}
|
|
377
|
+
function resolveWorkerToken() {
|
|
378
|
+
const envCandidates = [
|
|
379
|
+
process.env.JONGODB_WORKER_ID,
|
|
380
|
+
process.env.JEST_WORKER_ID,
|
|
381
|
+
process.env.VITEST_WORKER_ID,
|
|
382
|
+
process.env.VITEST_POOL_ID,
|
|
383
|
+
process.env.NODE_UNIQUE_ID,
|
|
384
|
+
];
|
|
385
|
+
for (const candidate of envCandidates) {
|
|
386
|
+
const normalized = candidate?.trim();
|
|
387
|
+
if (normalized !== undefined && normalized.length > 0) {
|
|
388
|
+
return normalized;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return String(process.pid);
|
|
392
|
+
}
|
|
393
|
+
function sanitizeDatabaseNameToken(token) {
|
|
394
|
+
const sanitized = token.replace(/[^A-Za-z0-9_-]/g, "_");
|
|
395
|
+
if (sanitized.length > 0) {
|
|
396
|
+
return sanitized;
|
|
397
|
+
}
|
|
398
|
+
return "unknown";
|
|
399
|
+
}
|
|
354
400
|
function resolveClasspathOrNull(classpath) {
|
|
355
401
|
const explicit = resolveExplicitClasspath(classpath);
|
|
356
402
|
if (explicit !== null) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jest.d.ts","sourceRoot":"","sources":["../../src/jest.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,0BAA0B,EAEhC,MAAM,YAAY,CAAC;AAWpB,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,QAAQ,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5D,QAAQ,CAAC,QAAQ,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;CAC5D;AAED,MAAM,WAAW,eAAgB,SAAQ,0BAA0B;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,0BAA2B,SAAQ,0BAA0B;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,iBAAiB,EACxB,OAAO,GAAE,eAAoB,GAC5B,2BAA2B,CAgB7B;AAED,wBAAgB,qBAAqB,CACnC,OAAO,GAAE,0BAA+B,GACvC,MAAM,OAAO,CAAC,IAAI,CAAC,CAiBrB;AAED,wBAAgB,wBAAwB,CACtC,OAAO,GAAE,0BAA+B,GACvC,MAAM,OAAO,CAAC,IAAI,CAAC,CAkBrB;AAED,wBAAsB,mBAAmB,CAAC,OAAO,GAAE;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAmBvC;AAED,wBAAsB,iBAAiB,CAAC,OAAO,GAAE;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAM9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nestjs.d.ts","sourceRoot":"","sources":["../../src/nestjs.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,2BAA2B,EAEjC,MAAM,WAAW,CAAC;AAEnB,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,CAAC;AACtD,MAAM,MAAM,kBAAkB,GAAG,eAAe,CAAC;AACjD,MAAM,MAAM,2BAA2B,GAAG,2BAA2B,CAAC;AAEtE;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,qBAAqB,EAC5B,OAAO,GAAE,kBAAuB,GAC/B,2BAA2B,CAE7B"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { type JongodbMemoryServerOptions } from "./index.js";
|
|
2
2
|
export interface JongodbEnvRuntimeOptions extends JongodbMemoryServerOptions {
|
|
3
3
|
envVarName?: string;
|
|
4
|
+
envVarNames?: string[];
|
|
4
5
|
}
|
|
5
6
|
export interface JongodbEnvRuntime {
|
|
6
7
|
readonly envVarName: string;
|
|
8
|
+
readonly envVarNames: readonly string[];
|
|
7
9
|
readonly running: boolean;
|
|
8
10
|
readonly uri: string;
|
|
9
11
|
setup(): Promise<string>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,0BAA0B,EAEhC,MAAM,YAAY,CAAC;AAIpB,MAAM,WAAW,wBAAyB,SAAQ,0BAA0B;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,wBAA6B,GACrC,iBAAiB,CAmDnB"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { startJongodbMemoryServer, } from "./index.js";
|
|
2
|
+
const DEFAULT_ENV_VAR_NAME = "MONGODB_URI";
|
|
3
|
+
export function createJongodbEnvRuntime(options = {}) {
|
|
4
|
+
const envVarNames = resolveEnvVarNames(options);
|
|
5
|
+
const envVarName = envVarNames[0];
|
|
6
|
+
const { envVarName: _envVarName, envVarNames: _envVarNames, ...serverOptions } = options;
|
|
7
|
+
let runtimeServer = null;
|
|
8
|
+
let uri = null;
|
|
9
|
+
let previousEnvState = captureEnvState(envVarNames);
|
|
10
|
+
return {
|
|
11
|
+
envVarName,
|
|
12
|
+
envVarNames,
|
|
13
|
+
get running() {
|
|
14
|
+
return runtimeServer !== null;
|
|
15
|
+
},
|
|
16
|
+
get uri() {
|
|
17
|
+
if (uri === null) {
|
|
18
|
+
throw new Error("Jongodb URI is not available before setup completes.");
|
|
19
|
+
}
|
|
20
|
+
return uri;
|
|
21
|
+
},
|
|
22
|
+
async setup() {
|
|
23
|
+
if (runtimeServer !== null && uri !== null) {
|
|
24
|
+
return uri;
|
|
25
|
+
}
|
|
26
|
+
previousEnvState = captureEnvState(envVarNames);
|
|
27
|
+
runtimeServer = await startJongodbMemoryServer(serverOptions);
|
|
28
|
+
uri = runtimeServer.uri;
|
|
29
|
+
for (const candidate of envVarNames) {
|
|
30
|
+
process.env[candidate] = uri;
|
|
31
|
+
}
|
|
32
|
+
return uri;
|
|
33
|
+
},
|
|
34
|
+
async teardown() {
|
|
35
|
+
if (runtimeServer !== null) {
|
|
36
|
+
await runtimeServer.stop();
|
|
37
|
+
runtimeServer = null;
|
|
38
|
+
}
|
|
39
|
+
restoreEnvState(previousEnvState);
|
|
40
|
+
uri = null;
|
|
41
|
+
previousEnvState = captureEnvState(envVarNames);
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function resolveEnvVarNames(options) {
|
|
46
|
+
const explicitCandidates = [];
|
|
47
|
+
if (options.envVarName !== undefined) {
|
|
48
|
+
explicitCandidates.push(options.envVarName);
|
|
49
|
+
}
|
|
50
|
+
if (options.envVarNames !== undefined) {
|
|
51
|
+
explicitCandidates.push(...options.envVarNames);
|
|
52
|
+
}
|
|
53
|
+
if (explicitCandidates.length === 0) {
|
|
54
|
+
return [DEFAULT_ENV_VAR_NAME];
|
|
55
|
+
}
|
|
56
|
+
const resolved = [];
|
|
57
|
+
const seen = new Set();
|
|
58
|
+
for (const candidate of explicitCandidates) {
|
|
59
|
+
const normalized = normalizeEnvVarName(candidate);
|
|
60
|
+
if (seen.has(normalized)) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
seen.add(normalized);
|
|
64
|
+
resolved.push(normalized);
|
|
65
|
+
}
|
|
66
|
+
if (resolved.length === 0) {
|
|
67
|
+
return [DEFAULT_ENV_VAR_NAME];
|
|
68
|
+
}
|
|
69
|
+
return resolved;
|
|
70
|
+
}
|
|
71
|
+
function normalizeEnvVarName(name) {
|
|
72
|
+
const normalized = name.trim();
|
|
73
|
+
if (normalized.length === 0) {
|
|
74
|
+
throw new Error("envVarName/envVarNames entries must not be empty.");
|
|
75
|
+
}
|
|
76
|
+
return normalized;
|
|
77
|
+
}
|
|
78
|
+
function captureEnvState(envVarNames) {
|
|
79
|
+
const state = new Map();
|
|
80
|
+
for (const envVarName of envVarNames) {
|
|
81
|
+
state.set(envVarName, {
|
|
82
|
+
hadPrevious: Object.prototype.hasOwnProperty.call(process.env, envVarName),
|
|
83
|
+
previousValue: process.env[envVarName],
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return state;
|
|
87
|
+
}
|
|
88
|
+
function restoreEnvState(state) {
|
|
89
|
+
for (const [envVarName, previous] of state.entries()) {
|
|
90
|
+
if (previous.hadPrevious) {
|
|
91
|
+
process.env[envVarName] = previous.previousValue;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
delete process.env[envVarName];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vitest.d.ts","sourceRoot":"","sources":["../../src/vitest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAG7D,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,QAAQ,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5D,QAAQ,CAAC,QAAQ,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;CAC5D;AAED,MAAM,WAAW,iBAAkB,SAAQ,0BAA0B;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,mBAAmB,EAC1B,OAAO,GAAE,iBAAsB,GAC9B,6BAA6B,CAgB/B"}
|