@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.
- package/dist/{authoring-type-constructors-D9b8AG6y.mjs → authoring-type-constructors-F4JpCJl7.mjs} +2 -3
- package/dist/{authoring-type-constructors-D9b8AG6y.mjs.map → authoring-type-constructors-F4JpCJl7.mjs.map} +1 -1
- package/dist/control-adapter.d.mts +9 -2
- package/dist/control-adapter.d.mts.map +1 -1
- package/dist/control-adapter.mjs +1 -1
- package/dist/control.d.mts +28 -16
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +148 -22
- package/dist/control.mjs.map +1 -1
- package/dist/migration.d.mts +1 -2
- package/dist/migration.d.mts.map +1 -1
- package/dist/migration.mjs +1 -2
- package/dist/migration.mjs.map +1 -1
- package/dist/pack.d.mts.map +1 -1
- package/dist/pack.mjs +3 -5
- package/dist/pack.mjs.map +1 -1
- package/dist/runtime.d.mts +0 -1
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +2 -6
- package/dist/runtime.mjs.map +1 -1
- package/dist/schema-verify.d.mts +2 -4
- package/dist/schema-verify.d.mts.map +1 -1
- package/dist/schema-verify.mjs +2 -3
- package/dist/test-utils.mjs +1 -2
- package/dist/{timestamp-now-generator-Bt4L3cfM.mjs → timestamp-now-generator-BWp8S2sa.mjs} +2 -2
- package/dist/{timestamp-now-generator-Bt4L3cfM.mjs.map → timestamp-now-generator-BWp8S2sa.mjs.map} +1 -1
- package/dist/{types-DFQkcr8A.d.mts → types-CIdiS2QK.d.mts} +117 -3
- package/dist/types-CIdiS2QK.d.mts.map +1 -0
- package/dist/{verify-BdES8wgQ.mjs → verify-pRYxnpiG.mjs} +2 -3
- package/dist/verify-pRYxnpiG.mjs.map +1 -0
- package/dist/{verify-sql-schema-Ovz7RXR5.mjs → verify-sql-schema-C84vejAP.mjs} +2 -6
- package/dist/verify-sql-schema-C84vejAP.mjs.map +1 -0
- package/dist/{verify-sql-schema-DW8Agf1F.d.mts → verify-sql-schema-CPHiuYHR.d.mts} +1 -2
- package/dist/verify-sql-schema-CPHiuYHR.d.mts.map +1 -0
- package/dist/verify.d.mts +0 -1
- package/dist/verify.d.mts.map +1 -1
- package/dist/verify.mjs +2 -3
- package/package.json +23 -23
- package/src/core/control-adapter.ts +11 -0
- package/src/core/control-descriptor.ts +2 -1
- package/src/core/control-instance.ts +70 -2
- package/src/core/migrations/field-event-planner.ts +196 -0
- package/src/core/migrations/types.ts +117 -1
- package/src/exports/control.ts +7 -0
- package/dist/types-DFQkcr8A.d.mts.map +0 -1
- package/dist/verify-BdES8wgQ.mjs.map +0 -1
- package/dist/verify-sql-schema-DW8Agf1F.d.mts.map +0 -1
- 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 {
|
|
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>;
|
package/src/exports/control.ts
CHANGED
|
@@ -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"}
|