@prisma-next/framework-components 0.6.0-dev.8 → 0.6.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/dist/control.d.mts +13 -10
- package/dist/control.d.mts.map +1 -1
- package/dist/runtime.d.mts +196 -103
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +90 -22
- package/dist/runtime.mjs.map +1 -1
- package/package.json +7 -7
- package/src/control/control-migration-types.ts +12 -9
- package/src/execution/before-execute-chain.ts +77 -0
- package/src/execution/run-with-middleware.ts +20 -38
- package/src/execution/runtime-core.ts +16 -3
- package/src/execution/runtime-middleware.ts +26 -0
- package/src/exports/runtime.ts +1 -0
package/dist/control.d.mts
CHANGED
|
@@ -758,16 +758,19 @@ interface MultiSpaceRunnerFailure extends MigrationRunnerFailure {
|
|
|
758
758
|
}
|
|
759
759
|
type MultiSpaceRunnerResult = Result<MultiSpaceRunnerSuccessValue, MultiSpaceRunnerFailure>;
|
|
760
760
|
/**
|
|
761
|
-
* Optional capability for runners that can apply a list of per-space plans
|
|
762
|
-
*
|
|
763
|
-
*
|
|
764
|
-
*
|
|
765
|
-
*
|
|
766
|
-
*
|
|
767
|
-
*
|
|
768
|
-
*
|
|
769
|
-
*
|
|
770
|
-
*
|
|
761
|
+
* Optional capability for runners that can apply a list of per-space plans.
|
|
762
|
+
* Atomicity semantics differ by family:
|
|
763
|
+
*
|
|
764
|
+
* - SQL (`SqlMigrationRunner`) opens one outer transaction across every
|
|
765
|
+
* space; a failure on any space rolls back every space's writes.
|
|
766
|
+
* - Mongo (`mongoTargetDescriptor`) cannot wrap most DDL ops in a session
|
|
767
|
+
* transaction (TML-2408), so it iterates per-space without an outer
|
|
768
|
+
* transaction and relies on per-space-internal verify-gated marker
|
|
769
|
+
* atomicity. Earlier-advanced markers are not rolled back when a later
|
|
770
|
+
* space fails; re-running resumes from the failing space.
|
|
771
|
+
*
|
|
772
|
+
* The capability is declared at the framework layer so CLI utilities can
|
|
773
|
+
* route through it without importing any specific family directly.
|
|
771
774
|
*/
|
|
772
775
|
interface MultiSpaceCapableRunner<TFamilyId extends string = string, TTargetId extends string = string> {
|
|
773
776
|
executeAcrossSpaces(options: {
|
package/dist/control.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control.d.mts","names":[],"sources":["../src/control/control-result-types.ts","../src/control/control-instances.ts","../src/control/control-stack.ts","../src/control/control-descriptors.ts","../src/control/control-migration-types.ts","../src/control/control-operation-preview.ts","../src/control/control-schema-view.ts","../src/control/control-capabilities.ts","../src/control/control-spaces.ts"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"control.d.mts","names":[],"sources":["../src/control/control-result-types.ts","../src/control/control-instances.ts","../src/control/control-stack.ts","../src/control/control-descriptors.ts","../src/control/control-migration-types.ts","../src/control/control-operation-preview.ts","../src/control/control-schema-view.ts","../src/control/control-capabilities.ts","../src/control/control-spaces.ts"],"mappings":"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"}
|
package/dist/runtime.d.mts
CHANGED
|
@@ -64,95 +64,6 @@ type ResultType<P> = '_row' extends keyof P ? P extends {
|
|
|
64
64
|
readonly _row?: infer R;
|
|
65
65
|
} ? R : never : never;
|
|
66
66
|
//#endregion
|
|
67
|
-
//#region src/execution/runtime-error.d.ts
|
|
68
|
-
interface RuntimeErrorEnvelope extends Error {
|
|
69
|
-
readonly code: string;
|
|
70
|
-
readonly category: 'PLAN' | 'CONTRACT' | 'LINT' | 'BUDGET' | 'RUNTIME';
|
|
71
|
-
readonly severity: 'error';
|
|
72
|
-
readonly details?: Record<string, unknown>;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Stable code emitted by the runtime when an in-flight `execute()`
|
|
76
|
-
* is cancelled via the per-query `AbortSignal`. The envelope's
|
|
77
|
-
* `details.phase` distinguishes where the abort was observed:
|
|
78
|
-
*
|
|
79
|
-
* - `'encode'` — abort fired during `encodeParams` (SQL) or
|
|
80
|
-
* `resolveValue` (Mongo).
|
|
81
|
-
* - `'decode'` — abort fired during `decodeRow` / `decodeField`.
|
|
82
|
-
* - `'stream'` — abort fired between rows or before any codec call
|
|
83
|
-
* (already-aborted at entry).
|
|
84
|
-
* - `'beforeExecute'` / `'afterExecute'` / `'onRow'` — abort fired
|
|
85
|
-
* on entry to or during the corresponding middleware phase
|
|
86
|
-
* (cooperative cancellation per the param-transform seam).
|
|
87
|
-
*/
|
|
88
|
-
declare const RUNTIME_ABORTED: "RUNTIME.ABORTED";
|
|
89
|
-
/** Discriminator placed in `details.phase` of a `RUNTIME.ABORTED` envelope. */
|
|
90
|
-
type RuntimeAbortedPhase = 'encode' | 'decode' | 'stream' | 'beforeExecute' | 'afterExecute' | 'onRow';
|
|
91
|
-
/**
|
|
92
|
-
* Type guard for the runtime-error envelope produced by `runtimeError`.
|
|
93
|
-
*
|
|
94
|
-
* Prefer this over duck-typing on `error.code` directly so consumers stay
|
|
95
|
-
* insulated from the envelope's internal shape.
|
|
96
|
-
*/
|
|
97
|
-
declare function isRuntimeError(error: unknown): error is RuntimeErrorEnvelope;
|
|
98
|
-
declare function runtimeError(code: string, message: string, details?: Record<string, unknown>): RuntimeErrorEnvelope;
|
|
99
|
-
/**
|
|
100
|
-
* Construct a `RUNTIME.ABORTED` envelope. Phase distinguishes where the
|
|
101
|
-
* abort was observed — codec call sites (`encode` / `decode` / `stream`)
|
|
102
|
-
* or middleware seams (`beforeExecute` / `afterExecute` / `onRow`), as
|
|
103
|
-
* enumerated on {@link RuntimeAbortedPhase}. Cause carries
|
|
104
|
-
* `signal.reason` verbatim from the platform — native abort produces a
|
|
105
|
-
* `DOMException`, explicit `controller.abort(reason)` produces whatever
|
|
106
|
-
* the caller passed. No synthesis happens here.
|
|
107
|
-
*/
|
|
108
|
-
declare function runtimeAborted(phase: RuntimeAbortedPhase, cause?: unknown): RuntimeErrorEnvelope;
|
|
109
|
-
//#endregion
|
|
110
|
-
//#region src/execution/race-against-abort.d.ts
|
|
111
|
-
/**
|
|
112
|
-
* Throw a phase-tagged `RUNTIME.ABORTED` envelope if the supplied
|
|
113
|
-
* context is already aborted at the precheck site. Centralises the
|
|
114
|
-
* `if (ctx.signal?.aborted) throw runtimeAborted(...)` pattern that
|
|
115
|
-
* every codec dispatch site (and the `beforeExecute` middleware phase)
|
|
116
|
-
* repeats. Accepts both the framework `CodecCallContext` and the
|
|
117
|
-
* `RuntimeMiddlewareContext`; both expose `signal?: AbortSignal`.
|
|
118
|
-
*/
|
|
119
|
-
declare function checkAborted(ctx: {
|
|
120
|
-
readonly signal?: AbortSignal;
|
|
121
|
-
}, phase: RuntimeAbortedPhase): void;
|
|
122
|
-
/**
|
|
123
|
-
* Race a per-cell `Promise.all` (or any other in-flight work promise) against
|
|
124
|
-
* the supplied abort signal so the runtime returns `RUNTIME.ABORTED` promptly
|
|
125
|
-
* even when codec bodies ignore the signal. In-flight bodies that ignore the
|
|
126
|
-
* signal are abandoned and run to completion in the background — the
|
|
127
|
-
* cooperative-cancellation contract documented in ADR 204.
|
|
128
|
-
*
|
|
129
|
-
* Call sites still SHOULD pre-check `signal.aborted` and short-circuit with
|
|
130
|
-
* a phase-tagged `RUNTIME.ABORTED` envelope before invoking this helper —
|
|
131
|
-
* that path is the canonical "aborted at entry" surface and avoids
|
|
132
|
-
* scheduling the work promise. As a defensive belt-and-braces, this helper
|
|
133
|
-
* also handles the already-aborted case internally: `AbortSignal` does not
|
|
134
|
-
* replay past abort events to listeners registered after the abort, so we
|
|
135
|
-
* inspect `signal.aborted` synchronously and reject with the sentinel
|
|
136
|
-
* before installing the listener. The rejection is still attributed to the
|
|
137
|
-
* abort path via the sentinel-identity check.
|
|
138
|
-
*
|
|
139
|
-
* Distinguishing the rejection source is load-bearing for AC-ERR4
|
|
140
|
-
* (`RUNTIME.ENCODE_FAILED` / `RUNTIME.DECODE_FAILED` pass through unchanged).
|
|
141
|
-
* The semantically equivalent `abortable(signal)` helper in
|
|
142
|
-
* `@prisma-next/utils` rejects with `signal.reason ?? new DOMException(...)`,
|
|
143
|
-
* which is not stably distinguishable from a codec-thrown error by identity
|
|
144
|
-
* alone (a fresh fallback DOMException is allocated per call). We instead
|
|
145
|
-
* track abort attribution with a unique sentinel: only the `onAbort` listener
|
|
146
|
-
* installed here ever rejects with the sentinel, so an `error === sentinel`
|
|
147
|
-
* identity check after the race is unambiguous.
|
|
148
|
-
*
|
|
149
|
-
* Lives in `framework-components` (rather than the SQL family, where it
|
|
150
|
-
* originated in m2) so every family runtime that needs cooperative
|
|
151
|
-
* cancellation around a codec-dispatch `Promise.all` (SQL encode + decode
|
|
152
|
-
* today, Mongo encode in m3) shares the same attribution logic.
|
|
153
|
-
*/
|
|
154
|
-
declare function raceAgainstAbort<T>(work: Promise<T>, signal: AbortSignal | undefined, phase: RuntimeAbortedPhase): Promise<T>;
|
|
155
|
-
//#endregion
|
|
156
67
|
//#region src/execution/runtime-middleware.d.ts
|
|
157
68
|
interface RuntimeLog {
|
|
158
69
|
info(event: unknown): void;
|
|
@@ -308,6 +219,32 @@ interface RuntimeMiddleware<TPlan extends QueryPlan = QueryPlan, TMutator extend
|
|
|
308
219
|
* rows directly: caching, mocks, rate limiting, circuit breaking.
|
|
309
220
|
*/
|
|
310
221
|
intercept?(plan: TPlan, ctx: RuntimeMiddlewareContext): Promise<InterceptResult | undefined>;
|
|
222
|
+
/**
|
|
223
|
+
* Fires after the family runtime has produced a draft execution
|
|
224
|
+
* plan from the AST, but before the family encodes parameter values
|
|
225
|
+
* to driver wire format. Mutations applied via the
|
|
226
|
+
* family-specific `params` mutator are visible to the subsequent
|
|
227
|
+
* encode step.
|
|
228
|
+
*
|
|
229
|
+
* Lifecycle position (SQL example):
|
|
230
|
+
* `runBeforeCompile → lowerSqlPlan → beforeExecute → encodeParams → intercept → driver`.
|
|
231
|
+
*
|
|
232
|
+
* The `params` argument is a family-specific {@link ParamRefMutator}
|
|
233
|
+
* scoped to the value slots of `ParamRef` nodes in the plan's AST.
|
|
234
|
+
* Middleware that doesn't need to mutate params can ignore the
|
|
235
|
+
* argument; existing `(plan)` / `(plan, ctx)` bodies stay compatible.
|
|
236
|
+
*
|
|
237
|
+
* `ctx.signal` carries the per-query `AbortSignal`; middleware that
|
|
238
|
+
* wraps a network SDK forwards it. Cooperative cancellation
|
|
239
|
+
* surfaces a `RUNTIME.ABORTED { phase: 'beforeExecute' }` envelope
|
|
240
|
+
* promptly even when the body ignores the signal.
|
|
241
|
+
*
|
|
242
|
+
* Intercept ordering: `intercept` runs *after* this hook; an
|
|
243
|
+
* interceptor that short-circuits the driver path still observes
|
|
244
|
+
* the post-`beforeExecute`, fully-encoded plan. The trade-off is
|
|
245
|
+
* that any `beforeExecute` SDK round-trips happen even when a
|
|
246
|
+
* downstream interceptor would have skipped the driver entirely.
|
|
247
|
+
*/
|
|
311
248
|
beforeExecute?(plan: TPlan, ctx: RuntimeMiddlewareContext, params?: TMutator): void | Promise<void>;
|
|
312
249
|
onRow?(row: Record<string, unknown>, plan: TPlan, ctx: RuntimeMiddlewareContext): Promise<void>;
|
|
313
250
|
afterExecute?(plan: TPlan, result: AfterExecuteResult, ctx: RuntimeMiddlewareContext): Promise<void>;
|
|
@@ -340,9 +277,151 @@ interface RuntimeExecutor<TPlan extends QueryPlan> {
|
|
|
340
277
|
}
|
|
341
278
|
declare function checkMiddlewareCompatibility(middleware: RuntimeMiddleware, runtimeFamilyId: string, runtimeTargetId: string): void;
|
|
342
279
|
//#endregion
|
|
280
|
+
//#region src/execution/before-execute-chain.d.ts
|
|
281
|
+
/**
|
|
282
|
+
* Runs every middleware's `beforeExecute` hook in registration order,
|
|
283
|
+
* threading through the (optional) family-specific `paramsMutator`.
|
|
284
|
+
*
|
|
285
|
+
* Why this lives outside {@link runWithMiddleware}: middleware that
|
|
286
|
+
* mutates parameter values (e.g. cipherstash's bulk-encrypt SDK
|
|
287
|
+
* round-trip) must run *before* the family runtime encodes those
|
|
288
|
+
* parameters to driver wire format. Family runtimes call
|
|
289
|
+
* `runBeforeExecuteChain` between the AST → plan lowering step and
|
|
290
|
+
* the parameter encode step; the encode then observes the mutator's
|
|
291
|
+
* `currentParams()` view. `runWithMiddleware` retains the rest of
|
|
292
|
+
* the lifecycle (`intercept`, driver/row source loop, `onRow`,
|
|
293
|
+
* `afterExecute`) but no longer fires `beforeExecute` itself.
|
|
294
|
+
*
|
|
295
|
+
* Lifecycle within this helper:
|
|
296
|
+
*
|
|
297
|
+
* 1. For each middleware in registration order, if `beforeExecute`
|
|
298
|
+
* is implemented:
|
|
299
|
+
* - `checkAborted(ctx, 'beforeExecute')` short-circuits if the
|
|
300
|
+
* caller already aborted at entry.
|
|
301
|
+
* - The hook is invoked with `(plan, ctx, paramsMutator)`. A
|
|
302
|
+
* middleware body that ignores the mutator stays compatible —
|
|
303
|
+
* JavaScript allows extra positional arguments.
|
|
304
|
+
* - If the hook returns a Promise, it is raced against
|
|
305
|
+
* `ctx.signal` via {@link raceAgainstAbort} so cooperative
|
|
306
|
+
* cancellation surfaces a `RUNTIME.ABORTED { phase:
|
|
307
|
+
* 'beforeExecute' }` envelope even when the body itself
|
|
308
|
+
* ignores the signal.
|
|
309
|
+
*
|
|
310
|
+
* Error propagation: any error thrown by a `beforeExecute` body
|
|
311
|
+
* (or surfaced by the abort race) propagates out of this helper
|
|
312
|
+
* unchanged. The family runtime is responsible for converting it
|
|
313
|
+
* into the appropriate `afterExecute(completed: false)` notification
|
|
314
|
+
* once `runWithMiddleware` runs.
|
|
315
|
+
*
|
|
316
|
+
* Relationship to {@link runWithMiddleware}: the framework's
|
|
317
|
+
* `RuntimeCore.execute` template calls this helper between
|
|
318
|
+
* `lower(plan)` and `runWithMiddleware(...)`. Family runtimes that
|
|
319
|
+
* override `execute` (e.g. SQL, which inlines lower + encode for
|
|
320
|
+
* direct mutator threading) call this helper themselves at the
|
|
321
|
+
* equivalent point — between the family's AST → draft-plan
|
|
322
|
+
* lowering and the parameter-encode step.
|
|
323
|
+
*
|
|
324
|
+
* Intercept ordering: this helper fires unconditionally before
|
|
325
|
+
* `runWithMiddleware`. `intercept` (inside `runWithMiddleware`)
|
|
326
|
+
* therefore observes the post-`beforeExecute` plan — mutator
|
|
327
|
+
* mutations are visible in the params interceptors see. The
|
|
328
|
+
* trade-off is documented on `RuntimeMiddleware.intercept`.
|
|
329
|
+
*/
|
|
330
|
+
declare function runBeforeExecuteChain<TExec extends ExecutionPlan, TMutator extends ParamRefMutator = ParamRefMutator>(plan: TExec, middleware: ReadonlyArray<RuntimeMiddleware<TExec, TMutator>>, ctx: RuntimeMiddlewareContext, paramsMutator?: TMutator): Promise<void>;
|
|
331
|
+
//#endregion
|
|
332
|
+
//#region src/execution/runtime-error.d.ts
|
|
333
|
+
interface RuntimeErrorEnvelope extends Error {
|
|
334
|
+
readonly code: string;
|
|
335
|
+
readonly category: 'PLAN' | 'CONTRACT' | 'LINT' | 'BUDGET' | 'RUNTIME';
|
|
336
|
+
readonly severity: 'error';
|
|
337
|
+
readonly details?: Record<string, unknown>;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Stable code emitted by the runtime when an in-flight `execute()`
|
|
341
|
+
* is cancelled via the per-query `AbortSignal`. The envelope's
|
|
342
|
+
* `details.phase` distinguishes where the abort was observed:
|
|
343
|
+
*
|
|
344
|
+
* - `'encode'` — abort fired during `encodeParams` (SQL) or
|
|
345
|
+
* `resolveValue` (Mongo).
|
|
346
|
+
* - `'decode'` — abort fired during `decodeRow` / `decodeField`.
|
|
347
|
+
* - `'stream'` — abort fired between rows or before any codec call
|
|
348
|
+
* (already-aborted at entry).
|
|
349
|
+
* - `'beforeExecute'` / `'afterExecute'` / `'onRow'` — abort fired
|
|
350
|
+
* on entry to or during the corresponding middleware phase
|
|
351
|
+
* (cooperative cancellation per the param-transform seam).
|
|
352
|
+
*/
|
|
353
|
+
declare const RUNTIME_ABORTED: "RUNTIME.ABORTED";
|
|
354
|
+
/** Discriminator placed in `details.phase` of a `RUNTIME.ABORTED` envelope. */
|
|
355
|
+
type RuntimeAbortedPhase = 'encode' | 'decode' | 'stream' | 'beforeExecute' | 'afterExecute' | 'onRow';
|
|
356
|
+
/**
|
|
357
|
+
* Type guard for the runtime-error envelope produced by `runtimeError`.
|
|
358
|
+
*
|
|
359
|
+
* Prefer this over duck-typing on `error.code` directly so consumers stay
|
|
360
|
+
* insulated from the envelope's internal shape.
|
|
361
|
+
*/
|
|
362
|
+
declare function isRuntimeError(error: unknown): error is RuntimeErrorEnvelope;
|
|
363
|
+
declare function runtimeError(code: string, message: string, details?: Record<string, unknown>): RuntimeErrorEnvelope;
|
|
364
|
+
/**
|
|
365
|
+
* Construct a `RUNTIME.ABORTED` envelope. Phase distinguishes where the
|
|
366
|
+
* abort was observed — codec call sites (`encode` / `decode` / `stream`)
|
|
367
|
+
* or middleware seams (`beforeExecute` / `afterExecute` / `onRow`), as
|
|
368
|
+
* enumerated on {@link RuntimeAbortedPhase}. Cause carries
|
|
369
|
+
* `signal.reason` verbatim from the platform — native abort produces a
|
|
370
|
+
* `DOMException`, explicit `controller.abort(reason)` produces whatever
|
|
371
|
+
* the caller passed. No synthesis happens here.
|
|
372
|
+
*/
|
|
373
|
+
declare function runtimeAborted(phase: RuntimeAbortedPhase, cause?: unknown): RuntimeErrorEnvelope;
|
|
374
|
+
//#endregion
|
|
375
|
+
//#region src/execution/race-against-abort.d.ts
|
|
376
|
+
/**
|
|
377
|
+
* Throw a phase-tagged `RUNTIME.ABORTED` envelope if the supplied
|
|
378
|
+
* context is already aborted at the precheck site. Centralises the
|
|
379
|
+
* `if (ctx.signal?.aborted) throw runtimeAborted(...)` pattern that
|
|
380
|
+
* every codec dispatch site (and the `beforeExecute` middleware phase)
|
|
381
|
+
* repeats. Accepts both the framework `CodecCallContext` and the
|
|
382
|
+
* `RuntimeMiddlewareContext`; both expose `signal?: AbortSignal`.
|
|
383
|
+
*/
|
|
384
|
+
declare function checkAborted(ctx: {
|
|
385
|
+
readonly signal?: AbortSignal;
|
|
386
|
+
}, phase: RuntimeAbortedPhase): void;
|
|
387
|
+
/**
|
|
388
|
+
* Race a per-cell `Promise.all` (or any other in-flight work promise) against
|
|
389
|
+
* the supplied abort signal so the runtime returns `RUNTIME.ABORTED` promptly
|
|
390
|
+
* even when codec bodies ignore the signal. In-flight bodies that ignore the
|
|
391
|
+
* signal are abandoned and run to completion in the background — the
|
|
392
|
+
* cooperative-cancellation contract documented in ADR 204.
|
|
393
|
+
*
|
|
394
|
+
* Call sites still SHOULD pre-check `signal.aborted` and short-circuit with
|
|
395
|
+
* a phase-tagged `RUNTIME.ABORTED` envelope before invoking this helper —
|
|
396
|
+
* that path is the canonical "aborted at entry" surface and avoids
|
|
397
|
+
* scheduling the work promise. As a defensive belt-and-braces, this helper
|
|
398
|
+
* also handles the already-aborted case internally: `AbortSignal` does not
|
|
399
|
+
* replay past abort events to listeners registered after the abort, so we
|
|
400
|
+
* inspect `signal.aborted` synchronously and reject with the sentinel
|
|
401
|
+
* before installing the listener. The rejection is still attributed to the
|
|
402
|
+
* abort path via the sentinel-identity check.
|
|
403
|
+
*
|
|
404
|
+
* Distinguishing the rejection source is load-bearing for AC-ERR4
|
|
405
|
+
* (`RUNTIME.ENCODE_FAILED` / `RUNTIME.DECODE_FAILED` pass through unchanged).
|
|
406
|
+
* The semantically equivalent `abortable(signal)` helper in
|
|
407
|
+
* `@prisma-next/utils` rejects with `signal.reason ?? new DOMException(...)`,
|
|
408
|
+
* which is not stably distinguishable from a codec-thrown error by identity
|
|
409
|
+
* alone (a fresh fallback DOMException is allocated per call). We instead
|
|
410
|
+
* track abort attribution with a unique sentinel: only the `onAbort` listener
|
|
411
|
+
* installed here ever rejects with the sentinel, so an `error === sentinel`
|
|
412
|
+
* identity check after the race is unambiguous.
|
|
413
|
+
*
|
|
414
|
+
* Lives in `framework-components` (rather than the SQL family, where it
|
|
415
|
+
* originated in m2) so every family runtime that needs cooperative
|
|
416
|
+
* cancellation around a codec-dispatch `Promise.all` (SQL encode + decode
|
|
417
|
+
* today, Mongo encode in m3) shares the same attribution logic.
|
|
418
|
+
*/
|
|
419
|
+
declare function raceAgainstAbort<T>(work: Promise<T>, signal: AbortSignal | undefined, phase: RuntimeAbortedPhase): Promise<T>;
|
|
420
|
+
//#endregion
|
|
343
421
|
//#region src/execution/run-with-middleware.d.ts
|
|
344
422
|
/**
|
|
345
|
-
* Drives a single execution of `runDriver()` through the middleware
|
|
423
|
+
* Drives a single execution of `runDriver()` through the middleware
|
|
424
|
+
* lifecycle's intercept + row-source + termination phases.
|
|
346
425
|
*
|
|
347
426
|
* Lifecycle, in order:
|
|
348
427
|
* 1. For each middleware in registration order: `intercept(exec, ctx)`. The
|
|
@@ -352,31 +431,38 @@ declare function checkMiddlewareCompatibility(middleware: RuntimeMiddleware, run
|
|
|
352
431
|
* the intercepted rows, and proceeds with `source: 'middleware'`. On
|
|
353
432
|
* all-passthrough (every `intercept` returns `undefined` or is omitted),
|
|
354
433
|
* `source: 'driver'` is used and the row source is `runDriver()`.
|
|
355
|
-
* 2.
|
|
356
|
-
* `beforeExecute(exec, ctx)`. Skipped on the intercepted hit path —
|
|
357
|
-
* `beforeExecute` semantically means "about to hit the driver".
|
|
358
|
-
* 3. Iterate the row source. On the driver path, for each row, for each
|
|
434
|
+
* 2. Iterate the row source. On the driver path, for each row, for each
|
|
359
435
|
* middleware in registration order: `onRow(row, exec, ctx)`; then yield
|
|
360
436
|
* the row. On the intercepted hit path, `onRow` is skipped — intercepted
|
|
361
437
|
* rows did not originate from a driver row stream — but rows are still
|
|
362
438
|
* yielded to the consumer in order.
|
|
363
|
-
*
|
|
439
|
+
* 3. On successful completion: for each middleware in registration order:
|
|
364
440
|
* `afterExecute(exec, { rowCount, latencyMs, completed: true, source },
|
|
365
441
|
* ctx)`.
|
|
366
|
-
*
|
|
442
|
+
* 4. On any error thrown during steps 1–2: for each middleware in
|
|
367
443
|
* registration order: `afterExecute(exec, { rowCount, latencyMs,
|
|
368
444
|
* completed: false, source }, ctx)`. Errors thrown by `afterExecute`
|
|
369
445
|
* during the error path are swallowed so they do not mask the original
|
|
370
446
|
* error. The original error is then rethrown.
|
|
371
447
|
*
|
|
448
|
+
* `beforeExecute` is **not** fired here — see
|
|
449
|
+
* {@link runBeforeExecuteChain} in `before-execute-chain.ts`. Family
|
|
450
|
+
* runtimes call that helper between the AST → plan lowering step and
|
|
451
|
+
* the parameter encode step so middleware that mutates ParamRef
|
|
452
|
+
* values (e.g. cipherstash bulk-encrypt) can have its mutations
|
|
453
|
+
* visible to encode. `runWithMiddleware` operates on the fully-
|
|
454
|
+
* encoded plan; interceptors therefore observe a fully-mutated,
|
|
455
|
+
* encoded plan.
|
|
456
|
+
*
|
|
372
457
|
* The `source` field on `AfterExecuteResult` lets observers (telemetry,
|
|
373
458
|
* lints, budgets) distinguish driver-served from middleware-served
|
|
374
459
|
* executions without needing their own out-of-band signal.
|
|
375
460
|
*
|
|
376
|
-
* This helper is the single canonical implementation of the
|
|
377
|
-
*
|
|
461
|
+
* This helper is the single canonical implementation of the
|
|
462
|
+
* intercept-and-row-source loop; family runtimes should not
|
|
463
|
+
* reimplement it.
|
|
378
464
|
*/
|
|
379
|
-
declare function runWithMiddleware<TExec extends ExecutionPlan, Row
|
|
465
|
+
declare function runWithMiddleware<TExec extends ExecutionPlan, Row>(exec: TExec, middleware: ReadonlyArray<RuntimeMiddleware<TExec>>, ctx: RuntimeMiddlewareContext, runDriver: () => AsyncIterable<Row>): AsyncIterableResult<Row>;
|
|
380
466
|
//#endregion
|
|
381
467
|
//#region src/execution/runtime-core.d.ts
|
|
382
468
|
/**
|
|
@@ -399,9 +485,16 @@ interface RuntimeCoreOptions<TMiddleware extends RuntimeMiddleware<ExecutionPlan
|
|
|
399
485
|
* this to run its `beforeCompile` middleware-hook chain.
|
|
400
486
|
* 2. `lower(plan)` — abstract. Each family produces its `*ExecutionPlan`
|
|
401
487
|
* (SQL via `lowerSqlPlan`, Mongo via `adapter.lower`).
|
|
402
|
-
* 3. `
|
|
403
|
-
*
|
|
404
|
-
*
|
|
488
|
+
* 3. `runBeforeExecuteChain(exec, this.middleware, this.ctx)` — concrete;
|
|
489
|
+
* runs every middleware's `beforeExecute` hook after lowering but
|
|
490
|
+
* before the row source is opened. Family runtimes that need a
|
|
491
|
+
* params mutator visible to a downstream encode step (SQL) override
|
|
492
|
+
* `execute` and call this helper themselves at the equivalent
|
|
493
|
+
* pre-encode point.
|
|
494
|
+
* 4. `runWithMiddleware(exec, this.middleware, this.ctx,
|
|
495
|
+
* () => runDriver(exec))` — concrete; runs the intercept chain,
|
|
496
|
+
* drives the row source, fires `onRow` / `afterExecute`. Does
|
|
497
|
+
* **not** fire `beforeExecute` — see step 3.
|
|
405
498
|
*
|
|
406
499
|
* Concrete subclasses must implement `lower`, `runDriver`, and `close`.
|
|
407
500
|
*
|
|
@@ -456,5 +549,5 @@ declare abstract class RuntimeCore<TPlan extends QueryPlan, TExec extends Execut
|
|
|
456
549
|
}, options?: RuntimeExecuteOptions): AsyncIterableResult<Row>;
|
|
457
550
|
}
|
|
458
551
|
//#endregion
|
|
459
|
-
export { type AfterExecuteResult, AsyncIterableResult, type ExecutionPlan, type InterceptResult, type ParamRefMutator, type QueryPlan, RUNTIME_ABORTED, type ResultType, type RuntimeAbortedPhase, RuntimeCore, type RuntimeCoreOptions, type RuntimeErrorEnvelope, type RuntimeExecuteOptions, type RuntimeExecutor, type RuntimeLog, type RuntimeMiddleware, type RuntimeMiddlewareContext, checkAborted, checkMiddlewareCompatibility, isRuntimeError, raceAgainstAbort, runWithMiddleware, runtimeAborted, runtimeError };
|
|
552
|
+
export { type AfterExecuteResult, AsyncIterableResult, type ExecutionPlan, type InterceptResult, type ParamRefMutator, type QueryPlan, RUNTIME_ABORTED, type ResultType, type RuntimeAbortedPhase, RuntimeCore, type RuntimeCoreOptions, type RuntimeErrorEnvelope, type RuntimeExecuteOptions, type RuntimeExecutor, type RuntimeLog, type RuntimeMiddleware, type RuntimeMiddlewareContext, checkAborted, checkMiddlewareCompatibility, isRuntimeError, raceAgainstAbort, runBeforeExecuteChain, runWithMiddleware, runtimeAborted, runtimeError };
|
|
460
553
|
//# sourceMappingURL=runtime.d.mts.map
|
package/dist/runtime.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.mts","names":[],"sources":["../src/execution/async-iterable-result.ts","../src/execution/query-plan.ts","../src/execution/runtime-
|
|
1
|
+
{"version":3,"file":"runtime.d.mts","names":[],"sources":["../src/execution/async-iterable-result.ts","../src/execution/query-plan.ts","../src/execution/runtime-middleware.ts","../src/execution/before-execute-chain.ts","../src/execution/runtime-error.ts","../src/execution/race-against-abort.ts","../src/execution/run-with-middleware.ts","../src/execution/runtime-core.ts"],"mappings":";;;;cAEa,mBAAA,iBAAoC,aAAA,CAAc,GAAA,GAAM,WAAA,CAAY,GAAA;EAAA,iBAC9D,SAAA;EAAA,QACT,QAAA;EAAA,QACA,UAAA;EAAA,QACA,oBAAA;cAEI,SAAA,EAAW,cAAA,CAAe,GAAA;EAAA,CAIrC,MAAA,CAAO,aAAA,KAAkB,aAAA,CAAc,GAAA;EAmBxC,OAAA,CAAA,GAAW,OAAA,CAAQ,GAAA;EA+Bb,KAAA,CAAA,GAAS,OAAA,CAAQ,GAAA;EAKjB,YAAA,CAAA,GAAgB,OAAA,CAAQ,GAAA;EAY9B,IAAA,YAAgB,GAAA,qBAAA,CACd,WAAA,KAAgB,KAAA,EAAO,GAAA,OAAU,QAAA,GAAW,WAAA,CAAY,QAAA,uBACxD,UAAA,KAAe,MAAA,cAAoB,QAAA,GAAW,WAAA,CAAY,QAAA,wBACzD,WAAA,CAAY,QAAA,GAAW,QAAA;AAAA;;;;;;AAhF5B;;;;;;;;;UCYiB,SAAA;EAAA,SACN,IAAA,EAAM,QAAA;EDgBJ;;;;EAAA,SCXF,IAAA,GAAO,GAAA;AAAA;;;;;;;;;;UAYD,aAAA,wBAAqC,SAAA,CAAU,GAAA;;;;;;;;;;;;;;;KAgBpD,UAAA,2BAAqC,CAAA,GAC7C,CAAA;EAAA,SAAqB,IAAA;AAAA,IACnB,CAAA;;;UC9CW,UAAA;EACf,IAAA,CAAK,KAAA;EACL,IAAA,CAAK,KAAA;EACL,KAAA,CAAM,KAAA;EACN,KAAA,EAAO,KAAA;AAAA;;;;;;;;;;;;;;;;;;;;UAsBQ,wBAAA;EAAA,SACN,QAAA;EAAA,SACA,IAAA;EAAA,SACA,GAAA;EAAA,SACA,GAAA,EAAK,UAAA;EFhCqD;;;;;;;;;;;;;;;;;EEkDnE,WAAA,CAAY,IAAA,EAAM,aAAA,GAAgB,OAAA;EFxCR;;;;;;EAAA,SE+CjB,MAAA,GAAS,WAAA;AAAA;AAAA,UAGH,kBAAA;EAAA,SACN,QAAA;EAAA,SACA,SAAA;EAAA,SACA,SAAA;EFcJ;;;;;;;;;;;;EAAA,SEDI,MAAA;AAAA;;;;;;;;;ADhEX;;;;;;;;;;;AAkBA;;UCsEiB,eAAA;EAAA,SACN,IAAA,EAAM,aAAA,CAAc,MAAA,qBAA2B,QAAA,CAAS,MAAA;AAAA;;;;;ADvDnE;;;;;;;cCqEc,uBAAA;AAAA,KACF,eAAA;EAAA,UAA8B,uBAAA;AAAA;;;;;AAlH1C;;;;;;;;;;UAkIiB,iBAAA,eACD,SAAA,GAAY,SAAA,mBACT,eAAA,GAAkB,eAAA;EAAA,SAE1B,IAAA;EAAA,SACA,QAAA;EAAA,SACA,QAAA;EA9GM;;;;;;;;;;;;;;;;;;;;;;EAqIf,SAAA,EAAW,IAAA,EAAM,KAAA,EAAO,GAAA,EAAK,wBAAA,GAA2B,OAAA,CAAQ,eAAA;EArG/B;;;;;;;;;AAwCnC;;;;;;;;;;;;;;;;AAEC;EAsFC,aAAA,EACE,IAAA,EAAM,KAAA,EACN,GAAA,EAAK,wBAAA,EACL,MAAA,GAAS,QAAA,UACD,OAAA;EACV,KAAA,EAAO,GAAA,EAAK,MAAA,mBAAyB,IAAA,EAAM,KAAA,EAAO,GAAA,EAAK,wBAAA,GAA2B,OAAA;EAClF,YAAA,EACE,IAAA,EAAM,KAAA,EACN,MAAA,EAAQ,kBAAA,EACR,GAAA,EAAK,wBAAA,GACJ,OAAA;AAAA;AAlFL;;;;;AAgBA;;;;AAhBA,UA8FiB,qBAAA;EAAA,SACN,MAAA,GAAS,WAAA;AAAA;;;;;;;;;UAWH,eAAA,eAA8B,SAAA;EAC7C,OAAA,MACE,IAAA,EAAM,KAAA;IAAA,SAAmB,IAAA,GAAO,GAAA;EAAA,GAChC,OAAA,GAAU,qBAAA,GACT,mBAAA,CAAoB,GAAA;EACvB,KAAA,IAAS,OAAA;AAAA;AAAA,iBAGK,4BAAA,CACd,UAAA,EAAY,iBAAA,EACZ,eAAA,UACA,eAAA;;;;;AFzOF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBGuDsB,qBAAA,eACN,aAAA,mBACG,eAAA,GAAkB,eAAA,CAAA,CAEnC,IAAA,EAAM,KAAA,EACN,UAAA,EAAY,aAAA,CAAc,iBAAA,CAAkB,KAAA,EAAO,QAAA,IACnD,GAAA,EAAK,wBAAA,EACL,aAAA,GAAgB,QAAA,GACf,OAAA;;;UCjEc,oBAAA,SAA6B,KAAA;EAAA,SACnC,IAAA;EAAA,SACA,QAAA;EAAA,SACA,QAAA;EAAA,SACA,OAAA,GAAU,MAAA;AAAA;;;;;;;;;;;;;;;cAiBR,eAAA;;KAGD,mBAAA;;;;;;;iBAcI,cAAA,CAAe,KAAA,YAAiB,KAAA,IAAS,oBAAA;AAAA,iBAUzC,YAAA,CACd,IAAA,UACA,OAAA,UACA,OAAA,GAAU,MAAA,oBACT,oBAAA;;;;;;;;;;iBAsCa,cAAA,CAAe,KAAA,EAAO,mBAAA,EAAqB,KAAA,aAAkB,oBAAA;;;;;;AJxF7E;;;;;iBKSgB,YAAA,CACd,GAAA;EAAA,SAAgB,MAAA,GAAS,WAAA;AAAA,GACzB,KAAA,EAAO,mBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuCa,gBAAA,GAAA,CACpB,IAAA,EAAM,OAAA,CAAQ,CAAA,GACd,MAAA,EAAQ,WAAA,cACR,KAAA,EAAO,mBAAA,GACN,OAAA,CAAQ,CAAA;;;;ALtDX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBM6CgB,iBAAA,eAAgC,aAAA,MAAA,CAC9C,IAAA,EAAM,KAAA,EACN,UAAA,EAAY,aAAA,CAAc,iBAAA,CAAkB,KAAA,IAC5C,GAAA,EAAK,wBAAA,EACL,SAAA,QAAiB,aAAA,CAAc,GAAA,IAC9B,mBAAA,CAAoB,GAAA;;;ANlDvB;;;;;;;AAAA,UOkBiB,kBAAA,qBAAuC,iBAAA,CAAkB,aAAA;EAAA,SAC/D,UAAA,EAAY,aAAA,CAAc,WAAA;EAAA,SAC1B,GAAA,EAAK,wBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAmCM,WAAA,eACN,SAAA,gBACA,aAAA,sBACM,iBAAA,CAAkB,KAAA,cAC3B,eAAA,CAAgB,KAAA;EAAA,mBAER,UAAA,EAAY,aAAA,CAAc,WAAA;EAAA,mBAC1B,GAAA,EAAK,wBAAA;cAEZ,OAAA,EAAS,kBAAA,CAAmB,WAAA;EPtDA;;;;;EAAA,UOgE9B,gBAAA,CAAiB,IAAA,EAAM,KAAA,GAAQ,KAAA,GAAQ,OAAA,CAAQ,KAAA;EPdlC;;;;;;;;;;;;;EAAA,mBO+BJ,KAAA,CAAM,IAAA,EAAM,KAAA,EAAO,GAAA,EAAK,gBAAA,GAAmB,KAAA,GAAQ,OAAA,CAAQ,KAAA;EPZ7D;;;;;;;;;;EAAA,mBOwBE,SAAA,CAAU,IAAA,EAAM,KAAA,GAAQ,aAAA,CAAc,MAAA;EAAA,SAEhD,KAAA,CAAA,GAAS,OAAA;EAElB,OAAA,KAAA,CACE,IAAA,EAAM,KAAA;IAAA,SAAmB,IAAA,GAAO,GAAA;EAAA,GAChC,OAAA,GAAU,qBAAA,GACT,mBAAA,CAAoB,GAAA;AAAA"}
|
package/dist/runtime.mjs
CHANGED
|
@@ -177,9 +177,69 @@ async function raceAgainstAbort(work, signal, phase) {
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
//#endregion
|
|
180
|
+
//#region src/execution/before-execute-chain.ts
|
|
181
|
+
/**
|
|
182
|
+
* Runs every middleware's `beforeExecute` hook in registration order,
|
|
183
|
+
* threading through the (optional) family-specific `paramsMutator`.
|
|
184
|
+
*
|
|
185
|
+
* Why this lives outside {@link runWithMiddleware}: middleware that
|
|
186
|
+
* mutates parameter values (e.g. cipherstash's bulk-encrypt SDK
|
|
187
|
+
* round-trip) must run *before* the family runtime encodes those
|
|
188
|
+
* parameters to driver wire format. Family runtimes call
|
|
189
|
+
* `runBeforeExecuteChain` between the AST → plan lowering step and
|
|
190
|
+
* the parameter encode step; the encode then observes the mutator's
|
|
191
|
+
* `currentParams()` view. `runWithMiddleware` retains the rest of
|
|
192
|
+
* the lifecycle (`intercept`, driver/row source loop, `onRow`,
|
|
193
|
+
* `afterExecute`) but no longer fires `beforeExecute` itself.
|
|
194
|
+
*
|
|
195
|
+
* Lifecycle within this helper:
|
|
196
|
+
*
|
|
197
|
+
* 1. For each middleware in registration order, if `beforeExecute`
|
|
198
|
+
* is implemented:
|
|
199
|
+
* - `checkAborted(ctx, 'beforeExecute')` short-circuits if the
|
|
200
|
+
* caller already aborted at entry.
|
|
201
|
+
* - The hook is invoked with `(plan, ctx, paramsMutator)`. A
|
|
202
|
+
* middleware body that ignores the mutator stays compatible —
|
|
203
|
+
* JavaScript allows extra positional arguments.
|
|
204
|
+
* - If the hook returns a Promise, it is raced against
|
|
205
|
+
* `ctx.signal` via {@link raceAgainstAbort} so cooperative
|
|
206
|
+
* cancellation surfaces a `RUNTIME.ABORTED { phase:
|
|
207
|
+
* 'beforeExecute' }` envelope even when the body itself
|
|
208
|
+
* ignores the signal.
|
|
209
|
+
*
|
|
210
|
+
* Error propagation: any error thrown by a `beforeExecute` body
|
|
211
|
+
* (or surfaced by the abort race) propagates out of this helper
|
|
212
|
+
* unchanged. The family runtime is responsible for converting it
|
|
213
|
+
* into the appropriate `afterExecute(completed: false)` notification
|
|
214
|
+
* once `runWithMiddleware` runs.
|
|
215
|
+
*
|
|
216
|
+
* Relationship to {@link runWithMiddleware}: the framework's
|
|
217
|
+
* `RuntimeCore.execute` template calls this helper between
|
|
218
|
+
* `lower(plan)` and `runWithMiddleware(...)`. Family runtimes that
|
|
219
|
+
* override `execute` (e.g. SQL, which inlines lower + encode for
|
|
220
|
+
* direct mutator threading) call this helper themselves at the
|
|
221
|
+
* equivalent point — between the family's AST → draft-plan
|
|
222
|
+
* lowering and the parameter-encode step.
|
|
223
|
+
*
|
|
224
|
+
* Intercept ordering: this helper fires unconditionally before
|
|
225
|
+
* `runWithMiddleware`. `intercept` (inside `runWithMiddleware`)
|
|
226
|
+
* therefore observes the post-`beforeExecute` plan — mutator
|
|
227
|
+
* mutations are visible in the params interceptors see. The
|
|
228
|
+
* trade-off is documented on `RuntimeMiddleware.intercept`.
|
|
229
|
+
*/
|
|
230
|
+
async function runBeforeExecuteChain(plan, middleware, ctx, paramsMutator) {
|
|
231
|
+
for (const mw of middleware) {
|
|
232
|
+
if (!mw.beforeExecute) continue;
|
|
233
|
+
checkAborted(ctx, "beforeExecute");
|
|
234
|
+
const work = mw.beforeExecute(plan, ctx, paramsMutator);
|
|
235
|
+
if (work !== void 0) await raceAgainstAbort(Promise.resolve(work), ctx.signal, "beforeExecute");
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
//#endregion
|
|
180
239
|
//#region src/execution/run-with-middleware.ts
|
|
181
240
|
/**
|
|
182
|
-
* Drives a single execution of `runDriver()` through the middleware
|
|
241
|
+
* Drives a single execution of `runDriver()` through the middleware
|
|
242
|
+
* lifecycle's intercept + row-source + termination phases.
|
|
183
243
|
*
|
|
184
244
|
* Lifecycle, in order:
|
|
185
245
|
* 1. For each middleware in registration order: `intercept(exec, ctx)`. The
|
|
@@ -189,31 +249,38 @@ async function raceAgainstAbort(work, signal, phase) {
|
|
|
189
249
|
* the intercepted rows, and proceeds with `source: 'middleware'`. On
|
|
190
250
|
* all-passthrough (every `intercept` returns `undefined` or is omitted),
|
|
191
251
|
* `source: 'driver'` is used and the row source is `runDriver()`.
|
|
192
|
-
* 2.
|
|
193
|
-
* `beforeExecute(exec, ctx)`. Skipped on the intercepted hit path —
|
|
194
|
-
* `beforeExecute` semantically means "about to hit the driver".
|
|
195
|
-
* 3. Iterate the row source. On the driver path, for each row, for each
|
|
252
|
+
* 2. Iterate the row source. On the driver path, for each row, for each
|
|
196
253
|
* middleware in registration order: `onRow(row, exec, ctx)`; then yield
|
|
197
254
|
* the row. On the intercepted hit path, `onRow` is skipped — intercepted
|
|
198
255
|
* rows did not originate from a driver row stream — but rows are still
|
|
199
256
|
* yielded to the consumer in order.
|
|
200
|
-
*
|
|
257
|
+
* 3. On successful completion: for each middleware in registration order:
|
|
201
258
|
* `afterExecute(exec, { rowCount, latencyMs, completed: true, source },
|
|
202
259
|
* ctx)`.
|
|
203
|
-
*
|
|
260
|
+
* 4. On any error thrown during steps 1–2: for each middleware in
|
|
204
261
|
* registration order: `afterExecute(exec, { rowCount, latencyMs,
|
|
205
262
|
* completed: false, source }, ctx)`. Errors thrown by `afterExecute`
|
|
206
263
|
* during the error path are swallowed so they do not mask the original
|
|
207
264
|
* error. The original error is then rethrown.
|
|
208
265
|
*
|
|
266
|
+
* `beforeExecute` is **not** fired here — see
|
|
267
|
+
* {@link runBeforeExecuteChain} in `before-execute-chain.ts`. Family
|
|
268
|
+
* runtimes call that helper between the AST → plan lowering step and
|
|
269
|
+
* the parameter encode step so middleware that mutates ParamRef
|
|
270
|
+
* values (e.g. cipherstash bulk-encrypt) can have its mutations
|
|
271
|
+
* visible to encode. `runWithMiddleware` operates on the fully-
|
|
272
|
+
* encoded plan; interceptors therefore observe a fully-mutated,
|
|
273
|
+
* encoded plan.
|
|
274
|
+
*
|
|
209
275
|
* The `source` field on `AfterExecuteResult` lets observers (telemetry,
|
|
210
276
|
* lints, budgets) distinguish driver-served from middleware-served
|
|
211
277
|
* executions without needing their own out-of-band signal.
|
|
212
278
|
*
|
|
213
|
-
* This helper is the single canonical implementation of the
|
|
214
|
-
*
|
|
279
|
+
* This helper is the single canonical implementation of the
|
|
280
|
+
* intercept-and-row-source loop; family runtimes should not
|
|
281
|
+
* reimplement it.
|
|
215
282
|
*/
|
|
216
|
-
function runWithMiddleware(exec, middleware, ctx, runDriver
|
|
283
|
+
function runWithMiddleware(exec, middleware, ctx, runDriver) {
|
|
217
284
|
const iterator = async function* () {
|
|
218
285
|
const startedAt = Date.now();
|
|
219
286
|
let rowCount = 0;
|
|
@@ -236,14 +303,7 @@ function runWithMiddleware(exec, middleware, ctx, runDriver, paramsMutator) {
|
|
|
236
303
|
rowSource = result.rows;
|
|
237
304
|
break;
|
|
238
305
|
}
|
|
239
|
-
if (source === "driver")
|
|
240
|
-
for (const mw of middleware) if (mw.beforeExecute) {
|
|
241
|
-
checkAborted(ctx, "beforeExecute");
|
|
242
|
-
const work = mw.beforeExecute(exec, ctx, paramsMutator);
|
|
243
|
-
if (work !== void 0) await raceAgainstAbort(Promise.resolve(work), ctx.signal, "beforeExecute");
|
|
244
|
-
}
|
|
245
|
-
rowSource = runDriver();
|
|
246
|
-
}
|
|
306
|
+
if (source === "driver") rowSource = runDriver();
|
|
247
307
|
for await (const row of rowSource) {
|
|
248
308
|
if (source === "driver") {
|
|
249
309
|
for (const mw of middleware) if (mw.onRow) await mw.onRow(row, exec, ctx);
|
|
@@ -285,9 +345,16 @@ function runWithMiddleware(exec, middleware, ctx, runDriver, paramsMutator) {
|
|
|
285
345
|
* this to run its `beforeCompile` middleware-hook chain.
|
|
286
346
|
* 2. `lower(plan)` — abstract. Each family produces its `*ExecutionPlan`
|
|
287
347
|
* (SQL via `lowerSqlPlan`, Mongo via `adapter.lower`).
|
|
288
|
-
* 3. `
|
|
289
|
-
*
|
|
290
|
-
*
|
|
348
|
+
* 3. `runBeforeExecuteChain(exec, this.middleware, this.ctx)` — concrete;
|
|
349
|
+
* runs every middleware's `beforeExecute` hook after lowering but
|
|
350
|
+
* before the row source is opened. Family runtimes that need a
|
|
351
|
+
* params mutator visible to a downstream encode step (SQL) override
|
|
352
|
+
* `execute` and call this helper themselves at the equivalent
|
|
353
|
+
* pre-encode point.
|
|
354
|
+
* 4. `runWithMiddleware(exec, this.middleware, this.ctx,
|
|
355
|
+
* () => runDriver(exec))` — concrete; runs the intercept chain,
|
|
356
|
+
* drives the row source, fires `onRow` / `afterExecute`. Does
|
|
357
|
+
* **not** fire `beforeExecute` — see step 3.
|
|
291
358
|
*
|
|
292
359
|
* Concrete subclasses must implement `lower`, `runDriver`, and `close`.
|
|
293
360
|
*
|
|
@@ -324,6 +391,7 @@ var RuntimeCore = class {
|
|
|
324
391
|
checkAborted(codecCtx, "stream");
|
|
325
392
|
const compiled = await self.runBeforeCompile(plan);
|
|
326
393
|
const exec = await self.lower(compiled, codecCtx);
|
|
394
|
+
await runBeforeExecuteChain(exec, self.middleware, self.ctx);
|
|
327
395
|
yield* runWithMiddleware(exec, self.middleware, self.ctx, () => self.runDriver(exec));
|
|
328
396
|
}
|
|
329
397
|
return new AsyncIterableResult(generator());
|
|
@@ -348,6 +416,6 @@ function checkMiddlewareCompatibility(middleware, runtimeFamilyId, runtimeTarget
|
|
|
348
416
|
});
|
|
349
417
|
}
|
|
350
418
|
//#endregion
|
|
351
|
-
export { AsyncIterableResult, RUNTIME_ABORTED, RuntimeCore, checkAborted, checkMiddlewareCompatibility, isRuntimeError, raceAgainstAbort, runWithMiddleware, runtimeAborted, runtimeError };
|
|
419
|
+
export { AsyncIterableResult, RUNTIME_ABORTED, RuntimeCore, checkAborted, checkMiddlewareCompatibility, isRuntimeError, raceAgainstAbort, runBeforeExecuteChain, runWithMiddleware, runtimeAborted, runtimeError };
|
|
352
420
|
|
|
353
421
|
//# sourceMappingURL=runtime.mjs.map
|
package/dist/runtime.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.mjs","names":[],"sources":["../src/execution/runtime-error.ts","../src/execution/async-iterable-result.ts","../src/execution/race-against-abort.ts","../src/execution/run-with-middleware.ts","../src/execution/runtime-core.ts","../src/execution/runtime-middleware.ts"],"sourcesContent":["export interface RuntimeErrorEnvelope extends Error {\n readonly code: string;\n readonly category: 'PLAN' | 'CONTRACT' | 'LINT' | 'BUDGET' | 'RUNTIME';\n readonly severity: 'error';\n readonly details?: Record<string, unknown>;\n}\n\n/**\n * Stable code emitted by the runtime when an in-flight `execute()`\n * is cancelled via the per-query `AbortSignal`. The envelope's\n * `details.phase` distinguishes where the abort was observed:\n *\n * - `'encode'` — abort fired during `encodeParams` (SQL) or\n * `resolveValue` (Mongo).\n * - `'decode'` — abort fired during `decodeRow` / `decodeField`.\n * - `'stream'` — abort fired between rows or before any codec call\n * (already-aborted at entry).\n * - `'beforeExecute'` / `'afterExecute'` / `'onRow'` — abort fired\n * on entry to or during the corresponding middleware phase\n * (cooperative cancellation per the param-transform seam).\n */\nexport const RUNTIME_ABORTED = 'RUNTIME.ABORTED' as const;\n\n/** Discriminator placed in `details.phase` of a `RUNTIME.ABORTED` envelope. */\nexport type RuntimeAbortedPhase =\n | 'encode'\n | 'decode'\n | 'stream'\n | 'beforeExecute'\n | 'afterExecute'\n | 'onRow';\n\n/**\n * Type guard for the runtime-error envelope produced by `runtimeError`.\n *\n * Prefer this over duck-typing on `error.code` directly so consumers stay\n * insulated from the envelope's internal shape.\n */\nexport function isRuntimeError(error: unknown): error is RuntimeErrorEnvelope {\n return (\n error instanceof Error &&\n 'code' in error &&\n typeof (error as { code?: unknown }).code === 'string' &&\n 'category' in error &&\n 'severity' in error\n );\n}\n\nexport function runtimeError(\n code: string,\n message: string,\n details?: Record<string, unknown>,\n): RuntimeErrorEnvelope {\n const error = new Error(message) as RuntimeErrorEnvelope;\n Object.defineProperty(error, 'name', {\n value: 'RuntimeError',\n configurable: true,\n });\n\n return Object.assign(error, {\n code,\n category: resolveCategory(code),\n severity: 'error' as const,\n message,\n details,\n });\n}\n\nfunction resolveCategory(code: string): RuntimeErrorEnvelope['category'] {\n const prefix = code.split('.')[0] ?? 'RUNTIME';\n switch (prefix) {\n case 'PLAN':\n case 'CONTRACT':\n case 'LINT':\n case 'BUDGET':\n return prefix;\n default:\n return 'RUNTIME';\n }\n}\n\n/**\n * Construct a `RUNTIME.ABORTED` envelope. Phase distinguishes where the\n * abort was observed — codec call sites (`encode` / `decode` / `stream`)\n * or middleware seams (`beforeExecute` / `afterExecute` / `onRow`), as\n * enumerated on {@link RuntimeAbortedPhase}. Cause carries\n * `signal.reason` verbatim from the platform — native abort produces a\n * `DOMException`, explicit `controller.abort(reason)` produces whatever\n * the caller passed. No synthesis happens here.\n */\nexport function runtimeAborted(phase: RuntimeAbortedPhase, cause?: unknown): RuntimeErrorEnvelope {\n const envelope = runtimeError(RUNTIME_ABORTED, `Operation aborted during ${phase}`, { phase });\n return Object.assign(envelope, { cause });\n}\n","import { runtimeError } from './runtime-error';\n\nexport class AsyncIterableResult<Row> implements AsyncIterable<Row>, PromiseLike<Row[]> {\n private readonly generator: AsyncGenerator<Row, void, unknown>;\n private consumed = false;\n private consumedBy: 'bufferedArray' | 'iterator' | undefined;\n private bufferedArrayPromise: Promise<Row[]> | undefined;\n\n constructor(generator: AsyncGenerator<Row, void, unknown>) {\n this.generator = generator;\n }\n\n [Symbol.asyncIterator](): AsyncIterator<Row> {\n if (this.consumed) {\n throw runtimeError(\n 'RUNTIME.ITERATOR_CONSUMED',\n `AsyncIterableResult iterator has already been consumed via ${this.consumedBy === 'bufferedArray' ? 'toArray()/then()' : 'for-await loop'}. Each AsyncIterableResult can only be iterated once.`,\n {\n consumedBy: this.consumedBy,\n suggestion:\n this.consumedBy === 'bufferedArray'\n ? 'If you need to iterate multiple times, store the results from toArray() in a variable and reuse that.'\n : 'If you need to iterate multiple times, use toArray() to collect all results first.',\n },\n );\n }\n this.consumed = true;\n this.consumedBy = 'iterator';\n return this.generator;\n }\n\n toArray(): Promise<Row[]> {\n if (this.consumedBy === 'iterator') {\n return Promise.reject(\n runtimeError(\n 'RUNTIME.ITERATOR_CONSUMED',\n 'AsyncIterableResult iterator has already been consumed via for-await loop. Each AsyncIterableResult can only be iterated once.',\n {\n consumedBy: this.consumedBy,\n suggestion:\n 'The iterator was already consumed by a for-await loop. Use toArray() or await the result before iterating.',\n },\n ),\n );\n }\n\n if (this.bufferedArrayPromise) {\n return this.bufferedArrayPromise;\n }\n\n this.consumed = true;\n this.consumedBy = 'bufferedArray';\n this.bufferedArrayPromise = (async () => {\n const out: Row[] = [];\n for await (const item of this.generator) {\n out.push(item);\n }\n return out;\n })();\n return this.bufferedArrayPromise;\n }\n\n async first(): Promise<Row | null> {\n const rows = await this.toArray();\n return rows[0] ?? null;\n }\n\n async firstOrThrow(): Promise<Row> {\n const row = await this.first();\n if (row === null)\n throw runtimeError(\n 'RUNTIME.NO_ROWS',\n 'Expected at least one row, but none were returned',\n {},\n );\n return row;\n }\n\n // biome-ignore lint/suspicious/noThenProperty: PromiseLike implementation is intentional for await support.\n then<TResult1 = Row[], TResult2 = never>(\n onfulfilled?: ((value: Row[]) => TResult1 | PromiseLike<TResult1>) | undefined | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | undefined | null,\n ): PromiseLike<TResult1 | TResult2> {\n return this.toArray().then(onfulfilled, onrejected);\n }\n}\n","import type { RuntimeAbortedPhase } from './runtime-error';\nimport { runtimeAborted } from './runtime-error';\n\n/**\n * Throw a phase-tagged `RUNTIME.ABORTED` envelope if the supplied\n * context is already aborted at the precheck site. Centralises the\n * `if (ctx.signal?.aborted) throw runtimeAborted(...)` pattern that\n * every codec dispatch site (and the `beforeExecute` middleware phase)\n * repeats. Accepts both the framework `CodecCallContext` and the\n * `RuntimeMiddlewareContext`; both expose `signal?: AbortSignal`.\n */\nexport function checkAborted(\n ctx: { readonly signal?: AbortSignal },\n phase: RuntimeAbortedPhase,\n): void {\n if (ctx.signal?.aborted) {\n throw runtimeAborted(phase, ctx.signal.reason);\n }\n}\n\n/**\n * Race a per-cell `Promise.all` (or any other in-flight work promise) against\n * the supplied abort signal so the runtime returns `RUNTIME.ABORTED` promptly\n * even when codec bodies ignore the signal. In-flight bodies that ignore the\n * signal are abandoned and run to completion in the background — the\n * cooperative-cancellation contract documented in ADR 204.\n *\n * Call sites still SHOULD pre-check `signal.aborted` and short-circuit with\n * a phase-tagged `RUNTIME.ABORTED` envelope before invoking this helper —\n * that path is the canonical \"aborted at entry\" surface and avoids\n * scheduling the work promise. As a defensive belt-and-braces, this helper\n * also handles the already-aborted case internally: `AbortSignal` does not\n * replay past abort events to listeners registered after the abort, so we\n * inspect `signal.aborted` synchronously and reject with the sentinel\n * before installing the listener. The rejection is still attributed to the\n * abort path via the sentinel-identity check.\n *\n * Distinguishing the rejection source is load-bearing for AC-ERR4\n * (`RUNTIME.ENCODE_FAILED` / `RUNTIME.DECODE_FAILED` pass through unchanged).\n * The semantically equivalent `abortable(signal)` helper in\n * `@prisma-next/utils` rejects with `signal.reason ?? new DOMException(...)`,\n * which is not stably distinguishable from a codec-thrown error by identity\n * alone (a fresh fallback DOMException is allocated per call). We instead\n * track abort attribution with a unique sentinel: only the `onAbort` listener\n * installed here ever rejects with the sentinel, so an `error === sentinel`\n * identity check after the race is unambiguous.\n *\n * Lives in `framework-components` (rather than the SQL family, where it\n * originated in m2) so every family runtime that needs cooperative\n * cancellation around a codec-dispatch `Promise.all` (SQL encode + decode\n * today, Mongo encode in m3) shares the same attribution logic.\n */\nexport async function raceAgainstAbort<T>(\n work: Promise<T>,\n signal: AbortSignal | undefined,\n phase: RuntimeAbortedPhase,\n): Promise<T> {\n if (signal === undefined) {\n return await work;\n }\n const sentinel: { reason: unknown } = { reason: undefined };\n let onAbort: (() => void) | undefined;\n\n const abortPromise = new Promise<never>((_, reject) => {\n if (signal.aborted) {\n sentinel.reason = signal.reason;\n reject(sentinel);\n return;\n }\n onAbort = () => {\n sentinel.reason = signal.reason;\n reject(sentinel);\n };\n signal.addEventListener('abort', onAbort, { once: true });\n });\n\n try {\n return await Promise.race([work, abortPromise]);\n } catch (error) {\n if (error === sentinel) {\n throw runtimeAborted(phase, sentinel.reason);\n }\n throw error;\n } finally {\n if (onAbort) {\n signal.removeEventListener('abort', onAbort);\n }\n }\n}\n","import { AsyncIterableResult } from './async-iterable-result';\nimport type { ExecutionPlan } from './query-plan';\nimport { checkAborted, raceAgainstAbort } from './race-against-abort';\nimport type {\n ParamRefMutator,\n RuntimeMiddleware,\n RuntimeMiddlewareContext,\n} from './runtime-middleware';\n\n/**\n * Drives a single execution of `runDriver()` through the middleware lifecycle.\n *\n * Lifecycle, in order:\n * 1. For each middleware in registration order: `intercept(exec, ctx)`. The\n * first non-`undefined` result wins; subsequent middleware's `intercept`\n * does not fire. On a hit, the runtime emits a `middleware.intercept`\n * debug event naming the winning middleware, switches the row source to\n * the intercepted rows, and proceeds with `source: 'middleware'`. On\n * all-passthrough (every `intercept` returns `undefined` or is omitted),\n * `source: 'driver'` is used and the row source is `runDriver()`.\n * 2. If `source === 'driver'`: for each middleware in registration order,\n * `beforeExecute(exec, ctx)`. Skipped on the intercepted hit path —\n * `beforeExecute` semantically means \"about to hit the driver\".\n * 3. Iterate the row source. On the driver path, for each row, for each\n * middleware in registration order: `onRow(row, exec, ctx)`; then yield\n * the row. On the intercepted hit path, `onRow` is skipped — intercepted\n * rows did not originate from a driver row stream — but rows are still\n * yielded to the consumer in order.\n * 4. On successful completion: for each middleware in registration order:\n * `afterExecute(exec, { rowCount, latencyMs, completed: true, source },\n * ctx)`.\n * 5. On any error thrown during steps 1–3: for each middleware in\n * registration order: `afterExecute(exec, { rowCount, latencyMs,\n * completed: false, source }, ctx)`. Errors thrown by `afterExecute`\n * during the error path are swallowed so they do not mask the original\n * error. The original error is then rethrown.\n *\n * The `source` field on `AfterExecuteResult` lets observers (telemetry,\n * lints, budgets) distinguish driver-served from middleware-served\n * executions without needing their own out-of-band signal.\n *\n * This helper is the single canonical implementation of the middleware\n * orchestration loop; family runtimes should not reimplement it.\n */\nexport function runWithMiddleware<\n TExec extends ExecutionPlan,\n Row,\n TMutator extends ParamRefMutator = ParamRefMutator,\n>(\n exec: TExec,\n middleware: ReadonlyArray<RuntimeMiddleware<TExec, TMutator>>,\n ctx: RuntimeMiddlewareContext,\n runDriver: () => AsyncIterable<Row>,\n paramsMutator?: TMutator,\n): AsyncIterableResult<Row> {\n const iterator = async function* (): AsyncGenerator<Row, void, unknown> {\n const startedAt = Date.now();\n let rowCount = 0;\n let completed = false;\n let source: 'driver' | 'middleware' = 'driver';\n // Deferred so a winning interceptor can skip `runDriver()` entirely.\n // For factories that lazily produce async generators this is a no-op,\n // but factories that do eager work (e.g. acquiring a connection,\n // sending a query) must not run on the intercepted hit path.\n let rowSource: AsyncIterable<Row> | Iterable<Row> | undefined;\n\n try {\n for (const mw of middleware) {\n if (!mw.intercept) {\n continue;\n }\n // Mark the lifecycle as middleware-driven *before* awaiting the\n // hook. If `intercept` throws, the catch block reports the failure\n // as `source: 'middleware'` — the failure originated in the\n // intercept chain, not in the driver. If `intercept` returns\n // `undefined` (passthrough), we revert to `'driver'` and continue.\n source = 'middleware';\n const result = await mw.intercept(exec, ctx);\n if (result === undefined) {\n source = 'driver';\n continue;\n }\n ctx.log.debug?.({ event: 'middleware.intercept', middleware: mw.name });\n // The intercepted rows are typed as `Record<string, unknown>` at\n // the SPI level; the consumer's `Row` type parameter is enforced by\n // the caller (via the plan's phantom `_row`) the same way driver\n // rows are. Cast through unknown to bridge the SPI shape to the\n // caller-supplied Row.\n rowSource = result.rows as unknown as AsyncIterable<Row> | Iterable<Row>;\n break;\n }\n\n if (source === 'driver') {\n for (const mw of middleware) {\n if (mw.beforeExecute) {\n checkAborted(ctx, 'beforeExecute');\n // The framework only forwards the mutator the caller supplied; a\n // pass-through `undefined` for non-mutating families is safe — the\n // base `RuntimeMiddleware` declares the third parameter, and\n // existing `(plan, ctx)` bodies that ignore it stay unchanged.\n // The cast below is the single point at which the framework's\n // generic mutator slot meets the (possibly absent) caller value;\n // `runWithMiddleware` cannot synthesize a TMutator instance.\n const work = mw.beforeExecute(exec, ctx, paramsMutator as TMutator);\n if (work !== undefined) {\n await raceAgainstAbort(Promise.resolve(work), ctx.signal, 'beforeExecute');\n }\n }\n }\n rowSource = runDriver();\n }\n\n // `rowSource` is always assigned by this point: either the intercepted\n // rows (on a hit) or `runDriver()` (on the driver path).\n for await (const row of rowSource as AsyncIterable<Row> | Iterable<Row>) {\n if (source === 'driver') {\n for (const mw of middleware) {\n if (mw.onRow) {\n await mw.onRow(row as Record<string, unknown>, exec, ctx);\n }\n }\n }\n rowCount++;\n yield row;\n }\n\n completed = true;\n } catch (error) {\n const latencyMs = Date.now() - startedAt;\n for (const mw of middleware) {\n if (mw.afterExecute) {\n try {\n await mw.afterExecute(exec, { rowCount, latencyMs, completed, source }, ctx);\n } catch {\n // Swallow afterExecute errors during the error path so they do not\n // mask the original error.\n }\n }\n }\n\n throw error;\n }\n\n const latencyMs = Date.now() - startedAt;\n for (const mw of middleware) {\n if (mw.afterExecute) {\n await mw.afterExecute(exec, { rowCount, latencyMs, completed, source }, ctx);\n }\n }\n };\n\n return new AsyncIterableResult(iterator());\n}\n","import type { CodecCallContext } from '../shared/codec-types';\nimport { AsyncIterableResult } from './async-iterable-result';\nimport type { ExecutionPlan, QueryPlan } from './query-plan';\nimport { checkAborted } from './race-against-abort';\nimport { runWithMiddleware } from './run-with-middleware';\nimport type {\n RuntimeExecuteOptions,\n RuntimeExecutor,\n RuntimeMiddleware,\n RuntimeMiddlewareContext,\n} from './runtime-middleware';\n\n/**\n * Constructor options shared by every concrete `RuntimeCore` subclass.\n *\n * Family runtimes typically build the middleware list and the\n * `RuntimeMiddlewareContext` themselves (running compatibility checks,\n * narrowing the context's `contract` field, etc.) before calling `super`.\n */\nexport interface RuntimeCoreOptions<TMiddleware extends RuntimeMiddleware<ExecutionPlan>> {\n readonly middleware: ReadonlyArray<TMiddleware>;\n readonly ctx: RuntimeMiddlewareContext;\n}\n\n/**\n * Family-agnostic abstract runtime base.\n *\n * Defines the entire `execute(plan)` template in one place:\n *\n * 1. `runBeforeCompile(plan)` — concrete; defaults to identity. SQL overrides\n * this to run its `beforeCompile` middleware-hook chain.\n * 2. `lower(plan)` — abstract. Each family produces its `*ExecutionPlan`\n * (SQL via `lowerSqlPlan`, Mongo via `adapter.lower`).\n * 3. `runWithMiddleware(exec, this.middleware, this.ctx,\n * () => runDriver(exec))` — concrete; lifts the middleware lifecycle\n * out of the family runtimes into the canonical helper.\n *\n * Concrete subclasses must implement `lower`, `runDriver`, and `close`.\n *\n * The class is generic over:\n * - `TPlan` — the family's pre-lowering plan type.\n * - `TExec` — the family's post-lowering (executable) plan type.\n * - `TMiddleware` — the family's middleware type. Constrained to\n * `RuntimeMiddleware<TExec>` because `runWithMiddleware` invokes the\n * `beforeExecute` / `onRow` / `afterExecute` hooks with the lowered\n * `TExec`. (The spec/plan wording \"RuntimeMiddleware<TPlan>\" is\n * tightened to `<TExec>` here so the helper call typechecks; the\n * intent is unchanged — middleware sees the post-lowering plan.)\n */\nexport abstract class RuntimeCore<\n TPlan extends QueryPlan,\n TExec extends ExecutionPlan,\n TMiddleware extends RuntimeMiddleware<TExec>,\n> implements RuntimeExecutor<TPlan>\n{\n protected readonly middleware: ReadonlyArray<TMiddleware>;\n protected readonly ctx: RuntimeMiddlewareContext;\n\n constructor(options: RuntimeCoreOptions<TMiddleware>) {\n this.middleware = options.middleware;\n this.ctx = options.ctx;\n }\n\n /**\n * Pre-lowering hook for plan rewriting. Defaults to identity. Subclasses\n * may override to run a `beforeCompile` middleware chain (SQL does this\n * to support typed AST rewrites — see `before-compile-chain.ts`).\n */\n protected runBeforeCompile(plan: TPlan): TPlan | Promise<TPlan> {\n return plan;\n }\n\n /**\n * Lower a pre-lowering `TPlan` into the family's executable `TExec`.\n * Family-specific: SQL produces `{ sql, params, ast?, ... }`; Mongo\n * produces `{ command, ... }`.\n *\n * `ctx` carries per-query cancellation (and any future fields on\n * `CodecCallContext`); concrete subclasses forward it to the\n * encode-side codec dispatch site (e.g. SQL's `encodeParams` in m2,\n * Mongo's `resolveValue` in m3). The runtime allocates one ctx per\n * `execute()` call and threads the same reference everywhere; the\n * `signal` field inside may be `undefined`, but the ctx object itself\n * is always present.\n */\n protected abstract lower(plan: TPlan, ctx: CodecCallContext): TExec | Promise<TExec>;\n\n /**\n * Drive the underlying transport for a lowered `TExec`. Yields raw rows\n * directly from the driver as `Record<string, unknown>`; codec decoding\n * (if any) is the subclass's responsibility, applied by wrapping\n * `execute()` rather than living inside this hook.\n *\n * The `Row` type parameter on `execute()` is satisfied by the caller via\n * the plan's phantom `_row`; the runtime treats rows as opaque records\n * here and trusts the caller's row typing.\n */\n protected abstract runDriver(exec: TExec): AsyncIterable<Record<string, unknown>>;\n\n abstract close(): Promise<void>;\n\n execute<Row>(\n plan: TPlan & { readonly _row?: Row },\n options?: RuntimeExecuteOptions,\n ): AsyncIterableResult<Row> {\n const self = this;\n const signal = options?.signal;\n // One ctx per execute() call. The ctx object is always allocated; the\n // `signal` field is only included when a signal was supplied (required\n // under exactOptionalPropertyTypes — `{ signal: undefined }` would not\n // satisfy `signal?: AbortSignal`).\n const codecCtx: CodecCallContext = signal === undefined ? {} : { signal };\n\n async function* generator(): AsyncGenerator<Row, void, unknown> {\n // Pre-check the signal at entry so an already-aborted caller observes\n // RUNTIME.ABORTED on the first `next()` without any work being done.\n checkAborted(codecCtx, 'stream');\n\n const compiled = await self.runBeforeCompile(plan);\n const exec = await self.lower(compiled, codecCtx);\n // The driver yields raw `Record<string, unknown>`; we cast to `Row` here.\n // The Row contract is enforced by the caller via `plan._row`.\n yield* runWithMiddleware<TExec, Row>(\n exec,\n self.middleware,\n self.ctx,\n () => self.runDriver(exec) as AsyncIterable<Row>,\n );\n }\n\n return new AsyncIterableResult(generator());\n }\n}\n","import type { AsyncIterableResult } from './async-iterable-result';\nimport type { ExecutionPlan, QueryPlan } from './query-plan';\nimport { runtimeError } from './runtime-error';\n\nexport interface RuntimeLog {\n info(event: unknown): void;\n warn(event: unknown): void;\n error(event: unknown): void;\n debug?(event: unknown): void;\n}\n\n/**\n * Per-execute context threaded through every middleware phase\n * (`beforeExecute`, `onRow`, `afterExecute`). Allocated once per\n * `runtime.execute()` call and shared by reference across all\n * middleware in the chain.\n *\n * - `signal` carries the per-query `AbortSignal` -- the same\n * reference that `runtime.execute(plan, { signal })` was invoked\n * with, and the same reference threaded into the per-call\n * `CodecCallContext` (ADR 207). Middleware that wraps a\n * network-backed SDK forwards `ctx.signal` into that SDK to\n * propagate caller cancellation; pure-CPU middleware ignores it.\n *\n * Symmetric plumbing across all middleware phases (rather than only\n * `beforeExecute`) is a deliberate choice: a middleware that wraps a\n * downstream observability hook or post-processor in `afterExecute` /\n * `onRow` needs the same cancellation reach as its `beforeExecute`\n * counterpart.\n */\nexport interface RuntimeMiddlewareContext {\n readonly contract: unknown;\n readonly mode: 'strict' | 'permissive';\n readonly now: () => number;\n readonly log: RuntimeLog;\n /**\n * Returns a stable string identifying the (storage, statement, params)\n * tuple of an execution. Two semantically equivalent executions return\n * the same string. Used by middleware that need per-execution identity\n * (caching, request coalescing).\n *\n * The family runtime owns the implementation:\n * - SQL: `meta.storageHash` + `exec.sql` + `canonicalStringify(exec.params)`\n * - Mongo: `meta.storageHash` + `canonicalStringify({ ...exec.command })`\n *\n * The method is `async` because the underlying digest helper\n * (`hashContent`) uses the WebCrypto API, whose `crypto.subtle.digest`\n * primitive is asynchronous by design.\n *\n * The returned string is intended to be consumed directly as a `Map` key\n * — it is not (and should not be) further hashed by callers.\n */\n contentHash(exec: ExecutionPlan): Promise<string>;\n /**\n * Per-execute cancellation signal threaded through every middleware\n * phase. Middleware that wraps async work or downstream cancellable\n * primitives should observe this and abort early when the consumer\n * cancels.\n */\n readonly signal?: AbortSignal;\n}\n\nexport interface AfterExecuteResult {\n readonly rowCount: number;\n readonly latencyMs: number;\n readonly completed: boolean;\n /**\n * Indicates where the rows observed during this execution came from.\n *\n * - `'driver'` — the default. Rows came from the underlying driver via\n * `runDriver` / `runWithMiddleware`'s normal path.\n * - `'middleware'` — a `RuntimeMiddleware.intercept` hook short-circuited\n * execution and supplied the rows directly. The driver was not invoked.\n *\n * Observers (telemetry, lints, budgets) that need to distinguish between\n * driver-served and middleware-served executions read this field.\n * Observers that don't care can ignore it.\n */\n readonly source: 'driver' | 'middleware';\n}\n\n/**\n * Result of a successful `RuntimeMiddleware.intercept` hook.\n *\n * Carries the rows that the middleware wishes to return in place of\n * invoking the driver. The runtime iterates `rows` in order and yields\n * each row to the consumer; `beforeExecute`, `runDriver`, and `onRow` are\n * all skipped on the hit path. `afterExecute` still fires with\n * `source: 'middleware'`.\n *\n * `rows` accepts both `Iterable` (arrays, sync generators) and\n * `AsyncIterable` (async generators). `for await` natively handles both\n * via `Symbol.asyncIterator` / `Symbol.iterator` fallback, so the\n * orchestrator does not need to branch on the variant. Cached arrays in\n * the cache middleware are the common case; streaming variants support\n * future use cases like mock layers replaying recordings.\n *\n * Row shape is `Record<string, unknown>` — the same untyped shape\n * `onRow` receives. The SQL runtime decodes intercepted rows through its\n * normal codec pass, so interceptors cache and return raw (undecoded)\n * rows.\n */\nexport interface InterceptResult {\n readonly rows: AsyncIterable<Record<string, unknown>> | Iterable<Record<string, unknown>>;\n}\n\n/**\n * Marker interface for family-specific param-ref mutators threaded into\n * `beforeExecute` as the third argument. The framework treats the mutator\n * opaquely — it allocates and forwards the family's mutator instance so\n * `runWithMiddleware` can stay family-agnostic. SQL extends this with\n * `SqlParamRefMutator` (over `ParamRef`); Mongo extends with\n * `MongoParamRefMutator` (over `MongoParamRef`).\n *\n * Extension authors target the family-specific mutator type, not this\n * marker.\n */\ndeclare const PARAM_REF_MUTATOR_BRAND: unique symbol;\nexport type ParamRefMutator = { readonly [PARAM_REF_MUTATOR_BRAND]?: never };\n\n/**\n * Family-agnostic middleware SPI parameterized over the plan marker.\n *\n * `TPlan` defaults to the framework `QueryPlan` marker so a generic\n * middleware (e.g. cross-family telemetry) can be authored without\n * naming a family. Family-specific middleware (`SqlMiddleware`,\n * `MongoMiddleware`) narrow `TPlan` to their concrete plan type.\n *\n * `TMutator` is the family-specific {@link ParamRefMutator} the runtime\n * threads into `beforeExecute(plan, ctx, params)` as a third argument.\n * Existing `(plan)` / `(plan, ctx)` middleware bodies continue to compile\n * — TypeScript permits assigning a function with fewer parameters to a\n * function-typed slot that declares more. The third arg is additive.\n */\nexport interface RuntimeMiddleware<\n TPlan extends QueryPlan = QueryPlan,\n TMutator extends ParamRefMutator = ParamRefMutator,\n> {\n readonly name: string;\n readonly familyId?: string;\n readonly targetId?: string;\n /**\n * Optional short-circuit hook. Runs inside `runWithMiddleware`, after\n * the orchestrator receives the lowered plan and before any\n * `beforeExecute` hook fires. Middleware run in registration order; the\n * first to return a non-`undefined` `InterceptResult` wins, and\n * subsequent middleware's `intercept` does not fire.\n *\n * On a hit, `beforeExecute`, `runDriver`, and `onRow` are all skipped.\n * `afterExecute` still fires with `source: 'middleware'`.\n *\n * Returning `undefined` (or omitting the hook entirely) signals\n * passthrough — execution proceeds through the normal driver path.\n *\n * Errors thrown inside `intercept` are rethrown by `runWithMiddleware`\n * as the original `Error` — no envelope is guaranteed at this layer.\n * Before rethrowing, `afterExecute` fires with `completed: false` and\n * `source: 'middleware'`. Errors thrown by `afterExecute` during the\n * error path remain swallowed (existing semantics, unchanged).\n *\n * Used by middleware that need to short-circuit execution and supply\n * rows directly: caching, mocks, rate limiting, circuit breaking.\n */\n intercept?(plan: TPlan, ctx: RuntimeMiddlewareContext): Promise<InterceptResult | undefined>;\n beforeExecute?(\n plan: TPlan,\n ctx: RuntimeMiddlewareContext,\n params?: TMutator,\n ): void | Promise<void>;\n onRow?(row: Record<string, unknown>, plan: TPlan, ctx: RuntimeMiddlewareContext): Promise<void>;\n afterExecute?(\n plan: TPlan,\n result: AfterExecuteResult,\n ctx: RuntimeMiddlewareContext,\n ): Promise<void>;\n}\n\n/**\n * Optional per-`execute` options accepted by every family runtime.\n *\n * `signal` is the per-query cancellation signal. The runtime threads the\n * signal through to every codec call for the query and uses it to short-\n * circuit the row stream with `RUNTIME.ABORTED` when the caller aborts.\n * Omitting the option (or passing `undefined`) preserves today's behavior\n * bit-for-bit.\n */\nexport interface RuntimeExecuteOptions {\n readonly signal?: AbortSignal;\n}\n\n/**\n * Cross-family SPI for any runtime that can execute plans and be shut down.\n * Each family runtime (SQL, Mongo) satisfies this interface — SQL nominally,\n * Mongo structurally (due to its phantom Row parameter using a unique symbol).\n *\n * The `_row` intersection on `execute` connects the `Row` type parameter to the\n * plan, mirroring how `QueryPlan<Row>` carries a phantom `_row?: Row`.\n */\nexport interface RuntimeExecutor<TPlan extends QueryPlan> {\n execute<Row>(\n plan: TPlan & { readonly _row?: Row },\n options?: RuntimeExecuteOptions,\n ): AsyncIterableResult<Row>;\n close(): Promise<void>;\n}\n\nexport function checkMiddlewareCompatibility(\n middleware: RuntimeMiddleware,\n runtimeFamilyId: string,\n runtimeTargetId: string,\n): void {\n if (middleware.targetId !== undefined && middleware.familyId === undefined) {\n throw runtimeError(\n 'RUNTIME.MIDDLEWARE_INCOMPATIBLE',\n `Middleware '${middleware.name}' specifies targetId '${middleware.targetId}' without familyId`,\n { middleware: middleware.name, targetId: middleware.targetId },\n );\n }\n\n if (middleware.familyId !== undefined && middleware.familyId !== runtimeFamilyId) {\n throw runtimeError(\n 'RUNTIME.MIDDLEWARE_FAMILY_MISMATCH',\n `Middleware '${middleware.name}' requires family '${middleware.familyId}' but the runtime is configured for family '${runtimeFamilyId}'`,\n { middleware: middleware.name, middlewareFamilyId: middleware.familyId, runtimeFamilyId },\n );\n }\n\n if (middleware.targetId !== undefined && middleware.targetId !== runtimeTargetId) {\n throw runtimeError(\n 'RUNTIME.MIDDLEWARE_TARGET_MISMATCH',\n `Middleware '${middleware.name}' requires target '${middleware.targetId}' but the runtime is configured for target '${runtimeTargetId}'`,\n { middleware: middleware.name, middlewareTargetId: middleware.targetId, runtimeTargetId },\n );\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runtime.mjs","names":[],"sources":["../src/execution/runtime-error.ts","../src/execution/async-iterable-result.ts","../src/execution/race-against-abort.ts","../src/execution/before-execute-chain.ts","../src/execution/run-with-middleware.ts","../src/execution/runtime-core.ts","../src/execution/runtime-middleware.ts"],"sourcesContent":["export interface RuntimeErrorEnvelope extends Error {\n readonly code: string;\n readonly category: 'PLAN' | 'CONTRACT' | 'LINT' | 'BUDGET' | 'RUNTIME';\n readonly severity: 'error';\n readonly details?: Record<string, unknown>;\n}\n\n/**\n * Stable code emitted by the runtime when an in-flight `execute()`\n * is cancelled via the per-query `AbortSignal`. The envelope's\n * `details.phase` distinguishes where the abort was observed:\n *\n * - `'encode'` — abort fired during `encodeParams` (SQL) or\n * `resolveValue` (Mongo).\n * - `'decode'` — abort fired during `decodeRow` / `decodeField`.\n * - `'stream'` — abort fired between rows or before any codec call\n * (already-aborted at entry).\n * - `'beforeExecute'` / `'afterExecute'` / `'onRow'` — abort fired\n * on entry to or during the corresponding middleware phase\n * (cooperative cancellation per the param-transform seam).\n */\nexport const RUNTIME_ABORTED = 'RUNTIME.ABORTED' as const;\n\n/** Discriminator placed in `details.phase` of a `RUNTIME.ABORTED` envelope. */\nexport type RuntimeAbortedPhase =\n | 'encode'\n | 'decode'\n | 'stream'\n | 'beforeExecute'\n | 'afterExecute'\n | 'onRow';\n\n/**\n * Type guard for the runtime-error envelope produced by `runtimeError`.\n *\n * Prefer this over duck-typing on `error.code` directly so consumers stay\n * insulated from the envelope's internal shape.\n */\nexport function isRuntimeError(error: unknown): error is RuntimeErrorEnvelope {\n return (\n error instanceof Error &&\n 'code' in error &&\n typeof (error as { code?: unknown }).code === 'string' &&\n 'category' in error &&\n 'severity' in error\n );\n}\n\nexport function runtimeError(\n code: string,\n message: string,\n details?: Record<string, unknown>,\n): RuntimeErrorEnvelope {\n const error = new Error(message) as RuntimeErrorEnvelope;\n Object.defineProperty(error, 'name', {\n value: 'RuntimeError',\n configurable: true,\n });\n\n return Object.assign(error, {\n code,\n category: resolveCategory(code),\n severity: 'error' as const,\n message,\n details,\n });\n}\n\nfunction resolveCategory(code: string): RuntimeErrorEnvelope['category'] {\n const prefix = code.split('.')[0] ?? 'RUNTIME';\n switch (prefix) {\n case 'PLAN':\n case 'CONTRACT':\n case 'LINT':\n case 'BUDGET':\n return prefix;\n default:\n return 'RUNTIME';\n }\n}\n\n/**\n * Construct a `RUNTIME.ABORTED` envelope. Phase distinguishes where the\n * abort was observed — codec call sites (`encode` / `decode` / `stream`)\n * or middleware seams (`beforeExecute` / `afterExecute` / `onRow`), as\n * enumerated on {@link RuntimeAbortedPhase}. Cause carries\n * `signal.reason` verbatim from the platform — native abort produces a\n * `DOMException`, explicit `controller.abort(reason)` produces whatever\n * the caller passed. No synthesis happens here.\n */\nexport function runtimeAborted(phase: RuntimeAbortedPhase, cause?: unknown): RuntimeErrorEnvelope {\n const envelope = runtimeError(RUNTIME_ABORTED, `Operation aborted during ${phase}`, { phase });\n return Object.assign(envelope, { cause });\n}\n","import { runtimeError } from './runtime-error';\n\nexport class AsyncIterableResult<Row> implements AsyncIterable<Row>, PromiseLike<Row[]> {\n private readonly generator: AsyncGenerator<Row, void, unknown>;\n private consumed = false;\n private consumedBy: 'bufferedArray' | 'iterator' | undefined;\n private bufferedArrayPromise: Promise<Row[]> | undefined;\n\n constructor(generator: AsyncGenerator<Row, void, unknown>) {\n this.generator = generator;\n }\n\n [Symbol.asyncIterator](): AsyncIterator<Row> {\n if (this.consumed) {\n throw runtimeError(\n 'RUNTIME.ITERATOR_CONSUMED',\n `AsyncIterableResult iterator has already been consumed via ${this.consumedBy === 'bufferedArray' ? 'toArray()/then()' : 'for-await loop'}. Each AsyncIterableResult can only be iterated once.`,\n {\n consumedBy: this.consumedBy,\n suggestion:\n this.consumedBy === 'bufferedArray'\n ? 'If you need to iterate multiple times, store the results from toArray() in a variable and reuse that.'\n : 'If you need to iterate multiple times, use toArray() to collect all results first.',\n },\n );\n }\n this.consumed = true;\n this.consumedBy = 'iterator';\n return this.generator;\n }\n\n toArray(): Promise<Row[]> {\n if (this.consumedBy === 'iterator') {\n return Promise.reject(\n runtimeError(\n 'RUNTIME.ITERATOR_CONSUMED',\n 'AsyncIterableResult iterator has already been consumed via for-await loop. Each AsyncIterableResult can only be iterated once.',\n {\n consumedBy: this.consumedBy,\n suggestion:\n 'The iterator was already consumed by a for-await loop. Use toArray() or await the result before iterating.',\n },\n ),\n );\n }\n\n if (this.bufferedArrayPromise) {\n return this.bufferedArrayPromise;\n }\n\n this.consumed = true;\n this.consumedBy = 'bufferedArray';\n this.bufferedArrayPromise = (async () => {\n const out: Row[] = [];\n for await (const item of this.generator) {\n out.push(item);\n }\n return out;\n })();\n return this.bufferedArrayPromise;\n }\n\n async first(): Promise<Row | null> {\n const rows = await this.toArray();\n return rows[0] ?? null;\n }\n\n async firstOrThrow(): Promise<Row> {\n const row = await this.first();\n if (row === null)\n throw runtimeError(\n 'RUNTIME.NO_ROWS',\n 'Expected at least one row, but none were returned',\n {},\n );\n return row;\n }\n\n // biome-ignore lint/suspicious/noThenProperty: PromiseLike implementation is intentional for await support.\n then<TResult1 = Row[], TResult2 = never>(\n onfulfilled?: ((value: Row[]) => TResult1 | PromiseLike<TResult1>) | undefined | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | undefined | null,\n ): PromiseLike<TResult1 | TResult2> {\n return this.toArray().then(onfulfilled, onrejected);\n }\n}\n","import type { RuntimeAbortedPhase } from './runtime-error';\nimport { runtimeAborted } from './runtime-error';\n\n/**\n * Throw a phase-tagged `RUNTIME.ABORTED` envelope if the supplied\n * context is already aborted at the precheck site. Centralises the\n * `if (ctx.signal?.aborted) throw runtimeAborted(...)` pattern that\n * every codec dispatch site (and the `beforeExecute` middleware phase)\n * repeats. Accepts both the framework `CodecCallContext` and the\n * `RuntimeMiddlewareContext`; both expose `signal?: AbortSignal`.\n */\nexport function checkAborted(\n ctx: { readonly signal?: AbortSignal },\n phase: RuntimeAbortedPhase,\n): void {\n if (ctx.signal?.aborted) {\n throw runtimeAborted(phase, ctx.signal.reason);\n }\n}\n\n/**\n * Race a per-cell `Promise.all` (or any other in-flight work promise) against\n * the supplied abort signal so the runtime returns `RUNTIME.ABORTED` promptly\n * even when codec bodies ignore the signal. In-flight bodies that ignore the\n * signal are abandoned and run to completion in the background — the\n * cooperative-cancellation contract documented in ADR 204.\n *\n * Call sites still SHOULD pre-check `signal.aborted` and short-circuit with\n * a phase-tagged `RUNTIME.ABORTED` envelope before invoking this helper —\n * that path is the canonical \"aborted at entry\" surface and avoids\n * scheduling the work promise. As a defensive belt-and-braces, this helper\n * also handles the already-aborted case internally: `AbortSignal` does not\n * replay past abort events to listeners registered after the abort, so we\n * inspect `signal.aborted` synchronously and reject with the sentinel\n * before installing the listener. The rejection is still attributed to the\n * abort path via the sentinel-identity check.\n *\n * Distinguishing the rejection source is load-bearing for AC-ERR4\n * (`RUNTIME.ENCODE_FAILED` / `RUNTIME.DECODE_FAILED` pass through unchanged).\n * The semantically equivalent `abortable(signal)` helper in\n * `@prisma-next/utils` rejects with `signal.reason ?? new DOMException(...)`,\n * which is not stably distinguishable from a codec-thrown error by identity\n * alone (a fresh fallback DOMException is allocated per call). We instead\n * track abort attribution with a unique sentinel: only the `onAbort` listener\n * installed here ever rejects with the sentinel, so an `error === sentinel`\n * identity check after the race is unambiguous.\n *\n * Lives in `framework-components` (rather than the SQL family, where it\n * originated in m2) so every family runtime that needs cooperative\n * cancellation around a codec-dispatch `Promise.all` (SQL encode + decode\n * today, Mongo encode in m3) shares the same attribution logic.\n */\nexport async function raceAgainstAbort<T>(\n work: Promise<T>,\n signal: AbortSignal | undefined,\n phase: RuntimeAbortedPhase,\n): Promise<T> {\n if (signal === undefined) {\n return await work;\n }\n const sentinel: { reason: unknown } = { reason: undefined };\n let onAbort: (() => void) | undefined;\n\n const abortPromise = new Promise<never>((_, reject) => {\n if (signal.aborted) {\n sentinel.reason = signal.reason;\n reject(sentinel);\n return;\n }\n onAbort = () => {\n sentinel.reason = signal.reason;\n reject(sentinel);\n };\n signal.addEventListener('abort', onAbort, { once: true });\n });\n\n try {\n return await Promise.race([work, abortPromise]);\n } catch (error) {\n if (error === sentinel) {\n throw runtimeAborted(phase, sentinel.reason);\n }\n throw error;\n } finally {\n if (onAbort) {\n signal.removeEventListener('abort', onAbort);\n }\n }\n}\n","import type { ExecutionPlan } from './query-plan';\nimport { checkAborted, raceAgainstAbort } from './race-against-abort';\nimport type {\n ParamRefMutator,\n RuntimeMiddleware,\n RuntimeMiddlewareContext,\n} from './runtime-middleware';\n\n/**\n * Runs every middleware's `beforeExecute` hook in registration order,\n * threading through the (optional) family-specific `paramsMutator`.\n *\n * Why this lives outside {@link runWithMiddleware}: middleware that\n * mutates parameter values (e.g. cipherstash's bulk-encrypt SDK\n * round-trip) must run *before* the family runtime encodes those\n * parameters to driver wire format. Family runtimes call\n * `runBeforeExecuteChain` between the AST → plan lowering step and\n * the parameter encode step; the encode then observes the mutator's\n * `currentParams()` view. `runWithMiddleware` retains the rest of\n * the lifecycle (`intercept`, driver/row source loop, `onRow`,\n * `afterExecute`) but no longer fires `beforeExecute` itself.\n *\n * Lifecycle within this helper:\n *\n * 1. For each middleware in registration order, if `beforeExecute`\n * is implemented:\n * - `checkAborted(ctx, 'beforeExecute')` short-circuits if the\n * caller already aborted at entry.\n * - The hook is invoked with `(plan, ctx, paramsMutator)`. A\n * middleware body that ignores the mutator stays compatible —\n * JavaScript allows extra positional arguments.\n * - If the hook returns a Promise, it is raced against\n * `ctx.signal` via {@link raceAgainstAbort} so cooperative\n * cancellation surfaces a `RUNTIME.ABORTED { phase:\n * 'beforeExecute' }` envelope even when the body itself\n * ignores the signal.\n *\n * Error propagation: any error thrown by a `beforeExecute` body\n * (or surfaced by the abort race) propagates out of this helper\n * unchanged. The family runtime is responsible for converting it\n * into the appropriate `afterExecute(completed: false)` notification\n * once `runWithMiddleware` runs.\n *\n * Relationship to {@link runWithMiddleware}: the framework's\n * `RuntimeCore.execute` template calls this helper between\n * `lower(plan)` and `runWithMiddleware(...)`. Family runtimes that\n * override `execute` (e.g. SQL, which inlines lower + encode for\n * direct mutator threading) call this helper themselves at the\n * equivalent point — between the family's AST → draft-plan\n * lowering and the parameter-encode step.\n *\n * Intercept ordering: this helper fires unconditionally before\n * `runWithMiddleware`. `intercept` (inside `runWithMiddleware`)\n * therefore observes the post-`beforeExecute` plan — mutator\n * mutations are visible in the params interceptors see. The\n * trade-off is documented on `RuntimeMiddleware.intercept`.\n */\nexport async function runBeforeExecuteChain<\n TExec extends ExecutionPlan,\n TMutator extends ParamRefMutator = ParamRefMutator,\n>(\n plan: TExec,\n middleware: ReadonlyArray<RuntimeMiddleware<TExec, TMutator>>,\n ctx: RuntimeMiddlewareContext,\n paramsMutator?: TMutator,\n): Promise<void> {\n for (const mw of middleware) {\n if (!mw.beforeExecute) {\n continue;\n }\n checkAborted(ctx, 'beforeExecute');\n const work = mw.beforeExecute(plan, ctx, paramsMutator as TMutator);\n if (work !== undefined) {\n await raceAgainstAbort(Promise.resolve(work), ctx.signal, 'beforeExecute');\n }\n }\n}\n","import { AsyncIterableResult } from './async-iterable-result';\nimport type { ExecutionPlan } from './query-plan';\nimport type { RuntimeMiddleware, RuntimeMiddlewareContext } from './runtime-middleware';\n\n/**\n * Drives a single execution of `runDriver()` through the middleware\n * lifecycle's intercept + row-source + termination phases.\n *\n * Lifecycle, in order:\n * 1. For each middleware in registration order: `intercept(exec, ctx)`. The\n * first non-`undefined` result wins; subsequent middleware's `intercept`\n * does not fire. On a hit, the runtime emits a `middleware.intercept`\n * debug event naming the winning middleware, switches the row source to\n * the intercepted rows, and proceeds with `source: 'middleware'`. On\n * all-passthrough (every `intercept` returns `undefined` or is omitted),\n * `source: 'driver'` is used and the row source is `runDriver()`.\n * 2. Iterate the row source. On the driver path, for each row, for each\n * middleware in registration order: `onRow(row, exec, ctx)`; then yield\n * the row. On the intercepted hit path, `onRow` is skipped — intercepted\n * rows did not originate from a driver row stream — but rows are still\n * yielded to the consumer in order.\n * 3. On successful completion: for each middleware in registration order:\n * `afterExecute(exec, { rowCount, latencyMs, completed: true, source },\n * ctx)`.\n * 4. On any error thrown during steps 1–2: for each middleware in\n * registration order: `afterExecute(exec, { rowCount, latencyMs,\n * completed: false, source }, ctx)`. Errors thrown by `afterExecute`\n * during the error path are swallowed so they do not mask the original\n * error. The original error is then rethrown.\n *\n * `beforeExecute` is **not** fired here — see\n * {@link runBeforeExecuteChain} in `before-execute-chain.ts`. Family\n * runtimes call that helper between the AST → plan lowering step and\n * the parameter encode step so middleware that mutates ParamRef\n * values (e.g. cipherstash bulk-encrypt) can have its mutations\n * visible to encode. `runWithMiddleware` operates on the fully-\n * encoded plan; interceptors therefore observe a fully-mutated,\n * encoded plan.\n *\n * The `source` field on `AfterExecuteResult` lets observers (telemetry,\n * lints, budgets) distinguish driver-served from middleware-served\n * executions without needing their own out-of-band signal.\n *\n * This helper is the single canonical implementation of the\n * intercept-and-row-source loop; family runtimes should not\n * reimplement it.\n */\nexport function runWithMiddleware<TExec extends ExecutionPlan, Row>(\n exec: TExec,\n middleware: ReadonlyArray<RuntimeMiddleware<TExec>>,\n ctx: RuntimeMiddlewareContext,\n runDriver: () => AsyncIterable<Row>,\n): AsyncIterableResult<Row> {\n const iterator = async function* (): AsyncGenerator<Row, void, unknown> {\n const startedAt = Date.now();\n let rowCount = 0;\n let completed = false;\n let source: 'driver' | 'middleware' = 'driver';\n // Deferred so a winning interceptor can skip `runDriver()` entirely.\n // For factories that lazily produce async generators this is a no-op,\n // but factories that do eager work (e.g. acquiring a connection,\n // sending a query) must not run on the intercepted hit path.\n let rowSource: AsyncIterable<Row> | Iterable<Row> | undefined;\n\n try {\n for (const mw of middleware) {\n if (!mw.intercept) {\n continue;\n }\n // Mark the lifecycle as middleware-driven *before* awaiting the\n // hook. If `intercept` throws, the catch block reports the failure\n // as `source: 'middleware'` — the failure originated in the\n // intercept chain, not in the driver. If `intercept` returns\n // `undefined` (passthrough), we revert to `'driver'` and continue.\n source = 'middleware';\n const result = await mw.intercept(exec, ctx);\n if (result === undefined) {\n source = 'driver';\n continue;\n }\n ctx.log.debug?.({ event: 'middleware.intercept', middleware: mw.name });\n // The intercepted rows are typed as `Record<string, unknown>` at\n // the SPI level; the consumer's `Row` type parameter is enforced by\n // the caller (via the plan's phantom `_row`) the same way driver\n // rows are. Cast through unknown to bridge the SPI shape to the\n // caller-supplied Row.\n rowSource = result.rows as unknown as AsyncIterable<Row> | Iterable<Row>;\n break;\n }\n\n if (source === 'driver') {\n rowSource = runDriver();\n }\n\n // `rowSource` is always assigned by this point: either the intercepted\n // rows (on a hit) or `runDriver()` (on the driver path).\n for await (const row of rowSource as AsyncIterable<Row> | Iterable<Row>) {\n if (source === 'driver') {\n for (const mw of middleware) {\n if (mw.onRow) {\n await mw.onRow(row as Record<string, unknown>, exec, ctx);\n }\n }\n }\n rowCount++;\n yield row;\n }\n\n completed = true;\n } catch (error) {\n const latencyMs = Date.now() - startedAt;\n for (const mw of middleware) {\n if (mw.afterExecute) {\n try {\n await mw.afterExecute(exec, { rowCount, latencyMs, completed, source }, ctx);\n } catch {\n // Swallow afterExecute errors during the error path so they do not\n // mask the original error.\n }\n }\n }\n\n throw error;\n }\n\n const latencyMs = Date.now() - startedAt;\n for (const mw of middleware) {\n if (mw.afterExecute) {\n await mw.afterExecute(exec, { rowCount, latencyMs, completed, source }, ctx);\n }\n }\n };\n\n return new AsyncIterableResult(iterator());\n}\n","import type { CodecCallContext } from '../shared/codec-types';\nimport { AsyncIterableResult } from './async-iterable-result';\nimport { runBeforeExecuteChain } from './before-execute-chain';\nimport type { ExecutionPlan, QueryPlan } from './query-plan';\nimport { checkAborted } from './race-against-abort';\nimport { runWithMiddleware } from './run-with-middleware';\nimport type {\n RuntimeExecuteOptions,\n RuntimeExecutor,\n RuntimeMiddleware,\n RuntimeMiddlewareContext,\n} from './runtime-middleware';\n\n/**\n * Constructor options shared by every concrete `RuntimeCore` subclass.\n *\n * Family runtimes typically build the middleware list and the\n * `RuntimeMiddlewareContext` themselves (running compatibility checks,\n * narrowing the context's `contract` field, etc.) before calling `super`.\n */\nexport interface RuntimeCoreOptions<TMiddleware extends RuntimeMiddleware<ExecutionPlan>> {\n readonly middleware: ReadonlyArray<TMiddleware>;\n readonly ctx: RuntimeMiddlewareContext;\n}\n\n/**\n * Family-agnostic abstract runtime base.\n *\n * Defines the entire `execute(plan)` template in one place:\n *\n * 1. `runBeforeCompile(plan)` — concrete; defaults to identity. SQL overrides\n * this to run its `beforeCompile` middleware-hook chain.\n * 2. `lower(plan)` — abstract. Each family produces its `*ExecutionPlan`\n * (SQL via `lowerSqlPlan`, Mongo via `adapter.lower`).\n * 3. `runBeforeExecuteChain(exec, this.middleware, this.ctx)` — concrete;\n * runs every middleware's `beforeExecute` hook after lowering but\n * before the row source is opened. Family runtimes that need a\n * params mutator visible to a downstream encode step (SQL) override\n * `execute` and call this helper themselves at the equivalent\n * pre-encode point.\n * 4. `runWithMiddleware(exec, this.middleware, this.ctx,\n * () => runDriver(exec))` — concrete; runs the intercept chain,\n * drives the row source, fires `onRow` / `afterExecute`. Does\n * **not** fire `beforeExecute` — see step 3.\n *\n * Concrete subclasses must implement `lower`, `runDriver`, and `close`.\n *\n * The class is generic over:\n * - `TPlan` — the family's pre-lowering plan type.\n * - `TExec` — the family's post-lowering (executable) plan type.\n * - `TMiddleware` — the family's middleware type. Constrained to\n * `RuntimeMiddleware<TExec>` because `runWithMiddleware` invokes the\n * `beforeExecute` / `onRow` / `afterExecute` hooks with the lowered\n * `TExec`. (The spec/plan wording \"RuntimeMiddleware<TPlan>\" is\n * tightened to `<TExec>` here so the helper call typechecks; the\n * intent is unchanged — middleware sees the post-lowering plan.)\n */\nexport abstract class RuntimeCore<\n TPlan extends QueryPlan,\n TExec extends ExecutionPlan,\n TMiddleware extends RuntimeMiddleware<TExec>,\n> implements RuntimeExecutor<TPlan>\n{\n protected readonly middleware: ReadonlyArray<TMiddleware>;\n protected readonly ctx: RuntimeMiddlewareContext;\n\n constructor(options: RuntimeCoreOptions<TMiddleware>) {\n this.middleware = options.middleware;\n this.ctx = options.ctx;\n }\n\n /**\n * Pre-lowering hook for plan rewriting. Defaults to identity. Subclasses\n * may override to run a `beforeCompile` middleware chain (SQL does this\n * to support typed AST rewrites — see `before-compile-chain.ts`).\n */\n protected runBeforeCompile(plan: TPlan): TPlan | Promise<TPlan> {\n return plan;\n }\n\n /**\n * Lower a pre-lowering `TPlan` into the family's executable `TExec`.\n * Family-specific: SQL produces `{ sql, params, ast?, ... }`; Mongo\n * produces `{ command, ... }`.\n *\n * `ctx` carries per-query cancellation (and any future fields on\n * `CodecCallContext`); concrete subclasses forward it to the\n * encode-side codec dispatch site (e.g. SQL's `encodeParams` in m2,\n * Mongo's `resolveValue` in m3). The runtime allocates one ctx per\n * `execute()` call and threads the same reference everywhere; the\n * `signal` field inside may be `undefined`, but the ctx object itself\n * is always present.\n */\n protected abstract lower(plan: TPlan, ctx: CodecCallContext): TExec | Promise<TExec>;\n\n /**\n * Drive the underlying transport for a lowered `TExec`. Yields raw rows\n * directly from the driver as `Record<string, unknown>`; codec decoding\n * (if any) is the subclass's responsibility, applied by wrapping\n * `execute()` rather than living inside this hook.\n *\n * The `Row` type parameter on `execute()` is satisfied by the caller via\n * the plan's phantom `_row`; the runtime treats rows as opaque records\n * here and trusts the caller's row typing.\n */\n protected abstract runDriver(exec: TExec): AsyncIterable<Record<string, unknown>>;\n\n abstract close(): Promise<void>;\n\n execute<Row>(\n plan: TPlan & { readonly _row?: Row },\n options?: RuntimeExecuteOptions,\n ): AsyncIterableResult<Row> {\n const self = this;\n const signal = options?.signal;\n // One ctx per execute() call. The ctx object is always allocated; the\n // `signal` field is only included when a signal was supplied (required\n // under exactOptionalPropertyTypes — `{ signal: undefined }` would not\n // satisfy `signal?: AbortSignal`).\n const codecCtx: CodecCallContext = signal === undefined ? {} : { signal };\n\n async function* generator(): AsyncGenerator<Row, void, unknown> {\n // Pre-check the signal at entry so an already-aborted caller observes\n // RUNTIME.ABORTED on the first `next()` without any work being done.\n checkAborted(codecCtx, 'stream');\n\n const compiled = await self.runBeforeCompile(plan);\n const exec = await self.lower(compiled, codecCtx);\n // Fire the framework-level `beforeExecute` chain on the lowered\n // plan before opening the row source. Families that need\n // pre-encode mutator visibility (SQL) override `execute` to\n // inject the same chain at the equivalent point.\n await runBeforeExecuteChain<TExec>(exec, self.middleware, self.ctx);\n // The driver yields raw `Record<string, unknown>`; we cast to `Row` here.\n // The Row contract is enforced by the caller via `plan._row`.\n yield* runWithMiddleware<TExec, Row>(\n exec,\n self.middleware,\n self.ctx,\n () => self.runDriver(exec) as AsyncIterable<Row>,\n );\n }\n\n return new AsyncIterableResult(generator());\n }\n}\n","import type { AsyncIterableResult } from './async-iterable-result';\nimport type { ExecutionPlan, QueryPlan } from './query-plan';\nimport { runtimeError } from './runtime-error';\n\nexport interface RuntimeLog {\n info(event: unknown): void;\n warn(event: unknown): void;\n error(event: unknown): void;\n debug?(event: unknown): void;\n}\n\n/**\n * Per-execute context threaded through every middleware phase\n * (`beforeExecute`, `onRow`, `afterExecute`). Allocated once per\n * `runtime.execute()` call and shared by reference across all\n * middleware in the chain.\n *\n * - `signal` carries the per-query `AbortSignal` -- the same\n * reference that `runtime.execute(plan, { signal })` was invoked\n * with, and the same reference threaded into the per-call\n * `CodecCallContext` (ADR 207). Middleware that wraps a\n * network-backed SDK forwards `ctx.signal` into that SDK to\n * propagate caller cancellation; pure-CPU middleware ignores it.\n *\n * Symmetric plumbing across all middleware phases (rather than only\n * `beforeExecute`) is a deliberate choice: a middleware that wraps a\n * downstream observability hook or post-processor in `afterExecute` /\n * `onRow` needs the same cancellation reach as its `beforeExecute`\n * counterpart.\n */\nexport interface RuntimeMiddlewareContext {\n readonly contract: unknown;\n readonly mode: 'strict' | 'permissive';\n readonly now: () => number;\n readonly log: RuntimeLog;\n /**\n * Returns a stable string identifying the (storage, statement, params)\n * tuple of an execution. Two semantically equivalent executions return\n * the same string. Used by middleware that need per-execution identity\n * (caching, request coalescing).\n *\n * The family runtime owns the implementation:\n * - SQL: `meta.storageHash` + `exec.sql` + `canonicalStringify(exec.params)`\n * - Mongo: `meta.storageHash` + `canonicalStringify({ ...exec.command })`\n *\n * The method is `async` because the underlying digest helper\n * (`hashContent`) uses the WebCrypto API, whose `crypto.subtle.digest`\n * primitive is asynchronous by design.\n *\n * The returned string is intended to be consumed directly as a `Map` key\n * — it is not (and should not be) further hashed by callers.\n */\n contentHash(exec: ExecutionPlan): Promise<string>;\n /**\n * Per-execute cancellation signal threaded through every middleware\n * phase. Middleware that wraps async work or downstream cancellable\n * primitives should observe this and abort early when the consumer\n * cancels.\n */\n readonly signal?: AbortSignal;\n}\n\nexport interface AfterExecuteResult {\n readonly rowCount: number;\n readonly latencyMs: number;\n readonly completed: boolean;\n /**\n * Indicates where the rows observed during this execution came from.\n *\n * - `'driver'` — the default. Rows came from the underlying driver via\n * `runDriver` / `runWithMiddleware`'s normal path.\n * - `'middleware'` — a `RuntimeMiddleware.intercept` hook short-circuited\n * execution and supplied the rows directly. The driver was not invoked.\n *\n * Observers (telemetry, lints, budgets) that need to distinguish between\n * driver-served and middleware-served executions read this field.\n * Observers that don't care can ignore it.\n */\n readonly source: 'driver' | 'middleware';\n}\n\n/**\n * Result of a successful `RuntimeMiddleware.intercept` hook.\n *\n * Carries the rows that the middleware wishes to return in place of\n * invoking the driver. The runtime iterates `rows` in order and yields\n * each row to the consumer; `beforeExecute`, `runDriver`, and `onRow` are\n * all skipped on the hit path. `afterExecute` still fires with\n * `source: 'middleware'`.\n *\n * `rows` accepts both `Iterable` (arrays, sync generators) and\n * `AsyncIterable` (async generators). `for await` natively handles both\n * via `Symbol.asyncIterator` / `Symbol.iterator` fallback, so the\n * orchestrator does not need to branch on the variant. Cached arrays in\n * the cache middleware are the common case; streaming variants support\n * future use cases like mock layers replaying recordings.\n *\n * Row shape is `Record<string, unknown>` — the same untyped shape\n * `onRow` receives. The SQL runtime decodes intercepted rows through its\n * normal codec pass, so interceptors cache and return raw (undecoded)\n * rows.\n */\nexport interface InterceptResult {\n readonly rows: AsyncIterable<Record<string, unknown>> | Iterable<Record<string, unknown>>;\n}\n\n/**\n * Marker interface for family-specific param-ref mutators threaded into\n * `beforeExecute` as the third argument. The framework treats the mutator\n * opaquely — it allocates and forwards the family's mutator instance so\n * `runWithMiddleware` can stay family-agnostic. SQL extends this with\n * `SqlParamRefMutator` (over `ParamRef`); Mongo extends with\n * `MongoParamRefMutator` (over `MongoParamRef`).\n *\n * Extension authors target the family-specific mutator type, not this\n * marker.\n */\ndeclare const PARAM_REF_MUTATOR_BRAND: unique symbol;\nexport type ParamRefMutator = { readonly [PARAM_REF_MUTATOR_BRAND]?: never };\n\n/**\n * Family-agnostic middleware SPI parameterized over the plan marker.\n *\n * `TPlan` defaults to the framework `QueryPlan` marker so a generic\n * middleware (e.g. cross-family telemetry) can be authored without\n * naming a family. Family-specific middleware (`SqlMiddleware`,\n * `MongoMiddleware`) narrow `TPlan` to their concrete plan type.\n *\n * `TMutator` is the family-specific {@link ParamRefMutator} the runtime\n * threads into `beforeExecute(plan, ctx, params)` as a third argument.\n * Existing `(plan)` / `(plan, ctx)` middleware bodies continue to compile\n * — TypeScript permits assigning a function with fewer parameters to a\n * function-typed slot that declares more. The third arg is additive.\n */\nexport interface RuntimeMiddleware<\n TPlan extends QueryPlan = QueryPlan,\n TMutator extends ParamRefMutator = ParamRefMutator,\n> {\n readonly name: string;\n readonly familyId?: string;\n readonly targetId?: string;\n /**\n * Optional short-circuit hook. Runs inside `runWithMiddleware`, after\n * the orchestrator receives the lowered plan and before any\n * `beforeExecute` hook fires. Middleware run in registration order; the\n * first to return a non-`undefined` `InterceptResult` wins, and\n * subsequent middleware's `intercept` does not fire.\n *\n * On a hit, `beforeExecute`, `runDriver`, and `onRow` are all skipped.\n * `afterExecute` still fires with `source: 'middleware'`.\n *\n * Returning `undefined` (or omitting the hook entirely) signals\n * passthrough — execution proceeds through the normal driver path.\n *\n * Errors thrown inside `intercept` are rethrown by `runWithMiddleware`\n * as the original `Error` — no envelope is guaranteed at this layer.\n * Before rethrowing, `afterExecute` fires with `completed: false` and\n * `source: 'middleware'`. Errors thrown by `afterExecute` during the\n * error path remain swallowed (existing semantics, unchanged).\n *\n * Used by middleware that need to short-circuit execution and supply\n * rows directly: caching, mocks, rate limiting, circuit breaking.\n */\n intercept?(plan: TPlan, ctx: RuntimeMiddlewareContext): Promise<InterceptResult | undefined>;\n /**\n * Fires after the family runtime has produced a draft execution\n * plan from the AST, but before the family encodes parameter values\n * to driver wire format. Mutations applied via the\n * family-specific `params` mutator are visible to the subsequent\n * encode step.\n *\n * Lifecycle position (SQL example):\n * `runBeforeCompile → lowerSqlPlan → beforeExecute → encodeParams → intercept → driver`.\n *\n * The `params` argument is a family-specific {@link ParamRefMutator}\n * scoped to the value slots of `ParamRef` nodes in the plan's AST.\n * Middleware that doesn't need to mutate params can ignore the\n * argument; existing `(plan)` / `(plan, ctx)` bodies stay compatible.\n *\n * `ctx.signal` carries the per-query `AbortSignal`; middleware that\n * wraps a network SDK forwards it. Cooperative cancellation\n * surfaces a `RUNTIME.ABORTED { phase: 'beforeExecute' }` envelope\n * promptly even when the body ignores the signal.\n *\n * Intercept ordering: `intercept` runs *after* this hook; an\n * interceptor that short-circuits the driver path still observes\n * the post-`beforeExecute`, fully-encoded plan. The trade-off is\n * that any `beforeExecute` SDK round-trips happen even when a\n * downstream interceptor would have skipped the driver entirely.\n */\n beforeExecute?(\n plan: TPlan,\n ctx: RuntimeMiddlewareContext,\n params?: TMutator,\n ): void | Promise<void>;\n onRow?(row: Record<string, unknown>, plan: TPlan, ctx: RuntimeMiddlewareContext): Promise<void>;\n afterExecute?(\n plan: TPlan,\n result: AfterExecuteResult,\n ctx: RuntimeMiddlewareContext,\n ): Promise<void>;\n}\n\n/**\n * Optional per-`execute` options accepted by every family runtime.\n *\n * `signal` is the per-query cancellation signal. The runtime threads the\n * signal through to every codec call for the query and uses it to short-\n * circuit the row stream with `RUNTIME.ABORTED` when the caller aborts.\n * Omitting the option (or passing `undefined`) preserves today's behavior\n * bit-for-bit.\n */\nexport interface RuntimeExecuteOptions {\n readonly signal?: AbortSignal;\n}\n\n/**\n * Cross-family SPI for any runtime that can execute plans and be shut down.\n * Each family runtime (SQL, Mongo) satisfies this interface — SQL nominally,\n * Mongo structurally (due to its phantom Row parameter using a unique symbol).\n *\n * The `_row` intersection on `execute` connects the `Row` type parameter to the\n * plan, mirroring how `QueryPlan<Row>` carries a phantom `_row?: Row`.\n */\nexport interface RuntimeExecutor<TPlan extends QueryPlan> {\n execute<Row>(\n plan: TPlan & { readonly _row?: Row },\n options?: RuntimeExecuteOptions,\n ): AsyncIterableResult<Row>;\n close(): Promise<void>;\n}\n\nexport function checkMiddlewareCompatibility(\n middleware: RuntimeMiddleware,\n runtimeFamilyId: string,\n runtimeTargetId: string,\n): void {\n if (middleware.targetId !== undefined && middleware.familyId === undefined) {\n throw runtimeError(\n 'RUNTIME.MIDDLEWARE_INCOMPATIBLE',\n `Middleware '${middleware.name}' specifies targetId '${middleware.targetId}' without familyId`,\n { middleware: middleware.name, targetId: middleware.targetId },\n );\n }\n\n if (middleware.familyId !== undefined && middleware.familyId !== runtimeFamilyId) {\n throw runtimeError(\n 'RUNTIME.MIDDLEWARE_FAMILY_MISMATCH',\n `Middleware '${middleware.name}' requires family '${middleware.familyId}' but the runtime is configured for family '${runtimeFamilyId}'`,\n { middleware: middleware.name, middlewareFamilyId: middleware.familyId, runtimeFamilyId },\n );\n }\n\n if (middleware.targetId !== undefined && middleware.targetId !== runtimeTargetId) {\n throw runtimeError(\n 'RUNTIME.MIDDLEWARE_TARGET_MISMATCH',\n `Middleware '${middleware.name}' requires target '${middleware.targetId}' but the runtime is configured for target '${runtimeTargetId}'`,\n { middleware: middleware.name, middlewareTargetId: middleware.targetId, runtimeTargetId },\n );\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/framework-components",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"description": "Framework component types, assembly logic, and stack creation for Prisma Next",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"@standard-schema/spec": "^1.1.0",
|
|
10
|
-
"@prisma-next/
|
|
11
|
-
"@prisma-next/
|
|
12
|
-
"@prisma-next/
|
|
13
|
-
"@prisma-next/
|
|
10
|
+
"@prisma-next/operations": "0.6.1",
|
|
11
|
+
"@prisma-next/contract": "0.6.1",
|
|
12
|
+
"@prisma-next/ts-render": "0.6.1",
|
|
13
|
+
"@prisma-next/utils": "0.6.1"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"tsdown": "0.22.0",
|
|
17
17
|
"typescript": "5.9.3",
|
|
18
18
|
"vitest": "4.1.5",
|
|
19
|
-
"@prisma-next/
|
|
20
|
-
"@prisma-next/
|
|
19
|
+
"@prisma-next/tsdown": "0.0.0",
|
|
20
|
+
"@prisma-next/tsconfig": "0.0.0"
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
23
23
|
"dist",
|
|
@@ -526,16 +526,19 @@ export interface MultiSpaceRunnerFailure extends MigrationRunnerFailure {
|
|
|
526
526
|
export type MultiSpaceRunnerResult = Result<MultiSpaceRunnerSuccessValue, MultiSpaceRunnerFailure>;
|
|
527
527
|
|
|
528
528
|
/**
|
|
529
|
-
* Optional capability for runners that can apply a list of per-space plans
|
|
530
|
-
*
|
|
531
|
-
* space's writes.
|
|
529
|
+
* Optional capability for runners that can apply a list of per-space plans.
|
|
530
|
+
* Atomicity semantics differ by family:
|
|
532
531
|
*
|
|
533
|
-
*
|
|
534
|
-
*
|
|
535
|
-
*
|
|
536
|
-
*
|
|
537
|
-
*
|
|
538
|
-
*
|
|
532
|
+
* - SQL (`SqlMigrationRunner`) opens one outer transaction across every
|
|
533
|
+
* space; a failure on any space rolls back every space's writes.
|
|
534
|
+
* - Mongo (`mongoTargetDescriptor`) cannot wrap most DDL ops in a session
|
|
535
|
+
* transaction (TML-2408), so it iterates per-space without an outer
|
|
536
|
+
* transaction and relies on per-space-internal verify-gated marker
|
|
537
|
+
* atomicity. Earlier-advanced markers are not rolled back when a later
|
|
538
|
+
* space fails; re-running resumes from the failing space.
|
|
539
|
+
*
|
|
540
|
+
* The capability is declared at the framework layer so CLI utilities can
|
|
541
|
+
* route through it without importing any specific family directly.
|
|
539
542
|
*/
|
|
540
543
|
export interface MultiSpaceCapableRunner<
|
|
541
544
|
TFamilyId extends string = string,
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { ExecutionPlan } from './query-plan';
|
|
2
|
+
import { checkAborted, raceAgainstAbort } from './race-against-abort';
|
|
3
|
+
import type {
|
|
4
|
+
ParamRefMutator,
|
|
5
|
+
RuntimeMiddleware,
|
|
6
|
+
RuntimeMiddlewareContext,
|
|
7
|
+
} from './runtime-middleware';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Runs every middleware's `beforeExecute` hook in registration order,
|
|
11
|
+
* threading through the (optional) family-specific `paramsMutator`.
|
|
12
|
+
*
|
|
13
|
+
* Why this lives outside {@link runWithMiddleware}: middleware that
|
|
14
|
+
* mutates parameter values (e.g. cipherstash's bulk-encrypt SDK
|
|
15
|
+
* round-trip) must run *before* the family runtime encodes those
|
|
16
|
+
* parameters to driver wire format. Family runtimes call
|
|
17
|
+
* `runBeforeExecuteChain` between the AST → plan lowering step and
|
|
18
|
+
* the parameter encode step; the encode then observes the mutator's
|
|
19
|
+
* `currentParams()` view. `runWithMiddleware` retains the rest of
|
|
20
|
+
* the lifecycle (`intercept`, driver/row source loop, `onRow`,
|
|
21
|
+
* `afterExecute`) but no longer fires `beforeExecute` itself.
|
|
22
|
+
*
|
|
23
|
+
* Lifecycle within this helper:
|
|
24
|
+
*
|
|
25
|
+
* 1. For each middleware in registration order, if `beforeExecute`
|
|
26
|
+
* is implemented:
|
|
27
|
+
* - `checkAborted(ctx, 'beforeExecute')` short-circuits if the
|
|
28
|
+
* caller already aborted at entry.
|
|
29
|
+
* - The hook is invoked with `(plan, ctx, paramsMutator)`. A
|
|
30
|
+
* middleware body that ignores the mutator stays compatible —
|
|
31
|
+
* JavaScript allows extra positional arguments.
|
|
32
|
+
* - If the hook returns a Promise, it is raced against
|
|
33
|
+
* `ctx.signal` via {@link raceAgainstAbort} so cooperative
|
|
34
|
+
* cancellation surfaces a `RUNTIME.ABORTED { phase:
|
|
35
|
+
* 'beforeExecute' }` envelope even when the body itself
|
|
36
|
+
* ignores the signal.
|
|
37
|
+
*
|
|
38
|
+
* Error propagation: any error thrown by a `beforeExecute` body
|
|
39
|
+
* (or surfaced by the abort race) propagates out of this helper
|
|
40
|
+
* unchanged. The family runtime is responsible for converting it
|
|
41
|
+
* into the appropriate `afterExecute(completed: false)` notification
|
|
42
|
+
* once `runWithMiddleware` runs.
|
|
43
|
+
*
|
|
44
|
+
* Relationship to {@link runWithMiddleware}: the framework's
|
|
45
|
+
* `RuntimeCore.execute` template calls this helper between
|
|
46
|
+
* `lower(plan)` and `runWithMiddleware(...)`. Family runtimes that
|
|
47
|
+
* override `execute` (e.g. SQL, which inlines lower + encode for
|
|
48
|
+
* direct mutator threading) call this helper themselves at the
|
|
49
|
+
* equivalent point — between the family's AST → draft-plan
|
|
50
|
+
* lowering and the parameter-encode step.
|
|
51
|
+
*
|
|
52
|
+
* Intercept ordering: this helper fires unconditionally before
|
|
53
|
+
* `runWithMiddleware`. `intercept` (inside `runWithMiddleware`)
|
|
54
|
+
* therefore observes the post-`beforeExecute` plan — mutator
|
|
55
|
+
* mutations are visible in the params interceptors see. The
|
|
56
|
+
* trade-off is documented on `RuntimeMiddleware.intercept`.
|
|
57
|
+
*/
|
|
58
|
+
export async function runBeforeExecuteChain<
|
|
59
|
+
TExec extends ExecutionPlan,
|
|
60
|
+
TMutator extends ParamRefMutator = ParamRefMutator,
|
|
61
|
+
>(
|
|
62
|
+
plan: TExec,
|
|
63
|
+
middleware: ReadonlyArray<RuntimeMiddleware<TExec, TMutator>>,
|
|
64
|
+
ctx: RuntimeMiddlewareContext,
|
|
65
|
+
paramsMutator?: TMutator,
|
|
66
|
+
): Promise<void> {
|
|
67
|
+
for (const mw of middleware) {
|
|
68
|
+
if (!mw.beforeExecute) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
checkAborted(ctx, 'beforeExecute');
|
|
72
|
+
const work = mw.beforeExecute(plan, ctx, paramsMutator as TMutator);
|
|
73
|
+
if (work !== undefined) {
|
|
74
|
+
await raceAgainstAbort(Promise.resolve(work), ctx.signal, 'beforeExecute');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import { AsyncIterableResult } from './async-iterable-result';
|
|
2
2
|
import type { ExecutionPlan } from './query-plan';
|
|
3
|
-
import {
|
|
4
|
-
import type {
|
|
5
|
-
ParamRefMutator,
|
|
6
|
-
RuntimeMiddleware,
|
|
7
|
-
RuntimeMiddlewareContext,
|
|
8
|
-
} from './runtime-middleware';
|
|
3
|
+
import type { RuntimeMiddleware, RuntimeMiddlewareContext } from './runtime-middleware';
|
|
9
4
|
|
|
10
5
|
/**
|
|
11
|
-
* Drives a single execution of `runDriver()` through the middleware
|
|
6
|
+
* Drives a single execution of `runDriver()` through the middleware
|
|
7
|
+
* lifecycle's intercept + row-source + termination phases.
|
|
12
8
|
*
|
|
13
9
|
* Lifecycle, in order:
|
|
14
10
|
* 1. For each middleware in registration order: `intercept(exec, ctx)`. The
|
|
@@ -18,40 +14,42 @@ import type {
|
|
|
18
14
|
* the intercepted rows, and proceeds with `source: 'middleware'`. On
|
|
19
15
|
* all-passthrough (every `intercept` returns `undefined` or is omitted),
|
|
20
16
|
* `source: 'driver'` is used and the row source is `runDriver()`.
|
|
21
|
-
* 2.
|
|
22
|
-
* `beforeExecute(exec, ctx)`. Skipped on the intercepted hit path —
|
|
23
|
-
* `beforeExecute` semantically means "about to hit the driver".
|
|
24
|
-
* 3. Iterate the row source. On the driver path, for each row, for each
|
|
17
|
+
* 2. Iterate the row source. On the driver path, for each row, for each
|
|
25
18
|
* middleware in registration order: `onRow(row, exec, ctx)`; then yield
|
|
26
19
|
* the row. On the intercepted hit path, `onRow` is skipped — intercepted
|
|
27
20
|
* rows did not originate from a driver row stream — but rows are still
|
|
28
21
|
* yielded to the consumer in order.
|
|
29
|
-
*
|
|
22
|
+
* 3. On successful completion: for each middleware in registration order:
|
|
30
23
|
* `afterExecute(exec, { rowCount, latencyMs, completed: true, source },
|
|
31
24
|
* ctx)`.
|
|
32
|
-
*
|
|
25
|
+
* 4. On any error thrown during steps 1–2: for each middleware in
|
|
33
26
|
* registration order: `afterExecute(exec, { rowCount, latencyMs,
|
|
34
27
|
* completed: false, source }, ctx)`. Errors thrown by `afterExecute`
|
|
35
28
|
* during the error path are swallowed so they do not mask the original
|
|
36
29
|
* error. The original error is then rethrown.
|
|
37
30
|
*
|
|
31
|
+
* `beforeExecute` is **not** fired here — see
|
|
32
|
+
* {@link runBeforeExecuteChain} in `before-execute-chain.ts`. Family
|
|
33
|
+
* runtimes call that helper between the AST → plan lowering step and
|
|
34
|
+
* the parameter encode step so middleware that mutates ParamRef
|
|
35
|
+
* values (e.g. cipherstash bulk-encrypt) can have its mutations
|
|
36
|
+
* visible to encode. `runWithMiddleware` operates on the fully-
|
|
37
|
+
* encoded plan; interceptors therefore observe a fully-mutated,
|
|
38
|
+
* encoded plan.
|
|
39
|
+
*
|
|
38
40
|
* The `source` field on `AfterExecuteResult` lets observers (telemetry,
|
|
39
41
|
* lints, budgets) distinguish driver-served from middleware-served
|
|
40
42
|
* executions without needing their own out-of-band signal.
|
|
41
43
|
*
|
|
42
|
-
* This helper is the single canonical implementation of the
|
|
43
|
-
*
|
|
44
|
+
* This helper is the single canonical implementation of the
|
|
45
|
+
* intercept-and-row-source loop; family runtimes should not
|
|
46
|
+
* reimplement it.
|
|
44
47
|
*/
|
|
45
|
-
export function runWithMiddleware<
|
|
46
|
-
TExec extends ExecutionPlan,
|
|
47
|
-
Row,
|
|
48
|
-
TMutator extends ParamRefMutator = ParamRefMutator,
|
|
49
|
-
>(
|
|
48
|
+
export function runWithMiddleware<TExec extends ExecutionPlan, Row>(
|
|
50
49
|
exec: TExec,
|
|
51
|
-
middleware: ReadonlyArray<RuntimeMiddleware<TExec
|
|
50
|
+
middleware: ReadonlyArray<RuntimeMiddleware<TExec>>,
|
|
52
51
|
ctx: RuntimeMiddlewareContext,
|
|
53
52
|
runDriver: () => AsyncIterable<Row>,
|
|
54
|
-
paramsMutator?: TMutator,
|
|
55
53
|
): AsyncIterableResult<Row> {
|
|
56
54
|
const iterator = async function* (): AsyncGenerator<Row, void, unknown> {
|
|
57
55
|
const startedAt = Date.now();
|
|
@@ -91,22 +89,6 @@ export function runWithMiddleware<
|
|
|
91
89
|
}
|
|
92
90
|
|
|
93
91
|
if (source === 'driver') {
|
|
94
|
-
for (const mw of middleware) {
|
|
95
|
-
if (mw.beforeExecute) {
|
|
96
|
-
checkAborted(ctx, 'beforeExecute');
|
|
97
|
-
// The framework only forwards the mutator the caller supplied; a
|
|
98
|
-
// pass-through `undefined` for non-mutating families is safe — the
|
|
99
|
-
// base `RuntimeMiddleware` declares the third parameter, and
|
|
100
|
-
// existing `(plan, ctx)` bodies that ignore it stay unchanged.
|
|
101
|
-
// The cast below is the single point at which the framework's
|
|
102
|
-
// generic mutator slot meets the (possibly absent) caller value;
|
|
103
|
-
// `runWithMiddleware` cannot synthesize a TMutator instance.
|
|
104
|
-
const work = mw.beforeExecute(exec, ctx, paramsMutator as TMutator);
|
|
105
|
-
if (work !== undefined) {
|
|
106
|
-
await raceAgainstAbort(Promise.resolve(work), ctx.signal, 'beforeExecute');
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
92
|
rowSource = runDriver();
|
|
111
93
|
}
|
|
112
94
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CodecCallContext } from '../shared/codec-types';
|
|
2
2
|
import { AsyncIterableResult } from './async-iterable-result';
|
|
3
|
+
import { runBeforeExecuteChain } from './before-execute-chain';
|
|
3
4
|
import type { ExecutionPlan, QueryPlan } from './query-plan';
|
|
4
5
|
import { checkAborted } from './race-against-abort';
|
|
5
6
|
import { runWithMiddleware } from './run-with-middleware';
|
|
@@ -31,9 +32,16 @@ export interface RuntimeCoreOptions<TMiddleware extends RuntimeMiddleware<Execut
|
|
|
31
32
|
* this to run its `beforeCompile` middleware-hook chain.
|
|
32
33
|
* 2. `lower(plan)` — abstract. Each family produces its `*ExecutionPlan`
|
|
33
34
|
* (SQL via `lowerSqlPlan`, Mongo via `adapter.lower`).
|
|
34
|
-
* 3. `
|
|
35
|
-
*
|
|
36
|
-
*
|
|
35
|
+
* 3. `runBeforeExecuteChain(exec, this.middleware, this.ctx)` — concrete;
|
|
36
|
+
* runs every middleware's `beforeExecute` hook after lowering but
|
|
37
|
+
* before the row source is opened. Family runtimes that need a
|
|
38
|
+
* params mutator visible to a downstream encode step (SQL) override
|
|
39
|
+
* `execute` and call this helper themselves at the equivalent
|
|
40
|
+
* pre-encode point.
|
|
41
|
+
* 4. `runWithMiddleware(exec, this.middleware, this.ctx,
|
|
42
|
+
* () => runDriver(exec))` — concrete; runs the intercept chain,
|
|
43
|
+
* drives the row source, fires `onRow` / `afterExecute`. Does
|
|
44
|
+
* **not** fire `beforeExecute` — see step 3.
|
|
37
45
|
*
|
|
38
46
|
* Concrete subclasses must implement `lower`, `runDriver`, and `close`.
|
|
39
47
|
*
|
|
@@ -118,6 +126,11 @@ export abstract class RuntimeCore<
|
|
|
118
126
|
|
|
119
127
|
const compiled = await self.runBeforeCompile(plan);
|
|
120
128
|
const exec = await self.lower(compiled, codecCtx);
|
|
129
|
+
// Fire the framework-level `beforeExecute` chain on the lowered
|
|
130
|
+
// plan before opening the row source. Families that need
|
|
131
|
+
// pre-encode mutator visibility (SQL) override `execute` to
|
|
132
|
+
// inject the same chain at the equivalent point.
|
|
133
|
+
await runBeforeExecuteChain<TExec>(exec, self.middleware, self.ctx);
|
|
121
134
|
// The driver yields raw `Record<string, unknown>`; we cast to `Row` here.
|
|
122
135
|
// The Row contract is enforced by the caller via `plan._row`.
|
|
123
136
|
yield* runWithMiddleware<TExec, Row>(
|
|
@@ -162,6 +162,32 @@ export interface RuntimeMiddleware<
|
|
|
162
162
|
* rows directly: caching, mocks, rate limiting, circuit breaking.
|
|
163
163
|
*/
|
|
164
164
|
intercept?(plan: TPlan, ctx: RuntimeMiddlewareContext): Promise<InterceptResult | undefined>;
|
|
165
|
+
/**
|
|
166
|
+
* Fires after the family runtime has produced a draft execution
|
|
167
|
+
* plan from the AST, but before the family encodes parameter values
|
|
168
|
+
* to driver wire format. Mutations applied via the
|
|
169
|
+
* family-specific `params` mutator are visible to the subsequent
|
|
170
|
+
* encode step.
|
|
171
|
+
*
|
|
172
|
+
* Lifecycle position (SQL example):
|
|
173
|
+
* `runBeforeCompile → lowerSqlPlan → beforeExecute → encodeParams → intercept → driver`.
|
|
174
|
+
*
|
|
175
|
+
* The `params` argument is a family-specific {@link ParamRefMutator}
|
|
176
|
+
* scoped to the value slots of `ParamRef` nodes in the plan's AST.
|
|
177
|
+
* Middleware that doesn't need to mutate params can ignore the
|
|
178
|
+
* argument; existing `(plan)` / `(plan, ctx)` bodies stay compatible.
|
|
179
|
+
*
|
|
180
|
+
* `ctx.signal` carries the per-query `AbortSignal`; middleware that
|
|
181
|
+
* wraps a network SDK forwards it. Cooperative cancellation
|
|
182
|
+
* surfaces a `RUNTIME.ABORTED { phase: 'beforeExecute' }` envelope
|
|
183
|
+
* promptly even when the body ignores the signal.
|
|
184
|
+
*
|
|
185
|
+
* Intercept ordering: `intercept` runs *after* this hook; an
|
|
186
|
+
* interceptor that short-circuits the driver path still observes
|
|
187
|
+
* the post-`beforeExecute`, fully-encoded plan. The trade-off is
|
|
188
|
+
* that any `beforeExecute` SDK round-trips happen even when a
|
|
189
|
+
* downstream interceptor would have skipped the driver entirely.
|
|
190
|
+
*/
|
|
165
191
|
beforeExecute?(
|
|
166
192
|
plan: TPlan,
|
|
167
193
|
ctx: RuntimeMiddlewareContext,
|
package/src/exports/runtime.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { AsyncIterableResult } from '../execution/async-iterable-result';
|
|
2
|
+
export { runBeforeExecuteChain } from '../execution/before-execute-chain';
|
|
2
3
|
export type { ExecutionPlan, QueryPlan, ResultType } from '../execution/query-plan';
|
|
3
4
|
export { checkAborted, raceAgainstAbort } from '../execution/race-against-abort';
|
|
4
5
|
export { runWithMiddleware } from '../execution/run-with-middleware';
|