@classytic/arc-testkit 0.5.0 → 0.7.0
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 +52 -13
- package/dist/conformance.d.mts +439 -0
- package/dist/conformance.mjs +977 -0
- package/dist/index.d.mts +5 -8
- package/dist/index.mjs +1 -2
- package/dist/mongo-commands.d.mts +6 -8
- package/dist/mongo-commands.mjs +1 -2
- package/dist/mongo-explain.d.mts +57 -7
- package/dist/mongo-explain.mjs +72 -3
- package/dist/mongo.d.mts +122 -12
- package/dist/mongo.mjs +296 -10
- package/dist/pool.d.mts +13 -10
- package/dist/pool.mjs +27 -25
- package/dist/process-cleanup-1iBIS_o_.mjs +66 -0
- package/dist/story.d.mts +202 -0
- package/dist/story.mjs +330 -0
- package/llms.txt +33 -0
- package/package.json +26 -3
- package/skills/arc-testkit/SKILL.md +112 -0
- package/skills/arc-testkit/references/conformance.md +105 -0
- package/skills/arc-testkit/references/fixtures.md +104 -0
- package/skills/arc-testkit/references/list-filters.md +3 -0
- package/skills/arc-testkit/references/story.md +80 -0
package/dist/index.d.mts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { BootModuleAppOptions as BootModuleAppOptions$1, BootModulesInput, ModuleTestApp as ModuleTestApp$1, TestkitContext as TestkitContext$1 } from "@classytic/arc/testing";
|
|
2
2
|
import { Connection } from "mongoose";
|
|
3
|
-
|
|
4
|
-
type
|
|
5
|
-
type
|
|
6
|
-
type
|
|
7
|
-
|
|
8
|
-
declare function bootModuleApp(modules: ModulesInput, options?: BootModuleAppOptions): Promise<ModuleTestApp>;
|
|
9
|
-
//#endregion
|
|
10
|
-
export { BootModuleAppOptions, ModuleTestApp, ModulesInput, TestkitContext, bootModuleApp };
|
|
3
|
+
export type TestkitContext = TestkitContext$1<Connection>;
|
|
4
|
+
export type ModulesInput = BootModulesInput<Connection>;
|
|
5
|
+
export type BootModuleAppOptions = BootModuleAppOptions$1<Connection>;
|
|
6
|
+
export type ModuleTestApp = ModuleTestApp$1<Connection>;
|
|
7
|
+
export declare function bootModuleApp(modules: ModulesInput, options?: BootModuleAppOptions): Promise<ModuleTestApp>;
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { bootModuleApp as bootModuleApp$1 } from "@classytic/arc/testing";
|
|
2
|
-
|
|
2
|
+
// src/index.ts
|
|
3
3
|
/**
|
|
4
4
|
* @classytic/arc-testkit — boots a REAL arc app around the module(s) under
|
|
5
5
|
* test on in-memory MongoDB. The contributor contract: if your module boots
|
|
@@ -23,5 +23,4 @@ import { bootModuleApp as bootModuleApp$1 } from "@classytic/arc/testing";
|
|
|
23
23
|
function bootModuleApp(modules, options = {}) {
|
|
24
24
|
return bootModuleApp$1(modules, options);
|
|
25
25
|
}
|
|
26
|
-
//#endregion
|
|
27
26
|
export { bootModuleApp };
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Connection } from "mongoose";
|
|
2
|
-
//#region src/mongo-commands.d.ts
|
|
3
2
|
type MongoClientLike = ReturnType<Connection["getClient"]>;
|
|
4
|
-
interface CountCommandsOptions {
|
|
3
|
+
export interface CountCommandsOptions {
|
|
5
4
|
/** Count only commands against these collections. */
|
|
6
5
|
readonly collections?: readonly string[];
|
|
7
6
|
/** Count only these command names (`find`, `aggregate`, `insert`, …). */
|
|
@@ -9,12 +8,12 @@ interface CountCommandsOptions {
|
|
|
9
8
|
/** Never count these command names — e.g. `createIndexes` a model may run lazily. */
|
|
10
9
|
readonly ignore?: readonly string[];
|
|
11
10
|
}
|
|
12
|
-
interface WireCommand {
|
|
11
|
+
export interface WireCommand {
|
|
13
12
|
readonly command: string;
|
|
14
13
|
/** The collection the command targets; `undefined` for session, transaction and admin commands. */
|
|
15
14
|
readonly collection: string | undefined;
|
|
16
15
|
}
|
|
17
|
-
interface CommandCount<T> {
|
|
16
|
+
export interface CommandCount<T> {
|
|
18
17
|
readonly result: T;
|
|
19
18
|
readonly total: number;
|
|
20
19
|
/** Counted commands, in the order the driver sent them. */
|
|
@@ -23,7 +22,6 @@ interface CommandCount<T> {
|
|
|
23
22
|
readonly byCollection: Readonly<Record<string, number>>;
|
|
24
23
|
readonly byCommand: Readonly<Record<string, number>>;
|
|
25
24
|
}
|
|
26
|
-
declare function countCommands<T>(source: Connection | MongoClientLike, fn: () => Promise<T>, options?: CountCommandsOptions): Promise<CommandCount<T>>;
|
|
27
|
-
declare function assertConstantCommands<T>(source: Connection | MongoClientLike, run: (size: number) => Promise<T>, sizes: readonly number[], options?: CountCommandsOptions): Promise<readonly CommandCount<T>[]>;
|
|
28
|
-
|
|
29
|
-
export { CommandCount, CountCommandsOptions, WireCommand, assertConstantCommands, countCommands };
|
|
25
|
+
export declare function countCommands<T>(source: Connection | MongoClientLike, fn: () => Promise<T>, options?: CountCommandsOptions): Promise<CommandCount<T>>;
|
|
26
|
+
export declare function assertConstantCommands<T>(source: Connection | MongoClientLike, run: (size: number) => Promise<T>, sizes: readonly number[], options?: CountCommandsOptions): Promise<readonly CommandCount<T>[]>;
|
|
27
|
+
export {};
|
package/dist/mongo-commands.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/mongo-commands.ts
|
|
2
2
|
async function countCommands(source, fn, options = {}) {
|
|
3
3
|
const client = "getClient" in source ? source.getClient() : source;
|
|
4
4
|
if (client.options.monitorCommands !== true) throw new Error("[arc-testkit] countCommands: the client was created without `monitorCommands: true` — the driver emits no command events, so every count would read 0");
|
|
@@ -50,5 +50,4 @@ function tally(keys) {
|
|
|
50
50
|
for (const k of keys) out[k] = (out[k] ?? 0) + 1;
|
|
51
51
|
return out;
|
|
52
52
|
}
|
|
53
|
-
//#endregion
|
|
54
53
|
export { assertConstantCommands, countCommands };
|
package/dist/mongo-explain.d.mts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//#region src/mongo-explain.d.ts
|
|
2
1
|
/**
|
|
3
2
|
* Read a MongoDB `explain()` result — find, aggregate, classic or SBE — as the WINNING plan's stage
|
|
4
3
|
* names, the indexes it scans, and its execution stats (`executionStats` verbosity). Rejected plans
|
|
@@ -9,8 +8,17 @@
|
|
|
9
8
|
* const explain = await Model.find({ organizationId, state: "posted" }).explain("executionStats");
|
|
10
9
|
* assertIndexServed(explain, { index: "org_state_date", maxDocsExamined: 40 });
|
|
11
10
|
* ```
|
|
11
|
+
*
|
|
12
|
+
* `explainCaptured` explains the query a piece of code ACTUALLY sends (a repository method, a
|
|
13
|
+
* plugin-built filter) instead of a copy of it: it runs the code with command monitoring, captures
|
|
14
|
+
* the matching command and explains exactly that.
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* const { explain } = await explainCaptured(conn, () => timers.claim(now), { collection: "timers", commands: ["findAndModify"] });
|
|
18
|
+
* assertIndexServed(explain, { index: "state_due", maxDocsExamined: 6 });
|
|
19
|
+
* ```
|
|
12
20
|
*/
|
|
13
|
-
interface ExplainSummary {
|
|
21
|
+
export interface ExplainSummary {
|
|
14
22
|
/** Stage names of the winning plan(s), outermost first. */
|
|
15
23
|
readonly stages: readonly string[];
|
|
16
24
|
/** Index names the winning plan scans (`_id_` for an id lookup). */
|
|
@@ -20,7 +28,7 @@ interface ExplainSummary {
|
|
|
20
28
|
readonly keysExamined: number | undefined;
|
|
21
29
|
readonly returned: number | undefined;
|
|
22
30
|
}
|
|
23
|
-
interface IndexServedOptions {
|
|
31
|
+
export interface IndexServedOptions {
|
|
24
32
|
/** Every one of these must be scanned. */
|
|
25
33
|
readonly index?: string | readonly string[];
|
|
26
34
|
/** Every one of these stages must appear — e.g. `OR` for a `$or` served arm by arm. */
|
|
@@ -28,7 +36,49 @@ interface IndexServedOptions {
|
|
|
28
36
|
/** Ceiling on `totalDocsExamined`; requires `executionStats` verbosity. */
|
|
29
37
|
readonly maxDocsExamined?: number;
|
|
30
38
|
}
|
|
31
|
-
declare function summarizeExplain(explain: unknown): ExplainSummary;
|
|
32
|
-
declare function assertIndexServed(explain: unknown, options?: IndexServedOptions): ExplainSummary;
|
|
33
|
-
|
|
34
|
-
export
|
|
39
|
+
export declare function summarizeExplain(explain: unknown): ExplainSummary;
|
|
40
|
+
export declare function assertIndexServed(explain: unknown, options?: IndexServedOptions): ExplainSummary;
|
|
41
|
+
/** A `commandStarted` event, as far as `explainCaptured` reads it. */
|
|
42
|
+
export interface CommandStartedLike {
|
|
43
|
+
readonly commandName: string;
|
|
44
|
+
readonly databaseName: string;
|
|
45
|
+
readonly command: Readonly<Record<string, unknown>>;
|
|
46
|
+
}
|
|
47
|
+
/** A MongoDB driver client (`connection.getClient()` of mongoose, or a `MongoClient`). */
|
|
48
|
+
export interface MonitoredClientLike {
|
|
49
|
+
readonly options: {
|
|
50
|
+
readonly monitorCommands?: boolean;
|
|
51
|
+
};
|
|
52
|
+
on(event: "commandStarted", listener: (event: CommandStartedLike) => void): unknown;
|
|
53
|
+
off(event: "commandStarted", listener: (event: CommandStartedLike) => void): unknown;
|
|
54
|
+
db(name: string): {
|
|
55
|
+
command(command: Record<string, unknown>): Promise<unknown>;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export interface ExplainCapturedOptions {
|
|
59
|
+
/** The collection the command targets. */
|
|
60
|
+
readonly collection: string;
|
|
61
|
+
/** Command names to capture. Default: `find`, `aggregate`, `findAndModify`, `count`, `distinct`, `update`, `delete`. */
|
|
62
|
+
readonly commands?: readonly string[];
|
|
63
|
+
/** Which captured command to explain (0-based). Required when more than one matches. */
|
|
64
|
+
readonly index?: number;
|
|
65
|
+
/** Default: `executionStats` (what `maxDocsExamined` needs). */
|
|
66
|
+
readonly verbosity?: "queryPlanner" | "executionStats" | "allPlansExecution";
|
|
67
|
+
}
|
|
68
|
+
export interface ExplainCaptured<T> {
|
|
69
|
+
readonly result: T;
|
|
70
|
+
/** The explain of the chosen command, ready for `assertIndexServed`. */
|
|
71
|
+
readonly explain: unknown;
|
|
72
|
+
/** The chosen command as the driver sent it, minus session and transport fields. */
|
|
73
|
+
readonly command: Readonly<Record<string, unknown>>;
|
|
74
|
+
/** Every matching command, in the order sent (same fields removed). */
|
|
75
|
+
readonly captured: readonly Readonly<Record<string, unknown>>[];
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Runs `run` with command monitoring, captures the commands it sends to `collection` and explains
|
|
79
|
+
* the chosen one (the explain never applies a write). Refuses a client without
|
|
80
|
+
* `monitorCommands: true`, a run that sent no matching command, and an ambiguous capture.
|
|
81
|
+
*/
|
|
82
|
+
export declare function explainCaptured<T>(source: {
|
|
83
|
+
getClient(): MonitoredClientLike;
|
|
84
|
+
} | MonitoredClientLike, run: () => Promise<T>, options: ExplainCapturedOptions): Promise<ExplainCaptured<T>>;
|
package/dist/mongo-explain.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/mongo-explain.ts
|
|
2
2
|
/** Keys whose subtree is a rejected alternative or a query predicate — never plan structure. */
|
|
3
3
|
const SKIPPED = /* @__PURE__ */ new Set([
|
|
4
4
|
"rejectedPlans",
|
|
@@ -57,11 +57,80 @@ function assertIndexServed(explain, options = {}) {
|
|
|
57
57
|
}
|
|
58
58
|
return plan;
|
|
59
59
|
}
|
|
60
|
+
const EXPLAINABLE = [
|
|
61
|
+
"find",
|
|
62
|
+
"aggregate",
|
|
63
|
+
"findAndModify",
|
|
64
|
+
"count",
|
|
65
|
+
"distinct",
|
|
66
|
+
"update",
|
|
67
|
+
"delete"
|
|
68
|
+
];
|
|
69
|
+
/** Fields the driver adds to a command that an `explain` wrapper must not carry. */
|
|
70
|
+
const TRANSPORT = /* @__PURE__ */ new Set([
|
|
71
|
+
"lsid",
|
|
72
|
+
"$db",
|
|
73
|
+
"$clusterTime",
|
|
74
|
+
"$readPreference",
|
|
75
|
+
"txnNumber",
|
|
76
|
+
"autocommit",
|
|
77
|
+
"startTransaction",
|
|
78
|
+
"readConcern",
|
|
79
|
+
"writeConcern",
|
|
80
|
+
"apiVersion",
|
|
81
|
+
"apiStrict",
|
|
82
|
+
"apiDeprecationErrors"
|
|
83
|
+
]);
|
|
84
|
+
/**
|
|
85
|
+
* Runs `run` with command monitoring, captures the commands it sends to `collection` and explains
|
|
86
|
+
* the chosen one (the explain never applies a write). Refuses a client without
|
|
87
|
+
* `monitorCommands: true`, a run that sent no matching command, and an ambiguous capture.
|
|
88
|
+
*/
|
|
89
|
+
async function explainCaptured(source, run, options) {
|
|
90
|
+
const client = "getClient" in source ? source.getClient() : source;
|
|
91
|
+
const fail = (msg) => {
|
|
92
|
+
throw new Error(`[arc-testkit] explainCaptured: ${msg}`);
|
|
93
|
+
};
|
|
94
|
+
if (client.options.monitorCommands !== true) fail("the client was created without `monitorCommands: true` — the driver emits no command events, so nothing can be captured");
|
|
95
|
+
const names = options.commands ?? EXPLAINABLE;
|
|
96
|
+
const seen = [];
|
|
97
|
+
const onStarted = (e) => {
|
|
98
|
+
if (!names.includes(e.commandName) || e.command[e.commandName] !== options.collection) return;
|
|
99
|
+
const command = {};
|
|
100
|
+
for (const [key, value] of Object.entries(e.command)) if (!TRANSPORT.has(key)) command[key] = value;
|
|
101
|
+
seen.push({
|
|
102
|
+
db: e.databaseName,
|
|
103
|
+
command
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
client.on("commandStarted", onStarted);
|
|
107
|
+
let result;
|
|
108
|
+
try {
|
|
109
|
+
result = await run();
|
|
110
|
+
} finally {
|
|
111
|
+
client.off("commandStarted", onStarted);
|
|
112
|
+
}
|
|
113
|
+
const what = `${names.join("/")} on "${options.collection}"`;
|
|
114
|
+
if (seen.length === 0) fail(`run sent no ${what}`);
|
|
115
|
+
if (options.index === void 0 && seen.length > 1) fail(`run sent ${seen.length} ${what} (${seen.map((s) => Object.keys(s.command)[0]).join(", ")}): pass \`index\` to pick one`);
|
|
116
|
+
const chosen = seen[options.index ?? 0];
|
|
117
|
+
if (chosen === void 0) fail(`no captured command at index ${options.index} (${seen.length} captured)`);
|
|
118
|
+
const { db, command } = chosen;
|
|
119
|
+
const explain = await client.db(db).command({
|
|
120
|
+
explain: command,
|
|
121
|
+
verbosity: options.verbosity ?? "executionStats"
|
|
122
|
+
});
|
|
123
|
+
return {
|
|
124
|
+
result,
|
|
125
|
+
explain,
|
|
126
|
+
command,
|
|
127
|
+
captured: seen.map((s) => s.command)
|
|
128
|
+
};
|
|
129
|
+
}
|
|
60
130
|
function isRecord(value) {
|
|
61
131
|
return typeof value === "object" && value !== null;
|
|
62
132
|
}
|
|
63
133
|
function numberOr(value) {
|
|
64
134
|
return typeof value === "number" ? value : void 0;
|
|
65
135
|
}
|
|
66
|
-
|
|
67
|
-
export { assertIndexServed, summarizeExplain };
|
|
136
|
+
export { assertIndexServed, explainCaptured, summarizeExplain };
|
package/dist/mongo.d.mts
CHANGED
|
@@ -1,10 +1,121 @@
|
|
|
1
1
|
import { TestServerProvider } from "./pool.mjs";
|
|
2
2
|
import { Connection } from "mongoose";
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* mongodb-memory-server temp-dir hygiene: start, stop and sweep so that a test
|
|
5
|
+
* run that is killed, crashes or times out does not leave its data dir behind.
|
|
6
|
+
*
|
|
7
|
+
* ## Why this exists
|
|
8
|
+
*
|
|
9
|
+
* mongodb-memory-server creates `mongo-mem-XXXXXX` under `os.tmpdir()` for every
|
|
10
|
+
* server and removes it in `stop()` (`doCleanup: true` is the default since v9).
|
|
11
|
+
* That only covers the orderly path. A run killed from an IDE, a CI cancel, a
|
|
12
|
+
* worker terminated on timeout or a hard crash never reaches `stop()`, and the
|
|
13
|
+
* dir (a full WiredTiger data set, ~15 MB at minimum) stays forever. On one
|
|
14
|
+
* development machine that came to 3,698 dirs, about 57 GB, in `%TEMP%`.
|
|
15
|
+
* mongodb-memory-server also stops a server that FAILED to start with
|
|
16
|
+
* `doCleanup: false` ("for investigation"), so a failed boot leaks one too.
|
|
17
|
+
*
|
|
18
|
+
* Three measures, each one usable on its own:
|
|
19
|
+
*
|
|
20
|
+
* 1. `launchMongoMemory` always stops with cleanup, cleans up after a failed
|
|
21
|
+
* start, and has a synchronous `stopSync()` for a process `exit` handler,
|
|
22
|
+
* where nothing async completes.
|
|
23
|
+
* 2. `sweepStaleMongoMemoryDirs` removes `mongo-mem-*` dirs that are old AND
|
|
24
|
+
* whose `mongod.lock` names no live process. Both conditions, always: a live
|
|
25
|
+
* mongod rewrites its WiredTiger files on every checkpoint (60 s), so its dir
|
|
26
|
+
* is never old, and its lock names a live pid.
|
|
27
|
+
* 3. `TEST_MONGO_TMPDIR` puts the data dirs under a dedicated base (for example
|
|
28
|
+
* a project-local `.tmp`), so whatever does leak is contained and visible.
|
|
29
|
+
*
|
|
30
|
+
* Environment:
|
|
31
|
+
* - `TEST_MONGO_TMPDIR`: base dir for new data dirs. Unset: mongodb-memory-server's
|
|
32
|
+
* own default (`os.tmpdir()`).
|
|
33
|
+
* - `TEST_MONGO_SWEEP_HOURS`: minimum age of a dir the sweep may remove. Default 6.
|
|
34
|
+
* `0`, `off` or `false` turns the sweep off.
|
|
35
|
+
*/
|
|
36
|
+
/** Prefix mongodb-memory-server gives its data dirs (and that ours use). */
|
|
37
|
+
export declare const MONGO_MEM_DIR_PREFIX = "mongo-mem-";
|
|
38
|
+
/** The dedicated base dir from `TEST_MONGO_TMPDIR`, resolved, or undefined. */
|
|
39
|
+
export declare function mongoMemoryTmpBase(): string | undefined;
|
|
40
|
+
/** Minimum age (ms) of a dir the sweep may remove; `null` when the sweep is off. */
|
|
41
|
+
export declare function staleMongoMemoryAgeMs(): number | null;
|
|
42
|
+
/** Whether a process with this pid exists. EPERM means it exists but is not ours. */
|
|
43
|
+
export declare function isPidAlive(pid: number): boolean;
|
|
44
|
+
interface SweepMongoMemoryOptions {
|
|
45
|
+
/** Dirs to scan. Default: `os.tmpdir()` plus `TEST_MONGO_TMPDIR` when set. */
|
|
46
|
+
readonly dirs?: readonly string[];
|
|
47
|
+
/** Minimum age in ms; `null` turns the sweep off. Default: `staleMongoMemoryAgeMs()`. */
|
|
48
|
+
readonly maxAgeMs?: number | null;
|
|
49
|
+
/** Clock, for tests. Default `Date.now()`. */
|
|
50
|
+
readonly now?: number;
|
|
51
|
+
/** Liveness probe, for tests. Default `isPidAlive`. */
|
|
52
|
+
readonly isAlive?: (pid: number) => boolean;
|
|
53
|
+
}
|
|
54
|
+
interface SweepMongoMemoryResult {
|
|
55
|
+
readonly removed: string[];
|
|
56
|
+
readonly kept: Array<{
|
|
57
|
+
path: string;
|
|
58
|
+
reason: "live-process" | "recent";
|
|
59
|
+
}>;
|
|
60
|
+
readonly failed: Array<{
|
|
61
|
+
path: string;
|
|
62
|
+
error: string;
|
|
63
|
+
}>;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Remove abandoned `mongo-mem-*` data dirs.
|
|
67
|
+
*
|
|
68
|
+
* A dir is removed only when BOTH hold: its `mongod.lock` names no live process
|
|
69
|
+
* (or is empty or missing), and nothing in it changed for `maxAgeMs`. Keyfile
|
|
70
|
+
* dirs and anything without the prefix are never touched. Errors are collected,
|
|
71
|
+
* never thrown: a sweep must not fail a test run.
|
|
72
|
+
*/
|
|
73
|
+
export declare function sweepStaleMongoMemoryDirs(options?: SweepMongoMemoryOptions): Promise<SweepMongoMemoryResult>;
|
|
74
|
+
/** The parts of `MongoMemoryServer` / `MongoMemoryReplSet` this module uses. */
|
|
75
|
+
interface MmsServerLike {
|
|
76
|
+
getUri(dbName?: string): string;
|
|
77
|
+
start(): Promise<unknown>;
|
|
78
|
+
stop(cleanup?: {
|
|
79
|
+
doCleanup?: boolean;
|
|
80
|
+
force?: boolean;
|
|
81
|
+
}): Promise<unknown>;
|
|
82
|
+
}
|
|
83
|
+
type MongoMemoryKind = "standalone" | "replset";
|
|
84
|
+
interface LaunchedMongoMemory<S extends MmsServerLike> {
|
|
85
|
+
readonly server: S;
|
|
86
|
+
/** Data dirs this module created under `TEST_MONGO_TMPDIR` (empty when unset). */
|
|
87
|
+
readonly ownedDirs: readonly string[];
|
|
88
|
+
/** Stop and remove the data dirs. Idempotent. */
|
|
89
|
+
stop(): Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* Best-effort SYNCHRONOUS stop for a process `exit` handler, where no async
|
|
92
|
+
* work completes: kill the mongod processes and remove their data dirs.
|
|
93
|
+
* Idempotent, never throws.
|
|
94
|
+
*/
|
|
95
|
+
stopSync(): void;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Create and start a `MongoMemoryServer` (`standalone`) or `MongoMemoryReplSet`
|
|
99
|
+
* (`replset`) with the cleanup guarantees described at the top of this file.
|
|
100
|
+
*
|
|
101
|
+
* `Ctor` is the class itself, so a caller that loads mongodb-memory-server its
|
|
102
|
+
* own way (by resolved path, through an alias) keeps doing so.
|
|
103
|
+
*/
|
|
104
|
+
export declare function launchMongoMemory<S extends MmsServerLike>(Ctor: new (opts?: never) => S, kind: MongoMemoryKind, createOptions?: Record<string, unknown>): Promise<LaunchedMongoMemory<S>>;
|
|
105
|
+
/**
|
|
106
|
+
* Stop a launched server when the process ends without its teardown: Ctrl-C /
|
|
107
|
+
* SIGTERM stop it properly, then re-raise so the exit code stays truthful; an
|
|
108
|
+
* `exit` (including an uncaught exception) kills mongod and removes the dir
|
|
109
|
+
* synchronously. Returns an untrack function for the orderly path.
|
|
110
|
+
*
|
|
111
|
+
* Uses the package's ONE shared process hook, so tracking many servers adds no
|
|
112
|
+
* listeners beyond one per event.
|
|
113
|
+
*/
|
|
114
|
+
export declare function stopOnProcessExit(handle: LaunchedMongoMemory<MmsServerLike>): () => void;
|
|
4
115
|
/** WiredTiger cache per server, in GB. 0.25 is mongod's own floor. */
|
|
5
|
-
declare function cacheSizeGB(): number;
|
|
116
|
+
export declare function cacheSizeGB(): number;
|
|
6
117
|
/** mongod CLI args that bound a test server's footprint. */
|
|
7
|
-
declare function mongodMemoryArgs(): string[];
|
|
118
|
+
export declare function mongodMemoryArgs(): string[];
|
|
8
119
|
/**
|
|
9
120
|
* Worker count bounded by cores AND memory.
|
|
10
121
|
*
|
|
@@ -12,11 +123,11 @@ declare function mongodMemoryArgs(): string[];
|
|
|
12
123
|
* app plus every server it holds live. `envVar` lets a host keep its existing
|
|
13
124
|
* override name rather than forcing a rename through every CI config.
|
|
14
125
|
*/
|
|
15
|
-
declare function safeWorkerCount(envVar?: string): number;
|
|
126
|
+
export declare function safeWorkerCount(envVar?: string): number;
|
|
16
127
|
/** How many servers the run may boot, bounded by FREE memory at call time. */
|
|
17
|
-
declare function safePoolSize(requested: number): number;
|
|
128
|
+
export declare function safePoolSize(requested: number): number;
|
|
18
129
|
/** Splice a database name into a mongodb:// URI, preserving its query string. */
|
|
19
|
-
declare function withDbName(baseUri: string, dbName: string): string;
|
|
130
|
+
export declare function withDbName(baseUri: string, dbName: string): string;
|
|
20
131
|
/**
|
|
21
132
|
* Block until every registered model's index build has finished.
|
|
22
133
|
*
|
|
@@ -37,14 +148,14 @@ declare function withDbName(baseUri: string, dbName: string): string;
|
|
|
37
148
|
* that does not exist, and it would pass for the wrong reason — precisely the
|
|
38
149
|
* failure this function was added to remove.
|
|
39
150
|
*/
|
|
40
|
-
declare function awaitIndexBuilds(connection?: {
|
|
151
|
+
export declare function awaitIndexBuilds(connection?: {
|
|
41
152
|
readyState: number;
|
|
42
153
|
models: Record<string, {
|
|
43
154
|
init(): Promise<unknown>;
|
|
44
155
|
}>;
|
|
45
156
|
}): Promise<void>;
|
|
46
157
|
/** The subset of the mongoose module this adapter uses. */
|
|
47
|
-
interface MongooseLike {
|
|
158
|
+
export interface MongooseLike {
|
|
48
159
|
connection: {
|
|
49
160
|
readyState: number;
|
|
50
161
|
models: Record<string, {
|
|
@@ -56,7 +167,7 @@ interface MongooseLike {
|
|
|
56
167
|
connect(uri: string): Promise<unknown>;
|
|
57
168
|
disconnect(): Promise<unknown>;
|
|
58
169
|
}
|
|
59
|
-
interface MongoServerProviderOptions {
|
|
170
|
+
export interface MongoServerProviderOptions {
|
|
60
171
|
/** Extra mongod args, appended after the memory bounds. */
|
|
61
172
|
readonly args?: readonly string[];
|
|
62
173
|
/** Await index builds after each lease connects. Default true — see above. */
|
|
@@ -82,6 +193,5 @@ interface MongoServerProviderOptions {
|
|
|
82
193
|
* transactions, and a strict superset of a standalone. That is what lets the
|
|
83
194
|
* pool serve both kinds from one process when sharing is on.
|
|
84
195
|
*/
|
|
85
|
-
declare function mongoServerProvider(options?: MongoServerProviderOptions): TestServerProvider<Connection>;
|
|
86
|
-
|
|
87
|
-
export { MongoServerProviderOptions, MongooseLike, awaitIndexBuilds, cacheSizeGB, mongoServerProvider, mongodMemoryArgs, safePoolSize, safeWorkerCount, withDbName };
|
|
196
|
+
export declare function mongoServerProvider(options?: MongoServerProviderOptions): TestServerProvider<Connection>;
|
|
197
|
+
export type { LaunchedMongoMemory, MmsServerLike, MongoMemoryKind, SweepMongoMemoryOptions, SweepMongoMemoryResult };
|