@prisma-next/runtime-executor 0.4.0-dev.9 → 0.5.0-dev.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/index.d.mts CHANGED
@@ -90,7 +90,28 @@ interface RuntimeCore<TContract = unknown, TDriver = unknown> extends RuntimeQue
90
90
  }
91
91
  interface RuntimeConnection extends RuntimeQueryable {
92
92
  transaction(): Promise<RuntimeTransaction>;
93
+ /**
94
+ * Returns the connection to the pool for reuse. Only call this when the
95
+ * connection is known to be in a clean state. If a transaction
96
+ * commit/rollback failed or the connection is otherwise suspect, call
97
+ * `destroy(reason)` instead.
98
+ */
93
99
  release(): Promise<void>;
100
+ /**
101
+ * Evicts the connection so it is never reused. Call this when the
102
+ * connection may be in an indeterminate state (e.g. a failed rollback
103
+ * leaving an open transaction, or a broken socket).
104
+ *
105
+ * If teardown fails the error is propagated and the connection remains
106
+ * retryable, so the caller can decide whether to swallow the failure or
107
+ * retry cleanup. Calling destroy() or release() more than once after a
108
+ * successful teardown is caller error.
109
+ *
110
+ * `reason` is advisory context only. It may be surfaced to driver-level
111
+ * observability hooks (e.g. pg-pool's `'release'` event) but does not
112
+ * influence eviction behavior and is not rethrown.
113
+ */
114
+ destroy(reason?: unknown): Promise<void>;
94
115
  }
95
116
  interface RuntimeTransaction extends RuntimeQueryable {
96
117
  commit(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/fingerprint.ts","../src/guardrails/raw.ts","../src/marker.ts","../src/middleware/types.ts","../src/runtime-spi.ts","../src/runtime-core.ts"],"sourcesContent":[],"mappings":";;;;iBAMgB,qBAAA;;;KCJJ,YAAA;KACA,cAAA;UAEK,WAAA;EDCD,SAAA,IAAA,EAAA,QAAA,MAAqB,EAAA;qBCChB;;qBAEA;AAPrB;AACY,UASK,aAAA,CATS;EAET,SAAA,IAAA,EAAW,UAEP,MAAA,EAAA;EAKJ,SAAA,QAAa,EAET,cAAA;EAKJ,SAAA,OAAA,EAAA,MAAkB;EAOlB,SAAA,OAAA,CAAA,EAVI,MAUc,CAAA,MACjB,EAAA,OAAA,CAAA;AAWlB;AACQ,UApBS,kBAAA,CAoBT;EACG,SAAA,OAAA,CAAA,EAAA;IACR,SAAA,uBAAA,CAAA,EApBoC,cAoBpC;IAAkB,SAAA,aAAA,CAAA,EAAA,MAAA;;;UAfJ,kBAAA;ECuBD,SAAA,KAAA,EDtBE,WCsBoB,EAAA;oBDrBlB;;;AEpBR,iBF8BI,qBAAA,CE9BI,IAAA,EF+BZ,aE/BY,EAAA,MAAA,CAAA,EFgCT,kBEhCS,CAAA,EFiCjB,kBEjCiB;;;AFHH,iBC4CD,sBAAA,CDxCK,GAAM,EAAA,OAAA,CAAA,ECwC2B,oBDxC3B;;;KEDf,QAAA;AHFI,UGMC,iBHNoB,CAAA,YAAA,OAAA,CAAA,SGM2B,wBHN3B,CAAA;qBGOhB;;UAGJ,wCAAwC;EFd7C,aAAA,EAAY,IAAA,EEeD,aFfC,EAAA,GAAA,EEemB,iBFfnB,CEeqC,SFfrC,CAAA,CAAA,EEekD,OFflD,CAAA,IAAA,CAAA;EACZ,KAAA,EAAA,GAAA,EEgBH,MFhBiB,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,IAAA,EEiBhB,aFjBgB,EAAA,GAAA,EEkBjB,iBFlBiB,CEkBC,SFlBD,CAAA,CAAA,EEmBrB,OFnBqB,CAAA,IAAA,CAAA;EAET,YAAA,EAAW,IAAA,EEmBlB,aFjBW,EAAA,MAEA,EEgBT,kBFhBe,EAAA,GAAA,EEiBlB,iBFjBkB,CEiBA,SFjBA,CAAA,CAAA,EEkBtB,OFlBsB,CAAA,IAAA,CAAA;AAG3B;;;UGViB,eAAA;;;AJIjB;UICiB,YAAA;yBACQ;;AHNb,UGSK,oBHTO,CAAA,YAAA,OAAA,CAAA,CAAA;EACZ,SAAA,QAAc,EGSL,SHTK;EAET,SAAA,YAAW,EGQH,YHNJ;EAKJ,YAAA,CAAA,IAAa,EGET,aHAA,EAAA,QAAA,EGAyB,SHEnB,CAAA,EAAA,IAAA;AAG3B;;;UIXiB,oBAAA;;;AJNjB;AACY,KIUA,gBAAA,GJVc,SAAA,GAAA,eAAA;AAET,UIUA,qBAAA,CJRI;EAKJ,SAAA,IAAA,EAAA,MAAa;EAOb,SAAA,MAAA,EAAA,MAAkB;EAOlB,SAAA,WAAA,EAAkB,MAAA;EAYnB,SAAA,OAAA,EInBI,gBJmBiB;EAC7B,SAAA,UAAA,CAAA,EAAA,MAAA;;AAEL,UIlBc,kBJkBd,CAAA,YAAA,OAAA,EAAA,UAAA,OAAA,CAAA,CAAA;EAAkB,SAAA,aAAA,EIjBK,oBJiBL,CIjB0B,SJiB1B,CAAA;mBIhBF;mBACA;iCACc,WAAW;EHsB5B,SAAA,IAAA,CAAA,EAAA,QAAA,GAAsB,YAAgB;iBGpBrC;;UAGA,4DACP,kBACN,gBAAgB;EF1BR,SAAA,aAAQ,CAAA,EE2BO,SF3BP;EAIH,SAAA,WAAiB,CAAA,EEwBT,OFxBS;EAIjB,UAAA,EAAA,EEqBD,OFrBW,CEqBH,iBFrBG,CAAA;EACJ,SAAA,EAAA,EEqBR,qBFrBQ,GAAA,IAAA;EAAsC,KAAA,EAAA,EEsBlD,OFtBkD,CAAA,IAAA,CAAA;;AAAa,UEyBzD,iBAAA,SAA0B,gBFzB+B,CAAA;EAEjE,WAAA,EAAA,EEwBQ,OFxBR,CEwBgB,kBFxBhB,CAAA;EACC,OAAA,EAAA,EEwBG,OFxBH,CAAA,IAAA,CAAA;;AACD,UE0BQ,kBAAA,SAA2B,gBF1BnC,CAAA;EACJ,MAAA,EAAA,EE0BO,OF1BP,CAAA,IAAA,CAAA;EAEK,QAAA,EAAA,EEyBI,OFzBJ,CAAA,IAAA,CAAA;;;;;;;;;;ACtBV;AAKA;AAIA;AACqB,UCmDJ,gBAAA,CDnDI;EACI,OAAA,CAAA,GAAA,CAAA,CAAA,IAAA,ECmDJ,aDnDI,GAAA;IACJ,SAAA,IAAA,CAAA,ECkDkC,GDlDlC;EAAyB,CAAA,CAAA,ECkDiB,qBDlDjB,CCkDqC,GDlDrC,CAAA;;ACe1B,iBA+TJ,iBA/TI,CAAA,YAAA,OAAA,EAAA,UAAA,OAAA,CAAA,CAAA,OAAA,EAgUT,kBAhUS,CAgUU,SAhUV,EAgUqB,OAhUrB,CAAA,CAAA,EAiUjB,WAjUiB,CAiUL,SAjUK,EAiUM,OAjUN,CAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/fingerprint.ts","../src/guardrails/raw.ts","../src/marker.ts","../src/middleware/types.ts","../src/runtime-spi.ts","../src/runtime-core.ts"],"sourcesContent":[],"mappings":";;;;iBAMgB,qBAAA;;;KCJJ,YAAA;KACA,cAAA;UAEK,WAAA;EDCD,SAAA,IAAA,EAAA,QAAA,MAAqB,EAAA;qBCChB;;qBAEA;AAPrB;AACY,UASK,aAAA,CATS;EAET,SAAA,IAAA,EAAW,UAEP,MAAA,EAAA;EAKJ,SAAA,QAAa,EAET,cAAA;EAKJ,SAAA,OAAA,EAAA,MAAkB;EAOlB,SAAA,OAAA,CAAA,EAVI,MAUc,CAAA,MACjB,EAAA,OAAA,CAAA;AAWlB;AACQ,UApBS,kBAAA,CAoBT;EACG,SAAA,OAAA,CAAA,EAAA;IACR,SAAA,uBAAA,CAAA,EApBoC,cAoBpC;IAAkB,SAAA,aAAA,CAAA,EAAA,MAAA;;;UAfJ,kBAAA;ECuBD,SAAA,KAAA,EDtBE,WCsBoB,EAAA;oBDrBlB;;;AEpBR,iBF8BI,qBAAA,CE9BI,IAAA,EF+BZ,aE/BY,EAAA,MAAA,CAAA,EFgCT,kBEhCS,CAAA,EFiCjB,kBEjCiB;;;AFHH,iBC4CD,sBAAA,CDxCK,GAAM,EAAA,OAAA,CAAA,ECwC2B,oBDxC3B;;;KEDf,QAAA;AHFI,UGMC,iBHNoB,CAAA,YAAA,OAAA,CAAA,SGM2B,wBHN3B,CAAA;qBGOhB;;UAGJ,wCAAwC;EFd7C,aAAA,EAAY,IAAA,EEeD,aFfC,EAAA,GAAA,EEemB,iBFfnB,CEeqC,SFfrC,CAAA,CAAA,EEekD,OFflD,CAAA,IAAA,CAAA;EACZ,KAAA,EAAA,GAAA,EEgBH,MFhBiB,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,IAAA,EEiBhB,aFjBgB,EAAA,GAAA,EEkBjB,iBFlBiB,CEkBC,SFlBD,CAAA,CAAA,EEmBrB,OFnBqB,CAAA,IAAA,CAAA;EAET,YAAA,EAAW,IAAA,EEmBlB,aFjBW,EAAA,MAEA,EEgBT,kBFhBe,EAAA,GAAA,EEiBlB,iBFjBkB,CEiBA,SFjBA,CAAA,CAAA,EEkBtB,OFlBsB,CAAA,IAAA,CAAA;AAG3B;;;UGViB,eAAA;;;AJIjB;UICiB,YAAA;yBACQ;;AHNb,UGSK,oBHTO,CAAA,YAAA,OAAA,CAAA,CAAA;EACZ,SAAA,QAAc,EGSL,SHTK;EAET,SAAA,YAAW,EGQH,YHNJ;EAKJ,YAAA,CAAA,IAAa,EGET,aHAA,EAAA,QAAA,EGAyB,SHEnB,CAAA,EAAA,IAAA;AAG3B;;;UIXiB,oBAAA;;;AJNjB;AACY,KIUA,gBAAA,GJVc,SAAA,GAAA,eAAA;AAET,UIUA,qBAAA,CJRI;EAKJ,SAAA,IAAA,EAAA,MAAa;EAOb,SAAA,MAAA,EAAA,MAAkB;EAOlB,SAAA,WAAA,EAAkB,MAAA;EAYnB,SAAA,OAAA,EInBI,gBJmBiB;EAC7B,SAAA,UAAA,CAAA,EAAA,MAAA;;AAEL,UIlBc,kBJkBd,CAAA,YAAA,OAAA,EAAA,UAAA,OAAA,CAAA,CAAA;EAAkB,SAAA,aAAA,EIjBK,oBJiBL,CIjB0B,SJiB1B,CAAA;mBIhBF;mBACA;iCACc,WAAW;EHsB5B,SAAA,IAAA,CAAA,EAAA,QAAA,GAAsB,YAAgB;iBGpBrC;;UAGA,4DACP,kBACN,gBAAgB;EF1BR,SAAA,aAAQ,CAAA,EE2BO,SF3BP;EAIH,SAAA,WAAiB,CAAA,EEwBT,OFxBS;EAIjB,UAAA,EAAA,EEqBD,OFrBW,CEqBH,iBFrBG,CAAA;EACJ,SAAA,EAAA,EEqBR,qBFrBQ,GAAA,IAAA;EAAsC,KAAA,EAAA,EEsBlD,OFtBkD,CAAA,IAAA,CAAA;;AAAa,UEyBzD,iBAAA,SAA0B,gBFzB+B,CAAA;EAEjE,WAAA,EAAA,EEwBQ,OFxBR,CEwBgB,kBFxBhB,CAAA;EACC;;;;;;EAMiB,OAAA,EAAA,EEwBd,OFxBc,CAAA,IAAA,CAAA;EAAlB;;;;;;;ACxBT;AAKA;AAIA;;;;;EAGuD,OAAA,CAAA,MAAA,CAAA,EAAA,OAAA,CAAA,ECmD1B,ODnD0B,CAAA,IAAA,CAAA;;UCsDtC,kBAAA,SAA2B;YAChC;EA7DK,QAAA,EAAA,EA8DH,OA9DG,CAAA,IAAoB,CAAA;AAKrC;AAEA;AAQA;;;;;;;;;AASA;AAEoB,UAkDH,gBAAA,CAlDG;EACO,OAAA,CAAA,GAAA,CAAA,CAAA,IAAA,EAkDN,aAlDM,GAAA;IACF,SAAA,IAAA,CAAA,EAiD8B,GAjD9B;EACD,CAAA,CAAA,EAgDuC,qBAhDvC,CAgD2D,GAhD3D,CAAA;;AA+BoB,iBAiT5B,iBAjT4B,CAAA,YAAA,OAAA,EAAA,UAAA,OAAA,CAAA,CAAA,OAAA,EAkTjC,kBAlTiC,CAkTd,SAlTc,EAkTH,OAlTG,CAAA,CAAA,EAmTzC,WAnTyC,CAmT7B,SAnT6B,EAmTlB,OAnTkB,CAAA"}
package/dist/index.mjs CHANGED
@@ -244,6 +244,9 @@ var RuntimeCoreImpl = class {
244
244
  },
245
245
  async release() {
246
246
  await driverConn.release();
247
+ },
248
+ async destroy(reason) {
249
+ await driverConn.destroy(reason);
247
250
  }
248
251
  };
249
252
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["lints: LintFinding[]","budgets: BudgetFinding[]","parsed: unknown","runtimeError","#executeWith","latencyMs","AsyncIterableResult"],"sources":["../src/fingerprint.ts","../src/guardrails/raw.ts","../src/marker.ts","../src/runtime-core.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\n\nconst STRING_LITERAL_REGEX = /'(?:''|[^'])*'/g;\nconst NUMERIC_LITERAL_REGEX = /\\b\\d+(?:\\.\\d+)?\\b/g;\nconst WHITESPACE_REGEX = /\\s+/g;\n\nexport function computeSqlFingerprint(sql: string): string {\n const withoutStrings = sql.replace(STRING_LITERAL_REGEX, '?');\n const withoutNumbers = withoutStrings.replace(NUMERIC_LITERAL_REGEX, '?');\n const normalized = withoutNumbers.replace(WHITESPACE_REGEX, ' ').trim().toLowerCase();\n\n const hash = createHash('sha256').update(normalized).digest('hex');\n return `sha256:${hash}`;\n}\n","import type { ExecutionPlan, PlanMeta, PlanRefs } from '@prisma-next/contract/types';\n\nexport type LintSeverity = 'error' | 'warn';\nexport type BudgetSeverity = 'error' | 'warn';\n\nexport interface LintFinding {\n readonly code: `LINT.${string}`;\n readonly severity: LintSeverity;\n readonly message: string;\n readonly details?: Record<string, unknown>;\n}\n\nexport interface BudgetFinding {\n readonly code: `BUDGET.${string}`;\n readonly severity: BudgetSeverity;\n readonly message: string;\n readonly details?: Record<string, unknown>;\n}\n\nexport interface RawGuardrailConfig {\n readonly budgets?: {\n readonly unboundedSelectSeverity?: BudgetSeverity;\n readonly estimatedRows?: number;\n };\n}\n\nexport interface RawGuardrailResult {\n readonly lints: LintFinding[];\n readonly budgets: BudgetFinding[];\n readonly statement: 'select' | 'mutation' | 'other';\n}\n\nconst SELECT_STAR_REGEX = /select\\s+\\*/i;\nconst LIMIT_REGEX = /\\blimit\\b/i;\nconst MUTATION_PREFIX_REGEX = /^(insert|update|delete|create|alter|drop|truncate)\\b/i;\n\nconst READ_ONLY_INTENTS = new Set(['read', 'report', 'readonly']);\n\nexport function evaluateRawGuardrails(\n plan: ExecutionPlan,\n config?: RawGuardrailConfig,\n): RawGuardrailResult {\n const lints: LintFinding[] = [];\n const budgets: BudgetFinding[] = [];\n\n const normalized = normalizeWhitespace(plan.sql);\n const statementType = classifyStatement(normalized);\n\n if (statementType === 'select') {\n if (SELECT_STAR_REGEX.test(normalized)) {\n lints.push(\n createLint('LINT.SELECT_STAR', 'error', 'Raw SQL plan selects all columns via *', {\n sql: snippet(plan.sql),\n }),\n );\n }\n\n if (!LIMIT_REGEX.test(normalized)) {\n const severity = config?.budgets?.unboundedSelectSeverity ?? 'error';\n lints.push(\n createLint('LINT.NO_LIMIT', 'warn', 'Raw SQL plan omits LIMIT clause', {\n sql: snippet(plan.sql),\n }),\n );\n\n budgets.push(\n createBudget(\n 'BUDGET.ROWS_EXCEEDED',\n severity,\n 'Raw SQL plan is unbounded and may exceed row budget',\n {\n sql: snippet(plan.sql),\n ...(config?.budgets?.estimatedRows !== undefined\n ? { estimatedRows: config.budgets.estimatedRows }\n : {}),\n },\n ),\n );\n }\n }\n\n if (isMutationStatement(statementType) && isReadOnlyIntent(plan.meta)) {\n lints.push(\n createLint(\n 'LINT.READ_ONLY_MUTATION',\n 'error',\n 'Raw SQL plan mutates data despite read-only intent',\n {\n sql: snippet(plan.sql),\n intent: plan.meta.annotations?.['intent'],\n },\n ),\n );\n }\n\n const refs = plan.meta.refs;\n if (refs) {\n evaluateIndexCoverage(refs, lints);\n }\n\n return { lints, budgets, statement: statementType };\n}\n\nfunction evaluateIndexCoverage(refs: PlanRefs, lints: LintFinding[]) {\n const predicateColumns = refs.columns ?? [];\n if (predicateColumns.length === 0) {\n return;\n }\n\n const indexes = refs.indexes ?? [];\n\n if (indexes.length === 0) {\n lints.push(\n createLint(\n 'LINT.UNINDEXED_PREDICATE',\n 'warn',\n 'Raw SQL plan predicates lack supporting indexes',\n {\n predicates: predicateColumns,\n },\n ),\n );\n return;\n }\n\n const hasSupportingIndex = predicateColumns.every((column) =>\n indexes.some(\n (index) =>\n index.table === column.table &&\n index.columns.some((col) => col.toLowerCase() === column.column.toLowerCase()),\n ),\n );\n\n if (!hasSupportingIndex) {\n lints.push(\n createLint(\n 'LINT.UNINDEXED_PREDICATE',\n 'warn',\n 'Raw SQL plan predicates lack supporting indexes',\n {\n predicates: predicateColumns,\n },\n ),\n );\n }\n}\n\nfunction classifyStatement(sql: string): 'select' | 'mutation' | 'other' {\n const trimmed = sql.trim();\n const lower = trimmed.toLowerCase();\n\n if (lower.startsWith('with')) {\n if (lower.includes('select')) {\n return 'select';\n }\n }\n\n if (lower.startsWith('select')) {\n return 'select';\n }\n\n if (MUTATION_PREFIX_REGEX.test(trimmed)) {\n return 'mutation';\n }\n\n return 'other';\n}\n\nfunction isMutationStatement(statement: 'select' | 'mutation' | 'other'): boolean {\n return statement === 'mutation';\n}\n\nfunction isReadOnlyIntent(meta: PlanMeta): boolean {\n const annotations = meta.annotations as { intent?: string } | undefined;\n const intent =\n typeof annotations?.intent === 'string' ? annotations.intent.toLowerCase() : undefined;\n return intent !== undefined && READ_ONLY_INTENTS.has(intent);\n}\n\nfunction normalizeWhitespace(value: string): string {\n return value.replace(/\\s+/g, ' ').trim();\n}\n\nfunction snippet(sql: string): string {\n return normalizeWhitespace(sql).slice(0, 200);\n}\n\nfunction createLint(\n code: LintFinding['code'],\n severity: LintFinding['severity'],\n message: string,\n details?: Record<string, unknown>,\n): LintFinding {\n return { code, severity, message, ...(details ? { details } : {}) };\n}\n\nfunction createBudget(\n code: BudgetFinding['code'],\n severity: BudgetFinding['severity'],\n message: string,\n details?: Record<string, unknown>,\n): BudgetFinding {\n return { code, severity, message, ...(details ? { details } : {}) };\n}\n","import type { ContractMarkerRecord } from '@prisma-next/contract/types';\nimport { type } from 'arktype';\n\nexport interface ContractMarkerRow {\n core_hash: string;\n profile_hash: string;\n contract_json: unknown | null;\n canonical_version: number | null;\n updated_at: Date;\n app_tag: string | null;\n meta: unknown | null;\n}\n\nconst MetaSchema = type({ '[string]': 'unknown' });\n\nfunction parseMeta(meta: unknown): Record<string, unknown> {\n if (meta === null || meta === undefined) {\n return {};\n }\n\n let parsed: unknown;\n if (typeof meta === 'string') {\n try {\n parsed = JSON.parse(meta);\n } catch {\n return {};\n }\n } else {\n parsed = meta;\n }\n\n const result = MetaSchema(parsed);\n if (result instanceof type.errors) {\n return {};\n }\n\n return result as Record<string, unknown>;\n}\n\nconst ContractMarkerRowSchema = type({\n core_hash: 'string',\n profile_hash: 'string',\n 'contract_json?': 'unknown | null',\n 'canonical_version?': 'number | null',\n 'updated_at?': 'Date | string',\n 'app_tag?': 'string | null',\n 'meta?': 'unknown | null',\n});\n\nexport function parseContractMarkerRow(row: unknown): ContractMarkerRecord {\n const result = ContractMarkerRowSchema(row);\n if (result instanceof type.errors) {\n const messages = result.map((p: { message: string }) => p.message).join('; ');\n throw new Error(`Invalid contract marker row: ${messages}`);\n }\n\n const validatedRow = result as {\n core_hash: string;\n profile_hash: string;\n contract_json?: unknown | null;\n canonical_version?: number | null;\n updated_at?: Date | string;\n app_tag?: string | null;\n meta?: unknown | null;\n };\n\n const updatedAt = validatedRow.updated_at\n ? validatedRow.updated_at instanceof Date\n ? validatedRow.updated_at\n : new Date(validatedRow.updated_at)\n : new Date();\n\n return {\n storageHash: validatedRow.core_hash,\n profileHash: validatedRow.profile_hash,\n contractJson: validatedRow.contract_json ?? null,\n canonicalVersion: validatedRow.canonical_version ?? null,\n updatedAt,\n appTag: validatedRow.app_tag ?? null,\n meta: parseMeta(validatedRow.meta),\n };\n}\n","import type { ExecutionPlan } from '@prisma-next/contract/types';\nimport type { RuntimeExecutor } from '@prisma-next/framework-components/runtime';\nimport { AsyncIterableResult, runtimeError } from '@prisma-next/framework-components/runtime';\nimport { computeSqlFingerprint } from './fingerprint';\nimport { parseContractMarkerRow } from './marker';\nimport type { Log, Middleware, MiddlewareContext } from './middleware/types';\nimport type { RuntimeFamilyAdapter } from './runtime-spi';\n\nexport interface RuntimeVerifyOptions {\n readonly mode: 'onFirstUse' | 'startup' | 'always';\n readonly requireMarker: boolean;\n}\n\nexport type TelemetryOutcome = 'success' | 'runtime-error';\n\nexport interface RuntimeTelemetryEvent {\n readonly lane: string;\n readonly target: string;\n readonly fingerprint: string;\n readonly outcome: TelemetryOutcome;\n readonly durationMs?: number;\n}\n\nexport interface RuntimeCoreOptions<TContract = unknown, TDriver = unknown> {\n readonly familyAdapter: RuntimeFamilyAdapter<TContract>;\n readonly driver: TDriver;\n readonly verify: RuntimeVerifyOptions;\n readonly middleware?: readonly Middleware<TContract>[];\n readonly mode?: 'strict' | 'permissive';\n readonly log?: Log;\n}\n\nexport interface RuntimeCore<TContract = unknown, TDriver = unknown>\n extends RuntimeQueryable,\n RuntimeExecutor<ExecutionPlan> {\n readonly _typeContract?: TContract;\n readonly _typeDriver?: TDriver;\n connection(): Promise<RuntimeConnection>;\n telemetry(): RuntimeTelemetryEvent | null;\n close(): Promise<void>;\n}\n\nexport interface RuntimeConnection extends RuntimeQueryable {\n transaction(): Promise<RuntimeTransaction>;\n release(): Promise<void>;\n}\n\nexport interface RuntimeTransaction extends RuntimeQueryable {\n commit(): Promise<void>;\n rollback(): Promise<void>;\n}\n\n/**\n * Shared query execution trait for anything that can run an ExecutionPlan:\n * RuntimeCore, RuntimeConnection, and RuntimeTransaction. This is a\n * SQL-domain internal mixin — it is NOT the cross-family SPI.\n *\n * For the cross-family SPI, see RuntimeExecutor in framework-components.\n * RuntimeCore nominally extends both this interface and RuntimeExecutor.\n *\n * The execute signature uses the same `_row` phantom intersection as\n * RuntimeExecutor so that RuntimeCore can extend both without conflicts.\n */\nexport interface RuntimeQueryable {\n execute<Row>(plan: ExecutionPlan & { readonly _row?: Row }): AsyncIterableResult<Row>;\n}\n\ninterface DriverWithQuery<_TDriver> {\n query(sql: string, params: readonly unknown[]): Promise<{ rows: ReadonlyArray<unknown> }>;\n}\n\ninterface DriverWithConnection<_TDriver> {\n acquireConnection(): Promise<DriverConnection>;\n}\n\nexport interface DriverConnection extends Queryable {\n beginTransaction(): Promise<DriverTransaction>;\n release(): Promise<void>;\n}\n\nexport interface DriverTransaction extends Queryable {\n commit(): Promise<void>;\n rollback(): Promise<void>;\n}\n\nexport interface Queryable {\n execute<Row = Record<string, unknown>>(options: {\n sql: string;\n params: readonly unknown[];\n }): AsyncIterable<Row>;\n}\n\ninterface DriverWithClose<_TDriver> {\n close(): Promise<void>;\n}\n\nclass RuntimeCoreImpl<TContract = unknown, TDriver = unknown>\n implements RuntimeCore<TContract, TDriver>\n{\n readonly _typeContract?: TContract;\n readonly _typeDriver?: TDriver;\n private readonly contract: TContract;\n private readonly familyAdapter: RuntimeFamilyAdapter<TContract>;\n private readonly driver: TDriver;\n private readonly middleware: readonly Middleware<TContract>[];\n private readonly mode: 'strict' | 'permissive';\n private readonly verify: RuntimeVerifyOptions;\n private readonly middlewareContext: MiddlewareContext<TContract>;\n\n private verified: boolean;\n private startupVerified: boolean;\n private _telemetry: RuntimeTelemetryEvent | null;\n\n constructor(options: RuntimeCoreOptions<TContract, TDriver>) {\n const { familyAdapter, driver } = options;\n this.contract = familyAdapter.contract;\n this.familyAdapter = familyAdapter;\n this.driver = driver;\n this.middleware = options.middleware ?? [];\n this.mode = options.mode ?? 'strict';\n this.verify = options.verify;\n this.verified = options.verify.mode === 'startup' ? false : options.verify.mode === 'always';\n this.startupVerified = false;\n this._telemetry = null;\n\n this.middlewareContext = {\n contract: this.contract,\n mode: this.mode,\n now: () => Date.now(),\n log: options.log ?? {\n info: () => {},\n warn: () => {},\n error: () => {},\n },\n };\n }\n\n private async verifyPlanIfNeeded(_plan: ExecutionPlan): Promise<void> {\n void _plan;\n if (this.verify.mode === 'always') {\n this.verified = false;\n }\n\n if (this.verified) {\n return;\n }\n\n const readStatement = this.familyAdapter.markerReader.readMarkerStatement();\n const driver = this.driver as unknown as DriverWithQuery<TDriver>;\n const result = await driver.query(readStatement.sql, readStatement.params);\n\n if (result.rows.length === 0) {\n if (this.verify.requireMarker) {\n throw runtimeError('CONTRACT.MARKER_MISSING', 'Contract marker not found in database');\n }\n\n this.verified = true;\n return;\n }\n\n const marker = parseContractMarkerRow(result.rows[0]);\n\n const contract = this.contract as {\n storage: { storageHash: string };\n execution?: { executionHash?: string | null };\n profileHash?: string | null;\n };\n if (marker.storageHash !== contract.storage.storageHash) {\n throw runtimeError(\n 'CONTRACT.MARKER_MISMATCH',\n 'Database storage hash does not match contract',\n {\n expected: contract.storage.storageHash,\n actual: marker.storageHash,\n },\n );\n }\n\n const expectedProfile = contract.profileHash ?? null;\n if (expectedProfile !== null && marker.profileHash !== expectedProfile) {\n throw runtimeError(\n 'CONTRACT.MARKER_MISMATCH',\n 'Database profile hash does not match contract',\n {\n expectedProfile,\n actualProfile: marker.profileHash,\n },\n );\n }\n\n this.verified = true;\n this.startupVerified = true;\n }\n\n private validatePlan(plan: ExecutionPlan): void {\n this.familyAdapter.validatePlan(plan, this.contract);\n }\n\n private recordTelemetry(\n plan: ExecutionPlan,\n outcome: TelemetryOutcome,\n durationMs?: number,\n ): void {\n const contract = this.contract as { target: string };\n this._telemetry = Object.freeze({\n lane: plan.meta.lane,\n target: contract.target,\n fingerprint: computeSqlFingerprint(plan.sql),\n outcome,\n ...(durationMs !== undefined ? { durationMs } : {}),\n });\n }\n\n execute<Row = Record<string, unknown>>(plan: ExecutionPlan<Row>): AsyncIterableResult<Row> {\n return this.#executeWith(plan, this.driver as Queryable);\n }\n\n async connection(): Promise<RuntimeConnection> {\n const driver = this.driver as unknown as DriverWithConnection<TDriver>;\n const driverConn = await driver.acquireConnection();\n const self = this;\n\n const runtimeConnection: RuntimeConnection = {\n async transaction(): Promise<RuntimeTransaction> {\n const driverTx = await driverConn.beginTransaction();\n const runtimeTx: RuntimeTransaction = {\n async commit(): Promise<void> {\n await driverTx.commit();\n },\n async rollback(): Promise<void> {\n await driverTx.rollback();\n },\n execute<Row = Record<string, unknown>>(\n plan: ExecutionPlan<Row>,\n ): AsyncIterableResult<Row> {\n return self.#executeWith(plan, driverTx);\n },\n };\n return runtimeTx;\n },\n execute<Row = Record<string, unknown>>(plan: ExecutionPlan<Row>): AsyncIterableResult<Row> {\n return self.#executeWith(plan, driverConn);\n },\n async release(): Promise<void> {\n await driverConn.release();\n },\n };\n\n return runtimeConnection;\n }\n\n telemetry(): RuntimeTelemetryEvent | null {\n return this._telemetry;\n }\n\n close(): Promise<void> {\n const driver = this.driver as unknown as DriverWithClose<TDriver>;\n if (typeof driver.close === 'function') {\n return driver.close();\n }\n return Promise.resolve();\n }\n\n #executeWith<Row = Record<string, unknown>>(\n plan: ExecutionPlan<Row>,\n queryable: Queryable,\n ): AsyncIterableResult<Row> {\n this.validatePlan(plan);\n this._telemetry = null;\n\n const iterator = async function* (\n self: RuntimeCoreImpl<TContract, TDriver>,\n ): AsyncGenerator<Row, void, unknown> {\n const startedAt = Date.now();\n let rowCount = 0;\n let completed = false;\n\n if (!self.startupVerified && self.verify.mode === 'startup') {\n await self.verifyPlanIfNeeded(plan);\n }\n\n if (self.verify.mode === 'onFirstUse') {\n await self.verifyPlanIfNeeded(plan);\n }\n\n try {\n if (self.verify.mode === 'always') {\n await self.verifyPlanIfNeeded(plan);\n }\n\n for (const mw of self.middleware) {\n if (mw.beforeExecute) {\n await mw.beforeExecute(plan, self.middlewareContext);\n }\n }\n\n const encodedParams = plan.params;\n\n for await (const row of queryable.execute<Record<string, unknown>>({\n sql: plan.sql,\n params: encodedParams,\n })) {\n for (const mw of self.middleware) {\n if (mw.onRow) {\n await mw.onRow(row, plan, self.middlewareContext);\n }\n }\n rowCount++;\n yield row as Row;\n }\n\n completed = true;\n self.recordTelemetry(plan, 'success', Date.now() - startedAt);\n } catch (error) {\n if (self._telemetry === null) {\n self.recordTelemetry(plan, 'runtime-error', Date.now() - startedAt);\n }\n\n const latencyMs = Date.now() - startedAt;\n for (const mw of self.middleware) {\n if (mw.afterExecute) {\n try {\n await mw.afterExecute(\n plan,\n { rowCount, latencyMs, completed },\n self.middlewareContext,\n );\n } catch {\n // Ignore errors from afterExecute hooks\n }\n }\n }\n\n throw error;\n }\n\n const latencyMs = Date.now() - startedAt;\n for (const mw of self.middleware) {\n if (mw.afterExecute) {\n await mw.afterExecute(plan, { rowCount, latencyMs, completed }, self.middlewareContext);\n }\n }\n };\n\n return new AsyncIterableResult(iterator(this));\n }\n}\n\nexport function createRuntimeCore<TContract = unknown, TDriver = unknown>(\n options: RuntimeCoreOptions<TContract, TDriver>,\n): RuntimeCore<TContract, TDriver> {\n return new RuntimeCoreImpl(options);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["lints: LintFinding[]","budgets: BudgetFinding[]","parsed: unknown","runtimeError","#executeWith","latencyMs","AsyncIterableResult"],"sources":["../src/fingerprint.ts","../src/guardrails/raw.ts","../src/marker.ts","../src/runtime-core.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\n\nconst STRING_LITERAL_REGEX = /'(?:''|[^'])*'/g;\nconst NUMERIC_LITERAL_REGEX = /\\b\\d+(?:\\.\\d+)?\\b/g;\nconst WHITESPACE_REGEX = /\\s+/g;\n\nexport function computeSqlFingerprint(sql: string): string {\n const withoutStrings = sql.replace(STRING_LITERAL_REGEX, '?');\n const withoutNumbers = withoutStrings.replace(NUMERIC_LITERAL_REGEX, '?');\n const normalized = withoutNumbers.replace(WHITESPACE_REGEX, ' ').trim().toLowerCase();\n\n const hash = createHash('sha256').update(normalized).digest('hex');\n return `sha256:${hash}`;\n}\n","import type { ExecutionPlan, PlanMeta, PlanRefs } from '@prisma-next/contract/types';\n\nexport type LintSeverity = 'error' | 'warn';\nexport type BudgetSeverity = 'error' | 'warn';\n\nexport interface LintFinding {\n readonly code: `LINT.${string}`;\n readonly severity: LintSeverity;\n readonly message: string;\n readonly details?: Record<string, unknown>;\n}\n\nexport interface BudgetFinding {\n readonly code: `BUDGET.${string}`;\n readonly severity: BudgetSeverity;\n readonly message: string;\n readonly details?: Record<string, unknown>;\n}\n\nexport interface RawGuardrailConfig {\n readonly budgets?: {\n readonly unboundedSelectSeverity?: BudgetSeverity;\n readonly estimatedRows?: number;\n };\n}\n\nexport interface RawGuardrailResult {\n readonly lints: LintFinding[];\n readonly budgets: BudgetFinding[];\n readonly statement: 'select' | 'mutation' | 'other';\n}\n\nconst SELECT_STAR_REGEX = /select\\s+\\*/i;\nconst LIMIT_REGEX = /\\blimit\\b/i;\nconst MUTATION_PREFIX_REGEX = /^(insert|update|delete|create|alter|drop|truncate)\\b/i;\n\nconst READ_ONLY_INTENTS = new Set(['read', 'report', 'readonly']);\n\nexport function evaluateRawGuardrails(\n plan: ExecutionPlan,\n config?: RawGuardrailConfig,\n): RawGuardrailResult {\n const lints: LintFinding[] = [];\n const budgets: BudgetFinding[] = [];\n\n const normalized = normalizeWhitespace(plan.sql);\n const statementType = classifyStatement(normalized);\n\n if (statementType === 'select') {\n if (SELECT_STAR_REGEX.test(normalized)) {\n lints.push(\n createLint('LINT.SELECT_STAR', 'error', 'Raw SQL plan selects all columns via *', {\n sql: snippet(plan.sql),\n }),\n );\n }\n\n if (!LIMIT_REGEX.test(normalized)) {\n const severity = config?.budgets?.unboundedSelectSeverity ?? 'error';\n lints.push(\n createLint('LINT.NO_LIMIT', 'warn', 'Raw SQL plan omits LIMIT clause', {\n sql: snippet(plan.sql),\n }),\n );\n\n budgets.push(\n createBudget(\n 'BUDGET.ROWS_EXCEEDED',\n severity,\n 'Raw SQL plan is unbounded and may exceed row budget',\n {\n sql: snippet(plan.sql),\n ...(config?.budgets?.estimatedRows !== undefined\n ? { estimatedRows: config.budgets.estimatedRows }\n : {}),\n },\n ),\n );\n }\n }\n\n if (isMutationStatement(statementType) && isReadOnlyIntent(plan.meta)) {\n lints.push(\n createLint(\n 'LINT.READ_ONLY_MUTATION',\n 'error',\n 'Raw SQL plan mutates data despite read-only intent',\n {\n sql: snippet(plan.sql),\n intent: plan.meta.annotations?.['intent'],\n },\n ),\n );\n }\n\n const refs = plan.meta.refs;\n if (refs) {\n evaluateIndexCoverage(refs, lints);\n }\n\n return { lints, budgets, statement: statementType };\n}\n\nfunction evaluateIndexCoverage(refs: PlanRefs, lints: LintFinding[]) {\n const predicateColumns = refs.columns ?? [];\n if (predicateColumns.length === 0) {\n return;\n }\n\n const indexes = refs.indexes ?? [];\n\n if (indexes.length === 0) {\n lints.push(\n createLint(\n 'LINT.UNINDEXED_PREDICATE',\n 'warn',\n 'Raw SQL plan predicates lack supporting indexes',\n {\n predicates: predicateColumns,\n },\n ),\n );\n return;\n }\n\n const hasSupportingIndex = predicateColumns.every((column) =>\n indexes.some(\n (index) =>\n index.table === column.table &&\n index.columns.some((col) => col.toLowerCase() === column.column.toLowerCase()),\n ),\n );\n\n if (!hasSupportingIndex) {\n lints.push(\n createLint(\n 'LINT.UNINDEXED_PREDICATE',\n 'warn',\n 'Raw SQL plan predicates lack supporting indexes',\n {\n predicates: predicateColumns,\n },\n ),\n );\n }\n}\n\nfunction classifyStatement(sql: string): 'select' | 'mutation' | 'other' {\n const trimmed = sql.trim();\n const lower = trimmed.toLowerCase();\n\n if (lower.startsWith('with')) {\n if (lower.includes('select')) {\n return 'select';\n }\n }\n\n if (lower.startsWith('select')) {\n return 'select';\n }\n\n if (MUTATION_PREFIX_REGEX.test(trimmed)) {\n return 'mutation';\n }\n\n return 'other';\n}\n\nfunction isMutationStatement(statement: 'select' | 'mutation' | 'other'): boolean {\n return statement === 'mutation';\n}\n\nfunction isReadOnlyIntent(meta: PlanMeta): boolean {\n const annotations = meta.annotations as { intent?: string } | undefined;\n const intent =\n typeof annotations?.intent === 'string' ? annotations.intent.toLowerCase() : undefined;\n return intent !== undefined && READ_ONLY_INTENTS.has(intent);\n}\n\nfunction normalizeWhitespace(value: string): string {\n return value.replace(/\\s+/g, ' ').trim();\n}\n\nfunction snippet(sql: string): string {\n return normalizeWhitespace(sql).slice(0, 200);\n}\n\nfunction createLint(\n code: LintFinding['code'],\n severity: LintFinding['severity'],\n message: string,\n details?: Record<string, unknown>,\n): LintFinding {\n return { code, severity, message, ...(details ? { details } : {}) };\n}\n\nfunction createBudget(\n code: BudgetFinding['code'],\n severity: BudgetFinding['severity'],\n message: string,\n details?: Record<string, unknown>,\n): BudgetFinding {\n return { code, severity, message, ...(details ? { details } : {}) };\n}\n","import type { ContractMarkerRecord } from '@prisma-next/contract/types';\nimport { type } from 'arktype';\n\nexport interface ContractMarkerRow {\n core_hash: string;\n profile_hash: string;\n contract_json: unknown | null;\n canonical_version: number | null;\n updated_at: Date;\n app_tag: string | null;\n meta: unknown | null;\n}\n\nconst MetaSchema = type({ '[string]': 'unknown' });\n\nfunction parseMeta(meta: unknown): Record<string, unknown> {\n if (meta === null || meta === undefined) {\n return {};\n }\n\n let parsed: unknown;\n if (typeof meta === 'string') {\n try {\n parsed = JSON.parse(meta);\n } catch {\n return {};\n }\n } else {\n parsed = meta;\n }\n\n const result = MetaSchema(parsed);\n if (result instanceof type.errors) {\n return {};\n }\n\n return result as Record<string, unknown>;\n}\n\nconst ContractMarkerRowSchema = type({\n core_hash: 'string',\n profile_hash: 'string',\n 'contract_json?': 'unknown | null',\n 'canonical_version?': 'number | null',\n 'updated_at?': 'Date | string',\n 'app_tag?': 'string | null',\n 'meta?': 'unknown | null',\n});\n\nexport function parseContractMarkerRow(row: unknown): ContractMarkerRecord {\n const result = ContractMarkerRowSchema(row);\n if (result instanceof type.errors) {\n const messages = result.map((p: { message: string }) => p.message).join('; ');\n throw new Error(`Invalid contract marker row: ${messages}`);\n }\n\n const validatedRow = result as {\n core_hash: string;\n profile_hash: string;\n contract_json?: unknown | null;\n canonical_version?: number | null;\n updated_at?: Date | string;\n app_tag?: string | null;\n meta?: unknown | null;\n };\n\n const updatedAt = validatedRow.updated_at\n ? validatedRow.updated_at instanceof Date\n ? validatedRow.updated_at\n : new Date(validatedRow.updated_at)\n : new Date();\n\n return {\n storageHash: validatedRow.core_hash,\n profileHash: validatedRow.profile_hash,\n contractJson: validatedRow.contract_json ?? null,\n canonicalVersion: validatedRow.canonical_version ?? null,\n updatedAt,\n appTag: validatedRow.app_tag ?? null,\n meta: parseMeta(validatedRow.meta),\n };\n}\n","import type { ExecutionPlan } from '@prisma-next/contract/types';\nimport type { RuntimeExecutor } from '@prisma-next/framework-components/runtime';\nimport { AsyncIterableResult, runtimeError } from '@prisma-next/framework-components/runtime';\nimport { computeSqlFingerprint } from './fingerprint';\nimport { parseContractMarkerRow } from './marker';\nimport type { Log, Middleware, MiddlewareContext } from './middleware/types';\nimport type { RuntimeFamilyAdapter } from './runtime-spi';\n\nexport interface RuntimeVerifyOptions {\n readonly mode: 'onFirstUse' | 'startup' | 'always';\n readonly requireMarker: boolean;\n}\n\nexport type TelemetryOutcome = 'success' | 'runtime-error';\n\nexport interface RuntimeTelemetryEvent {\n readonly lane: string;\n readonly target: string;\n readonly fingerprint: string;\n readonly outcome: TelemetryOutcome;\n readonly durationMs?: number;\n}\n\nexport interface RuntimeCoreOptions<TContract = unknown, TDriver = unknown> {\n readonly familyAdapter: RuntimeFamilyAdapter<TContract>;\n readonly driver: TDriver;\n readonly verify: RuntimeVerifyOptions;\n readonly middleware?: readonly Middleware<TContract>[];\n readonly mode?: 'strict' | 'permissive';\n readonly log?: Log;\n}\n\nexport interface RuntimeCore<TContract = unknown, TDriver = unknown>\n extends RuntimeQueryable,\n RuntimeExecutor<ExecutionPlan> {\n readonly _typeContract?: TContract;\n readonly _typeDriver?: TDriver;\n connection(): Promise<RuntimeConnection>;\n telemetry(): RuntimeTelemetryEvent | null;\n close(): Promise<void>;\n}\n\nexport interface RuntimeConnection extends RuntimeQueryable {\n transaction(): Promise<RuntimeTransaction>;\n /**\n * Returns the connection to the pool for reuse. Only call this when the\n * connection is known to be in a clean state. If a transaction\n * commit/rollback failed or the connection is otherwise suspect, call\n * `destroy(reason)` instead.\n */\n release(): Promise<void>;\n /**\n * Evicts the connection so it is never reused. Call this when the\n * connection may be in an indeterminate state (e.g. a failed rollback\n * leaving an open transaction, or a broken socket).\n *\n * If teardown fails the error is propagated and the connection remains\n * retryable, so the caller can decide whether to swallow the failure or\n * retry cleanup. Calling destroy() or release() more than once after a\n * successful teardown is caller error.\n *\n * `reason` is advisory context only. It may be surfaced to driver-level\n * observability hooks (e.g. pg-pool's `'release'` event) but does not\n * influence eviction behavior and is not rethrown.\n */\n destroy(reason?: unknown): Promise<void>;\n}\n\nexport interface RuntimeTransaction extends RuntimeQueryable {\n commit(): Promise<void>;\n rollback(): Promise<void>;\n}\n\n/**\n * Shared query execution trait for anything that can run an ExecutionPlan:\n * RuntimeCore, RuntimeConnection, and RuntimeTransaction. This is a\n * SQL-domain internal mixin — it is NOT the cross-family SPI.\n *\n * For the cross-family SPI, see RuntimeExecutor in framework-components.\n * RuntimeCore nominally extends both this interface and RuntimeExecutor.\n *\n * The execute signature uses the same `_row` phantom intersection as\n * RuntimeExecutor so that RuntimeCore can extend both without conflicts.\n */\nexport interface RuntimeQueryable {\n execute<Row>(plan: ExecutionPlan & { readonly _row?: Row }): AsyncIterableResult<Row>;\n}\n\ninterface DriverWithQuery<_TDriver> {\n query(sql: string, params: readonly unknown[]): Promise<{ rows: ReadonlyArray<unknown> }>;\n}\n\ninterface DriverWithConnection<_TDriver> {\n acquireConnection(): Promise<DriverConnection>;\n}\n\nexport interface DriverConnection extends Queryable {\n beginTransaction(): Promise<DriverTransaction>;\n release(): Promise<void>;\n destroy(reason?: unknown): Promise<void>;\n}\n\nexport interface DriverTransaction extends Queryable {\n commit(): Promise<void>;\n rollback(): Promise<void>;\n}\n\nexport interface Queryable {\n execute<Row = Record<string, unknown>>(options: {\n sql: string;\n params: readonly unknown[];\n }): AsyncIterable<Row>;\n}\n\ninterface DriverWithClose<_TDriver> {\n close(): Promise<void>;\n}\n\nclass RuntimeCoreImpl<TContract = unknown, TDriver = unknown>\n implements RuntimeCore<TContract, TDriver>\n{\n readonly _typeContract?: TContract;\n readonly _typeDriver?: TDriver;\n private readonly contract: TContract;\n private readonly familyAdapter: RuntimeFamilyAdapter<TContract>;\n private readonly driver: TDriver;\n private readonly middleware: readonly Middleware<TContract>[];\n private readonly mode: 'strict' | 'permissive';\n private readonly verify: RuntimeVerifyOptions;\n private readonly middlewareContext: MiddlewareContext<TContract>;\n\n private verified: boolean;\n private startupVerified: boolean;\n private _telemetry: RuntimeTelemetryEvent | null;\n\n constructor(options: RuntimeCoreOptions<TContract, TDriver>) {\n const { familyAdapter, driver } = options;\n this.contract = familyAdapter.contract;\n this.familyAdapter = familyAdapter;\n this.driver = driver;\n this.middleware = options.middleware ?? [];\n this.mode = options.mode ?? 'strict';\n this.verify = options.verify;\n this.verified = options.verify.mode === 'startup' ? false : options.verify.mode === 'always';\n this.startupVerified = false;\n this._telemetry = null;\n\n this.middlewareContext = {\n contract: this.contract,\n mode: this.mode,\n now: () => Date.now(),\n log: options.log ?? {\n info: () => {},\n warn: () => {},\n error: () => {},\n },\n };\n }\n\n private async verifyPlanIfNeeded(_plan: ExecutionPlan): Promise<void> {\n void _plan;\n if (this.verify.mode === 'always') {\n this.verified = false;\n }\n\n if (this.verified) {\n return;\n }\n\n const readStatement = this.familyAdapter.markerReader.readMarkerStatement();\n const driver = this.driver as unknown as DriverWithQuery<TDriver>;\n const result = await driver.query(readStatement.sql, readStatement.params);\n\n if (result.rows.length === 0) {\n if (this.verify.requireMarker) {\n throw runtimeError('CONTRACT.MARKER_MISSING', 'Contract marker not found in database');\n }\n\n this.verified = true;\n return;\n }\n\n const marker = parseContractMarkerRow(result.rows[0]);\n\n const contract = this.contract as {\n storage: { storageHash: string };\n execution?: { executionHash?: string | null };\n profileHash?: string | null;\n };\n if (marker.storageHash !== contract.storage.storageHash) {\n throw runtimeError(\n 'CONTRACT.MARKER_MISMATCH',\n 'Database storage hash does not match contract',\n {\n expected: contract.storage.storageHash,\n actual: marker.storageHash,\n },\n );\n }\n\n const expectedProfile = contract.profileHash ?? null;\n if (expectedProfile !== null && marker.profileHash !== expectedProfile) {\n throw runtimeError(\n 'CONTRACT.MARKER_MISMATCH',\n 'Database profile hash does not match contract',\n {\n expectedProfile,\n actualProfile: marker.profileHash,\n },\n );\n }\n\n this.verified = true;\n this.startupVerified = true;\n }\n\n private validatePlan(plan: ExecutionPlan): void {\n this.familyAdapter.validatePlan(plan, this.contract);\n }\n\n private recordTelemetry(\n plan: ExecutionPlan,\n outcome: TelemetryOutcome,\n durationMs?: number,\n ): void {\n const contract = this.contract as { target: string };\n this._telemetry = Object.freeze({\n lane: plan.meta.lane,\n target: contract.target,\n fingerprint: computeSqlFingerprint(plan.sql),\n outcome,\n ...(durationMs !== undefined ? { durationMs } : {}),\n });\n }\n\n execute<Row = Record<string, unknown>>(plan: ExecutionPlan<Row>): AsyncIterableResult<Row> {\n return this.#executeWith(plan, this.driver as Queryable);\n }\n\n async connection(): Promise<RuntimeConnection> {\n const driver = this.driver as unknown as DriverWithConnection<TDriver>;\n const driverConn = await driver.acquireConnection();\n const self = this;\n\n const runtimeConnection: RuntimeConnection = {\n async transaction(): Promise<RuntimeTransaction> {\n const driverTx = await driverConn.beginTransaction();\n const runtimeTx: RuntimeTransaction = {\n async commit(): Promise<void> {\n await driverTx.commit();\n },\n async rollback(): Promise<void> {\n await driverTx.rollback();\n },\n execute<Row = Record<string, unknown>>(\n plan: ExecutionPlan<Row>,\n ): AsyncIterableResult<Row> {\n return self.#executeWith(plan, driverTx);\n },\n };\n return runtimeTx;\n },\n execute<Row = Record<string, unknown>>(plan: ExecutionPlan<Row>): AsyncIterableResult<Row> {\n return self.#executeWith(plan, driverConn);\n },\n async release(): Promise<void> {\n await driverConn.release();\n },\n async destroy(reason?: unknown): Promise<void> {\n await driverConn.destroy(reason);\n },\n };\n\n return runtimeConnection;\n }\n\n telemetry(): RuntimeTelemetryEvent | null {\n return this._telemetry;\n }\n\n close(): Promise<void> {\n const driver = this.driver as unknown as DriverWithClose<TDriver>;\n if (typeof driver.close === 'function') {\n return driver.close();\n }\n return Promise.resolve();\n }\n\n #executeWith<Row = Record<string, unknown>>(\n plan: ExecutionPlan<Row>,\n queryable: Queryable,\n ): AsyncIterableResult<Row> {\n this.validatePlan(plan);\n this._telemetry = null;\n\n const iterator = async function* (\n self: RuntimeCoreImpl<TContract, TDriver>,\n ): AsyncGenerator<Row, void, unknown> {\n const startedAt = Date.now();\n let rowCount = 0;\n let completed = false;\n\n if (!self.startupVerified && self.verify.mode === 'startup') {\n await self.verifyPlanIfNeeded(plan);\n }\n\n if (self.verify.mode === 'onFirstUse') {\n await self.verifyPlanIfNeeded(plan);\n }\n\n try {\n if (self.verify.mode === 'always') {\n await self.verifyPlanIfNeeded(plan);\n }\n\n for (const mw of self.middleware) {\n if (mw.beforeExecute) {\n await mw.beforeExecute(plan, self.middlewareContext);\n }\n }\n\n const encodedParams = plan.params;\n\n for await (const row of queryable.execute<Record<string, unknown>>({\n sql: plan.sql,\n params: encodedParams,\n })) {\n for (const mw of self.middleware) {\n if (mw.onRow) {\n await mw.onRow(row, plan, self.middlewareContext);\n }\n }\n rowCount++;\n yield row as Row;\n }\n\n completed = true;\n self.recordTelemetry(plan, 'success', Date.now() - startedAt);\n } catch (error) {\n if (self._telemetry === null) {\n self.recordTelemetry(plan, 'runtime-error', Date.now() - startedAt);\n }\n\n const latencyMs = Date.now() - startedAt;\n for (const mw of self.middleware) {\n if (mw.afterExecute) {\n try {\n await mw.afterExecute(\n plan,\n { rowCount, latencyMs, completed },\n self.middlewareContext,\n );\n } catch {\n // Ignore errors from afterExecute hooks\n }\n }\n }\n\n throw error;\n }\n\n const latencyMs = Date.now() - startedAt;\n for (const mw of self.middleware) {\n if (mw.afterExecute) {\n await mw.afterExecute(plan, { rowCount, latencyMs, completed }, self.middlewareContext);\n }\n }\n };\n\n return new AsyncIterableResult(iterator(this));\n }\n}\n\nexport function createRuntimeCore<TContract = unknown, TDriver = unknown>(\n options: RuntimeCoreOptions<TContract, TDriver>,\n): RuntimeCore<TContract, TDriver> {\n return new RuntimeCoreImpl(options);\n}\n"],"mappings":";;;;;AAEA,MAAM,uBAAuB;AAC7B,MAAM,wBAAwB;AAC9B,MAAM,mBAAmB;AAEzB,SAAgB,sBAAsB,KAAqB;CAGzD,MAAM,aAFiB,IAAI,QAAQ,sBAAsB,IAAI,CACvB,QAAQ,uBAAuB,IAAI,CACvC,QAAQ,kBAAkB,IAAI,CAAC,MAAM,CAAC,aAAa;AAGrF,QAAO,UADM,WAAW,SAAS,CAAC,OAAO,WAAW,CAAC,OAAO,MAAM;;;;;ACqBpE,MAAM,oBAAoB;AAC1B,MAAM,cAAc;AACpB,MAAM,wBAAwB;AAE9B,MAAM,oBAAoB,IAAI,IAAI;CAAC;CAAQ;CAAU;CAAW,CAAC;AAEjE,SAAgB,sBACd,MACA,QACoB;CACpB,MAAMA,QAAuB,EAAE;CAC/B,MAAMC,UAA2B,EAAE;CAEnC,MAAM,aAAa,oBAAoB,KAAK,IAAI;CAChD,MAAM,gBAAgB,kBAAkB,WAAW;AAEnD,KAAI,kBAAkB,UAAU;AAC9B,MAAI,kBAAkB,KAAK,WAAW,CACpC,OAAM,KACJ,WAAW,oBAAoB,SAAS,0CAA0C,EAChF,KAAK,QAAQ,KAAK,IAAI,EACvB,CAAC,CACH;AAGH,MAAI,CAAC,YAAY,KAAK,WAAW,EAAE;GACjC,MAAM,WAAW,QAAQ,SAAS,2BAA2B;AAC7D,SAAM,KACJ,WAAW,iBAAiB,QAAQ,mCAAmC,EACrE,KAAK,QAAQ,KAAK,IAAI,EACvB,CAAC,CACH;AAED,WAAQ,KACN,aACE,wBACA,UACA,uDACA;IACE,KAAK,QAAQ,KAAK,IAAI;IACtB,GAAI,QAAQ,SAAS,kBAAkB,SACnC,EAAE,eAAe,OAAO,QAAQ,eAAe,GAC/C,EAAE;IACP,CACF,CACF;;;AAIL,KAAI,oBAAoB,cAAc,IAAI,iBAAiB,KAAK,KAAK,CACnE,OAAM,KACJ,WACE,2BACA,SACA,sDACA;EACE,KAAK,QAAQ,KAAK,IAAI;EACtB,QAAQ,KAAK,KAAK,cAAc;EACjC,CACF,CACF;CAGH,MAAM,OAAO,KAAK,KAAK;AACvB,KAAI,KACF,uBAAsB,MAAM,MAAM;AAGpC,QAAO;EAAE;EAAO;EAAS,WAAW;EAAe;;AAGrD,SAAS,sBAAsB,MAAgB,OAAsB;CACnE,MAAM,mBAAmB,KAAK,WAAW,EAAE;AAC3C,KAAI,iBAAiB,WAAW,EAC9B;CAGF,MAAM,UAAU,KAAK,WAAW,EAAE;AAElC,KAAI,QAAQ,WAAW,GAAG;AACxB,QAAM,KACJ,WACE,4BACA,QACA,mDACA,EACE,YAAY,kBACb,CACF,CACF;AACD;;AAWF,KAAI,CARuB,iBAAiB,OAAO,WACjD,QAAQ,MACL,UACC,MAAM,UAAU,OAAO,SACvB,MAAM,QAAQ,MAAM,QAAQ,IAAI,aAAa,KAAK,OAAO,OAAO,aAAa,CAAC,CACjF,CACF,CAGC,OAAM,KACJ,WACE,4BACA,QACA,mDACA,EACE,YAAY,kBACb,CACF,CACF;;AAIL,SAAS,kBAAkB,KAA8C;CACvE,MAAM,UAAU,IAAI,MAAM;CAC1B,MAAM,QAAQ,QAAQ,aAAa;AAEnC,KAAI,MAAM,WAAW,OAAO,EAC1B;MAAI,MAAM,SAAS,SAAS,CAC1B,QAAO;;AAIX,KAAI,MAAM,WAAW,SAAS,CAC5B,QAAO;AAGT,KAAI,sBAAsB,KAAK,QAAQ,CACrC,QAAO;AAGT,QAAO;;AAGT,SAAS,oBAAoB,WAAqD;AAChF,QAAO,cAAc;;AAGvB,SAAS,iBAAiB,MAAyB;CACjD,MAAM,cAAc,KAAK;CACzB,MAAM,SACJ,OAAO,aAAa,WAAW,WAAW,YAAY,OAAO,aAAa,GAAG;AAC/E,QAAO,WAAW,UAAa,kBAAkB,IAAI,OAAO;;AAG9D,SAAS,oBAAoB,OAAuB;AAClD,QAAO,MAAM,QAAQ,QAAQ,IAAI,CAAC,MAAM;;AAG1C,SAAS,QAAQ,KAAqB;AACpC,QAAO,oBAAoB,IAAI,CAAC,MAAM,GAAG,IAAI;;AAG/C,SAAS,WACP,MACA,UACA,SACA,SACa;AACb,QAAO;EAAE;EAAM;EAAU;EAAS,GAAI,UAAU,EAAE,SAAS,GAAG,EAAE;EAAG;;AAGrE,SAAS,aACP,MACA,UACA,SACA,SACe;AACf,QAAO;EAAE;EAAM;EAAU;EAAS,GAAI,UAAU,EAAE,SAAS,GAAG,EAAE;EAAG;;;;;AC7LrE,MAAM,aAAa,KAAK,EAAE,YAAY,WAAW,CAAC;AAElD,SAAS,UAAU,MAAwC;AACzD,KAAI,SAAS,QAAQ,SAAS,OAC5B,QAAO,EAAE;CAGX,IAAIC;AACJ,KAAI,OAAO,SAAS,SAClB,KAAI;AACF,WAAS,KAAK,MAAM,KAAK;SACnB;AACN,SAAO,EAAE;;KAGX,UAAS;CAGX,MAAM,SAAS,WAAW,OAAO;AACjC,KAAI,kBAAkB,KAAK,OACzB,QAAO,EAAE;AAGX,QAAO;;AAGT,MAAM,0BAA0B,KAAK;CACnC,WAAW;CACX,cAAc;CACd,kBAAkB;CAClB,sBAAsB;CACtB,eAAe;CACf,YAAY;CACZ,SAAS;CACV,CAAC;AAEF,SAAgB,uBAAuB,KAAoC;CACzE,MAAM,SAAS,wBAAwB,IAAI;AAC3C,KAAI,kBAAkB,KAAK,QAAQ;EACjC,MAAM,WAAW,OAAO,KAAK,MAA2B,EAAE,QAAQ,CAAC,KAAK,KAAK;AAC7E,QAAM,IAAI,MAAM,gCAAgC,WAAW;;CAG7D,MAAM,eAAe;CAUrB,MAAM,YAAY,aAAa,aAC3B,aAAa,sBAAsB,OACjC,aAAa,aACb,IAAI,KAAK,aAAa,WAAW,mBACnC,IAAI,MAAM;AAEd,QAAO;EACL,aAAa,aAAa;EAC1B,aAAa,aAAa;EAC1B,cAAc,aAAa,iBAAiB;EAC5C,kBAAkB,aAAa,qBAAqB;EACpD;EACA,QAAQ,aAAa,WAAW;EAChC,MAAM,UAAU,aAAa,KAAK;EACnC;;;;;ACsCH,IAAM,kBAAN,MAEA;CACE,AAAS;CACT,AAAS;CACT,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CAEjB,AAAQ;CACR,AAAQ;CACR,AAAQ;CAER,YAAY,SAAiD;EAC3D,MAAM,EAAE,eAAe,WAAW;AAClC,OAAK,WAAW,cAAc;AAC9B,OAAK,gBAAgB;AACrB,OAAK,SAAS;AACd,OAAK,aAAa,QAAQ,cAAc,EAAE;AAC1C,OAAK,OAAO,QAAQ,QAAQ;AAC5B,OAAK,SAAS,QAAQ;AACtB,OAAK,WAAW,QAAQ,OAAO,SAAS,YAAY,QAAQ,QAAQ,OAAO,SAAS;AACpF,OAAK,kBAAkB;AACvB,OAAK,aAAa;AAElB,OAAK,oBAAoB;GACvB,UAAU,KAAK;GACf,MAAM,KAAK;GACX,WAAW,KAAK,KAAK;GACrB,KAAK,QAAQ,OAAO;IAClB,YAAY;IACZ,YAAY;IACZ,aAAa;IACd;GACF;;CAGH,MAAc,mBAAmB,OAAqC;AAEpE,MAAI,KAAK,OAAO,SAAS,SACvB,MAAK,WAAW;AAGlB,MAAI,KAAK,SACP;EAGF,MAAM,gBAAgB,KAAK,cAAc,aAAa,qBAAqB;EAE3E,MAAM,SAAS,MADA,KAAK,OACQ,MAAM,cAAc,KAAK,cAAc,OAAO;AAE1E,MAAI,OAAO,KAAK,WAAW,GAAG;AAC5B,OAAI,KAAK,OAAO,cACd,OAAMC,eAAa,2BAA2B,wCAAwC;AAGxF,QAAK,WAAW;AAChB;;EAGF,MAAM,SAAS,uBAAuB,OAAO,KAAK,GAAG;EAErD,MAAM,WAAW,KAAK;AAKtB,MAAI,OAAO,gBAAgB,SAAS,QAAQ,YAC1C,OAAMA,eACJ,4BACA,iDACA;GACE,UAAU,SAAS,QAAQ;GAC3B,QAAQ,OAAO;GAChB,CACF;EAGH,MAAM,kBAAkB,SAAS,eAAe;AAChD,MAAI,oBAAoB,QAAQ,OAAO,gBAAgB,gBACrD,OAAMA,eACJ,4BACA,iDACA;GACE;GACA,eAAe,OAAO;GACvB,CACF;AAGH,OAAK,WAAW;AAChB,OAAK,kBAAkB;;CAGzB,AAAQ,aAAa,MAA2B;AAC9C,OAAK,cAAc,aAAa,MAAM,KAAK,SAAS;;CAGtD,AAAQ,gBACN,MACA,SACA,YACM;EACN,MAAM,WAAW,KAAK;AACtB,OAAK,aAAa,OAAO,OAAO;GAC9B,MAAM,KAAK,KAAK;GAChB,QAAQ,SAAS;GACjB,aAAa,sBAAsB,KAAK,IAAI;GAC5C;GACA,GAAI,eAAe,SAAY,EAAE,YAAY,GAAG,EAAE;GACnD,CAAC;;CAGJ,QAAuC,MAAoD;AACzF,SAAO,MAAKC,YAAa,MAAM,KAAK,OAAoB;;CAG1D,MAAM,aAAyC;EAE7C,MAAM,aAAa,MADJ,KAAK,OACY,mBAAmB;EACnD,MAAM,OAAO;AA+Bb,SA7B6C;GAC3C,MAAM,cAA2C;IAC/C,MAAM,WAAW,MAAM,WAAW,kBAAkB;AAcpD,WAbsC;KACpC,MAAM,SAAwB;AAC5B,YAAM,SAAS,QAAQ;;KAEzB,MAAM,WAA0B;AAC9B,YAAM,SAAS,UAAU;;KAE3B,QACE,MAC0B;AAC1B,aAAO,MAAKA,YAAa,MAAM,SAAS;;KAE3C;;GAGH,QAAuC,MAAoD;AACzF,WAAO,MAAKA,YAAa,MAAM,WAAW;;GAE5C,MAAM,UAAyB;AAC7B,UAAM,WAAW,SAAS;;GAE5B,MAAM,QAAQ,QAAiC;AAC7C,UAAM,WAAW,QAAQ,OAAO;;GAEnC;;CAKH,YAA0C;AACxC,SAAO,KAAK;;CAGd,QAAuB;EACrB,MAAM,SAAS,KAAK;AACpB,MAAI,OAAO,OAAO,UAAU,WAC1B,QAAO,OAAO,OAAO;AAEvB,SAAO,QAAQ,SAAS;;CAG1B,aACE,MACA,WAC0B;AAC1B,OAAK,aAAa,KAAK;AACvB,OAAK,aAAa;EAElB,MAAM,WAAW,iBACf,MACoC;GACpC,MAAM,YAAY,KAAK,KAAK;GAC5B,IAAI,WAAW;GACf,IAAI,YAAY;AAEhB,OAAI,CAAC,KAAK,mBAAmB,KAAK,OAAO,SAAS,UAChD,OAAM,KAAK,mBAAmB,KAAK;AAGrC,OAAI,KAAK,OAAO,SAAS,aACvB,OAAM,KAAK,mBAAmB,KAAK;AAGrC,OAAI;AACF,QAAI,KAAK,OAAO,SAAS,SACvB,OAAM,KAAK,mBAAmB,KAAK;AAGrC,SAAK,MAAM,MAAM,KAAK,WACpB,KAAI,GAAG,cACL,OAAM,GAAG,cAAc,MAAM,KAAK,kBAAkB;IAIxD,MAAM,gBAAgB,KAAK;AAE3B,eAAW,MAAM,OAAO,UAAU,QAAiC;KACjE,KAAK,KAAK;KACV,QAAQ;KACT,CAAC,EAAE;AACF,UAAK,MAAM,MAAM,KAAK,WACpB,KAAI,GAAG,MACL,OAAM,GAAG,MAAM,KAAK,MAAM,KAAK,kBAAkB;AAGrD;AACA,WAAM;;AAGR,gBAAY;AACZ,SAAK,gBAAgB,MAAM,WAAW,KAAK,KAAK,GAAG,UAAU;YACtD,OAAO;AACd,QAAI,KAAK,eAAe,KACtB,MAAK,gBAAgB,MAAM,iBAAiB,KAAK,KAAK,GAAG,UAAU;IAGrE,MAAMC,cAAY,KAAK,KAAK,GAAG;AAC/B,SAAK,MAAM,MAAM,KAAK,WACpB,KAAI,GAAG,aACL,KAAI;AACF,WAAM,GAAG,aACP,MACA;MAAE;MAAU;MAAW;MAAW,EAClC,KAAK,kBACN;YACK;AAMZ,UAAM;;GAGR,MAAM,YAAY,KAAK,KAAK,GAAG;AAC/B,QAAK,MAAM,MAAM,KAAK,WACpB,KAAI,GAAG,aACL,OAAM,GAAG,aAAa,MAAM;IAAE;IAAU;IAAW;IAAW,EAAE,KAAK,kBAAkB;;AAK7F,SAAO,IAAIC,sBAAoB,SAAS,KAAK,CAAC;;;AAIlD,SAAgB,kBACd,SACiC;AACjC,QAAO,IAAI,gBAAgB,QAAQ"}
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@prisma-next/runtime-executor",
3
- "version": "0.4.0-dev.9",
3
+ "version": "0.5.0-dev.1",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "Target-agnostic execution engine for Prisma Next",
7
7
  "dependencies": {
8
8
  "arktype": "^2.1.25",
9
- "@prisma-next/contract": "0.4.0-dev.9",
10
- "@prisma-next/operations": "0.4.0-dev.9",
11
- "@prisma-next/framework-components": "0.4.0-dev.9"
9
+ "@prisma-next/contract": "0.5.0-dev.1",
10
+ "@prisma-next/operations": "0.5.0-dev.1",
11
+ "@prisma-next/framework-components": "0.5.0-dev.1"
12
12
  },
13
13
  "devDependencies": {
14
14
  "@prisma/dev": "0.19.1",
@@ -42,7 +42,28 @@ export interface RuntimeCore<TContract = unknown, TDriver = unknown>
42
42
 
43
43
  export interface RuntimeConnection extends RuntimeQueryable {
44
44
  transaction(): Promise<RuntimeTransaction>;
45
+ /**
46
+ * Returns the connection to the pool for reuse. Only call this when the
47
+ * connection is known to be in a clean state. If a transaction
48
+ * commit/rollback failed or the connection is otherwise suspect, call
49
+ * `destroy(reason)` instead.
50
+ */
45
51
  release(): Promise<void>;
52
+ /**
53
+ * Evicts the connection so it is never reused. Call this when the
54
+ * connection may be in an indeterminate state (e.g. a failed rollback
55
+ * leaving an open transaction, or a broken socket).
56
+ *
57
+ * If teardown fails the error is propagated and the connection remains
58
+ * retryable, so the caller can decide whether to swallow the failure or
59
+ * retry cleanup. Calling destroy() or release() more than once after a
60
+ * successful teardown is caller error.
61
+ *
62
+ * `reason` is advisory context only. It may be surfaced to driver-level
63
+ * observability hooks (e.g. pg-pool's `'release'` event) but does not
64
+ * influence eviction behavior and is not rethrown.
65
+ */
66
+ destroy(reason?: unknown): Promise<void>;
46
67
  }
47
68
 
48
69
  export interface RuntimeTransaction extends RuntimeQueryable {
@@ -76,6 +97,7 @@ interface DriverWithConnection<_TDriver> {
76
97
  export interface DriverConnection extends Queryable {
77
98
  beginTransaction(): Promise<DriverTransaction>;
78
99
  release(): Promise<void>;
100
+ destroy(reason?: unknown): Promise<void>;
79
101
  }
80
102
 
81
103
  export interface DriverTransaction extends Queryable {
@@ -244,6 +266,9 @@ class RuntimeCoreImpl<TContract = unknown, TDriver = unknown>
244
266
  async release(): Promise<void> {
245
267
  await driverConn.release();
246
268
  },
269
+ async destroy(reason?: unknown): Promise<void> {
270
+ await driverConn.destroy(reason);
271
+ },
247
272
  };
248
273
 
249
274
  return runtimeConnection;