@prisma-next/sql-runtime 0.5.0-dev.8 → 0.5.0-dev.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -22
- package/dist/exports-C0exnDCV.mjs +1514 -0
- package/dist/exports-C0exnDCV.mjs.map +1 -0
- package/dist/{index-yb51L_1h.d.mts → index-CFbuVnYJ.d.mts} +130 -45
- package/dist/index-CFbuVnYJ.d.mts.map +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -3
- package/dist/test/utils.d.mts +38 -33
- package/dist/test/utils.d.mts.map +1 -1
- package/dist/test/utils.mjs +107 -61
- package/dist/test/utils.mjs.map +1 -1
- package/package.json +17 -17
- package/src/codecs/alias-resolver.ts +37 -0
- package/src/codecs/decoding.ts +168 -130
- package/src/codecs/encoding.ts +123 -47
- package/src/codecs/validation.ts +4 -4
- package/src/content-hash.ts +44 -0
- package/src/exports/index.ts +13 -7
- package/src/fingerprint.ts +22 -0
- package/src/guardrails/raw.ts +165 -0
- package/src/lower-sql-plan.ts +3 -3
- package/src/marker.ts +75 -0
- package/src/middleware/before-compile-chain.ts +1 -31
- package/src/middleware/budgets.ts +36 -120
- package/src/middleware/lints.ts +20 -26
- package/src/middleware/sql-middleware.ts +25 -5
- package/src/runtime-spi.ts +44 -0
- package/src/sql-context.ts +315 -105
- package/src/sql-family-adapter.ts +3 -2
- package/src/sql-marker.ts +89 -51
- package/src/sql-runtime.ts +325 -146
- package/dist/exports-Cssiepsb.mjs +0 -1068
- package/dist/exports-Cssiepsb.mjs.map +0 -1
- package/dist/index-yb51L_1h.d.mts.map +0 -1
- package/src/codecs/json-schema-validation.ts +0 -61
package/src/middleware/lints.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type { ExecutionPlan } from '@prisma-next/contract/types';
|
|
2
1
|
import { runtimeError } from '@prisma-next/framework-components/runtime';
|
|
3
|
-
import { evaluateRawGuardrails } from '@prisma-next/runtime-executor';
|
|
4
2
|
import {
|
|
5
3
|
type AnyFromSource,
|
|
6
4
|
type AnyQueryAst,
|
|
7
5
|
isQueryAst,
|
|
8
6
|
} from '@prisma-next/sql-relational-core/ast';
|
|
7
|
+
import type { SqlExecutionPlan } from '@prisma-next/sql-relational-core/plan';
|
|
9
8
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
9
|
+
import { evaluateRawGuardrails } from '../guardrails/raw';
|
|
10
10
|
import type { SqlMiddleware, SqlMiddlewareContext } from './sql-middleware';
|
|
11
11
|
|
|
12
12
|
export interface LintsOptions {
|
|
@@ -94,6 +94,12 @@ function evaluateAstLints(ast: AnyQueryAst): LintFinding[] {
|
|
|
94
94
|
case 'insert':
|
|
95
95
|
break;
|
|
96
96
|
|
|
97
|
+
case 'raw-sql':
|
|
98
|
+
// Raw-SQL ASTs opt out of structural lints (LIMIT / WHERE etc.) —
|
|
99
|
+
// the embedded SQL fragments are caller-authored and the lint's
|
|
100
|
+
// shape-based heuristics don't apply.
|
|
101
|
+
break;
|
|
102
|
+
|
|
97
103
|
// v8 ignore next 2
|
|
98
104
|
default:
|
|
99
105
|
throw new Error(`Unsupported AST kind: ${(ast satisfies never as { kind: string }).kind}`);
|
|
@@ -145,34 +151,22 @@ export function lints(options?: LintsOptions): SqlMiddleware {
|
|
|
145
151
|
name: 'lints',
|
|
146
152
|
familyId: 'sql' as const,
|
|
147
153
|
|
|
148
|
-
async beforeExecute(plan:
|
|
154
|
+
async beforeExecute(plan: SqlExecutionPlan, ctx: SqlMiddlewareContext) {
|
|
155
|
+
const findings: LintFinding[] = [];
|
|
149
156
|
if (isQueryAst(plan.ast)) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
throw runtimeError(lint.code, lint.message, lint.details);
|
|
158
|
-
}
|
|
159
|
-
if (effectiveSeverity === 'warn') {
|
|
160
|
-
ctx.log.warn({
|
|
161
|
-
code: lint.code,
|
|
162
|
-
message: lint.message,
|
|
163
|
-
details: lint.details,
|
|
164
|
-
});
|
|
165
|
-
}
|
|
157
|
+
findings.push(...evaluateAstLints(plan.ast));
|
|
158
|
+
// Raw-SQL ASTs opt out of structural AST lints (no LIMIT /
|
|
159
|
+
// WHERE shape to inspect) but the embedded SQL text still
|
|
160
|
+
// wants the raw-heuristic guardrails. Without this the lint
|
|
161
|
+
// middleware would silently disable both for raw plans.
|
|
162
|
+
if (plan.ast.kind === 'raw-sql') {
|
|
163
|
+
findings.push(...evaluateRawGuardrails(plan).lints);
|
|
166
164
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
if (fallback === 'skip') {
|
|
171
|
-
return;
|
|
165
|
+
} else if (fallback !== 'skip') {
|
|
166
|
+
findings.push(...evaluateRawGuardrails(plan).lints);
|
|
172
167
|
}
|
|
173
168
|
|
|
174
|
-
const
|
|
175
|
-
for (const lint of evaluation.lints) {
|
|
169
|
+
for (const lint of findings) {
|
|
176
170
|
const configuredSeverity = getConfiguredSeverity(lint.code, options);
|
|
177
171
|
const effectiveSeverity = configuredSeverity ?? lint.severity;
|
|
178
172
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Contract,
|
|
1
|
+
import type { Contract, PlanMeta } from '@prisma-next/contract/types';
|
|
2
2
|
import type {
|
|
3
3
|
AfterExecuteResult,
|
|
4
4
|
RuntimeMiddleware,
|
|
@@ -6,6 +6,8 @@ import type {
|
|
|
6
6
|
} from '@prisma-next/framework-components/runtime';
|
|
7
7
|
import type { SqlStorage } from '@prisma-next/sql-contract/types';
|
|
8
8
|
import type { AnyQueryAst } from '@prisma-next/sql-relational-core/ast';
|
|
9
|
+
import type { SqlParamRefMutator } from '@prisma-next/sql-relational-core/middleware';
|
|
10
|
+
import type { SqlExecutionPlan } from '@prisma-next/sql-relational-core/plan';
|
|
9
11
|
|
|
10
12
|
export interface SqlMiddlewareContext extends RuntimeMiddlewareContext {
|
|
11
13
|
readonly contract: Contract<SqlStorage>;
|
|
@@ -20,7 +22,8 @@ export interface DraftPlan {
|
|
|
20
22
|
readonly meta: PlanMeta;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
|
-
export interface SqlMiddleware extends
|
|
25
|
+
export interface SqlMiddleware<TCodecMap extends Record<string, unknown> = Record<string, unknown>>
|
|
26
|
+
extends RuntimeMiddleware<SqlExecutionPlan, SqlParamRefMutator<TCodecMap>> {
|
|
24
27
|
readonly familyId?: 'sql';
|
|
25
28
|
/**
|
|
26
29
|
* Rewrite the query AST before it is lowered to SQL. Middlewares run in
|
|
@@ -41,14 +44,31 @@ export interface SqlMiddleware extends RuntimeMiddleware {
|
|
|
41
44
|
* See `docs/architecture docs/subsystems/4. Runtime & Middleware Framework.md`.
|
|
42
45
|
*/
|
|
43
46
|
beforeCompile?(draft: DraftPlan, ctx: SqlMiddlewareContext): Promise<DraftPlan | undefined>;
|
|
44
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Mutate `ParamRef.value` slots before encode runs. The third `params`
|
|
49
|
+
* argument is a {@link SqlParamRefMutator} scoped to value slots only —
|
|
50
|
+
* SQL strings, projections, and `ParamRef` membership are not mutable.
|
|
51
|
+
* Existing `(plan)` and `(plan, ctx)` middleware bodies that ignore the
|
|
52
|
+
* additional argument continue to compile and run unchanged.
|
|
53
|
+
*
|
|
54
|
+
* `ctx.signal` carries the per-query `AbortSignal` (ADR 207); middleware
|
|
55
|
+
* that wraps a network SDK forwards `ctx.signal` to that SDK.
|
|
56
|
+
* Cooperative cancellation: a body that ignores the signal still
|
|
57
|
+
* surfaces `RUNTIME.ABORTED { phase: 'beforeExecute' }` promptly via
|
|
58
|
+
* the runtime's race against the signal.
|
|
59
|
+
*/
|
|
60
|
+
beforeExecute?(
|
|
61
|
+
plan: SqlExecutionPlan,
|
|
62
|
+
ctx: SqlMiddlewareContext,
|
|
63
|
+
params?: SqlParamRefMutator<TCodecMap>,
|
|
64
|
+
): void | Promise<void>;
|
|
45
65
|
onRow?(
|
|
46
66
|
row: Record<string, unknown>,
|
|
47
|
-
plan:
|
|
67
|
+
plan: SqlExecutionPlan,
|
|
48
68
|
ctx: SqlMiddlewareContext,
|
|
49
69
|
): Promise<void>;
|
|
50
70
|
afterExecute?(
|
|
51
|
-
plan:
|
|
71
|
+
plan: SqlExecutionPlan,
|
|
52
72
|
result: AfterExecuteResult,
|
|
53
73
|
ctx: SqlMiddlewareContext,
|
|
54
74
|
): Promise<void>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ContractMarkerRecord } from '@prisma-next/contract/types';
|
|
2
|
+
import type { ExecutionPlan } from '@prisma-next/framework-components/runtime';
|
|
3
|
+
import type { MarkerStatement } from '@prisma-next/sql-relational-core/ast';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Reader of the SQL contract marker. SQL runtimes verify the database's
|
|
7
|
+
* `prisma_contract.marker` row against the runtime's contract by issuing
|
|
8
|
+
* this statement before executing user queries (when `verify` is enabled).
|
|
9
|
+
* Each adapter is responsible for any target-specific row decoding before
|
|
10
|
+
* delegating to the shared row schema.
|
|
11
|
+
*/
|
|
12
|
+
export interface MarkerReader {
|
|
13
|
+
readMarkerStatement(): MarkerStatement;
|
|
14
|
+
parseMarkerRow(row: unknown): ContractMarkerRecord;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* SQL family adapter SPI consumed by `SqlRuntime`. Encapsulates the
|
|
19
|
+
* runtime contract, marker reader, and plan validation logic so the
|
|
20
|
+
* runtime can be unit-tested without a concrete SQL adapter profile.
|
|
21
|
+
*
|
|
22
|
+
* Implemented by `SqlFamilyAdapter` for production and by mock classes
|
|
23
|
+
* in tests.
|
|
24
|
+
*/
|
|
25
|
+
export interface RuntimeFamilyAdapter<TContract = unknown> {
|
|
26
|
+
readonly contract: TContract;
|
|
27
|
+
readonly markerReader: MarkerReader;
|
|
28
|
+
validatePlan(plan: ExecutionPlan, contract: TContract): void;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface RuntimeVerifyOptions {
|
|
32
|
+
readonly mode: 'onFirstUse' | 'startup' | 'always';
|
|
33
|
+
readonly requireMarker: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type TelemetryOutcome = 'success' | 'runtime-error';
|
|
37
|
+
|
|
38
|
+
export interface RuntimeTelemetryEvent {
|
|
39
|
+
readonly lane: string;
|
|
40
|
+
readonly target: string;
|
|
41
|
+
readonly fingerprint: string;
|
|
42
|
+
readonly outcome: TelemetryOutcome;
|
|
43
|
+
readonly durationMs?: number;
|
|
44
|
+
}
|