@prisma-next/family-sql 0.5.0-dev.66 → 0.5.0-dev.68

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.
Files changed (48) hide show
  1. package/dist/{authoring-type-constructors-D9b8AG6y.mjs → authoring-type-constructors-F4JpCJl7.mjs} +2 -3
  2. package/dist/{authoring-type-constructors-D9b8AG6y.mjs.map → authoring-type-constructors-F4JpCJl7.mjs.map} +1 -1
  3. package/dist/control-adapter.d.mts +9 -2
  4. package/dist/control-adapter.d.mts.map +1 -1
  5. package/dist/control-adapter.mjs +1 -1
  6. package/dist/control.d.mts +28 -16
  7. package/dist/control.d.mts.map +1 -1
  8. package/dist/control.mjs +148 -22
  9. package/dist/control.mjs.map +1 -1
  10. package/dist/migration.d.mts +1 -2
  11. package/dist/migration.d.mts.map +1 -1
  12. package/dist/migration.mjs +1 -2
  13. package/dist/migration.mjs.map +1 -1
  14. package/dist/pack.d.mts.map +1 -1
  15. package/dist/pack.mjs +3 -5
  16. package/dist/pack.mjs.map +1 -1
  17. package/dist/runtime.d.mts +0 -1
  18. package/dist/runtime.d.mts.map +1 -1
  19. package/dist/runtime.mjs +2 -6
  20. package/dist/runtime.mjs.map +1 -1
  21. package/dist/schema-verify.d.mts +2 -4
  22. package/dist/schema-verify.d.mts.map +1 -1
  23. package/dist/schema-verify.mjs +2 -3
  24. package/dist/test-utils.mjs +1 -2
  25. package/dist/{timestamp-now-generator-Bt4L3cfM.mjs → timestamp-now-generator-BWp8S2sa.mjs} +2 -2
  26. package/dist/{timestamp-now-generator-Bt4L3cfM.mjs.map → timestamp-now-generator-BWp8S2sa.mjs.map} +1 -1
  27. package/dist/{types-DFQkcr8A.d.mts → types-CIdiS2QK.d.mts} +117 -3
  28. package/dist/types-CIdiS2QK.d.mts.map +1 -0
  29. package/dist/{verify-BdES8wgQ.mjs → verify-pRYxnpiG.mjs} +2 -3
  30. package/dist/verify-pRYxnpiG.mjs.map +1 -0
  31. package/dist/{verify-sql-schema-Ovz7RXR5.mjs → verify-sql-schema-C84vejAP.mjs} +2 -6
  32. package/dist/verify-sql-schema-C84vejAP.mjs.map +1 -0
  33. package/dist/{verify-sql-schema-DW8Agf1F.d.mts → verify-sql-schema-CPHiuYHR.d.mts} +1 -2
  34. package/dist/verify-sql-schema-CPHiuYHR.d.mts.map +1 -0
  35. package/dist/verify.d.mts +0 -1
  36. package/dist/verify.d.mts.map +1 -1
  37. package/dist/verify.mjs +2 -3
  38. package/package.json +23 -23
  39. package/src/core/control-adapter.ts +11 -0
  40. package/src/core/control-descriptor.ts +2 -1
  41. package/src/core/control-instance.ts +70 -2
  42. package/src/core/migrations/field-event-planner.ts +196 -0
  43. package/src/core/migrations/types.ts +117 -1
  44. package/src/exports/control.ts +7 -0
  45. package/dist/types-DFQkcr8A.d.mts.map +0 -1
  46. package/dist/verify-BdES8wgQ.mjs.map +0 -1
  47. package/dist/verify-sql-schema-DW8Agf1F.d.mts.map +0 -1
  48. package/dist/verify-sql-schema-Ovz7RXR5.mjs.map +0 -1
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Codec lifecycle hook planner — runs `onFieldEvent` for every per-field
3
+ * delta between two contracts and concatenates the returned ops in a
4
+ * deterministic order.
5
+ *
6
+ * Wired by each target's planner (`PostgresMigrationPlanner`,
7
+ * `SqliteMigrationPlanner`) so codec-emitted ops are inlined alongside
8
+ * structural DDL in the app-space migration's `ops.json`. Pure, target-
9
+ * agnostic, and only ever invoked at the app-space emitter; extension-space
10
+ * planning never reaches this helper.
11
+ *
12
+ * Ordering rules:
13
+ *
14
+ * - Events are grouped by phase: `'added'` → `'dropped'` → `'altered'`.
15
+ * - Within each phase, entries are sorted alphabetically by
16
+ * `(tableName, fieldName)`.
17
+ * - The hook's returned ops are appended in the order the hook returned them.
18
+ *
19
+ * `'altered'` is suppressed when only `codecId` differs (codec rotation is a
20
+ * v1 non-goal).
21
+ */
22
+
23
+ import type { Contract } from '@prisma-next/contract/types';
24
+ import type { SqlStorage, StorageColumn, StorageTable } from '@prisma-next/sql-contract/types';
25
+ import type {
26
+ CodecControlHooks,
27
+ FieldEvent,
28
+ FieldEventContext,
29
+ SqlMigrationPlanOperation,
30
+ } from './types';
31
+
32
+ export interface PlanFieldEventOperationsOptions {
33
+ /**
34
+ * Prior contract the planner is diffing against. `null` for first emits
35
+ * (every field is treated as added).
36
+ */
37
+ readonly priorContract: Contract<SqlStorage> | null;
38
+ /**
39
+ * New contract the user just authored.
40
+ */
41
+ readonly newContract: Contract<SqlStorage>;
42
+ /**
43
+ * Codec-id keyed map of control hooks, as produced by
44
+ * {@link import('./assembly').extractCodecControlHooks}. Hooks carry
45
+ * `unknown` target details after extraction; the caller casts the
46
+ * helper's returned ops to its target's `SqlMigrationPlanOperation`
47
+ * specialisation at the integration boundary, mirroring how
48
+ * `storageTypePlanCallStrategy` lifts `planTypeOperations` results into
49
+ * `RawSqlCall`.
50
+ */
51
+ readonly codecHooks: ReadonlyMap<string, CodecControlHooks>;
52
+ }
53
+
54
+ interface FieldEntry {
55
+ readonly tableName: string;
56
+ readonly fieldName: string;
57
+ readonly priorTable: StorageTable | undefined;
58
+ readonly newTable: StorageTable | undefined;
59
+ readonly priorField: StorageColumn | undefined;
60
+ readonly newField: StorageColumn | undefined;
61
+ }
62
+
63
+ export function planFieldEventOperations(
64
+ options: PlanFieldEventOperationsOptions,
65
+ ): readonly SqlMigrationPlanOperation<unknown>[] {
66
+ const priorTables = options.priorContract?.storage.tables ?? {};
67
+ const newTables = options.newContract.storage.tables;
68
+
69
+ const added: FieldEntry[] = [];
70
+ const dropped: FieldEntry[] = [];
71
+ const altered: FieldEntry[] = [];
72
+
73
+ const tableNames = unionSorted(Object.keys(priorTables), Object.keys(newTables));
74
+ for (const tableName of tableNames) {
75
+ const priorTable = priorTables[tableName];
76
+ const newTable = newTables[tableName];
77
+ const fieldNames = unionSorted(
78
+ priorTable ? Object.keys(priorTable.columns) : [],
79
+ newTable ? Object.keys(newTable.columns) : [],
80
+ );
81
+ for (const fieldName of fieldNames) {
82
+ const priorField = priorTable?.columns[fieldName];
83
+ const newField = newTable?.columns[fieldName];
84
+ const entry: FieldEntry = {
85
+ tableName,
86
+ fieldName,
87
+ priorTable,
88
+ newTable,
89
+ priorField,
90
+ newField,
91
+ };
92
+ if (priorField === undefined && newField !== undefined) {
93
+ added.push(entry);
94
+ } else if (priorField !== undefined && newField === undefined) {
95
+ dropped.push(entry);
96
+ } else if (priorField !== undefined && newField !== undefined) {
97
+ if (isAlteration(priorField, newField)) altered.push(entry);
98
+ }
99
+ }
100
+ }
101
+
102
+ const ops: SqlMigrationPlanOperation<unknown>[] = [];
103
+ appendOps('added', added, options.codecHooks, ops, (e) => e.newField?.codecId);
104
+ appendOps('dropped', dropped, options.codecHooks, ops, (e) => e.priorField?.codecId);
105
+ appendOps('altered', altered, options.codecHooks, ops, (e) => e.newField?.codecId);
106
+ return ops;
107
+ }
108
+
109
+ function appendOps(
110
+ event: FieldEvent,
111
+ entries: readonly FieldEntry[],
112
+ codecHooks: ReadonlyMap<string, CodecControlHooks>,
113
+ ops: SqlMigrationPlanOperation<unknown>[],
114
+ pickCodecId: (entry: FieldEntry) => string | undefined,
115
+ ): void {
116
+ for (const entry of entries) {
117
+ const codecId = pickCodecId(entry);
118
+ if (codecId === undefined) continue;
119
+ const hook = codecHooks.get(codecId);
120
+ if (!hook?.onFieldEvent) continue;
121
+ const ctx = buildContext(event, entry);
122
+ const emitted = hook.onFieldEvent(event, ctx);
123
+ for (const op of emitted) ops.push(op);
124
+ }
125
+ }
126
+
127
+ /**
128
+ * The context's prior/new sides are scoped to the event:
129
+ *
130
+ * - `'added'` — only `newTable` / `newField` populated.
131
+ * - `'dropped'` — only `priorTable` / `priorField` populated.
132
+ * - `'altered'` — both sides populated.
133
+ */
134
+ function buildContext(event: FieldEvent, entry: FieldEntry): FieldEventContext {
135
+ const base = { tableName: entry.tableName, fieldName: entry.fieldName };
136
+ if (event === 'added') {
137
+ return {
138
+ ...base,
139
+ ...(entry.newTable !== undefined ? { newTable: entry.newTable } : {}),
140
+ ...(entry.newField !== undefined ? { newField: entry.newField } : {}),
141
+ };
142
+ }
143
+ if (event === 'dropped') {
144
+ return {
145
+ ...base,
146
+ ...(entry.priorTable !== undefined ? { priorTable: entry.priorTable } : {}),
147
+ ...(entry.priorField !== undefined ? { priorField: entry.priorField } : {}),
148
+ };
149
+ }
150
+ return {
151
+ ...base,
152
+ ...(entry.priorTable !== undefined ? { priorTable: entry.priorTable } : {}),
153
+ ...(entry.newTable !== undefined ? { newTable: entry.newTable } : {}),
154
+ ...(entry.priorField !== undefined ? { priorField: entry.priorField } : {}),
155
+ ...(entry.newField !== undefined ? { newField: entry.newField } : {}),
156
+ };
157
+ }
158
+
159
+ /**
160
+ * `'altered'` predicate. Returns `false` whenever `codecId` differs —
161
+ * any codec change suppresses the `altered` event entirely, including
162
+ * cases where another property also differs in the same diff. Codec
163
+ * rotation is a v1 non-goal (project spec § Non-goals); avoiding the
164
+ * mixed event keeps the migration semantics for codec changes explicit
165
+ * (out of scope) rather than smuggling them through as `altered`.
166
+ *
167
+ * For non-`codecId` diffs, returns `true` iff any other column property
168
+ * differs.
169
+ */
170
+ function isAlteration(prior: StorageColumn, current: StorageColumn): boolean {
171
+ if (prior.codecId !== current.codecId) return false;
172
+ return !sameStorageColumn(prior, current);
173
+ }
174
+
175
+ function sameStorageColumn(a: StorageColumn, b: StorageColumn): boolean {
176
+ if (a === b) return true;
177
+ if (a.nativeType !== b.nativeType) return false;
178
+ if (a.nullable !== b.nullable) return false;
179
+ if (a.typeRef !== b.typeRef) return false;
180
+ if (!sameJson(a.typeParams, b.typeParams)) return false;
181
+ if (!sameJson(a.default, b.default)) return false;
182
+ return true;
183
+ }
184
+
185
+ function sameJson(a: unknown, b: unknown): boolean {
186
+ if (a === b) return true;
187
+ if (a === undefined || b === undefined) return false;
188
+ return JSON.stringify(a) === JSON.stringify(b);
189
+ }
190
+
191
+ function unionSorted(a: readonly string[], b: readonly string[]): readonly string[] {
192
+ const set = new Set<string>();
193
+ for (const name of a) set.add(name);
194
+ for (const name of b) set.add(name);
195
+ return [...set].sort((x, y) => (x < y ? -1 : x > y ? 1 : 0));
196
+ }
@@ -18,7 +18,12 @@ import type {
18
18
  OperationContext,
19
19
  SchemaIssue,
20
20
  } from '@prisma-next/framework-components/control';
21
- import type { SqlStorage, StorageTypeInstance } from '@prisma-next/sql-contract/types';
21
+ import type {
22
+ SqlStorage,
23
+ StorageColumn,
24
+ StorageTable,
25
+ StorageTypeInstance,
26
+ } from '@prisma-next/sql-contract/types';
22
27
  import type { SqlOperationDescriptor } from '@prisma-next/sql-operations';
23
28
  import type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';
24
29
  import type { Result } from '@prisma-next/utils/result';
@@ -83,6 +88,41 @@ export interface ResolveIdentityValueInput {
83
88
  readonly typeParams?: Record<string, unknown>;
84
89
  }
85
90
 
91
+ /**
92
+ * Per-field lifecycle event a codec hook can react to.
93
+ *
94
+ * Fired during app-space migration emission as the SQL family diffs the
95
+ * prior contract against the new contract.
96
+ *
97
+ * - `'added'` — the field is present in the new contract but not the prior.
98
+ * - `'dropped'` — the field is present in the prior contract but not the new.
99
+ * - `'altered'` — the field is present in both and any property other than
100
+ * `codecId` differs. Codec-id changes are a v1 non-goal:
101
+ * when only `codecId` differs, no `'altered'` event fires.
102
+ */
103
+ export type FieldEvent = 'added' | 'dropped' | 'altered';
104
+
105
+ /**
106
+ * Context passed to {@link CodecControlHooks.onFieldEvent}.
107
+ *
108
+ * `tableName` and `fieldName` are always populated; `priorTable` /
109
+ * `priorField` carry the prior contract's view of the table and column
110
+ * (present for `'dropped'` and `'altered'`); `newTable` / `newField`
111
+ * carry the new contract's view (present for `'added'` and `'altered'`).
112
+ *
113
+ * The hook only ever receives app-space contract IR — extension-space
114
+ * fields are scoped out by the API: the hook is wired at the
115
+ * application emitter only.
116
+ */
117
+ export interface FieldEventContext {
118
+ readonly tableName: string;
119
+ readonly fieldName: string;
120
+ readonly priorTable?: StorageTable;
121
+ readonly newTable?: StorageTable;
122
+ readonly priorField?: StorageColumn;
123
+ readonly newField?: StorageColumn;
124
+ }
125
+
86
126
  export interface CodecControlHooks<TTargetDetails = unknown> {
87
127
  planTypeOperations?: (options: {
88
128
  readonly typeName: string;
@@ -123,6 +163,21 @@ export interface CodecControlHooks<TTargetDetails = unknown> {
123
163
  * - undefined: no opinion; planner may use built-in fallbacks
124
164
  */
125
165
  resolveIdentityValue?: (input: ResolveIdentityValueInput) => string | null | undefined;
166
+ /**
167
+ * Reacts to per-field added / dropped / altered events as the app-space
168
+ * emitter diffs the prior contract against the new contract. Returned
169
+ * ops are inlined into the app-space migration's `ops.json` alongside
170
+ * the user's structural ops.
171
+ *
172
+ * Synchronous. Each returned op must carry its own `invariantId`. Hooks
173
+ * are dispatched per `(table, field)` based on the field's `codecId`
174
+ * (the new field's codec for `'added'` / `'altered'`; the prior field's
175
+ * codec for `'dropped'`).
176
+ */
177
+ onFieldEvent?: (
178
+ event: FieldEvent,
179
+ ctx: FieldEventContext,
180
+ ) => readonly SqlMigrationPlanOperation<TTargetDetails>[];
126
181
  }
127
182
 
128
183
  export interface SqlControlExtensionDescriptor<TTargetId extends string>
@@ -320,6 +375,14 @@ export interface SqlMigrationRunnerExecuteCallbacks<TTargetDetails> {
320
375
  export interface SqlMigrationRunnerExecuteOptions<TTargetDetails> {
321
376
  readonly plan: SqlMigrationPlan<TTargetDetails>;
322
377
  readonly driver: ControlDriverInstance<'sql', string>;
378
+ /**
379
+ * Logical contract space this plan applies to. When omitted the
380
+ * runner derives the space from {@link SqlMigrationPlan.spaceId};
381
+ * when supplied, the runner asserts it matches `plan.spaceId` so a
382
+ * caller cannot accidentally write the marker row for a different
383
+ * space than the plan was produced for.
384
+ */
385
+ readonly space?: string;
323
386
  /**
324
387
  * Destination contract IR.
325
388
  * Must correspond to `plan.destination` and is used for schema verification and marker/ledger writes.
@@ -371,11 +434,64 @@ export type SqlMigrationRunnerResult = Result<
371
434
  >;
372
435
 
373
436
  export interface SqlMigrationRunner<TTargetDetails> {
437
+ /**
438
+ * Apply a single migration plan, opening and managing its own
439
+ * transaction (and any target-specific connection-level setup, e.g.
440
+ * SQLite's `PRAGMA foreign_keys` toggle). Existing single-space
441
+ * callers route through here.
442
+ */
374
443
  execute(
375
444
  options: SqlMigrationRunnerExecuteOptions<TTargetDetails>,
376
445
  ): Promise<SqlMigrationRunnerResult>;
446
+
447
+ /**
448
+ * Apply a single migration plan against an already-open connection
449
+ * **without** opening a transaction. The caller is responsible for
450
+ * wrapping the call (and any siblings) in `BEGIN` / `COMMIT` /
451
+ * `ROLLBACK`. Used by the per-space runner wiring to fan out across
452
+ * contract spaces inside one outer transaction so a mid-apply
453
+ * failure rolls back every space's writes.
454
+ *
455
+ * Idempotent control-table setup (`prisma_contract.*`) and marker
456
+ * writes use `options.space` to address the per-space marker row.
457
+ */
458
+ executeOnConnection(
459
+ options: SqlMigrationRunnerExecuteOptions<TTargetDetails>,
460
+ ): Promise<SqlMigrationRunnerResult>;
461
+
462
+ /**
463
+ * Apply per-space plans across multiple contract spaces inside a
464
+ * single outer transaction. The caller orders the input list
465
+ * (typically via the aggregate planner's `applyOrder`: extensions
466
+ * alphabetical, then app); the runner is responsible for opening
467
+ * / committing the outer
468
+ * transaction (and any target-specific connection-level setup such
469
+ * as the SQLite FK pragma toggle). A failure on any space rolls
470
+ * back every space's writes.
471
+ *
472
+ * Each space's `SqlMigrationRunnerExecuteOptions` must reference the
473
+ * same `driver` (the connection the outer transaction is open on).
474
+ * Per-space marker writes use `options.space` to address the row.
475
+ */
476
+ executeAcrossSpaces(options: {
477
+ readonly driver: ControlDriverInstance<'sql', string>;
478
+ readonly perSpaceOptions: ReadonlyArray<SqlMigrationRunnerExecuteOptions<TTargetDetails>>;
479
+ }): Promise<MultiSpaceRunnerResult>;
480
+ }
481
+
482
+ export interface MultiSpaceRunnerSuccessValue {
483
+ readonly perSpaceResults: ReadonlyArray<{
484
+ readonly space: string;
485
+ readonly value: SqlMigrationRunnerSuccessValue;
486
+ }>;
487
+ }
488
+
489
+ export interface MultiSpaceRunnerFailure extends SqlMigrationRunnerFailure {
490
+ readonly failingSpace: string;
377
491
  }
378
492
 
493
+ export type MultiSpaceRunnerResult = Result<MultiSpaceRunnerSuccessValue, MultiSpaceRunnerFailure>;
494
+
379
495
  export interface SqlControlTargetDescriptor<TTargetId extends string, TTargetDetails>
380
496
  extends MigratableTargetDescriptor<'sql', TTargetId, SqlControlFamilyInstance> {
381
497
  readonly queryOperations?: () => ReadonlyArray<SqlOperationDescriptor>;
@@ -24,6 +24,8 @@ export {
24
24
  contractToSchemaIR,
25
25
  detectDestructiveChanges,
26
26
  } from '../core/migrations/contract-to-schema-ir';
27
+ export type { PlanFieldEventOperationsOptions } from '../core/migrations/field-event-planner';
28
+ export { planFieldEventOperations } from '../core/migrations/field-event-planner';
27
29
  export {
28
30
  createMigrationPlan,
29
31
  plannerFailure,
@@ -38,6 +40,11 @@ export type {
38
40
  ComponentDatabaseDependency,
39
41
  CreateSqlMigrationPlanOptions,
40
42
  ExpandNativeTypeInput,
43
+ FieldEvent,
44
+ FieldEventContext,
45
+ MultiSpaceRunnerFailure,
46
+ MultiSpaceRunnerResult,
47
+ MultiSpaceRunnerSuccessValue,
41
48
  ResolveIdentityValueInput,
42
49
  SqlControlAdapterDescriptor,
43
50
  SqlControlExtensionDescriptor,
@@ -1 +0,0 @@
1
- {"version":3,"file":"types-DFQkcr8A.d.mts","names":[],"sources":["../src/core/control-instance.ts","../src/core/migrations/types.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"verify-BdES8wgQ.mjs","names":["parsed: unknown"],"sources":["../src/core/verify.ts"],"sourcesContent":["import type { ContractMarkerRecord } from '@prisma-next/contract/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\n/**\n * SQLite stores `contract_json` as TEXT, so the wire shape is a JSON string;\n * Postgres uses `jsonb` and returns an already-parsed value. Normalize both\n * here so `ContractMarkerRecord.contractJson` is always the structured form.\n */\nfunction parseContractJson(value: unknown): unknown {\n if (value === null || value === undefined) return null;\n if (typeof value !== 'string') return value;\n try {\n return JSON.parse(value);\n } catch {\n return null;\n }\n}\n\n/**\n * Wire shape of a `prisma_contract.marker` row as it comes out of a SQL\n * driver. Snake-cased to match the on-disk column names. Shared by every\n * SQL target's `readMarker` so each runner doesn't redeclare it inline.\n */\nexport type ContractMarkerRow = {\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 // SQLite stores arrays as JSON-TEXT, so this is `string` on the wire from\n // a SQLite driver and `string[]` from a Postgres driver. Targets normalize\n // before passing to `parseContractMarkerRow`.\n invariants: 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 invariants: type('string').array(),\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 updatedAt = result.updated_at\n ? result.updated_at instanceof Date\n ? result.updated_at\n : new Date(result.updated_at)\n : new Date();\n\n return {\n storageHash: result.core_hash,\n profileHash: result.profile_hash,\n contractJson: parseContractJson(result.contract_json),\n canonicalVersion: result.canonical_version ?? null,\n updatedAt,\n appTag: result.app_tag ?? null,\n meta: parseMeta(result.meta),\n invariants: result.invariants,\n };\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(\n descriptors: ReadonlyArray<{ readonly id: string }>,\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":";;;AAGA,MAAM,aAAa,KAAK,EAAE,YAAY,WAAW,CAAC;AAElD,SAAS,UAAU,MAAwC;AACzD,KAAI,SAAS,QAAQ,SAAS,OAC5B,QAAO,EAAE;CAGX,IAAIA;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;;;;;;;AAQT,SAAS,kBAAkB,OAAyB;AAClD,KAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,KAAI,OAAO,UAAU,SAAU,QAAO;AACtC,KAAI;AACF,SAAO,KAAK,MAAM,MAAM;SAClB;AACN,SAAO;;;AAuBX,MAAM,0BAA0B,KAAK;CACnC,WAAW;CACX,cAAc;CACd,kBAAkB;CAClB,sBAAsB;CACtB,eAAe;CACf,YAAY;CACZ,SAAS;CACT,YAAY,KAAK,SAAS,CAAC,OAAO;CACnC,CAAC;;;;;AAMF,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,YAAY,OAAO,aACrB,OAAO,sBAAsB,OAC3B,OAAO,aACP,IAAI,KAAK,OAAO,WAAW,mBAC7B,IAAI,MAAM;AAEd,QAAO;EACL,aAAa,OAAO;EACpB,aAAa,OAAO;EACpB,cAAc,kBAAkB,OAAO,cAAc;EACrD,kBAAkB,OAAO,qBAAqB;EAC9C;EACA,QAAQ,OAAO,WAAW;EAC1B,MAAM,UAAU,OAAO,KAAK;EAC5B,YAAY,OAAO;EACpB;;;;;;;;;;;;;;AAeH,SAAgB,6BACd,aACmB;AAKnB,QAAO,EAAE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"verify-sql-schema-DW8Agf1F.d.mts","names":[],"sources":["../src/core/schema-verify/verify-sql-schema.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;AAqEgC,KA9BpB,iBAAA,GA8BoB,CAAA,UAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,GA3B3B,aA2B2B,GAAA,SAAA;;;;AAyBhC;;KA7CY,oBAAA;;;;UAKK,sBAAA;;qBAEI,SAAS;;mBAEX;;;;qBAIE;;iCAEY;;;;;;;gCAKD,cAAc;;;;;;8BAMhB;;;;;;iCAMG;;;;;;;;;;;;iBAajB,eAAA,UAAyB,yBAAyB"}