@prisma-next/family-sql 0.0.1 → 0.1.0-pr.25.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/README.md CHANGED
@@ -76,6 +76,7 @@ The descriptor is "pure data + factory" - it only provides the hook and factory
76
76
  - **`./control`**: Control plane entry point for CLI/config usage (exports `SqlFamilyDescriptor`)
77
77
  - **`./control-adapter`**: SQL control adapter interface (`SqlControlAdapter`, `SqlControlAdapterDescriptor`) for target-specific adapters
78
78
  - **`./runtime`**: Runtime entry point (placeholder for future functionality)
79
+ - **`./verify`**: Verification utilities (`readMarker`, `readMarkerSql`, `parseContractMarkerRow`) for reading contract markers from databases
79
80
 
80
81
  ## Dependencies
81
82
 
@@ -0,0 +1,89 @@
1
+ // src/core/verify.ts
2
+ import { type } from "arktype";
3
+ var MetaSchema = type({ "[string]": "unknown" });
4
+ function parseMeta(meta) {
5
+ if (meta === null || meta === void 0) {
6
+ return {};
7
+ }
8
+ let parsed;
9
+ if (typeof meta === "string") {
10
+ try {
11
+ parsed = JSON.parse(meta);
12
+ } catch {
13
+ return {};
14
+ }
15
+ } else {
16
+ parsed = meta;
17
+ }
18
+ const result = MetaSchema(parsed);
19
+ if (result instanceof type.errors) {
20
+ return {};
21
+ }
22
+ return result;
23
+ }
24
+ var ContractMarkerRowSchema = type({
25
+ core_hash: "string",
26
+ profile_hash: "string",
27
+ "contract_json?": "unknown | null",
28
+ "canonical_version?": "number | null",
29
+ "updated_at?": "Date | string",
30
+ "app_tag?": "string | null",
31
+ "meta?": "unknown | null"
32
+ });
33
+ function parseContractMarkerRow(row) {
34
+ const result = ContractMarkerRowSchema(row);
35
+ if (result instanceof type.errors) {
36
+ const messages = result.map((p) => p.message).join("; ");
37
+ throw new Error(`Invalid contract marker row: ${messages}`);
38
+ }
39
+ const validatedRow = result;
40
+ const updatedAt = validatedRow.updated_at ? validatedRow.updated_at instanceof Date ? validatedRow.updated_at : new Date(validatedRow.updated_at) : /* @__PURE__ */ new Date();
41
+ return {
42
+ coreHash: validatedRow.core_hash,
43
+ profileHash: validatedRow.profile_hash,
44
+ contractJson: validatedRow.contract_json ?? null,
45
+ canonicalVersion: validatedRow.canonical_version ?? null,
46
+ updatedAt,
47
+ appTag: validatedRow.app_tag ?? null,
48
+ meta: parseMeta(validatedRow.meta)
49
+ };
50
+ }
51
+ function readMarkerSql() {
52
+ return {
53
+ sql: `select
54
+ core_hash,
55
+ profile_hash,
56
+ contract_json,
57
+ canonical_version,
58
+ updated_at,
59
+ app_tag,
60
+ meta
61
+ from prisma_contract.marker
62
+ where id = $1`,
63
+ params: [1]
64
+ };
65
+ }
66
+ async function readMarker(driver) {
67
+ const markerStatement = readMarkerSql();
68
+ const queryResult = await driver.query(markerStatement.sql, markerStatement.params);
69
+ if (queryResult.rows.length === 0) {
70
+ return null;
71
+ }
72
+ const markerRow = queryResult.rows[0];
73
+ if (!markerRow) {
74
+ throw new Error("Database query returned unexpected result structure");
75
+ }
76
+ return parseContractMarkerRow(markerRow);
77
+ }
78
+ function collectSupportedCodecTypeIds(descriptors) {
79
+ void descriptors;
80
+ return [];
81
+ }
82
+
83
+ export {
84
+ parseContractMarkerRow,
85
+ readMarkerSql,
86
+ readMarker,
87
+ collectSupportedCodecTypeIds
88
+ };
89
+ //# sourceMappingURL=chunk-3HYKCN35.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/verify.ts"],"sourcesContent":["import type { ContractMarkerRecord } from '@prisma-next/contract/types';\nimport type {\n ControlAdapterDescriptor,\n ControlDriverInstance,\n ControlExtensionDescriptor,\n ControlTargetDescriptor,\n} from '@prisma-next/core-control-plane/types';\nimport { type } from 'arktype';\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\n/**\n * Parses a contract marker row from database query result.\n * This is SQL-specific parsing logic (handles SQL row structure with snake_case columns).\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 coreHash: 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\n/**\n * Returns the SQL statement to read the contract marker.\n * This is a migration-plane helper (no runtime imports).\n * @internal - Used internally by readMarker(). Prefer readMarker() for Control Plane usage.\n */\nexport function readMarkerSql(): { readonly sql: string; readonly params: readonly unknown[] } {\n return {\n sql: `select\n core_hash,\n profile_hash,\n contract_json,\n canonical_version,\n updated_at,\n app_tag,\n meta\n from prisma_contract.marker\n where id = $1`,\n params: [1],\n };\n}\n\n/**\n * Reads the contract marker from the database using the provided driver.\n * Returns the parsed marker record or null if no marker is found.\n * This abstracts SQL-specific details from the Control Plane.\n *\n * @param driver - ControlDriverInstance instance for executing queries\n * @returns Promise resolving to ContractMarkerRecord or null if marker not found\n */\nexport async function readMarker(\n driver: ControlDriverInstance,\n): Promise<ContractMarkerRecord | null> {\n const markerStatement = readMarkerSql();\n const queryResult = await driver.query<{\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 }>(markerStatement.sql, markerStatement.params);\n\n if (queryResult.rows.length === 0) {\n return null;\n }\n\n const markerRow = queryResult.rows[0];\n if (!markerRow) {\n // If rows array has length > 0 but first element is undefined, this is an unexpected result structure\n throw new Error('Database query returned unexpected result structure');\n }\n\n return parseContractMarkerRow(markerRow);\n}\n\n/**\n * Collects supported codec type IDs from adapter and extension manifests.\n * Returns a sorted, unique array of type IDs that are declared in the manifests.\n * This enables coverage checks by comparing contract column types against supported types.\n *\n * Note: This extracts type IDs from manifest type imports, not from runtime codec registries.\n * The manifests declare which codec types are available, but the actual type IDs\n * are defined in the codec-types TypeScript modules that are imported.\n *\n * For MVP, we return an empty array since extracting type IDs from TypeScript modules\n * would require runtime evaluation or static analysis. This can be enhanced later.\n */\nexport function collectSupportedCodecTypeIds<TFamilyId extends string, TTargetId extends string>(\n descriptors: ReadonlyArray<\n | ControlTargetDescriptor<TFamilyId, TTargetId>\n | ControlAdapterDescriptor<TFamilyId, TTargetId>\n | ControlExtensionDescriptor<TFamilyId, TTargetId>\n >,\n): readonly string[] {\n // For MVP, return empty array\n // Future enhancement: Extract type IDs from codec-types modules via static analysis\n // or require manifests to explicitly list supported type IDs\n void descriptors;\n return [];\n}\n"],"mappings":";AAOA,SAAS,YAAY;AAErB,IAAM,aAAa,KAAK,EAAE,YAAY,UAAU,CAAC;AAEjD,SAAS,UAAU,MAAwC;AACzD,MAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,WAAO,CAAC;AAAA,EACV;AAEA,MAAI;AACJ,MAAI,OAAO,SAAS,UAAU;AAC5B,QAAI;AACF,eAAS,KAAK,MAAM,IAAI;AAAA,IAC1B,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF,OAAO;AACL,aAAS;AAAA,EACX;AAEA,QAAM,SAAS,WAAW,MAAM;AAChC,MAAI,kBAAkB,KAAK,QAAQ;AACjC,WAAO,CAAC;AAAA,EACV;AAEA,SAAO;AACT;AAEA,IAAM,0BAA0B,KAAK;AAAA,EACnC,WAAW;AAAA,EACX,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,sBAAsB;AAAA,EACtB,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,SAAS;AACX,CAAC;AAMM,SAAS,uBAAuB,KAAoC;AACzE,QAAM,SAAS,wBAAwB,GAAG;AAC1C,MAAI,kBAAkB,KAAK,QAAQ;AACjC,UAAM,WAAW,OAAO,IAAI,CAAC,MAA2B,EAAE,OAAO,EAAE,KAAK,IAAI;AAC5E,UAAM,IAAI,MAAM,gCAAgC,QAAQ,EAAE;AAAA,EAC5D;AAEA,QAAM,eAAe;AAUrB,QAAM,YAAY,aAAa,aAC3B,aAAa,sBAAsB,OACjC,aAAa,aACb,IAAI,KAAK,aAAa,UAAU,IAClC,oBAAI,KAAK;AAEb,SAAO;AAAA,IACL,UAAU,aAAa;AAAA,IACvB,aAAa,aAAa;AAAA,IAC1B,cAAc,aAAa,iBAAiB;AAAA,IAC5C,kBAAkB,aAAa,qBAAqB;AAAA,IACpD;AAAA,IACA,QAAQ,aAAa,WAAW;AAAA,IAChC,MAAM,UAAU,aAAa,IAAI;AAAA,EACnC;AACF;AAOO,SAAS,gBAA+E;AAC7F,SAAO;AAAA,IACL,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAUL,QAAQ,CAAC,CAAC;AAAA,EACZ;AACF;AAUA,eAAsB,WACpB,QACsC;AACtC,QAAM,kBAAkB,cAAc;AACtC,QAAM,cAAc,MAAM,OAAO,MAQ9B,gBAAgB,KAAK,gBAAgB,MAAM;AAE9C,MAAI,YAAY,KAAK,WAAW,GAAG;AACjC,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,YAAY,KAAK,CAAC;AACpC,MAAI,CAAC,WAAW;AAEd,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACvE;AAEA,SAAO,uBAAuB,SAAS;AACzC;AAcO,SAAS,6BACd,aAKmB;AAInB,OAAK;AACL,SAAO,CAAC;AACV;","names":[]}
@@ -1,14 +1,101 @@
1
- import * as _prisma_next_sql_contract_types from '@prisma-next/sql-contract/types';
2
- import * as _prisma_next_contract from '@prisma-next/contract';
3
- import * as _prisma_next_contract_ir from '@prisma-next/contract/ir';
4
- import { ContractIR } from '@prisma-next/contract/ir';
1
+ import { OperationRegistry } from '@prisma-next/operations';
5
2
  import { ExtensionPackManifest } from '@prisma-next/contract/pack-manifest-types';
6
3
  import { ControlFamilyInstance, ControlDriverInstance, VerifyDatabaseResult, VerifyDatabaseSchemaResult, SignDatabaseResult, EmitContractResult, ControlFamilyDescriptor, ControlTargetDescriptor, ControlAdapterDescriptor, ControlDriverDescriptor, ControlExtensionDescriptor } from '@prisma-next/core-control-plane/types';
7
- import { TypesImportSpec } from '@prisma-next/contract/types';
4
+ import { ContractIR as ContractIR$1 } from '@prisma-next/contract/ir';
5
+ import { TypesImportSpec as TypesImportSpec$1 } from '@prisma-next/contract/types';
8
6
  import { CoreSchemaView } from '@prisma-next/core-control-plane/schema-view';
9
- import { O as OperationRegistry } from './index-Bi3Sr19r.js';
10
7
  import { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';
11
8
 
9
+ type StorageColumn = {
10
+ readonly nativeType: string;
11
+ readonly codecId: string;
12
+ readonly nullable: boolean;
13
+ };
14
+ type PrimaryKey = {
15
+ readonly columns: readonly string[];
16
+ readonly name?: string;
17
+ };
18
+ type UniqueConstraint = {
19
+ readonly columns: readonly string[];
20
+ readonly name?: string;
21
+ };
22
+ type Index = {
23
+ readonly columns: readonly string[];
24
+ readonly name?: string;
25
+ };
26
+ type ForeignKeyReferences = {
27
+ readonly table: string;
28
+ readonly columns: readonly string[];
29
+ };
30
+ type ForeignKey = {
31
+ readonly columns: readonly string[];
32
+ readonly references: ForeignKeyReferences;
33
+ readonly name?: string;
34
+ };
35
+ type StorageTable = {
36
+ readonly columns: Record<string, StorageColumn>;
37
+ readonly primaryKey?: PrimaryKey;
38
+ readonly uniques: ReadonlyArray<UniqueConstraint>;
39
+ readonly indexes: ReadonlyArray<Index>;
40
+ readonly foreignKeys: ReadonlyArray<ForeignKey>;
41
+ };
42
+ type SqlStorage = {
43
+ readonly tables: Record<string, StorageTable>;
44
+ };
45
+ type ModelField = {
46
+ readonly column: string;
47
+ };
48
+ type ModelStorage = {
49
+ readonly table: string;
50
+ };
51
+ type ModelDefinition = {
52
+ readonly storage: ModelStorage;
53
+ readonly fields: Record<string, ModelField>;
54
+ readonly relations: Record<string, unknown>;
55
+ };
56
+
57
+ /**
58
+ * ContractIR types and factories for building contract intermediate representation.
59
+ * ContractIR is family-agnostic and used by authoring, emitter, and no-emit runtime.
60
+ */
61
+ /**
62
+ * ContractIR represents the intermediate representation of a contract.
63
+ * It is family-agnostic and contains generic storage, models, and relations.
64
+ * Note: coreHash and profileHash are computed by the emitter, not part of the IR.
65
+ */
66
+ interface ContractIR<TStorage extends Record<string, unknown> = Record<string, unknown>, TModels extends Record<string, unknown> = Record<string, unknown>, TRelations extends Record<string, unknown> = Record<string, unknown>> {
67
+ readonly schemaVersion: string;
68
+ readonly targetFamily: string;
69
+ readonly target: string;
70
+ readonly models: TModels;
71
+ readonly relations: TRelations;
72
+ readonly storage: TStorage;
73
+ readonly extensions: Record<string, unknown>;
74
+ readonly capabilities: Record<string, Record<string, boolean>>;
75
+ readonly meta: Record<string, unknown>;
76
+ readonly sources: Record<string, unknown>;
77
+ }
78
+
79
+ /**
80
+ * Specifies how to import TypeScript types from a package.
81
+ * Used in extension pack manifests to declare codec and operation type imports.
82
+ */
83
+ interface TypesImportSpec {
84
+ readonly package: string;
85
+ readonly named: string;
86
+ readonly alias: string;
87
+ }
88
+ /**
89
+ * Validation context passed to TargetFamilyHook.validateTypes().
90
+ * Contains pre-assembled operation registry, type imports, and extension IDs.
91
+ */
92
+ interface ValidationContext {
93
+ readonly operationRegistry?: OperationRegistry;
94
+ readonly codecTypeImports?: ReadonlyArray<TypesImportSpec>;
95
+ readonly operationTypeImports?: ReadonlyArray<TypesImportSpec>;
96
+ readonly extensionIds?: ReadonlyArray<string>;
97
+ }
98
+
12
99
  /**
13
100
  * Type metadata for SQL storage types.
14
101
  * Maps contract storage type IDs to native database types.
@@ -29,8 +116,8 @@ type SqlTypeMetadataRegistry = Map<string, SqlTypeMetadata>;
29
116
  */
30
117
  interface SqlFamilyInstanceState {
31
118
  readonly operationRegistry: OperationRegistry;
32
- readonly codecTypeImports: ReadonlyArray<TypesImportSpec>;
33
- readonly operationTypeImports: ReadonlyArray<TypesImportSpec>;
119
+ readonly codecTypeImports: ReadonlyArray<TypesImportSpec$1>;
120
+ readonly operationTypeImports: ReadonlyArray<TypesImportSpec$1>;
34
121
  readonly extensionIds: ReadonlyArray<string>;
35
122
  readonly typeMetadataRegistry: SqlTypeMetadataRegistry;
36
123
  }
@@ -108,7 +195,7 @@ interface SqlControlFamilyInstance extends ControlFamilyInstance<'sql'>, SqlFami
108
195
  * Handles stripping mappings and validation internally.
109
196
  */
110
197
  emitContract(options: {
111
- readonly contractIR: ContractIR | unknown;
198
+ readonly contractIR: ContractIR$1 | unknown;
112
199
  }): Promise<EmitContractResult>;
113
200
  }
114
201
 
@@ -123,13 +210,13 @@ declare class SqlFamilyDescriptor implements ControlFamilyDescriptor<'sql', SqlC
123
210
  readonly manifest: ExtensionPackManifest;
124
211
  readonly hook: {
125
212
  readonly id: "sql";
126
- readonly validateTypes: (ir: _prisma_next_contract_ir.ContractIR, ctx: _prisma_next_contract.ValidationContext) => void;
127
- readonly validateStructure: (ir: _prisma_next_contract_ir.ContractIR) => void;
128
- readonly generateContractTypes: (ir: _prisma_next_contract_ir.ContractIR, codecTypeImports: ReadonlyArray<_prisma_next_contract.TypesImportSpec>, operationTypeImports: ReadonlyArray<_prisma_next_contract.TypesImportSpec>) => string;
129
- readonly generateStorageType: (storage: _prisma_next_sql_contract_types.SqlStorage) => string;
130
- readonly generateModelsType: (models: Record<string, _prisma_next_sql_contract_types.ModelDefinition> | undefined, storage: _prisma_next_sql_contract_types.SqlStorage) => string;
213
+ readonly validateTypes: (ir: ContractIR, ctx: ValidationContext) => void;
214
+ readonly validateStructure: (ir: ContractIR) => void;
215
+ readonly generateContractTypes: (ir: ContractIR, codecTypeImports: ReadonlyArray<TypesImportSpec>, operationTypeImports: ReadonlyArray<TypesImportSpec>) => string;
216
+ readonly generateStorageType: (storage: SqlStorage) => string;
217
+ readonly generateModelsType: (models: Record<string, ModelDefinition> | undefined, storage: SqlStorage) => string;
131
218
  readonly generateRelationsType: (relations: Record<string, unknown> | undefined) => string;
132
- readonly generateMappingsType: (models: Record<string, _prisma_next_sql_contract_types.ModelDefinition> | undefined, storage: _prisma_next_sql_contract_types.SqlStorage, codecTypes: string, operationTypes: string) => string;
219
+ readonly generateMappingsType: (models: Record<string, ModelDefinition> | undefined, storage: SqlStorage, codecTypes: string, operationTypes: string) => string;
133
220
  };
134
221
  create<TTargetId extends string>(options: {
135
222
  readonly target: ControlTargetDescriptor<'sql', TTargetId>;
@@ -1,3 +1,8 @@
1
+ import {
2
+ collectSupportedCodecTypeIds,
3
+ readMarker
4
+ } from "./chunk-3HYKCN35.js";
5
+
1
6
  // src/core/descriptor.ts
2
7
  import { sqlTargetFamilyHook as sqlTargetFamilyHook2 } from "@prisma-next/sql-contract-emitter";
3
8
 
@@ -11,29 +16,8 @@ import {
11
16
  writeContractMarker
12
17
  } from "@prisma-next/sql-runtime";
13
18
 
14
- // ../../framework/core-operations/src/index.ts
15
- var OperationRegistryImpl = class {
16
- operations = /* @__PURE__ */ new Map();
17
- register(op) {
18
- const existing = this.operations.get(op.forTypeId) ?? [];
19
- const duplicate = existing.find((existingOp) => existingOp.method === op.method);
20
- if (duplicate) {
21
- throw new Error(
22
- `Operation method "${op.method}" already registered for typeId "${op.forTypeId}"`
23
- );
24
- }
25
- existing.push(op);
26
- this.operations.set(op.forTypeId, existing);
27
- }
28
- byType(typeId) {
29
- return this.operations.get(typeId) ?? [];
30
- }
31
- };
32
- function createOperationRegistry() {
33
- return new OperationRegistryImpl();
34
- }
35
-
36
19
  // src/core/assembly.ts
20
+ import { createOperationRegistry } from "@prisma-next/operations";
37
21
  function assembleOperationRegistry(descriptors, convertOperationManifest2) {
38
22
  const registry = createOperationRegistry();
39
23
  for (const descriptor of descriptors) {
@@ -85,88 +69,6 @@ function extractExtensionIds(adapter, target, extensions) {
85
69
  return ids;
86
70
  }
87
71
 
88
- // src/core/verify.ts
89
- import { type } from "arktype";
90
- var MetaSchema = type({ "[string]": "unknown" });
91
- function parseMeta(meta) {
92
- if (meta === null || meta === void 0) {
93
- return {};
94
- }
95
- let parsed;
96
- if (typeof meta === "string") {
97
- try {
98
- parsed = JSON.parse(meta);
99
- } catch {
100
- return {};
101
- }
102
- } else {
103
- parsed = meta;
104
- }
105
- const result = MetaSchema(parsed);
106
- if (result instanceof type.errors) {
107
- return {};
108
- }
109
- return result;
110
- }
111
- var ContractMarkerRowSchema = type({
112
- core_hash: "string",
113
- profile_hash: "string",
114
- "contract_json?": "unknown | null",
115
- "canonical_version?": "number | null",
116
- "updated_at?": "Date | string",
117
- "app_tag?": "string | null",
118
- "meta?": "unknown | null"
119
- });
120
- function parseContractMarkerRow(row) {
121
- const result = ContractMarkerRowSchema(row);
122
- if (result instanceof type.errors) {
123
- const messages = result.map((p) => p.message).join("; ");
124
- throw new Error(`Invalid contract marker row: ${messages}`);
125
- }
126
- const validatedRow = result;
127
- const updatedAt = validatedRow.updated_at ? validatedRow.updated_at instanceof Date ? validatedRow.updated_at : new Date(validatedRow.updated_at) : /* @__PURE__ */ new Date();
128
- return {
129
- coreHash: validatedRow.core_hash,
130
- profileHash: validatedRow.profile_hash,
131
- contractJson: validatedRow.contract_json ?? null,
132
- canonicalVersion: validatedRow.canonical_version ?? null,
133
- updatedAt,
134
- appTag: validatedRow.app_tag ?? null,
135
- meta: parseMeta(validatedRow.meta)
136
- };
137
- }
138
- function readMarkerSql() {
139
- return {
140
- sql: `select
141
- core_hash,
142
- profile_hash,
143
- contract_json,
144
- canonical_version,
145
- updated_at,
146
- app_tag,
147
- meta
148
- from prisma_contract.marker
149
- where id = $1`,
150
- params: [1]
151
- };
152
- }
153
- async function readMarker(driver) {
154
- const markerStatement = readMarkerSql();
155
- const queryResult = await driver.query(markerStatement.sql, markerStatement.params);
156
- if (queryResult.rows.length === 0) {
157
- return null;
158
- }
159
- const markerRow = queryResult.rows[0];
160
- if (!markerRow) {
161
- throw new Error("Database query returned unexpected result structure");
162
- }
163
- return parseContractMarkerRow(markerRow);
164
- }
165
- function collectSupportedCodecTypeIds(descriptors) {
166
- void descriptors;
167
- return [];
168
- }
169
-
170
72
  // src/core/instance.ts
171
73
  function convertOperationManifest(manifest) {
172
74
  return {
@@ -216,8 +118,8 @@ function extractCodecTypeIdsFromContract(contract) {
216
118
  if (typeof table === "object" && table !== null && "columns" in table && typeof table.columns === "object" && table.columns !== null) {
217
119
  const columns = table.columns;
218
120
  for (const column of Object.values(columns)) {
219
- if (column && typeof column === "object" && "type" in column && typeof column.type === "string") {
220
- typeIds.add(column.type);
121
+ if (column && typeof column === "object" && "codecId" in column && typeof column.codecId === "string") {
122
+ typeIds.add(column.codecId);
221
123
  }
222
124
  }
223
125
  }
@@ -895,39 +797,47 @@ function createSqlFamilyInstance(options) {
895
797
  }
896
798
  const columnChildren = [];
897
799
  let columnStatus = "pass";
898
- const typeMetadata = typeMetadataRegistry.get(contractColumn.type);
899
- const contractNativeType = typeMetadata?.nativeType;
800
+ const contractNativeType = contractColumn.nativeType;
900
801
  const schemaNativeType = schemaColumn.nativeType;
901
802
  if (!contractNativeType) {
803
+ issues.push({
804
+ kind: "type_mismatch",
805
+ table: tableName,
806
+ column: columnName,
807
+ expected: "nativeType required",
808
+ actual: schemaNativeType || "unknown",
809
+ message: `Column "${tableName}"."${columnName}" is missing nativeType in contract`
810
+ });
902
811
  columnChildren.push({
903
- status: "warn",
812
+ status: "fail",
904
813
  kind: "type",
905
814
  name: "type",
906
- contractPath: `${columnPath}.type`,
907
- code: "type_metadata_missing",
908
- message: `Contract type "${contractColumn.type}" has no nativeType metadata - native type comparison skipped`,
909
- expected: { typeId: contractColumn.type },
910
- actual: schemaColumn.typeId || schemaNativeType || "unknown",
815
+ contractPath: `${columnPath}.nativeType`,
816
+ code: "type_mismatch",
817
+ message: "Contract column is missing nativeType",
818
+ expected: "nativeType required",
819
+ actual: schemaNativeType || "unknown",
911
820
  children: []
912
821
  });
822
+ columnStatus = "fail";
913
823
  } else if (!schemaNativeType) {
914
824
  issues.push({
915
825
  kind: "type_mismatch",
916
826
  table: tableName,
917
827
  column: columnName,
918
828
  expected: contractNativeType,
919
- actual: schemaColumn.typeId || "unknown",
829
+ actual: "unknown",
920
830
  message: `Column "${tableName}"."${columnName}" has type mismatch: schema column has no nativeType`
921
831
  });
922
832
  columnChildren.push({
923
833
  status: "fail",
924
834
  kind: "type",
925
835
  name: "type",
926
- contractPath: `${columnPath}.type`,
836
+ contractPath: `${columnPath}.nativeType`,
927
837
  code: "type_mismatch",
928
838
  message: "Schema column has no nativeType",
929
839
  expected: contractNativeType,
930
- actual: schemaColumn.typeId || "unknown",
840
+ actual: "unknown",
931
841
  children: []
932
842
  });
933
843
  columnStatus = "fail";
@@ -944,7 +854,7 @@ function createSqlFamilyInstance(options) {
944
854
  status: "fail",
945
855
  kind: "type",
946
856
  name: "type",
947
- contractPath: `${columnPath}.type`,
857
+ contractPath: `${columnPath}.nativeType`,
948
858
  code: "type_mismatch",
949
859
  message: `Type mismatch: expected ${contractNativeType}, got ${schemaNativeType}`,
950
860
  expected: contractNativeType,
@@ -953,6 +863,34 @@ function createSqlFamilyInstance(options) {
953
863
  });
954
864
  columnStatus = "fail";
955
865
  }
866
+ if (contractColumn.codecId) {
867
+ const typeMetadata = typeMetadataRegistry.get(contractColumn.codecId);
868
+ if (!typeMetadata) {
869
+ columnChildren.push({
870
+ status: "warn",
871
+ kind: "type",
872
+ name: "type_metadata_missing",
873
+ contractPath: `${columnPath}.codecId`,
874
+ code: "type_metadata_missing",
875
+ message: `codecId "${contractColumn.codecId}" not found in type metadata registry`,
876
+ expected: contractColumn.codecId,
877
+ actual: void 0,
878
+ children: []
879
+ });
880
+ } else if (typeMetadata.nativeType && typeMetadata.nativeType !== contractNativeType) {
881
+ columnChildren.push({
882
+ status: "warn",
883
+ kind: "type",
884
+ name: "type_consistency",
885
+ contractPath: `${columnPath}.codecId`,
886
+ code: "type_consistency_warning",
887
+ message: `codecId "${contractColumn.codecId}" maps to nativeType "${typeMetadata.nativeType}" in registry, but contract has "${contractNativeType}"`,
888
+ expected: typeMetadata.nativeType,
889
+ actual: contractNativeType,
890
+ children: []
891
+ });
892
+ }
893
+ }
956
894
  if (contractColumn.nullable !== schemaColumn.nullable) {
957
895
  issues.push({
958
896
  kind: "nullability_mismatch",
@@ -978,7 +916,7 @@ function createSqlFamilyInstance(options) {
978
916
  const computedColumnStatus = columnChildren.some((c) => c.status === "fail") ? "fail" : columnChildren.some((c) => c.status === "warn") ? "warn" : "pass";
979
917
  const finalColumnStatus = columnChildren.length > 0 ? computedColumnStatus : columnStatus;
980
918
  const nullableText = contractColumn.nullable ? "nullable" : "not nullable";
981
- const columnTypeDisplay = contractNativeType ? `${contractColumn.type} \u2192 ${contractNativeType}` : contractColumn.type;
919
+ const columnTypeDisplay = contractColumn.codecId ? `${contractNativeType} (${contractColumn.codecId})` : contractNativeType;
982
920
  const failureMessages = columnChildren.filter((child) => child.status === "fail" && child.message).map((child) => child.message).filter((msg) => typeof msg === "string" && msg.length > 0);
983
921
  const columnMessage = finalColumnStatus === "fail" && failureMessages.length > 0 ? failureMessages.join("; ") : "";
984
922
  const columnCode = finalColumnStatus === "fail" && columnChildren.length > 0 && columnChildren[0] ? columnChildren[0].code : finalColumnStatus === "warn" && columnChildren.length > 0 && columnChildren[0] ? columnChildren[0].code : "";
@@ -1025,7 +963,7 @@ function createSqlFamilyInstance(options) {
1025
963
  code: "extra_column",
1026
964
  message: `Extra column "${columnName}" found`,
1027
965
  expected: void 0,
1028
- actual: schemaColumn.typeId,
966
+ actual: schemaColumn.nativeType,
1029
967
  children: []
1030
968
  });
1031
969
  }
@@ -1287,16 +1225,15 @@ function createSqlFamilyInstance(options) {
1287
1225
  const columnNodes = [];
1288
1226
  for (const [columnName, column] of Object.entries(table.columns)) {
1289
1227
  const nullableText = column.nullable ? "(nullable)" : "(not nullable)";
1290
- const typeDisplay = column.nativeType ?? column.typeId;
1228
+ const typeDisplay = column.nativeType;
1291
1229
  const label = `${columnName}: ${typeDisplay} ${nullableText}`;
1292
1230
  columnNodes.push({
1293
1231
  kind: "field",
1294
1232
  id: `column-${tableName}-${columnName}`,
1295
1233
  label,
1296
1234
  meta: {
1297
- typeId: column.typeId,
1298
- nullable: column.nullable,
1299
- ...column.nativeType ? { nativeType: column.nativeType } : {}
1235
+ nativeType: column.nativeType,
1236
+ nullable: column.nullable
1300
1237
  }
1301
1238
  });
1302
1239
  }