@jongodb/memory-server 0.1.1
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/LICENSE +179 -0
- package/README.md +270 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +539 -0
- package/dist/jest.d.ts +31 -0
- package/dist/jest.d.ts.map +1 -0
- package/dist/jest.js +162 -0
- package/dist/nestjs.d.ts +9 -0
- package/dist/nestjs.d.ts.map +1 -0
- package/dist/nestjs.js +7 -0
- package/dist/runtime.d.ts +13 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +55 -0
- package/dist/vitest.d.ts +13 -0
- package/dist/vitest.d.ts.map +1 -0
- package/dist/vitest.js +15 -0
- package/package.json +110 -0
package/dist/jest.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { startJongodbMemoryServer, } from "./index.js";
|
|
4
|
+
import { createJongodbEnvRuntime } from "./runtime.js";
|
|
5
|
+
const DEFAULT_ENV_VAR_NAME = "MONGODB_URI";
|
|
6
|
+
const DEFAULT_STATE_FILE = path.join(process.cwd(), ".jongodb", "jest-memory-server.json");
|
|
7
|
+
const DEFAULT_STOP_TIMEOUT_MS = 5_000;
|
|
8
|
+
export function registerJongodbForJest(hooks, options = {}) {
|
|
9
|
+
const runtime = createJongodbEnvRuntime(options);
|
|
10
|
+
hooks.beforeAll(async () => {
|
|
11
|
+
await runtime.setup();
|
|
12
|
+
});
|
|
13
|
+
hooks.afterAll(async () => {
|
|
14
|
+
await runtime.teardown();
|
|
15
|
+
});
|
|
16
|
+
return {
|
|
17
|
+
get uri() {
|
|
18
|
+
return runtime.uri;
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function createJestGlobalSetup(options = {}) {
|
|
23
|
+
return async () => {
|
|
24
|
+
const { envVarName, stateFile, runtimeOptions } = splitLifecycleOptions(options);
|
|
25
|
+
const server = await startJongodbMemoryServer(runtimeOptions);
|
|
26
|
+
process.env[envVarName] = server.uri;
|
|
27
|
+
await mkdir(path.dirname(stateFile), { recursive: true });
|
|
28
|
+
const state = {
|
|
29
|
+
uri: server.uri,
|
|
30
|
+
pid: server.pid,
|
|
31
|
+
envVarName,
|
|
32
|
+
};
|
|
33
|
+
await writeFile(stateFile, JSON.stringify(state, null, 2), "utf8");
|
|
34
|
+
server.detach();
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export function createJestGlobalTeardown(options = {}) {
|
|
38
|
+
return async () => {
|
|
39
|
+
const { stateFile } = splitLifecycleOptions(options);
|
|
40
|
+
const state = await readJestGlobalState({ stateFile });
|
|
41
|
+
if (state === null) {
|
|
42
|
+
await rm(stateFile, { force: true });
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
await terminatePid(state.pid, options.killTimeoutMs ?? DEFAULT_STOP_TIMEOUT_MS);
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
await rm(stateFile, { force: true });
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export async function readJestGlobalState(options = {}) {
|
|
54
|
+
const stateFile = normalizeStateFile(options.stateFile);
|
|
55
|
+
try {
|
|
56
|
+
const raw = await readFile(stateFile, "utf8");
|
|
57
|
+
const parsed = JSON.parse(raw);
|
|
58
|
+
if (typeof parsed.uri !== "string" ||
|
|
59
|
+
typeof parsed.pid !== "number" ||
|
|
60
|
+
typeof parsed.envVarName !== "string") {
|
|
61
|
+
throw new Error("Jest global state file has invalid schema.");
|
|
62
|
+
}
|
|
63
|
+
return parsed;
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
if (isMissingFileError(error)) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
export async function readJestGlobalUri(options = {}) {
|
|
73
|
+
const state = await readJestGlobalState(options);
|
|
74
|
+
if (state === null) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
return state.uri;
|
|
78
|
+
}
|
|
79
|
+
function splitLifecycleOptions(options) {
|
|
80
|
+
const { envVarName, stateFile, killTimeoutMs: _killTimeoutMs, ...runtimeOptions } = options;
|
|
81
|
+
return {
|
|
82
|
+
envVarName: normalizeEnvVarName(envVarName),
|
|
83
|
+
stateFile: normalizeStateFile(stateFile),
|
|
84
|
+
runtimeOptions,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function normalizeEnvVarName(name) {
|
|
88
|
+
const normalized = name?.trim() || DEFAULT_ENV_VAR_NAME;
|
|
89
|
+
if (normalized.length === 0) {
|
|
90
|
+
throw new Error("envVarName must not be empty.");
|
|
91
|
+
}
|
|
92
|
+
return normalized;
|
|
93
|
+
}
|
|
94
|
+
function normalizeStateFile(stateFile) {
|
|
95
|
+
const normalized = stateFile?.trim() || DEFAULT_STATE_FILE;
|
|
96
|
+
if (normalized.length === 0) {
|
|
97
|
+
throw new Error("stateFile must not be empty.");
|
|
98
|
+
}
|
|
99
|
+
return normalized;
|
|
100
|
+
}
|
|
101
|
+
async function terminatePid(pid, timeoutMs) {
|
|
102
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
103
|
+
throw new Error(`Invalid PID in Jest global state: ${pid}`);
|
|
104
|
+
}
|
|
105
|
+
if (!isProcessRunning(pid)) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
process.kill(pid, "SIGTERM");
|
|
109
|
+
const deadline = Date.now() + timeoutMs;
|
|
110
|
+
while (Date.now() < deadline) {
|
|
111
|
+
if (!isProcessRunning(pid)) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
await sleep(50);
|
|
115
|
+
}
|
|
116
|
+
if (!isProcessRunning(pid)) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
process.kill(pid, "SIGKILL");
|
|
120
|
+
await waitForProcessExit(pid, timeoutMs);
|
|
121
|
+
if (isProcessRunning(pid)) {
|
|
122
|
+
throw new Error(`Unable to stop detached Jest process pid=${pid} after SIGKILL.`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function isProcessRunning(pid) {
|
|
126
|
+
try {
|
|
127
|
+
process.kill(pid, 0);
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
if (isNoSuchProcessError(error)) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function isNoSuchProcessError(error) {
|
|
138
|
+
return (typeof error === "object" &&
|
|
139
|
+
error !== null &&
|
|
140
|
+
"code" in error &&
|
|
141
|
+
error.code === "ESRCH");
|
|
142
|
+
}
|
|
143
|
+
function isMissingFileError(error) {
|
|
144
|
+
return (typeof error === "object" &&
|
|
145
|
+
error !== null &&
|
|
146
|
+
"code" in error &&
|
|
147
|
+
error.code === "ENOENT");
|
|
148
|
+
}
|
|
149
|
+
function sleep(ms) {
|
|
150
|
+
return new Promise((resolve) => {
|
|
151
|
+
setTimeout(resolve, ms);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
async function waitForProcessExit(pid, timeoutMs) {
|
|
155
|
+
const deadline = Date.now() + timeoutMs;
|
|
156
|
+
while (Date.now() < deadline) {
|
|
157
|
+
if (!isProcessRunning(pid)) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
await sleep(50);
|
|
161
|
+
}
|
|
162
|
+
}
|
package/dist/nestjs.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type JestHookOptions, type JestHookRegistrar, type RegisteredJongodbTestServer } from "./jest.js";
|
|
2
|
+
export type NestJestHookRegistrar = JestHookRegistrar;
|
|
3
|
+
export type NestJongodbOptions = JestHookOptions;
|
|
4
|
+
export type RegisteredNestJongodbServer = RegisteredJongodbTestServer;
|
|
5
|
+
/**
|
|
6
|
+
* Convenience wrapper for NestJS E2E tests that run on Jest.
|
|
7
|
+
*/
|
|
8
|
+
export declare function registerJongodbForNestJest(hooks: NestJestHookRegistrar, options?: NestJongodbOptions): RegisteredNestJongodbServer;
|
|
9
|
+
//# sourceMappingURL=nestjs.d.ts.map
|
|
@@ -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"}
|
package/dist/nestjs.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type JongodbMemoryServerOptions } from "./index.js";
|
|
2
|
+
export interface JongodbEnvRuntimeOptions extends JongodbMemoryServerOptions {
|
|
3
|
+
envVarName?: string;
|
|
4
|
+
}
|
|
5
|
+
export interface JongodbEnvRuntime {
|
|
6
|
+
readonly envVarName: string;
|
|
7
|
+
readonly running: boolean;
|
|
8
|
+
readonly uri: string;
|
|
9
|
+
setup(): Promise<string>;
|
|
10
|
+
teardown(): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export declare function createJongodbEnvRuntime(options?: JongodbEnvRuntimeOptions): JongodbEnvRuntime;
|
|
13
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -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;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,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,CAkDnB"}
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { startJongodbMemoryServer, } from "./index.js";
|
|
2
|
+
const DEFAULT_ENV_VAR_NAME = "MONGODB_URI";
|
|
3
|
+
export function createJongodbEnvRuntime(options = {}) {
|
|
4
|
+
const envVarName = normalizeEnvVarName(options.envVarName);
|
|
5
|
+
const { envVarName: _envVarName, ...serverOptions } = options;
|
|
6
|
+
let runtimeServer = null;
|
|
7
|
+
let uri = null;
|
|
8
|
+
let previousEnvValue;
|
|
9
|
+
let hadPreviousEnv = false;
|
|
10
|
+
return {
|
|
11
|
+
envVarName,
|
|
12
|
+
get running() {
|
|
13
|
+
return runtimeServer !== null;
|
|
14
|
+
},
|
|
15
|
+
get uri() {
|
|
16
|
+
if (uri === null) {
|
|
17
|
+
throw new Error("Jongodb URI is not available before setup completes.");
|
|
18
|
+
}
|
|
19
|
+
return uri;
|
|
20
|
+
},
|
|
21
|
+
async setup() {
|
|
22
|
+
if (runtimeServer !== null && uri !== null) {
|
|
23
|
+
return uri;
|
|
24
|
+
}
|
|
25
|
+
hadPreviousEnv = Object.prototype.hasOwnProperty.call(process.env, envVarName);
|
|
26
|
+
previousEnvValue = process.env[envVarName];
|
|
27
|
+
runtimeServer = await startJongodbMemoryServer(serverOptions);
|
|
28
|
+
uri = runtimeServer.uri;
|
|
29
|
+
process.env[envVarName] = uri;
|
|
30
|
+
return uri;
|
|
31
|
+
},
|
|
32
|
+
async teardown() {
|
|
33
|
+
if (runtimeServer !== null) {
|
|
34
|
+
await runtimeServer.stop();
|
|
35
|
+
runtimeServer = null;
|
|
36
|
+
}
|
|
37
|
+
if (hadPreviousEnv) {
|
|
38
|
+
process.env[envVarName] = previousEnvValue;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
delete process.env[envVarName];
|
|
42
|
+
}
|
|
43
|
+
uri = null;
|
|
44
|
+
previousEnvValue = undefined;
|
|
45
|
+
hadPreviousEnv = false;
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function normalizeEnvVarName(name) {
|
|
50
|
+
const normalized = name?.trim() || DEFAULT_ENV_VAR_NAME;
|
|
51
|
+
if (normalized.length === 0) {
|
|
52
|
+
throw new Error("envVarName must not be empty.");
|
|
53
|
+
}
|
|
54
|
+
return normalized;
|
|
55
|
+
}
|
package/dist/vitest.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type JongodbMemoryServerOptions } from "./index.js";
|
|
2
|
+
export interface VitestHookRegistrar {
|
|
3
|
+
beforeAll(callback: () => unknown | Promise<unknown>): void;
|
|
4
|
+
afterAll(callback: () => unknown | Promise<unknown>): void;
|
|
5
|
+
}
|
|
6
|
+
export interface VitestHookOptions extends JongodbMemoryServerOptions {
|
|
7
|
+
envVarName?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface RegisteredVitestJongodbServer {
|
|
10
|
+
readonly uri: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function registerJongodbForVitest(hooks: VitestHookRegistrar, options?: VitestHookOptions): RegisteredVitestJongodbServer;
|
|
13
|
+
//# sourceMappingURL=vitest.d.ts.map
|
|
@@ -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;CACrB;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"}
|
package/dist/vitest.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createJongodbEnvRuntime } from "./runtime.js";
|
|
2
|
+
export function registerJongodbForVitest(hooks, options = {}) {
|
|
3
|
+
const runtime = createJongodbEnvRuntime(options);
|
|
4
|
+
hooks.beforeAll(async () => {
|
|
5
|
+
await runtime.setup();
|
|
6
|
+
});
|
|
7
|
+
hooks.afterAll(async () => {
|
|
8
|
+
await runtime.teardown();
|
|
9
|
+
});
|
|
10
|
+
return {
|
|
11
|
+
get uri() {
|
|
12
|
+
return runtime.uri;
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jongodb/memory-server",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Node.js test runtime adapter for jongodb standalone launcher (MongoDB-compatible integration tests).",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mongodb",
|
|
7
|
+
"mongodb-memory-server",
|
|
8
|
+
"jongodb",
|
|
9
|
+
"in-memory-mongodb",
|
|
10
|
+
"standalone-launcher",
|
|
11
|
+
"mongodb-test-runtime",
|
|
12
|
+
"integration-test",
|
|
13
|
+
"node-test",
|
|
14
|
+
"nestjs",
|
|
15
|
+
"express",
|
|
16
|
+
"fastify",
|
|
17
|
+
"mongoose",
|
|
18
|
+
"prisma",
|
|
19
|
+
"typeorm",
|
|
20
|
+
"jest",
|
|
21
|
+
"vitest",
|
|
22
|
+
"mocha",
|
|
23
|
+
"e2e"
|
|
24
|
+
],
|
|
25
|
+
"license": "Apache-2.0",
|
|
26
|
+
"author": "jongodb contributors",
|
|
27
|
+
"type": "module",
|
|
28
|
+
"main": "./dist/index.js",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"default": "./dist/index.js"
|
|
34
|
+
},
|
|
35
|
+
"./jest": {
|
|
36
|
+
"types": "./dist/jest.d.ts",
|
|
37
|
+
"default": "./dist/jest.js"
|
|
38
|
+
},
|
|
39
|
+
"./runtime": {
|
|
40
|
+
"types": "./dist/runtime.d.ts",
|
|
41
|
+
"default": "./dist/runtime.js"
|
|
42
|
+
},
|
|
43
|
+
"./nestjs": {
|
|
44
|
+
"types": "./dist/nestjs.d.ts",
|
|
45
|
+
"default": "./dist/nestjs.js"
|
|
46
|
+
},
|
|
47
|
+
"./vitest": {
|
|
48
|
+
"types": "./dist/vitest.d.ts",
|
|
49
|
+
"default": "./dist/vitest.js"
|
|
50
|
+
},
|
|
51
|
+
"./package.json": "./package.json"
|
|
52
|
+
},
|
|
53
|
+
"typesVersions": {
|
|
54
|
+
"*": {
|
|
55
|
+
"jest": [
|
|
56
|
+
"./dist/jest.d.ts"
|
|
57
|
+
],
|
|
58
|
+
"runtime": [
|
|
59
|
+
"./dist/runtime.d.ts"
|
|
60
|
+
],
|
|
61
|
+
"nestjs": [
|
|
62
|
+
"./dist/nestjs.d.ts"
|
|
63
|
+
],
|
|
64
|
+
"vitest": [
|
|
65
|
+
"./dist/vitest.d.ts"
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"repository": {
|
|
70
|
+
"type": "git",
|
|
71
|
+
"url": "git+https://github.com/midagedev/jongodb.git",
|
|
72
|
+
"directory": "packages/memory-server"
|
|
73
|
+
},
|
|
74
|
+
"bugs": {
|
|
75
|
+
"url": "https://github.com/midagedev/jongodb/issues"
|
|
76
|
+
},
|
|
77
|
+
"homepage": "https://github.com/midagedev/jongodb/tree/main/packages/memory-server#readme",
|
|
78
|
+
"publishConfig": {
|
|
79
|
+
"access": "public"
|
|
80
|
+
},
|
|
81
|
+
"optionalDependencies": {
|
|
82
|
+
"@jongodb/memory-server-bin-darwin-arm64": "0.1.1",
|
|
83
|
+
"@jongodb/memory-server-bin-linux-x64-gnu": "0.1.1",
|
|
84
|
+
"@jongodb/memory-server-bin-win32-x64": "0.1.1"
|
|
85
|
+
},
|
|
86
|
+
"files": [
|
|
87
|
+
"dist",
|
|
88
|
+
"README.md",
|
|
89
|
+
"LICENSE",
|
|
90
|
+
"!dist/test",
|
|
91
|
+
"!dist/test/**"
|
|
92
|
+
],
|
|
93
|
+
"engines": {
|
|
94
|
+
"node": ">=20"
|
|
95
|
+
},
|
|
96
|
+
"scripts": {
|
|
97
|
+
"clean": "rm -rf dist",
|
|
98
|
+
"build": "tsc -p tsconfig.json",
|
|
99
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
100
|
+
"pretest": "npm run build",
|
|
101
|
+
"test": "node --test dist/test/*.test.js",
|
|
102
|
+
"prepack": "npm run clean && npm run build",
|
|
103
|
+
"release:check": "npm run build && npm run typecheck && npm run test && npm pack --dry-run"
|
|
104
|
+
},
|
|
105
|
+
"devDependencies": {
|
|
106
|
+
"@types/node": "^20.17.57",
|
|
107
|
+
"mongodb": "^6.21.0",
|
|
108
|
+
"typescript": "^5.9.2"
|
|
109
|
+
}
|
|
110
|
+
}
|