@prisma-next/mongo-runtime 0.5.0-dev.8 → 0.5.0-dev.9
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 +39 -4
- package/dist/index.d.mts +48 -9
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +17 -56
- package/dist/index.mjs.map +1 -1
- package/package.json +17 -17
- package/src/exports/index.ts +1 -0
- package/src/mongo-execution-plan.ts +27 -0
- package/src/mongo-middleware.ts +17 -6
- package/src/mongo-runtime.ts +23 -71
package/README.md
CHANGED
|
@@ -2,18 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
MongoDB runtime executor for Prisma Next.
|
|
4
4
|
|
|
5
|
+
## Package Classification
|
|
6
|
+
|
|
7
|
+
- **Domain**: mongo
|
|
8
|
+
- **Layer**: runtime
|
|
9
|
+
- **Plane**: runtime
|
|
10
|
+
|
|
11
|
+
## Overview
|
|
12
|
+
|
|
13
|
+
The Mongo runtime package implements the Mongo family runtime by extending the abstract `RuntimeCore` base class from `@prisma-next/framework-components/runtime` with Mongo-specific lowering and driver dispatch. It provides the public runtime API for MongoDB, layering Mongo concerns (adapter lowering and wire-command dispatch) on top of the shared middleware lifecycle.
|
|
14
|
+
|
|
5
15
|
## Responsibilities
|
|
6
16
|
|
|
7
17
|
- **Runtime executor**: `createMongoRuntime()` composes adapter and driver into a `MongoRuntime` with a single `execute(plan)` entry point accepting `MongoQueryPlan<Row>` from `@prisma-next/mongo-query-ast`. Execution is one path for reads and writes: `adapter.lower(plan)` produces a wire command, then the driver runs it.
|
|
8
18
|
- **Unified flow**: There is no separate `execute` vs `executeCommand`; all operations use `execute(plan)`.
|
|
9
|
-
- **Lowering**: Happens in the adapter (`lower(plan)`),
|
|
10
|
-
- **
|
|
19
|
+
- **Lowering**: Happens in the adapter (`lower(plan)`), wrapped by the runtime's `lower` override into a `MongoExecutionPlan`.
|
|
20
|
+
- **Middleware lifecycle inheritance**: `MongoRuntime` extends `RuntimeCore<MongoQueryPlan, MongoExecutionPlan, MongoMiddleware>` and inherits the `beforeExecute` / `onRow` / `afterExecute` lifecycle from the framework via `runWithMiddleware`. Mongo does **not** override `runBeforeCompile` (Mongo middleware has no `beforeCompile` hook today).
|
|
21
|
+
- **Lifecycle management**: Connection lifecycle via `close()`.
|
|
11
22
|
|
|
12
23
|
## Dependencies
|
|
13
24
|
|
|
14
25
|
- **Depends on**:
|
|
15
26
|
- `@prisma-next/mongo-lowering` (`MongoAdapter`, `MongoDriver` interfaces)
|
|
16
27
|
- `@prisma-next/mongo-query-ast` (`MongoQueryPlan`, `AnyMongoCommand` — the typed plan shape)
|
|
17
|
-
- `@prisma-next/
|
|
28
|
+
- `@prisma-next/framework-components` (`RuntimeCore` base class, `runWithMiddleware` helper, `RuntimeMiddleware` SPI, `AsyncIterableResult` return type)
|
|
18
29
|
- **Depended on by**:
|
|
19
|
-
- Integration tests (`test/integration/test/mongo/`)
|
|
30
|
+
- Integration tests (`test/integration/test/mongo/` and `test/integration/test/cross-package/cross-family-middleware.test.ts`)
|
|
31
|
+
|
|
32
|
+
## Architecture
|
|
33
|
+
|
|
34
|
+
`MongoRuntimeImpl` extends `RuntimeCore<MongoQueryPlan, MongoExecutionPlan, MongoMiddleware>` and overrides:
|
|
35
|
+
|
|
36
|
+
- `lower(plan)` — calls the adapter's `lower(plan)` and wraps the resulting wire command into a `MongoExecutionPlan`.
|
|
37
|
+
- `runDriver(exec)` — dispatches the wire command to the Mongo driver via `driver.execute(exec.command)`.
|
|
38
|
+
- `close()` — closes the underlying driver.
|
|
39
|
+
|
|
40
|
+
The execution template (`execute(plan)` → `lower` → `runWithMiddleware` → `runDriver`) is inherited from `RuntimeCore`. The four inline middleware lifecycle loops (`beforeExecute`, `onRow`, `afterExecute`, plus the error-path `afterExecute`) that previously lived in `MongoRuntimeImpl.execute` are now delegated to the shared `runWithMiddleware` helper.
|
|
41
|
+
|
|
42
|
+
```mermaid
|
|
43
|
+
flowchart LR
|
|
44
|
+
Plan[MongoQueryPlan] --> Runtime[MongoRuntime]
|
|
45
|
+
Runtime -.extends.-> Core[RuntimeCore]
|
|
46
|
+
Runtime --> Adapter[MongoAdapter.lower]
|
|
47
|
+
Adapter --> Exec[MongoExecutionPlan]
|
|
48
|
+
Runtime --> Driver[MongoDriver.execute]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Related Subsystems
|
|
52
|
+
|
|
53
|
+
- **[Runtime & Middleware Framework](../../../../docs/architecture%20docs/subsystems/4.%20Runtime%20&%20Middleware%20Framework.md)** — Runtime execution pipeline
|
|
54
|
+
- **[Adapters & Targets](../../../../docs/architecture%20docs/subsystems/5.%20Adapters%20&%20Targets.md)** — Adapter and driver responsibilities
|
package/dist/index.d.mts
CHANGED
|
@@ -1,14 +1,53 @@
|
|
|
1
|
-
import { AfterExecuteResult, AsyncIterableResult, RuntimeMiddleware, RuntimeMiddlewareContext } from "@prisma-next/framework-components/runtime";
|
|
2
|
-
import {
|
|
1
|
+
import { AfterExecuteResult, AsyncIterableResult, ExecutionPlan, RuntimeMiddleware, RuntimeMiddlewareContext } from "@prisma-next/framework-components/runtime";
|
|
2
|
+
import { AnyMongoWireCommand } from "@prisma-next/mongo-wire";
|
|
3
3
|
import { MongoAdapter, MongoDriver } from "@prisma-next/mongo-lowering";
|
|
4
|
+
import { MongoQueryPlan } from "@prisma-next/mongo-query-ast/execution";
|
|
5
|
+
|
|
6
|
+
//#region src/mongo-execution-plan.d.ts
|
|
4
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Mongo-domain execution plan: a query lowered to the wire-command shape
|
|
10
|
+
* that a Mongo driver can run.
|
|
11
|
+
*
|
|
12
|
+
* The plan carries:
|
|
13
|
+
* - `command` — the wire command (e.g. `InsertOneWireCommand`,
|
|
14
|
+
* `AggregateWireCommand`) produced by `MongoAdapter.lower(plan)`
|
|
15
|
+
* - `meta` — family-agnostic plan metadata (target, lane, hashes, ...)
|
|
16
|
+
* - `_row` — phantom row type, propagated from the originating
|
|
17
|
+
* `MongoQueryPlan`
|
|
18
|
+
*
|
|
19
|
+
* Extends the framework-level `ExecutionPlan<Row>` marker so generic SPIs
|
|
20
|
+
* (`RuntimeExecutor<MongoExecutionPlan>`,
|
|
21
|
+
* `RuntimeMiddleware<MongoExecutionPlan>`) can be parameterized over it.
|
|
22
|
+
*
|
|
23
|
+
* Lives in the runtime layer (alongside `MongoRuntime`) because the wire
|
|
24
|
+
* command shape lives in the transport layer (`@prisma-next/mongo-wire`),
|
|
25
|
+
* which the lanes layer (`mongo-query-ast`, where `MongoQueryPlan` lives)
|
|
26
|
+
* cannot depend on. M1 establishes this type; `MongoRuntime.execute` does
|
|
27
|
+
* not yet accept it as input — that adoption lands in M4.
|
|
28
|
+
*/
|
|
29
|
+
interface MongoExecutionPlan<Row = unknown> extends ExecutionPlan<Row> {
|
|
30
|
+
readonly command: AnyMongoWireCommand;
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
5
33
|
//#region src/mongo-middleware.d.ts
|
|
6
34
|
interface MongoMiddlewareContext extends RuntimeMiddlewareContext {}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Mongo-domain middleware. Extends the framework `RuntimeMiddleware`
|
|
37
|
+
* parameterized over `MongoExecutionPlan` because `runWithMiddleware`
|
|
38
|
+
* (driven by `RuntimeCore`) invokes the lifecycle hooks with the
|
|
39
|
+
* post-lowering plan.
|
|
40
|
+
*
|
|
41
|
+
* `familyId` is optional so generic cross-family middleware (e.g.
|
|
42
|
+
* telemetry) — which carry no `familyId` — remain assignable. When
|
|
43
|
+
* present, it must be `'mongo'`; the runtime rejects mismatches at
|
|
44
|
+
* construction time via `checkMiddlewareCompatibility`.
|
|
45
|
+
*/
|
|
46
|
+
interface MongoMiddleware extends RuntimeMiddleware<MongoExecutionPlan> {
|
|
47
|
+
readonly familyId?: 'mongo';
|
|
48
|
+
beforeExecute?(plan: MongoExecutionPlan, ctx: MongoMiddlewareContext): Promise<void>;
|
|
49
|
+
onRow?(row: Record<string, unknown>, plan: MongoExecutionPlan, ctx: MongoMiddlewareContext): Promise<void>;
|
|
50
|
+
afterExecute?(plan: MongoExecutionPlan, result: AfterExecuteResult, ctx: MongoMiddlewareContext): Promise<void>;
|
|
12
51
|
}
|
|
13
52
|
//#endregion
|
|
14
53
|
//#region src/mongo-runtime.d.ts
|
|
@@ -17,7 +56,7 @@ interface MongoRuntimeOptions {
|
|
|
17
56
|
readonly driver: MongoDriver;
|
|
18
57
|
readonly contract: unknown;
|
|
19
58
|
readonly targetId: string;
|
|
20
|
-
readonly middleware?: readonly
|
|
59
|
+
readonly middleware?: readonly MongoMiddleware[];
|
|
21
60
|
readonly mode?: 'strict' | 'permissive';
|
|
22
61
|
}
|
|
23
62
|
interface MongoRuntime {
|
|
@@ -26,5 +65,5 @@ interface MongoRuntime {
|
|
|
26
65
|
}
|
|
27
66
|
declare function createMongoRuntime(options: MongoRuntimeOptions): MongoRuntime;
|
|
28
67
|
//#endregion
|
|
29
|
-
export { type MongoMiddleware, type MongoMiddlewareContext, type MongoRuntime, type MongoRuntimeOptions, createMongoRuntime };
|
|
68
|
+
export { type MongoExecutionPlan, type MongoMiddleware, type MongoMiddlewareContext, type MongoRuntime, type MongoRuntimeOptions, createMongoRuntime };
|
|
30
69
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/mongo-middleware.ts","../src/mongo-runtime.ts"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/mongo-execution-plan.ts","../src/mongo-middleware.ts","../src/mongo-runtime.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;AAwBA;;;;;;;;ACjBA;AAaA;;;;;;;;AAOK,UDHY,kBCGZ,CAAA,MAAA,OAAA,CAAA,SDHsD,aCGtD,CDHoE,GCGpE,CAAA,CAAA;EAEK,SAAA,OAAA,EDJU,mBCIV;;;;UAtBO,sBAAA,SAA+B;;;ADiBhD;;;;;;;;ACjBA;AAaiB,UAAA,eAAA,SAAwB,iBAAR,CAA0B,kBAA1B,CAAA,CAAA;EAA0B,SAAA,QAAA,CAAA,EAAA,OAAA;EAEpC,aAAA,EAAA,IAAA,EAAA,kBAAA,EAAA,GAAA,EAAyB,sBAAzB,CAAA,EAAkD,OAAlD,CAAA,IAAA,CAAA;EAAyB,KAAA,EAAA,GAAA,EAEvC,MAFuC,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,IAAA,EAGtC,kBAHsC,EAAA,GAAA,EAIvC,sBAJuC,CAAA,EAK3C,OAL2C,CAAA,IAAA,CAAA;EAAyB,YAAA,EAAA,IAAA,EAO/D,kBAP+D,EAAA,MAAA,EAQ7D,kBAR6D,EAAA,GAAA,EAShE,sBATgE,CAAA,EAUpE,OAVoE,CAAA,IAAA,CAAA;;;;UCVxD,mBAAA;oBACG;EFWH,SAAA,MAAA,EEVE,WFUgB;EAAsC,SAAA,QAAA,EAAA,OAAA;EACrD,SAAA,QAAA,EAAA,MAAA;EADuC,SAAA,UAAA,CAAA,EAAA,SEP1B,eFO0B,EAAA;EAAa,SAAA,IAAA,CAAA,EAAA,QAAA,GAAA,YAAA;;UEHvD,YAAA;qBACI,eAAe,OAAO,oBAAoB;EDf9C,KAAA,EAAA,ECgBN,ODhBM,CAAA,IAAA,CAAA;AAajB;AAA2D,iBCgD3C,kBAAA,CDhD2C,OAAA,ECgDf,mBDhDe,CAAA,ECgDO,YDhDP"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,77 +1,38 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RuntimeCore, checkMiddlewareCompatibility } from "@prisma-next/framework-components/runtime";
|
|
2
2
|
|
|
3
3
|
//#region src/mongo-runtime.ts
|
|
4
4
|
function noop() {}
|
|
5
|
-
|
|
6
|
-
return Date.now();
|
|
7
|
-
}
|
|
8
|
-
var MongoRuntimeImpl = class {
|
|
5
|
+
var MongoRuntimeImpl = class extends RuntimeCore {
|
|
9
6
|
#adapter;
|
|
10
7
|
#driver;
|
|
11
|
-
#middleware;
|
|
12
|
-
#middlewareContext;
|
|
13
8
|
constructor(options) {
|
|
14
|
-
this.#adapter = options.adapter;
|
|
15
|
-
this.#driver = options.driver;
|
|
16
9
|
const middleware = options.middleware ? [...options.middleware] : [];
|
|
17
10
|
for (const mw of middleware) checkMiddlewareCompatibility(mw, "mongo", options.targetId);
|
|
18
|
-
|
|
19
|
-
this.#middlewareContext = {
|
|
11
|
+
const ctx = {
|
|
20
12
|
contract: options.contract,
|
|
21
13
|
mode: options.mode ?? "strict",
|
|
22
|
-
now,
|
|
14
|
+
now: () => Date.now(),
|
|
23
15
|
log: {
|
|
24
16
|
info: noop,
|
|
25
17
|
warn: noop,
|
|
26
18
|
error: noop
|
|
27
19
|
}
|
|
28
20
|
};
|
|
21
|
+
super({
|
|
22
|
+
middleware,
|
|
23
|
+
ctx
|
|
24
|
+
});
|
|
25
|
+
this.#adapter = options.adapter;
|
|
26
|
+
this.#driver = options.driver;
|
|
29
27
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const ctx = this.#middlewareContext;
|
|
35
|
-
const iterator = async function* () {
|
|
36
|
-
const startedAt = ctx.now();
|
|
37
|
-
let rowCount = 0;
|
|
38
|
-
let completed = false;
|
|
39
|
-
let failed = false;
|
|
40
|
-
try {
|
|
41
|
-
for (const mw of middleware) if (mw.beforeExecute) await mw.beforeExecute(plan, ctx);
|
|
42
|
-
const wireCommand = await adapter.lower(plan);
|
|
43
|
-
for await (const row of driver.execute(wireCommand)) {
|
|
44
|
-
for (const mw of middleware) if (mw.onRow) await mw.onRow(row, plan, ctx);
|
|
45
|
-
rowCount++;
|
|
46
|
-
yield row;
|
|
47
|
-
}
|
|
48
|
-
completed = true;
|
|
49
|
-
} catch (error) {
|
|
50
|
-
failed = true;
|
|
51
|
-
throw error;
|
|
52
|
-
} finally {
|
|
53
|
-
const latencyMs = ctx.now() - startedAt;
|
|
54
|
-
for (const mw of middleware) {
|
|
55
|
-
if (!mw.afterExecute) continue;
|
|
56
|
-
if (failed) {
|
|
57
|
-
try {
|
|
58
|
-
await mw.afterExecute(plan, {
|
|
59
|
-
rowCount,
|
|
60
|
-
latencyMs,
|
|
61
|
-
completed
|
|
62
|
-
}, ctx);
|
|
63
|
-
} catch {}
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
await mw.afterExecute(plan, {
|
|
67
|
-
rowCount,
|
|
68
|
-
latencyMs,
|
|
69
|
-
completed
|
|
70
|
-
}, ctx);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
28
|
+
async lower(plan) {
|
|
29
|
+
return {
|
|
30
|
+
command: await this.#adapter.lower(plan),
|
|
31
|
+
meta: plan.meta
|
|
73
32
|
};
|
|
74
|
-
|
|
33
|
+
}
|
|
34
|
+
runDriver(exec) {
|
|
35
|
+
return this.#driver.execute(exec.command);
|
|
75
36
|
}
|
|
76
37
|
async close() {
|
|
77
38
|
await this.#driver.close();
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["#adapter","#driver","
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["#adapter","#driver","ctx: MongoMiddlewareContext"],"sources":["../src/mongo-runtime.ts"],"sourcesContent":["import type { AsyncIterableResult } from '@prisma-next/framework-components/runtime';\nimport {\n checkMiddlewareCompatibility,\n RuntimeCore,\n} from '@prisma-next/framework-components/runtime';\nimport type { MongoAdapter, MongoDriver } from '@prisma-next/mongo-lowering';\nimport type { MongoQueryPlan } from '@prisma-next/mongo-query-ast/execution';\nimport type { MongoExecutionPlan } from './mongo-execution-plan';\nimport type { MongoMiddleware, MongoMiddlewareContext } from './mongo-middleware';\n\nfunction noop() {}\n\nexport interface MongoRuntimeOptions {\n readonly adapter: MongoAdapter;\n readonly driver: MongoDriver;\n readonly contract: unknown;\n readonly targetId: string;\n readonly middleware?: readonly MongoMiddleware[];\n readonly mode?: 'strict' | 'permissive';\n}\n\nexport interface MongoRuntime {\n execute<Row>(plan: MongoQueryPlan<Row>): AsyncIterableResult<Row>;\n close(): Promise<void>;\n}\n\nclass MongoRuntimeImpl\n extends RuntimeCore<MongoQueryPlan, MongoExecutionPlan, MongoMiddleware>\n implements MongoRuntime\n{\n readonly #adapter: MongoAdapter;\n readonly #driver: MongoDriver;\n\n constructor(options: MongoRuntimeOptions) {\n const middleware = options.middleware ? [...options.middleware] : [];\n for (const mw of middleware) {\n checkMiddlewareCompatibility(mw, 'mongo', options.targetId);\n }\n\n const ctx: MongoMiddlewareContext = {\n contract: options.contract,\n mode: options.mode ?? 'strict',\n now: () => Date.now(),\n log: { info: noop, warn: noop, error: noop },\n };\n\n super({ middleware, ctx });\n\n this.#adapter = options.adapter;\n this.#driver = options.driver;\n }\n\n protected override async lower(plan: MongoQueryPlan): Promise<MongoExecutionPlan> {\n return {\n command: await this.#adapter.lower(plan),\n meta: plan.meta,\n };\n }\n\n protected override runDriver(exec: MongoExecutionPlan): AsyncIterable<Record<string, unknown>> {\n return this.#driver.execute<Record<string, unknown>>(exec.command);\n }\n\n override async close(): Promise<void> {\n await this.#driver.close();\n }\n}\n\nexport function createMongoRuntime(options: MongoRuntimeOptions): MongoRuntime {\n return new MongoRuntimeImpl(options);\n}\n"],"mappings":";;;AAUA,SAAS,OAAO;AAgBhB,IAAM,mBAAN,cACU,YAEV;CACE,CAASA;CACT,CAASC;CAET,YAAY,SAA8B;EACxC,MAAM,aAAa,QAAQ,aAAa,CAAC,GAAG,QAAQ,WAAW,GAAG,EAAE;AACpE,OAAK,MAAM,MAAM,WACf,8BAA6B,IAAI,SAAS,QAAQ,SAAS;EAG7D,MAAMC,MAA8B;GAClC,UAAU,QAAQ;GAClB,MAAM,QAAQ,QAAQ;GACtB,WAAW,KAAK,KAAK;GACrB,KAAK;IAAE,MAAM;IAAM,MAAM;IAAM,OAAO;IAAM;GAC7C;AAED,QAAM;GAAE;GAAY;GAAK,CAAC;AAE1B,QAAKF,UAAW,QAAQ;AACxB,QAAKC,SAAU,QAAQ;;CAGzB,MAAyB,MAAM,MAAmD;AAChF,SAAO;GACL,SAAS,MAAM,MAAKD,QAAS,MAAM,KAAK;GACxC,MAAM,KAAK;GACZ;;CAGH,AAAmB,UAAU,MAAkE;AAC7F,SAAO,MAAKC,OAAQ,QAAiC,KAAK,QAAQ;;CAGpE,MAAe,QAAuB;AACpC,QAAM,MAAKA,OAAQ,OAAO;;;AAI9B,SAAgB,mBAAmB,SAA4C;AAC7E,QAAO,IAAI,iBAAiB,QAAQ"}
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/mongo-runtime",
|
|
3
|
-
"version": "0.5.0-dev.
|
|
3
|
+
"version": "0.5.0-dev.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "MongoDB runtime implementation for Prisma Next",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@prisma-next/
|
|
9
|
-
"@prisma-next/
|
|
10
|
-
"@prisma-next/
|
|
11
|
-
"@prisma-next/mongo-query-ast": "0.5.0-dev.
|
|
8
|
+
"@prisma-next/mongo-lowering": "0.5.0-dev.9",
|
|
9
|
+
"@prisma-next/contract": "0.5.0-dev.9",
|
|
10
|
+
"@prisma-next/framework-components": "0.5.0-dev.9",
|
|
11
|
+
"@prisma-next/mongo-query-ast": "0.5.0-dev.9",
|
|
12
|
+
"@prisma-next/mongo-wire": "0.5.0-dev.9"
|
|
12
13
|
},
|
|
13
14
|
"devDependencies": {
|
|
14
15
|
"mongodb": "^6.16.0",
|
|
@@ -16,19 +17,18 @@
|
|
|
16
17
|
"tsdown": "0.18.4",
|
|
17
18
|
"typescript": "5.9.3",
|
|
18
19
|
"vitest": "4.0.17",
|
|
19
|
-
"@prisma-next/
|
|
20
|
-
"@prisma-next/
|
|
21
|
-
"@prisma-next/mongo
|
|
22
|
-
"@prisma-next/
|
|
23
|
-
"@prisma-next/
|
|
24
|
-
"@prisma-next/mongo-value": "0.5.0-dev.
|
|
25
|
-
"@prisma-next/driver-mongo": "0.5.0-dev.
|
|
26
|
-
"@prisma-next/mongo-
|
|
27
|
-
"@prisma-next/target-mongo": "0.5.0-dev.
|
|
28
|
-
"@prisma-next/
|
|
29
|
-
"@prisma-next/test-utils": "0.0.1",
|
|
20
|
+
"@prisma-next/middleware-telemetry": "0.5.0-dev.9",
|
|
21
|
+
"@prisma-next/adapter-mongo": "0.5.0-dev.9",
|
|
22
|
+
"@prisma-next/family-mongo": "0.5.0-dev.9",
|
|
23
|
+
"@prisma-next/mongo-contract-ts": "0.5.0-dev.9",
|
|
24
|
+
"@prisma-next/mongo-query-builder": "0.5.0-dev.9",
|
|
25
|
+
"@prisma-next/mongo-value": "0.5.0-dev.9",
|
|
26
|
+
"@prisma-next/driver-mongo": "0.5.0-dev.9",
|
|
27
|
+
"@prisma-next/mongo-contract": "0.5.0-dev.9",
|
|
28
|
+
"@prisma-next/target-mongo": "0.5.0-dev.9",
|
|
29
|
+
"@prisma-next/tsconfig": "0.0.0",
|
|
30
30
|
"@prisma-next/tsdown": "0.0.0",
|
|
31
|
-
"@prisma-next/
|
|
31
|
+
"@prisma-next/test-utils": "0.0.1"
|
|
32
32
|
},
|
|
33
33
|
"files": [
|
|
34
34
|
"dist",
|
package/src/exports/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export type { MongoExecutionPlan } from '../mongo-execution-plan';
|
|
1
2
|
export type { MongoMiddleware, MongoMiddlewareContext } from '../mongo-middleware';
|
|
2
3
|
export type { MongoRuntime, MongoRuntimeOptions } from '../mongo-runtime';
|
|
3
4
|
export { createMongoRuntime } from '../mongo-runtime';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ExecutionPlan } from '@prisma-next/framework-components/runtime';
|
|
2
|
+
import type { AnyMongoWireCommand } from '@prisma-next/mongo-wire';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Mongo-domain execution plan: a query lowered to the wire-command shape
|
|
6
|
+
* that a Mongo driver can run.
|
|
7
|
+
*
|
|
8
|
+
* The plan carries:
|
|
9
|
+
* - `command` — the wire command (e.g. `InsertOneWireCommand`,
|
|
10
|
+
* `AggregateWireCommand`) produced by `MongoAdapter.lower(plan)`
|
|
11
|
+
* - `meta` — family-agnostic plan metadata (target, lane, hashes, ...)
|
|
12
|
+
* - `_row` — phantom row type, propagated from the originating
|
|
13
|
+
* `MongoQueryPlan`
|
|
14
|
+
*
|
|
15
|
+
* Extends the framework-level `ExecutionPlan<Row>` marker so generic SPIs
|
|
16
|
+
* (`RuntimeExecutor<MongoExecutionPlan>`,
|
|
17
|
+
* `RuntimeMiddleware<MongoExecutionPlan>`) can be parameterized over it.
|
|
18
|
+
*
|
|
19
|
+
* Lives in the runtime layer (alongside `MongoRuntime`) because the wire
|
|
20
|
+
* command shape lives in the transport layer (`@prisma-next/mongo-wire`),
|
|
21
|
+
* which the lanes layer (`mongo-query-ast`, where `MongoQueryPlan` lives)
|
|
22
|
+
* cannot depend on. M1 establishes this type; `MongoRuntime.execute` does
|
|
23
|
+
* not yet accept it as input — that adoption lands in M4.
|
|
24
|
+
*/
|
|
25
|
+
export interface MongoExecutionPlan<Row = unknown> extends ExecutionPlan<Row> {
|
|
26
|
+
readonly command: AnyMongoWireCommand;
|
|
27
|
+
}
|
package/src/mongo-middleware.ts
CHANGED
|
@@ -3,20 +3,31 @@ import type {
|
|
|
3
3
|
RuntimeMiddleware,
|
|
4
4
|
RuntimeMiddlewareContext,
|
|
5
5
|
} from '@prisma-next/framework-components/runtime';
|
|
6
|
-
import type {
|
|
6
|
+
import type { MongoExecutionPlan } from './mongo-execution-plan';
|
|
7
7
|
|
|
8
8
|
export interface MongoMiddlewareContext extends RuntimeMiddlewareContext {}
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Mongo-domain middleware. Extends the framework `RuntimeMiddleware`
|
|
12
|
+
* parameterized over `MongoExecutionPlan` because `runWithMiddleware`
|
|
13
|
+
* (driven by `RuntimeCore`) invokes the lifecycle hooks with the
|
|
14
|
+
* post-lowering plan.
|
|
15
|
+
*
|
|
16
|
+
* `familyId` is optional so generic cross-family middleware (e.g.
|
|
17
|
+
* telemetry) — which carry no `familyId` — remain assignable. When
|
|
18
|
+
* present, it must be `'mongo'`; the runtime rejects mismatches at
|
|
19
|
+
* construction time via `checkMiddlewareCompatibility`.
|
|
20
|
+
*/
|
|
21
|
+
export interface MongoMiddleware extends RuntimeMiddleware<MongoExecutionPlan> {
|
|
22
|
+
readonly familyId?: 'mongo';
|
|
23
|
+
beforeExecute?(plan: MongoExecutionPlan, ctx: MongoMiddlewareContext): Promise<void>;
|
|
13
24
|
onRow?(
|
|
14
25
|
row: Record<string, unknown>,
|
|
15
|
-
plan:
|
|
26
|
+
plan: MongoExecutionPlan,
|
|
16
27
|
ctx: MongoMiddlewareContext,
|
|
17
28
|
): Promise<void>;
|
|
18
29
|
afterExecute?(
|
|
19
|
-
plan:
|
|
30
|
+
plan: MongoExecutionPlan,
|
|
20
31
|
result: AfterExecuteResult,
|
|
21
32
|
ctx: MongoMiddlewareContext,
|
|
22
33
|
): Promise<void>;
|
package/src/mongo-runtime.ts
CHANGED
|
@@ -1,25 +1,21 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
RuntimeMiddleware,
|
|
3
|
-
RuntimeMiddlewareContext,
|
|
4
|
-
} from '@prisma-next/framework-components/runtime';
|
|
1
|
+
import type { AsyncIterableResult } from '@prisma-next/framework-components/runtime';
|
|
5
2
|
import {
|
|
6
|
-
AsyncIterableResult,
|
|
7
3
|
checkMiddlewareCompatibility,
|
|
4
|
+
RuntimeCore,
|
|
8
5
|
} from '@prisma-next/framework-components/runtime';
|
|
9
6
|
import type { MongoAdapter, MongoDriver } from '@prisma-next/mongo-lowering';
|
|
10
7
|
import type { MongoQueryPlan } from '@prisma-next/mongo-query-ast/execution';
|
|
8
|
+
import type { MongoExecutionPlan } from './mongo-execution-plan';
|
|
9
|
+
import type { MongoMiddleware, MongoMiddlewareContext } from './mongo-middleware';
|
|
11
10
|
|
|
12
11
|
function noop() {}
|
|
13
|
-
function now() {
|
|
14
|
-
return Date.now();
|
|
15
|
-
}
|
|
16
12
|
|
|
17
13
|
export interface MongoRuntimeOptions {
|
|
18
14
|
readonly adapter: MongoAdapter;
|
|
19
15
|
readonly driver: MongoDriver;
|
|
20
16
|
readonly contract: unknown;
|
|
21
17
|
readonly targetId: string;
|
|
22
|
-
readonly middleware?: readonly
|
|
18
|
+
readonly middleware?: readonly MongoMiddleware[];
|
|
23
19
|
readonly mode?: 'strict' | 'permissive';
|
|
24
20
|
}
|
|
25
21
|
|
|
@@ -28,88 +24,44 @@ export interface MongoRuntime {
|
|
|
28
24
|
close(): Promise<void>;
|
|
29
25
|
}
|
|
30
26
|
|
|
31
|
-
class MongoRuntimeImpl
|
|
27
|
+
class MongoRuntimeImpl
|
|
28
|
+
extends RuntimeCore<MongoQueryPlan, MongoExecutionPlan, MongoMiddleware>
|
|
29
|
+
implements MongoRuntime
|
|
30
|
+
{
|
|
32
31
|
readonly #adapter: MongoAdapter;
|
|
33
32
|
readonly #driver: MongoDriver;
|
|
34
|
-
readonly #middleware: readonly RuntimeMiddleware[];
|
|
35
|
-
readonly #middlewareContext: RuntimeMiddlewareContext;
|
|
36
33
|
|
|
37
34
|
constructor(options: MongoRuntimeOptions) {
|
|
38
|
-
this.#adapter = options.adapter;
|
|
39
|
-
this.#driver = options.driver;
|
|
40
|
-
|
|
41
35
|
const middleware = options.middleware ? [...options.middleware] : [];
|
|
42
36
|
for (const mw of middleware) {
|
|
43
37
|
checkMiddlewareCompatibility(mw, 'mongo', options.targetId);
|
|
44
38
|
}
|
|
45
|
-
this.#middleware = middleware;
|
|
46
39
|
|
|
47
|
-
|
|
40
|
+
const ctx: MongoMiddlewareContext = {
|
|
48
41
|
contract: options.contract,
|
|
49
42
|
mode: options.mode ?? 'strict',
|
|
50
|
-
now,
|
|
43
|
+
now: () => Date.now(),
|
|
51
44
|
log: { info: noop, warn: noop, error: noop },
|
|
52
45
|
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
execute<Row>(plan: MongoQueryPlan<Row>): AsyncIterableResult<Row> {
|
|
56
|
-
const adapter = this.#adapter;
|
|
57
|
-
const driver = this.#driver;
|
|
58
|
-
const middleware = this.#middleware;
|
|
59
|
-
const ctx = this.#middlewareContext;
|
|
60
|
-
|
|
61
|
-
const iterator = async function* (): AsyncGenerator<Row, void, unknown> {
|
|
62
|
-
const startedAt = ctx.now();
|
|
63
|
-
let rowCount = 0;
|
|
64
|
-
let completed = false;
|
|
65
|
-
let failed = false;
|
|
66
46
|
|
|
67
|
-
|
|
68
|
-
for (const mw of middleware) {
|
|
69
|
-
if (mw.beforeExecute) {
|
|
70
|
-
await mw.beforeExecute(plan, ctx);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
47
|
+
super({ middleware, ctx });
|
|
73
48
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
for (const mw of middleware) {
|
|
78
|
-
if (mw.onRow) {
|
|
79
|
-
await mw.onRow(row as Record<string, unknown>, plan, ctx);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
rowCount++;
|
|
83
|
-
yield row;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
completed = true;
|
|
87
|
-
} catch (error) {
|
|
88
|
-
failed = true;
|
|
89
|
-
throw error;
|
|
90
|
-
} finally {
|
|
91
|
-
const latencyMs = ctx.now() - startedAt;
|
|
92
|
-
for (const mw of middleware) {
|
|
93
|
-
if (!mw.afterExecute) continue;
|
|
94
|
-
|
|
95
|
-
if (failed) {
|
|
96
|
-
try {
|
|
97
|
-
await mw.afterExecute(plan, { rowCount, latencyMs, completed }, ctx);
|
|
98
|
-
} catch {
|
|
99
|
-
// Ignore errors from afterExecute during error handling
|
|
100
|
-
}
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
49
|
+
this.#adapter = options.adapter;
|
|
50
|
+
this.#driver = options.driver;
|
|
51
|
+
}
|
|
103
52
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
53
|
+
protected override async lower(plan: MongoQueryPlan): Promise<MongoExecutionPlan> {
|
|
54
|
+
return {
|
|
55
|
+
command: await this.#adapter.lower(plan),
|
|
56
|
+
meta: plan.meta,
|
|
107
57
|
};
|
|
58
|
+
}
|
|
108
59
|
|
|
109
|
-
|
|
60
|
+
protected override runDriver(exec: MongoExecutionPlan): AsyncIterable<Record<string, unknown>> {
|
|
61
|
+
return this.#driver.execute<Record<string, unknown>>(exec.command);
|
|
110
62
|
}
|
|
111
63
|
|
|
112
|
-
async close(): Promise<void> {
|
|
64
|
+
override async close(): Promise<void> {
|
|
113
65
|
await this.#driver.close();
|
|
114
66
|
}
|
|
115
67
|
}
|