@prisma-next/sql-runtime 0.5.0-dev.12 → 0.5.0-dev.14
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/{exports-BOHa3Emo.mjs → exports-BET5HxxT.mjs} +117 -89
- package/dist/exports-BET5HxxT.mjs.map +1 -0
- package/dist/{index-CZmC2kD3.d.mts → index-Df2GsLSH.d.mts} +18 -6
- package/dist/index-Df2GsLSH.d.mts.map +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/test/utils.d.mts +1 -1
- package/dist/test/utils.d.mts.map +1 -1
- package/dist/test/utils.mjs +4 -3
- package/dist/test/utils.mjs.map +1 -1
- package/package.json +9 -9
- package/src/exports/index.ts +1 -0
- package/src/marker.ts +13 -20
- package/src/runtime-spi.ts +4 -3
- package/src/sql-marker.ts +61 -46
- package/src/sql-runtime.ts +1 -2
- package/dist/exports-BOHa3Emo.mjs.map +0 -1
- package/dist/index-CZmC2kD3.d.mts.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as readContractMarker, c as createSqlExecutionStack, d as
|
|
1
|
+
import { a as readContractMarker, c as createSqlExecutionStack, d as parseContractMarkerRow, f as lowerSqlPlan, h as validateContractCodecMappings, i as ensureTableStatement, l as lints, m as validateCodecRegistryCompleteness, n as withTransaction, o as writeContractMarker, p as extractCodecIds, r as ensureSchemaStatement, s as createExecutionContext, t as createRuntime, u as budgets } from "./exports-BET5HxxT.mjs";
|
|
2
2
|
|
|
3
|
-
export { budgets, createExecutionContext, createRuntime, createSqlExecutionStack, ensureSchemaStatement, ensureTableStatement, extractCodecIds, lints, lowerSqlPlan, readContractMarker, validateCodecRegistryCompleteness, validateContractCodecMappings, withTransaction, writeContractMarker };
|
|
3
|
+
export { budgets, createExecutionContext, createRuntime, createSqlExecutionStack, ensureSchemaStatement, ensureTableStatement, extractCodecIds, lints, lowerSqlPlan, parseContractMarkerRow, readContractMarker, validateCodecRegistryCompleteness, validateContractCodecMappings, withTransaction, writeContractMarker };
|
package/dist/test/utils.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as SqlRuntimeAdapterInstance, D as SqlRuntimeTargetDescriptor, E as SqlRuntimeExtensionInstance, S as SqlRuntimeAdapterDescriptor, T as SqlRuntimeExtensionDescriptor, _ as ExecutionContext, f as SqlStatement, u as createRuntime, w as SqlRuntimeDriverInstance } from "../index-
|
|
1
|
+
import { C as SqlRuntimeAdapterInstance, D as SqlRuntimeTargetDescriptor, E as SqlRuntimeExtensionInstance, S as SqlRuntimeAdapterDescriptor, T as SqlRuntimeExtensionDescriptor, _ as ExecutionContext, f as SqlStatement, u as createRuntime, w as SqlRuntimeDriverInstance } from "../index-Df2GsLSH.mjs";
|
|
2
2
|
import { ResultType } from "@prisma-next/framework-components/runtime";
|
|
3
3
|
import { Adapter, LoweredStatement, SelectAst } from "@prisma-next/sql-relational-core/ast";
|
|
4
4
|
import * as _prisma_next_framework_components_execution0 from "@prisma-next/framework-components/execution";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.mts","names":[],"sources":["../../test/utils.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"utils.d.mts","names":[],"sources":["../../test/utils.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;AA8CA;;;AACY,iBADU,qBACV,CAAA,UAAA,gBAAA,CAAiB,UAAjB,CAA4B,CAA5B,CAAA,CAAA,GAAkC,YAAlC,CAA+C,UAA/C,CAA0D,CAA1D,CAAA,CAAA,CAAA,CAAA,OAAA,EACD,UADC,CAAA,OACiB,aADjB,CAAA,EAAA,IAAA,EACuC,CADvC,CAAA,EAC2C,OAD3C,CACmD,UADnD,CAC8D,CAD9D,CAAA,EAAA,CAAA;;;;;AACD,iBASW,kBAAA,CATX,OAAA,EAUA,UAVA,CAAA,OAUkB,aAVlB,CAAA,EAAA,IAAA,EAWH,gBAXG,GAWgB,YAXhB,CAAA,OAAA,CAAA,CAAA,EAYR,OAZQ,CAAA,IAAA,CAAA;;;;AAA4C,iBAmBjC,gBAAA,CAnBiC,MAAA,EAmBR,MAnBQ,EAAA,SAAA,EAmBW,YAnBX,CAAA,EAmB0B,OAnB1B,CAAA,IAAA,CAAA;;AASvD;;;AAEQ,iBAqBc,iBAAA,CArBd,MAAA,EAsBE,MAtBF,EAAA,QAAA,EAuBI,QAvBJ,CAuBa,UAvBb,CAAA,EAAA,OAAA,EAAA,CAAA,MAAA,EAwBY,MAxBZ,EAAA,GAwBuB,OAxBvB,CAAA,IAAA,CAAA,CAAA,EAyBL,OAzBK,CAAA,IAAA,CAAA;;;;AAQR;AAA+C,iBAsCzB,uBAAA,CAtCyB,MAAA,EAuCrC,MAvCqC,EAAA,QAAA,EAwCnC,QAxCmC,CAwC1B,UAxC0B,CAAA,CAAA,EAyC5C,OAzC4C,CAAA,IAAA,CAAA;;;;AAa/C;;AAEqB,iBAyCL,2BAAA,CAzCK,OAAA,EA0CV,OA1CU,CA0CF,SA1CE,EA0CS,QA1CT,CA0CkB,UA1ClB,CAAA,EA0C+B,gBA1C/B,CAAA,CAAA,EA2ClB,2BA3CkB,CAAA,UAAA,CAAA;;;;AAElB,iBA6Da,0BAAA,CAAA,CA7Db,EA6D2C,0BA7D3C,CAAA,UAAA,CAAA;;AAqBH;;;;;;AAkBgB,iBA4CA,iBA5C2B,CAAA,kBA4CS,QA5CT,CA4CkB,UA5ClB,CAAA,CAAA,CAAA,QAAA,EA6C/B,SA7C+B,EAAA,OAAA,EA8ChC,OA9CgC,CA8CxB,SA9CwB,EA8Cb,QA9Ca,CA8CJ,UA9CI,CAAA,EA8CS,gBA9CT,CAAA,EAAA,OACJ,CADI,EAAA;EACxB,cAAA,CAAA,EA+CE,aA/CF,CA+CgB,6BA/ChB,CAAA,UAAA,CAAA,CAAA;CAAoB,CAAA,EAiDpC,gBAjDoC,CAiDnB,SAjDmB,CAAA;AAAT,iBA4Dd,uBAAA,CA5Dc,OAC3B,CAD2B,EAAA;EAAsB,cAAA,CAAA,EA6DjC,aA7DiC,CA6DnB,6BA7DmB,CAAA,UAAA,CAAA,CAAA;EAAzC,MAAA,CAAA,EA8DA,uBA9DA,CAAA,KAAA,EAAA,UAAA,EAAA,OAAA,EAkEP,wBAlEO,CAAA,UAAA,CAAA,CAAA;CACR,CAAA,EAmEF,4CAAA,CAAA,sBAnEE,CAAA,KAAA,EAAA,UAAA,EAmEF,yBAnEE,CAAA,UAAA,CAAA,EAmEF,wBAnEE,CAAA,UAAA,CAAA,EAmEF,2BAnEE,CAAA,UAAA,CAAA,CAAA;;AAoBH;AAsBA;;;;;AAEuC,iBAyCvB,iBAAA,CAAA,CAzCuB,EAyCF,OAzCE,CAyCM,SAzCN,EAyCiB,QAzCjB,CAyC0B,UAzC1B,CAAA,EAyCuC,gBAzCvC,CAAA;AAAT,iBAwGd,kBAAA,CAxGc,QAAA,EAyGlB,OAzGkB,CAyGV,IAzGU,CAyGL,QAzGK,CAyGI,UAzGJ,CAAA,EAAA,aAAA,GAAA,SAAA,CAAA,CAAA,GAAA;EAAsB,WAAA,CAAA,EAAA,MAAA;EAAzC,WAAA,CAAA,EAAA,MAAA;EAEwB,OAAA,CAAA,EA0GrB,IA1GqB,CA0GhB,UA1GgB,EAAA,aAAA,CAAA;CAAd,CAAA,EA4GlB,QA5GkB,CA4GT,UA5GS,CAAA"}
|
package/dist/test/utils.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as createSqlExecutionStack, i as ensureTableStatement, o as writeContractMarker, r as ensureSchemaStatement, s as createExecutionContext } from "../exports-
|
|
1
|
+
import { c as createSqlExecutionStack, d as parseContractMarkerRow, i as ensureTableStatement, o as writeContractMarker, r as ensureSchemaStatement, s as createExecutionContext } from "../exports-BET5HxxT.mjs";
|
|
2
2
|
import { codec, createCodecRegistry } from "@prisma-next/sql-relational-core/ast";
|
|
3
3
|
import { instantiateExecutionStack } from "@prisma-next/framework-components/execution";
|
|
4
4
|
import { coreHash, profileHash } from "@prisma-next/contract/types";
|
|
@@ -181,10 +181,11 @@ function createStubAdapter() {
|
|
|
181
181
|
},
|
|
182
182
|
readMarkerStatement() {
|
|
183
183
|
return {
|
|
184
|
-
sql: "select core_hash, profile_hash, contract_json, canonical_version, updated_at, app_tag, meta from prisma_contract.marker where id = $1",
|
|
184
|
+
sql: "select core_hash, profile_hash, contract_json, canonical_version, updated_at, app_tag, meta, invariants from prisma_contract.marker where id = $1",
|
|
185
185
|
params: [1]
|
|
186
186
|
};
|
|
187
|
-
}
|
|
187
|
+
},
|
|
188
|
+
parseMarkerRow: parseContractMarkerRow
|
|
188
189
|
},
|
|
189
190
|
lower(ast, ctx) {
|
|
190
191
|
const sqlText = JSON.stringify(ast);
|
package/dist/test/utils.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.mjs","names":["collectAsync"],"sources":["../../test/utils.ts"],"sourcesContent":["import type { Contract } from '@prisma-next/contract/types';\nimport { coreHash, profileHash } from '@prisma-next/contract/types';\nimport {\n instantiateExecutionStack,\n type RuntimeDriverDescriptor,\n} from '@prisma-next/framework-components/execution';\nimport type { ResultType } from '@prisma-next/framework-components/runtime';\nimport { builtinGeneratorIds } from '@prisma-next/ids';\nimport { generateId } from '@prisma-next/ids/runtime';\nimport type { SqlStorage } from '@prisma-next/sql-contract/types';\nimport type { Adapter, LoweredStatement, SelectAst } from '@prisma-next/sql-relational-core/ast';\nimport { codec, createCodecRegistry } from '@prisma-next/sql-relational-core/ast';\nimport type { SqlExecutionPlan, SqlQueryPlan } from '@prisma-next/sql-relational-core/plan';\nimport { collectAsync, drainAsyncIterable } from '@prisma-next/test-utils';\nimport type { Client } from 'pg';\nimport type { SqlStatement } from '../src/exports';\nimport {\n createExecutionContext,\n type createRuntime,\n createSqlExecutionStack,\n ensureSchemaStatement,\n ensureTableStatement,\n writeContractMarker,\n} from '../src/exports';\nimport type {\n ExecutionContext,\n SqlRuntimeAdapterDescriptor,\n SqlRuntimeAdapterInstance,\n SqlRuntimeDriverInstance,\n SqlRuntimeExtensionDescriptor,\n SqlRuntimeTargetDescriptor,\n} from '../src/sql-context';\n\nfunction createTestMutationDefaultGenerators() {\n return builtinGeneratorIds.map((id) => ({\n id,\n generate: (params?: Record<string, unknown>) => generateId(params ? { id, params } : { id }),\n }));\n}\n\n/**\n * Executes a plan and collects all results into an array.\n * This helper DRYs up the common pattern of executing plans in tests.\n * The return type is inferred from the plan's type parameter.\n */\nexport async function executePlanAndCollect<\n P extends SqlExecutionPlan<ResultType<P>> | SqlQueryPlan<ResultType<P>>,\n>(runtime: ReturnType<typeof createRuntime>, plan: P): Promise<ResultType<P>[]> {\n type Row = ResultType<P>;\n return collectAsync<Row>(runtime.execute<Row>(plan));\n}\n\n/**\n * Drains a plan execution, consuming all results without collecting them.\n * Useful for testing side effects without memory overhead.\n */\nexport async function drainPlanExecution(\n runtime: ReturnType<typeof createRuntime>,\n plan: SqlExecutionPlan | SqlQueryPlan<unknown>,\n): Promise<void> {\n return drainAsyncIterable(runtime.execute(plan));\n}\n\n/**\n * Executes a SQL statement on a database client.\n */\nexport async function executeStatement(client: Client, statement: SqlStatement): Promise<void> {\n if (statement.params.length > 0) {\n await client.query(statement.sql, [...statement.params]);\n return;\n }\n\n await client.query(statement.sql);\n}\n\n/**\n * Sets up database schema and data, then writes the contract marker.\n * This helper DRYs up the common pattern of database setup in tests.\n */\nexport async function setupTestDatabase(\n client: Client,\n contract: Contract<SqlStorage>,\n setupFn: (client: Client) => Promise<void>,\n): Promise<void> {\n await client.query('drop schema if exists prisma_contract cascade');\n await client.query('create schema if not exists public');\n\n await setupFn(client);\n\n await executeStatement(client, ensureSchemaStatement);\n await executeStatement(client, ensureTableStatement);\n const write = writeContractMarker({\n storageHash: contract.storage.storageHash,\n profileHash: contract.profileHash,\n contractJson: contract,\n canonicalVersion: 1,\n });\n await executeStatement(client, write.insert);\n}\n\n/**\n * Writes a contract marker to the database.\n * This helper DRYs up the common pattern of writing contract markers in tests.\n */\nexport async function writeTestContractMarker(\n client: Client,\n contract: Contract<SqlStorage>,\n): Promise<void> {\n const write = writeContractMarker({\n storageHash: contract.storage.storageHash,\n profileHash: contract.profileHash,\n contractJson: contract,\n canonicalVersion: 1,\n });\n await executeStatement(client, write.insert);\n}\n\n/**\n * Creates a test adapter descriptor from a raw adapter.\n * Wraps the adapter in an SqlRuntimeAdapterDescriptor with static contributions\n * derived from the adapter's codec registry.\n */\nexport function createTestAdapterDescriptor(\n adapter: Adapter<SelectAst, Contract<SqlStorage>, LoweredStatement>,\n): SqlRuntimeAdapterDescriptor<'postgres'> {\n const codecRegistry = adapter.profile.codecs();\n return {\n kind: 'adapter' as const,\n id: 'test-adapter',\n version: '0.0.1',\n familyId: 'sql' as const,\n targetId: 'postgres' as const,\n codecs: () => codecRegistry,\n parameterizedCodecs: () => [],\n mutationDefaultGenerators: createTestMutationDefaultGenerators,\n create(_stack): SqlRuntimeAdapterInstance<'postgres'> {\n return Object.assign({ familyId: 'sql' as const, targetId: 'postgres' as const }, adapter);\n },\n };\n}\n\n/**\n * Creates a test target descriptor with empty static contributions.\n */\nexport function createTestTargetDescriptor(): SqlRuntimeTargetDescriptor<'postgres'> {\n return {\n kind: 'target' as const,\n id: 'postgres',\n version: '0.0.1',\n familyId: 'sql' as const,\n targetId: 'postgres' as const,\n codecs: () => createCodecRegistry(),\n parameterizedCodecs: () => [],\n create() {\n return { familyId: 'sql' as const, targetId: 'postgres' as const };\n },\n };\n}\n\n/**\n * Creates an ExecutionContext for testing.\n * This helper DRYs up the common pattern of context creation in tests.\n *\n * Accepts a raw adapter and optional extension descriptors, wrapping the\n * adapter in a descriptor internally for descriptor-first context creation.\n */\nexport function createTestContext<TContract extends Contract<SqlStorage>>(\n contract: TContract,\n adapter: Adapter<SelectAst, Contract<SqlStorage>, LoweredStatement>,\n options?: {\n extensionPacks?: ReadonlyArray<SqlRuntimeExtensionDescriptor<'postgres'>>;\n },\n): ExecutionContext<TContract> {\n return createExecutionContext({\n contract,\n stack: {\n target: createTestTargetDescriptor(),\n adapter: createTestAdapterDescriptor(adapter),\n extensionPacks: options?.extensionPacks ?? [],\n },\n });\n}\n\nexport function createTestStackInstance(options?: {\n extensionPacks?: ReadonlyArray<SqlRuntimeExtensionDescriptor<'postgres'>>;\n driver?: RuntimeDriverDescriptor<\n 'sql',\n 'postgres',\n unknown,\n SqlRuntimeDriverInstance<'postgres'>\n >;\n}) {\n const stack = createSqlExecutionStack({\n target: createTestTargetDescriptor(),\n adapter: createTestAdapterDescriptor(createStubAdapter()),\n driver: options?.driver,\n extensionPacks: options?.extensionPacks ?? [],\n });\n\n return instantiateExecutionStack(stack);\n}\n\n/**\n * Creates a stub adapter for testing.\n * This helper DRYs up the common pattern of adapter creation in tests.\n *\n * The stub adapter includes simple codecs for common test types (pg/int4@1, pg/text@1, pg/timestamptz@1)\n * to enable type inference in tests without requiring the postgres adapter package.\n */\nexport function createStubAdapter(): Adapter<SelectAst, Contract<SqlStorage>, LoweredStatement> {\n const codecRegistry = createCodecRegistry();\n\n // Register stub codecs for common test types\n // These match the codec IDs used in test contracts (pg/int4@1, pg/text@1, pg/timestamptz@1)\n // but don't require importing from the postgres adapter package\n codecRegistry.register(\n codec({\n typeId: 'pg/int4@1',\n targetTypes: ['int4'],\n encode: (value: number) => value,\n decode: (wire: number) => wire,\n }),\n );\n\n codecRegistry.register(\n codec({\n typeId: 'pg/text@1',\n targetTypes: ['text'],\n encode: (value: string) => value,\n decode: (wire: string) => wire,\n }),\n );\n\n codecRegistry.register(\n codec({\n typeId: 'pg/timestamptz@1',\n targetTypes: ['timestamptz'],\n encode: (value: string | Date) => (value instanceof Date ? value.toISOString() : value),\n decode: (wire: string | Date) => (wire instanceof Date ? wire : new Date(wire)),\n // string | Date includes Date which is not assignable to JsonValue, so\n // the JSON round-trip pair must be supplied explicitly.\n encodeJson: (value: string | Date) => (value instanceof Date ? value.toISOString() : value),\n decodeJson: (json) => {\n if (typeof json !== 'string') throw new Error('expected ISO date string');\n return new Date(json);\n },\n }),\n );\n\n return {\n profile: {\n id: 'stub-profile',\n target: 'postgres',\n capabilities: {},\n codecs() {\n return codecRegistry;\n },\n readMarkerStatement() {\n return {\n sql: 'select core_hash, profile_hash, contract_json, canonical_version, updated_at, app_tag, meta from prisma_contract.marker where id = $1',\n params: [1],\n };\n },\n },\n lower(ast: SelectAst, ctx: { contract: Contract<SqlStorage>; params?: readonly unknown[] }) {\n const sqlText = JSON.stringify(ast);\n return Object.freeze({ sql: sqlText, params: ctx.params ? [...ctx.params] : [] });\n },\n };\n}\n\nexport function createTestContract(\n contract: Partial<Omit<Contract<SqlStorage>, 'profileHash' | 'storage'>> & {\n storageHash?: string;\n profileHash?: string;\n storage?: Omit<SqlStorage, 'storageHash'>;\n },\n): Contract<SqlStorage> {\n const { execution, ...rest } = contract;\n const storageHashValue = coreHash(rest['storageHash'] ?? 'sha256:testcore');\n\n return {\n target: rest['target'] ?? 'postgres',\n targetFamily: rest['targetFamily'] ?? 'sql',\n storage: rest['storage']\n ? { ...rest['storage'], storageHash: storageHashValue }\n : { storageHash: storageHashValue, tables: {} },\n models: rest['models'] ?? {},\n roots: rest['roots'] ?? {},\n capabilities: rest['capabilities'] ?? {},\n extensionPacks: rest['extensionPacks'] ?? {},\n meta: rest['meta'] ?? {},\n ...(execution ? { execution } : {}),\n profileHash: profileHash(rest['profileHash'] ?? 'sha256:testprofile'),\n };\n}\n\n// Re-export generic utilities from test-utils\nexport {\n collectAsync,\n createDevDatabase,\n type DevDatabase,\n teardownTestDatabase,\n withClient,\n} from '@prisma-next/test-utils';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.mjs","names":["collectAsync"],"sources":["../../test/utils.ts"],"sourcesContent":["import type { Contract } from '@prisma-next/contract/types';\nimport { coreHash, profileHash } from '@prisma-next/contract/types';\nimport {\n instantiateExecutionStack,\n type RuntimeDriverDescriptor,\n} from '@prisma-next/framework-components/execution';\nimport type { ResultType } from '@prisma-next/framework-components/runtime';\nimport { builtinGeneratorIds } from '@prisma-next/ids';\nimport { generateId } from '@prisma-next/ids/runtime';\nimport type { SqlStorage } from '@prisma-next/sql-contract/types';\nimport type { Adapter, LoweredStatement, SelectAst } from '@prisma-next/sql-relational-core/ast';\nimport { codec, createCodecRegistry } from '@prisma-next/sql-relational-core/ast';\nimport type { SqlExecutionPlan, SqlQueryPlan } from '@prisma-next/sql-relational-core/plan';\nimport { collectAsync, drainAsyncIterable } from '@prisma-next/test-utils';\nimport type { Client } from 'pg';\nimport type { SqlStatement } from '../src/exports';\nimport {\n createExecutionContext,\n type createRuntime,\n createSqlExecutionStack,\n ensureSchemaStatement,\n ensureTableStatement,\n parseContractMarkerRow,\n writeContractMarker,\n} from '../src/exports';\nimport type {\n ExecutionContext,\n SqlRuntimeAdapterDescriptor,\n SqlRuntimeAdapterInstance,\n SqlRuntimeDriverInstance,\n SqlRuntimeExtensionDescriptor,\n SqlRuntimeTargetDescriptor,\n} from '../src/sql-context';\n\nfunction createTestMutationDefaultGenerators() {\n return builtinGeneratorIds.map((id) => ({\n id,\n generate: (params?: Record<string, unknown>) => generateId(params ? { id, params } : { id }),\n }));\n}\n\n/**\n * Executes a plan and collects all results into an array.\n * This helper DRYs up the common pattern of executing plans in tests.\n * The return type is inferred from the plan's type parameter.\n */\nexport async function executePlanAndCollect<\n P extends SqlExecutionPlan<ResultType<P>> | SqlQueryPlan<ResultType<P>>,\n>(runtime: ReturnType<typeof createRuntime>, plan: P): Promise<ResultType<P>[]> {\n type Row = ResultType<P>;\n return collectAsync<Row>(runtime.execute<Row>(plan));\n}\n\n/**\n * Drains a plan execution, consuming all results without collecting them.\n * Useful for testing side effects without memory overhead.\n */\nexport async function drainPlanExecution(\n runtime: ReturnType<typeof createRuntime>,\n plan: SqlExecutionPlan | SqlQueryPlan<unknown>,\n): Promise<void> {\n return drainAsyncIterable(runtime.execute(plan));\n}\n\n/**\n * Executes a SQL statement on a database client.\n */\nexport async function executeStatement(client: Client, statement: SqlStatement): Promise<void> {\n if (statement.params.length > 0) {\n await client.query(statement.sql, [...statement.params]);\n return;\n }\n\n await client.query(statement.sql);\n}\n\n/**\n * Sets up database schema and data, then writes the contract marker.\n * This helper DRYs up the common pattern of database setup in tests.\n */\nexport async function setupTestDatabase(\n client: Client,\n contract: Contract<SqlStorage>,\n setupFn: (client: Client) => Promise<void>,\n): Promise<void> {\n await client.query('drop schema if exists prisma_contract cascade');\n await client.query('create schema if not exists public');\n\n await setupFn(client);\n\n await executeStatement(client, ensureSchemaStatement);\n await executeStatement(client, ensureTableStatement);\n const write = writeContractMarker({\n storageHash: contract.storage.storageHash,\n profileHash: contract.profileHash,\n contractJson: contract,\n canonicalVersion: 1,\n });\n await executeStatement(client, write.insert);\n}\n\n/**\n * Writes a contract marker to the database.\n * This helper DRYs up the common pattern of writing contract markers in tests.\n */\nexport async function writeTestContractMarker(\n client: Client,\n contract: Contract<SqlStorage>,\n): Promise<void> {\n const write = writeContractMarker({\n storageHash: contract.storage.storageHash,\n profileHash: contract.profileHash,\n contractJson: contract,\n canonicalVersion: 1,\n });\n await executeStatement(client, write.insert);\n}\n\n/**\n * Creates a test adapter descriptor from a raw adapter.\n * Wraps the adapter in an SqlRuntimeAdapterDescriptor with static contributions\n * derived from the adapter's codec registry.\n */\nexport function createTestAdapterDescriptor(\n adapter: Adapter<SelectAst, Contract<SqlStorage>, LoweredStatement>,\n): SqlRuntimeAdapterDescriptor<'postgres'> {\n const codecRegistry = adapter.profile.codecs();\n return {\n kind: 'adapter' as const,\n id: 'test-adapter',\n version: '0.0.1',\n familyId: 'sql' as const,\n targetId: 'postgres' as const,\n codecs: () => codecRegistry,\n parameterizedCodecs: () => [],\n mutationDefaultGenerators: createTestMutationDefaultGenerators,\n create(_stack): SqlRuntimeAdapterInstance<'postgres'> {\n return Object.assign({ familyId: 'sql' as const, targetId: 'postgres' as const }, adapter);\n },\n };\n}\n\n/**\n * Creates a test target descriptor with empty static contributions.\n */\nexport function createTestTargetDescriptor(): SqlRuntimeTargetDescriptor<'postgres'> {\n return {\n kind: 'target' as const,\n id: 'postgres',\n version: '0.0.1',\n familyId: 'sql' as const,\n targetId: 'postgres' as const,\n codecs: () => createCodecRegistry(),\n parameterizedCodecs: () => [],\n create() {\n return { familyId: 'sql' as const, targetId: 'postgres' as const };\n },\n };\n}\n\n/**\n * Creates an ExecutionContext for testing.\n * This helper DRYs up the common pattern of context creation in tests.\n *\n * Accepts a raw adapter and optional extension descriptors, wrapping the\n * adapter in a descriptor internally for descriptor-first context creation.\n */\nexport function createTestContext<TContract extends Contract<SqlStorage>>(\n contract: TContract,\n adapter: Adapter<SelectAst, Contract<SqlStorage>, LoweredStatement>,\n options?: {\n extensionPacks?: ReadonlyArray<SqlRuntimeExtensionDescriptor<'postgres'>>;\n },\n): ExecutionContext<TContract> {\n return createExecutionContext({\n contract,\n stack: {\n target: createTestTargetDescriptor(),\n adapter: createTestAdapterDescriptor(adapter),\n extensionPacks: options?.extensionPacks ?? [],\n },\n });\n}\n\nexport function createTestStackInstance(options?: {\n extensionPacks?: ReadonlyArray<SqlRuntimeExtensionDescriptor<'postgres'>>;\n driver?: RuntimeDriverDescriptor<\n 'sql',\n 'postgres',\n unknown,\n SqlRuntimeDriverInstance<'postgres'>\n >;\n}) {\n const stack = createSqlExecutionStack({\n target: createTestTargetDescriptor(),\n adapter: createTestAdapterDescriptor(createStubAdapter()),\n driver: options?.driver,\n extensionPacks: options?.extensionPacks ?? [],\n });\n\n return instantiateExecutionStack(stack);\n}\n\n/**\n * Creates a stub adapter for testing.\n * This helper DRYs up the common pattern of adapter creation in tests.\n *\n * The stub adapter includes simple codecs for common test types (pg/int4@1, pg/text@1, pg/timestamptz@1)\n * to enable type inference in tests without requiring the postgres adapter package.\n */\nexport function createStubAdapter(): Adapter<SelectAst, Contract<SqlStorage>, LoweredStatement> {\n const codecRegistry = createCodecRegistry();\n\n // Register stub codecs for common test types\n // These match the codec IDs used in test contracts (pg/int4@1, pg/text@1, pg/timestamptz@1)\n // but don't require importing from the postgres adapter package\n codecRegistry.register(\n codec({\n typeId: 'pg/int4@1',\n targetTypes: ['int4'],\n encode: (value: number) => value,\n decode: (wire: number) => wire,\n }),\n );\n\n codecRegistry.register(\n codec({\n typeId: 'pg/text@1',\n targetTypes: ['text'],\n encode: (value: string) => value,\n decode: (wire: string) => wire,\n }),\n );\n\n codecRegistry.register(\n codec({\n typeId: 'pg/timestamptz@1',\n targetTypes: ['timestamptz'],\n encode: (value: string | Date) => (value instanceof Date ? value.toISOString() : value),\n decode: (wire: string | Date) => (wire instanceof Date ? wire : new Date(wire)),\n // string | Date includes Date which is not assignable to JsonValue, so\n // the JSON round-trip pair must be supplied explicitly.\n encodeJson: (value: string | Date) => (value instanceof Date ? value.toISOString() : value),\n decodeJson: (json) => {\n if (typeof json !== 'string') throw new Error('expected ISO date string');\n return new Date(json);\n },\n }),\n );\n\n return {\n profile: {\n id: 'stub-profile',\n target: 'postgres',\n capabilities: {},\n codecs() {\n return codecRegistry;\n },\n readMarkerStatement() {\n return {\n sql: 'select core_hash, profile_hash, contract_json, canonical_version, updated_at, app_tag, meta, invariants from prisma_contract.marker where id = $1',\n params: [1],\n };\n },\n parseMarkerRow: parseContractMarkerRow,\n },\n lower(ast: SelectAst, ctx: { contract: Contract<SqlStorage>; params?: readonly unknown[] }) {\n const sqlText = JSON.stringify(ast);\n return Object.freeze({ sql: sqlText, params: ctx.params ? [...ctx.params] : [] });\n },\n };\n}\n\nexport function createTestContract(\n contract: Partial<Omit<Contract<SqlStorage>, 'profileHash' | 'storage'>> & {\n storageHash?: string;\n profileHash?: string;\n storage?: Omit<SqlStorage, 'storageHash'>;\n },\n): Contract<SqlStorage> {\n const { execution, ...rest } = contract;\n const storageHashValue = coreHash(rest['storageHash'] ?? 'sha256:testcore');\n\n return {\n target: rest['target'] ?? 'postgres',\n targetFamily: rest['targetFamily'] ?? 'sql',\n storage: rest['storage']\n ? { ...rest['storage'], storageHash: storageHashValue }\n : { storageHash: storageHashValue, tables: {} },\n models: rest['models'] ?? {},\n roots: rest['roots'] ?? {},\n capabilities: rest['capabilities'] ?? {},\n extensionPacks: rest['extensionPacks'] ?? {},\n meta: rest['meta'] ?? {},\n ...(execution ? { execution } : {}),\n profileHash: profileHash(rest['profileHash'] ?? 'sha256:testprofile'),\n };\n}\n\n// Re-export generic utilities from test-utils\nexport {\n collectAsync,\n createDevDatabase,\n type DevDatabase,\n teardownTestDatabase,\n withClient,\n} from '@prisma-next/test-utils';\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/sql-runtime",
|
|
3
|
-
"version": "0.5.0-dev.
|
|
3
|
+
"version": "0.5.0-dev.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "SQL runtime implementation for Prisma Next",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"arktype": "^2.1.26",
|
|
9
|
-
"@prisma-next/contract": "0.5.0-dev.
|
|
10
|
-
"@prisma-next/utils": "0.5.0-dev.
|
|
11
|
-
"@prisma-next/framework-components": "0.5.0-dev.
|
|
12
|
-
"@prisma-next/ids": "0.5.0-dev.
|
|
13
|
-
"@prisma-next/operations": "0.5.0-dev.
|
|
14
|
-
"@prisma-next/sql-
|
|
15
|
-
"@prisma-next/sql-
|
|
16
|
-
"@prisma-next/sql-relational-core": "0.5.0-dev.
|
|
9
|
+
"@prisma-next/contract": "0.5.0-dev.14",
|
|
10
|
+
"@prisma-next/utils": "0.5.0-dev.14",
|
|
11
|
+
"@prisma-next/framework-components": "0.5.0-dev.14",
|
|
12
|
+
"@prisma-next/ids": "0.5.0-dev.14",
|
|
13
|
+
"@prisma-next/operations": "0.5.0-dev.14",
|
|
14
|
+
"@prisma-next/sql-operations": "0.5.0-dev.14",
|
|
15
|
+
"@prisma-next/sql-contract": "0.5.0-dev.14",
|
|
16
|
+
"@prisma-next/sql-relational-core": "0.5.0-dev.14"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@types/pg": "8.16.0",
|
package/src/exports/index.ts
CHANGED
|
@@ -9,6 +9,7 @@ export {
|
|
|
9
9
|
validateContractCodecMappings,
|
|
10
10
|
} from '../codecs/validation';
|
|
11
11
|
export { lowerSqlPlan } from '../lower-sql-plan';
|
|
12
|
+
export { parseContractMarkerRow } from '../marker';
|
|
12
13
|
export type { BudgetsOptions } from '../middleware/budgets';
|
|
13
14
|
export { budgets } from '../middleware/budgets';
|
|
14
15
|
export type { LintsOptions } from '../middleware/lints';
|
package/src/marker.ts
CHANGED
|
@@ -9,6 +9,7 @@ export interface ContractMarkerRow {
|
|
|
9
9
|
updated_at: Date;
|
|
10
10
|
app_tag: string | null;
|
|
11
11
|
meta: unknown | null;
|
|
12
|
+
invariants: readonly string[];
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
const MetaSchema = type({ '[string]': 'unknown' });
|
|
@@ -45,6 +46,7 @@ const ContractMarkerRowSchema = type({
|
|
|
45
46
|
'updated_at?': 'Date | string',
|
|
46
47
|
'app_tag?': 'string | null',
|
|
47
48
|
'meta?': 'unknown | null',
|
|
49
|
+
invariants: type('string').array(),
|
|
48
50
|
});
|
|
49
51
|
|
|
50
52
|
export function parseContractMarkerRow(row: unknown): ContractMarkerRecord {
|
|
@@ -54,29 +56,20 @@ export function parseContractMarkerRow(row: unknown): ContractMarkerRecord {
|
|
|
54
56
|
throw new Error(`Invalid contract marker row: ${messages}`);
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
canonical_version?: number | null;
|
|
62
|
-
updated_at?: Date | string;
|
|
63
|
-
app_tag?: string | null;
|
|
64
|
-
meta?: unknown | null;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const updatedAt = validatedRow.updated_at
|
|
68
|
-
? validatedRow.updated_at instanceof Date
|
|
69
|
-
? validatedRow.updated_at
|
|
70
|
-
: new Date(validatedRow.updated_at)
|
|
59
|
+
const updatedAt = result.updated_at
|
|
60
|
+
? result.updated_at instanceof Date
|
|
61
|
+
? result.updated_at
|
|
62
|
+
: new Date(result.updated_at)
|
|
71
63
|
: new Date();
|
|
72
64
|
|
|
73
65
|
return {
|
|
74
|
-
storageHash:
|
|
75
|
-
profileHash:
|
|
76
|
-
contractJson:
|
|
77
|
-
canonicalVersion:
|
|
66
|
+
storageHash: result.core_hash,
|
|
67
|
+
profileHash: result.profile_hash,
|
|
68
|
+
contractJson: result.contract_json ?? null,
|
|
69
|
+
canonicalVersion: result.canonical_version ?? null,
|
|
78
70
|
updatedAt,
|
|
79
|
-
appTag:
|
|
80
|
-
meta: parseMeta(
|
|
71
|
+
appTag: result.app_tag ?? null,
|
|
72
|
+
meta: parseMeta(result.meta),
|
|
73
|
+
invariants: result.invariants,
|
|
81
74
|
};
|
|
82
75
|
}
|
package/src/runtime-spi.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ContractMarkerRecord } from '@prisma-next/contract/types';
|
|
1
2
|
import type { ExecutionPlan } from '@prisma-next/framework-components/runtime';
|
|
2
3
|
import type { MarkerStatement } from '@prisma-next/sql-relational-core/ast';
|
|
3
4
|
|
|
@@ -5,12 +6,12 @@ import type { MarkerStatement } from '@prisma-next/sql-relational-core/ast';
|
|
|
5
6
|
* Reader of the SQL contract marker. SQL runtimes verify the database's
|
|
6
7
|
* `prisma_contract.marker` row against the runtime's contract by issuing
|
|
7
8
|
* this statement before executing user queries (when `verify` is enabled).
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* `readMarkerStatement(): MarkerStatement` for adapter-level introspection.
|
|
9
|
+
* Each adapter is responsible for any target-specific row decoding before
|
|
10
|
+
* delegating to the shared row schema.
|
|
11
11
|
*/
|
|
12
12
|
export interface MarkerReader {
|
|
13
13
|
readMarkerStatement(): MarkerStatement;
|
|
14
|
+
parseMarkerRow(row: unknown): ContractMarkerRecord;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
/**
|
package/src/sql-marker.ts
CHANGED
|
@@ -12,6 +12,15 @@ export interface WriteMarkerInput {
|
|
|
12
12
|
readonly canonicalVersion?: number;
|
|
13
13
|
readonly appTag?: string;
|
|
14
14
|
readonly meta?: Record<string, unknown>;
|
|
15
|
+
/**
|
|
16
|
+
* Applied-invariants set on the marker.
|
|
17
|
+
*
|
|
18
|
+
* - `undefined` → existing column left untouched. Sign and
|
|
19
|
+
* verify-database paths use this; they don't accumulate invariants.
|
|
20
|
+
* - explicit value (including `[]`) → column overwritten with
|
|
21
|
+
* exactly that value.
|
|
22
|
+
*/
|
|
23
|
+
readonly invariants?: readonly string[];
|
|
15
24
|
}
|
|
16
25
|
|
|
17
26
|
export const ensureSchemaStatement: SqlStatement = {
|
|
@@ -28,7 +37,8 @@ export const ensureTableStatement: SqlStatement = {
|
|
|
28
37
|
canonical_version int,
|
|
29
38
|
updated_at timestamptz not null default now(),
|
|
30
39
|
app_tag text,
|
|
31
|
-
meta jsonb not null default '{}'
|
|
40
|
+
meta jsonb not null default '{}',
|
|
41
|
+
invariants text[] not null default '{}'
|
|
32
42
|
)`,
|
|
33
43
|
params: [],
|
|
34
44
|
};
|
|
@@ -42,7 +52,8 @@ export function readContractMarker(): MarkerStatement {
|
|
|
42
52
|
canonical_version,
|
|
43
53
|
updated_at,
|
|
44
54
|
app_tag,
|
|
45
|
-
meta
|
|
55
|
+
meta,
|
|
56
|
+
invariants
|
|
46
57
|
from prisma_contract.marker
|
|
47
58
|
where id = $1`,
|
|
48
59
|
params: [1],
|
|
@@ -54,52 +65,56 @@ export interface WriteContractMarkerStatements {
|
|
|
54
65
|
readonly update: SqlStatement;
|
|
55
66
|
}
|
|
56
67
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
68
|
+
/**
|
|
69
|
+
* Variable columns that participate in INSERT/UPDATE alongside the
|
|
70
|
+
* always-on `id = $1` and `updated_at = now()`. Each column declares
|
|
71
|
+
* its name, optional cast type, and parameter value; the placeholder
|
|
72
|
+
* (`$N`) is computed positionally below — adding or reordering a
|
|
73
|
+
* column doesn't desync indices. `invariants` only appears when the
|
|
74
|
+
* caller supplies it — see `WriteMarkerInput.invariants`.
|
|
75
|
+
*/
|
|
76
|
+
function markerColumns(
|
|
77
|
+
input: WriteMarkerInput,
|
|
78
|
+
): ReadonlyArray<{ readonly name: string; readonly type?: string; readonly param: unknown }> {
|
|
79
|
+
return [
|
|
80
|
+
{ name: 'core_hash', param: input.storageHash },
|
|
81
|
+
{ name: 'profile_hash', param: input.profileHash },
|
|
82
|
+
{ name: 'contract_json', type: 'jsonb', param: input.contractJson ?? null },
|
|
83
|
+
{ name: 'canonical_version', param: input.canonicalVersion ?? null },
|
|
84
|
+
{ name: 'app_tag', param: input.appTag ?? null },
|
|
85
|
+
{ name: 'meta', type: 'jsonb', param: JSON.stringify(input.meta ?? {}) },
|
|
86
|
+
...(input.invariants !== undefined
|
|
87
|
+
? [{ name: 'invariants' as const, type: 'text[]' as const, param: input.invariants }]
|
|
88
|
+
: []),
|
|
66
89
|
];
|
|
90
|
+
}
|
|
67
91
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
meta
|
|
78
|
-
) values (
|
|
79
|
-
$1,
|
|
80
|
-
$2,
|
|
81
|
-
$3,
|
|
82
|
-
$4::jsonb,
|
|
83
|
-
$5,
|
|
84
|
-
now(),
|
|
85
|
-
$6,
|
|
86
|
-
$7::jsonb
|
|
87
|
-
)`,
|
|
88
|
-
params: baseParams,
|
|
89
|
-
};
|
|
92
|
+
export function writeContractMarker(input: WriteMarkerInput): WriteContractMarkerStatements {
|
|
93
|
+
const cols = markerColumns(input);
|
|
94
|
+
// $1 is reserved for `id`; subsequent positions follow the order of cols.
|
|
95
|
+
const placed = cols.map((c, i) => ({
|
|
96
|
+
name: c.name,
|
|
97
|
+
expr: c.type ? `$${i + 2}::${c.type}` : `$${i + 2}`,
|
|
98
|
+
param: c.param,
|
|
99
|
+
}));
|
|
100
|
+
const params: readonly unknown[] = [1, ...placed.map((c) => c.param)];
|
|
90
101
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
app_tag = $6,
|
|
99
|
-
meta = $7::jsonb
|
|
100
|
-
where id = $1`,
|
|
101
|
-
params: baseParams,
|
|
102
|
-
};
|
|
102
|
+
// `updated_at = now()` is a SQL literal with no parameter slot, so it
|
|
103
|
+
// sits outside `placed` and is appended directly to each statement.
|
|
104
|
+
const insertColumns = ['id', ...placed.map((c) => c.name), 'updated_at'].join(', ');
|
|
105
|
+
const insertValues = ['$1', ...placed.map((c) => c.expr), 'now()'].join(', ');
|
|
106
|
+
const setClauses = [...placed.map((c) => `${c.name} = ${c.expr}`), 'updated_at = now()'].join(
|
|
107
|
+
', ',
|
|
108
|
+
);
|
|
103
109
|
|
|
104
|
-
return {
|
|
110
|
+
return {
|
|
111
|
+
insert: {
|
|
112
|
+
sql: `insert into prisma_contract.marker (${insertColumns}) values (${insertValues})`,
|
|
113
|
+
params,
|
|
114
|
+
},
|
|
115
|
+
update: {
|
|
116
|
+
sql: `update prisma_contract.marker set ${setClauses} where id = $1`,
|
|
117
|
+
params,
|
|
118
|
+
},
|
|
119
|
+
};
|
|
105
120
|
}
|
package/src/sql-runtime.ts
CHANGED
|
@@ -30,7 +30,6 @@ import { encodeParams } from './codecs/encoding';
|
|
|
30
30
|
import { validateCodecRegistryCompleteness } from './codecs/validation';
|
|
31
31
|
import { computeSqlFingerprint } from './fingerprint';
|
|
32
32
|
import { lowerSqlPlan } from './lower-sql-plan';
|
|
33
|
-
import { parseContractMarkerRow } from './marker';
|
|
34
33
|
import { runBeforeCompileChain } from './middleware/before-compile-chain';
|
|
35
34
|
import type { SqlMiddleware, SqlMiddlewareContext } from './middleware/sql-middleware';
|
|
36
35
|
import type {
|
|
@@ -381,7 +380,7 @@ class SqlRuntimeImpl<TContract extends Contract<SqlStorage> = Contract<SqlStorag
|
|
|
381
380
|
return;
|
|
382
381
|
}
|
|
383
382
|
|
|
384
|
-
const marker =
|
|
383
|
+
const marker = this.familyAdapter.markerReader.parseMarkerRow(result.rows[0]);
|
|
385
384
|
|
|
386
385
|
const contract = this.contract as {
|
|
387
386
|
storage: { storageHash: string };
|