@prisma-next/sql-schema-ir 0.14.0-dev.8 → 0.14.0-dev.81

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.
@@ -1,6 +1,9 @@
1
+ import type { DiffableNode } from '@prisma-next/framework-components/control';
1
2
  import { freezeNode } from '@prisma-next/framework-components/ir';
3
+ import { blindCast } from '@prisma-next/utils/casts';
4
+ import { RelationalSchemaNodeKind } from './schema-node-kinds';
2
5
  import type { SqlAnnotations } from './sql-column-ir';
3
- import { SqlSchemaIRNode } from './sql-schema-ir-node';
6
+ import { assertNode, SqlSchemaIRNode } from './sql-schema-ir-node';
4
7
 
5
8
  export interface SqlIndexIRInput {
6
9
  readonly columns: readonly string[];
@@ -17,8 +20,18 @@ export interface SqlIndexIRInput {
17
20
  * `unique` field — introspection sees the underlying index regardless
18
21
  * of whether the user expressed it as `@@index` or `@@unique`, and the
19
22
  * verifier needs to distinguish them when comparing to the Contract.
23
+ *
24
+ * Implements `DiffableNode` so an index is directly a table's diff-tree
25
+ * child. Indexes are frequently unnamed, so `id` is derived from the column
26
+ * tuple — the same tuple that makes two indexes the same index, so it
27
+ * doubles as the pairing key. `isEqualTo` is symmetric structural equality
28
+ * on the remaining attributes: `unique`, `type`, and `options`. A unique
29
+ * index and a non-unique index on the same columns are different objects
30
+ * and are not equal — there is no "stronger satisfies weaker".
20
31
  */
21
- export class SqlIndexIR extends SqlSchemaIRNode {
32
+ export class SqlIndexIR extends SqlSchemaIRNode implements DiffableNode {
33
+ override readonly nodeKind = RelationalSchemaNodeKind.index;
34
+
22
35
  readonly columns: readonly string[];
23
36
  readonly unique: boolean;
24
37
  declare readonly name?: string;
@@ -36,4 +49,62 @@ export class SqlIndexIR extends SqlSchemaIRNode {
36
49
  if (input.annotations !== undefined) this.annotations = input.annotations;
37
50
  freezeNode(this);
38
51
  }
52
+
53
+ get id(): string {
54
+ return `index:${this.columns.join(',')}`;
55
+ }
56
+
57
+ children(): readonly DiffableNode[] {
58
+ return [];
59
+ }
60
+
61
+ static is(node: SqlSchemaIRNode): node is SqlIndexIR {
62
+ return node.nodeKind === RelationalSchemaNodeKind.index;
63
+ }
64
+
65
+ /**
66
+ * Symmetric structural equality: two paired index nodes are equal iff their
67
+ * `unique` flag, `type`, and (loosely-compared) `options` all match. There
68
+ * is no satisfaction — a unique index does not equal a non-unique index.
69
+ * `options` compares loosely (introspection stringifies reloptions); `type`
70
+ * compares strictly after the introspection-side btree→undefined
71
+ * normalization done at construction.
72
+ */
73
+ isEqualTo(other: DiffableNode): boolean {
74
+ const node = blindCast<
75
+ SqlSchemaIRNode,
76
+ 'every diff-tree node the differ pairs is a SqlSchemaIRNode'
77
+ >(other);
78
+ assertNode(node, 'SqlIndexIR', SqlIndexIR.is);
79
+ return (
80
+ this.unique === node.unique &&
81
+ this.type === node.type &&
82
+ indexOptionsLooselyEqual(this.options, node.options)
83
+ );
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Option-bag equality ported from the relational walk: same key set, values
89
+ * compared via `String()` coercion — Postgres introspection returns
90
+ * reloptions values as raw strings (`'70'`, `'false'`) while contract option
91
+ * leaves are typed (number, boolean, string).
92
+ */
93
+ function indexOptionsLooselyEqual(
94
+ a: Record<string, unknown> | undefined,
95
+ b: Record<string, unknown> | undefined,
96
+ ): boolean {
97
+ const aKeys = a ? Object.keys(a).sort() : [];
98
+ const bKeys = b ? Object.keys(b).sort() : [];
99
+ if (aKeys.length !== bKeys.length) return false;
100
+ for (let i = 0; i < aKeys.length; i += 1) {
101
+ if (aKeys[i] !== bKeys[i]) return false;
102
+ }
103
+ if (aKeys.length === 0) return true;
104
+ for (const key of aKeys) {
105
+ if (String(a?.[key]) !== String(b?.[key])) {
106
+ return false;
107
+ }
108
+ }
109
+ return true;
39
110
  }
@@ -7,20 +7,32 @@ import { IRNodeBase } from '@prisma-next/framework-components/ir';
7
7
  *
8
8
  * SQL Schema IR represents the actual database state as discovered by
9
9
  * introspection (the parallel to SQL Contract IR, which represents the
10
- * desired state). Like the Contract side, today's Schema IR has no
11
- * polymorphic dispatch — verifiers and planners walk by structural
12
- * position, not by inspecting `kind` — so a single family-level
13
- * discriminator is sufficient. Future per-leaf overrides land cleanly
14
- * the same way as on the Contract side.
10
+ * desired state).
15
11
  *
16
12
  * The discriminator is installed as a non-enumerable own property,
17
13
  * matching the SqlNode pattern. This keeps `JSON.stringify(node)`
18
14
  * canonical (no `kind` field), keeps `toEqual({...})` test assertions
19
15
  * against pre-lift flat shapes passing, and keeps `node.kind` readable
20
- * for future polymorphic dispatch.
16
+ * for dispatch.
17
+ *
18
+ * Both `kind` and `nodeKind` are required: every concrete leaf is a node
19
+ * the generic differ can pair and compare, so every leaf must declare which
20
+ * node it is. `nodeKind` has no default here — every direct subclass sets its
21
+ * own literal value (the relational leaves via `RelationalSchemaNodeKind`,
22
+ * target concretions via their own vocabulary, e.g. `PostgresSchemaNodeKind`).
21
23
  */
22
24
  export abstract class SqlSchemaIRNode extends IRNodeBase {
23
- readonly kind?: string;
25
+ declare readonly kind: string;
26
+
27
+ /**
28
+ * Enumerable discriminant identifying which node this is (column / primary
29
+ * key / foreign key / unique / index / check / database / namespace /
30
+ * table / policy / role / …). Concretions set a unique value; the
31
+ * `.is`/`.assert` guards compare against it. Unlike `kind`, it is
32
+ * enumerable, so it survives a spread that flattens a node into a plain
33
+ * object.
34
+ */
35
+ abstract readonly nodeKind: string;
24
36
 
25
37
  constructor() {
26
38
  super();
@@ -32,3 +44,42 @@ export abstract class SqlSchemaIRNode extends IRNodeBase {
32
44
  });
33
45
  }
34
46
  }
47
+
48
+ /**
49
+ * Asserts `node` matches `predicate`, narrowing its type to `T`. The one
50
+ * shared implementation every node class's `static assert` and `isEqualTo`
51
+ * reach for, instead of each hand-writing its own throw: the message names
52
+ * the class the caller expected.
53
+ */
54
+ export function assertNode<T extends SqlSchemaIRNode>(
55
+ node: SqlSchemaIRNode | undefined,
56
+ className: string,
57
+ predicate: (node: SqlSchemaIRNode) => node is T,
58
+ ): asserts node is T {
59
+ if (node === undefined || !predicate(node)) {
60
+ throw new Error(`Expected a ${className} but got nodeKind=${node?.nodeKind ?? 'undefined'}`);
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Defines a non-enumerable own property, the same treatment `kind` gets
66
+ * above: a derivation-time render-support field stays out of
67
+ * `JSON.stringify`, `toEqual({...})` structural assertions, and spreads,
68
+ * while remaining directly readable (`node.field`) for the one consumer
69
+ * that resolves it at plan time. A no-op when `value` is `undefined` — the
70
+ * property is simply absent, matching every other optional field on these
71
+ * nodes.
72
+ */
73
+ export function defineNonEnumerable<T extends object>(
74
+ target: T,
75
+ key: string,
76
+ value: unknown,
77
+ ): void {
78
+ if (value === undefined) return;
79
+ Object.defineProperty(target, key, {
80
+ value,
81
+ enumerable: false,
82
+ writable: false,
83
+ configurable: false,
84
+ });
85
+ }
@@ -1,4 +1,6 @@
1
+ import type { DiffableNode } from '@prisma-next/framework-components/control';
1
2
  import { freezeNode } from '@prisma-next/framework-components/ir';
3
+ import { RelationalSchemaNodeKind } from './schema-node-kinds';
2
4
  import type { SqlAnnotations } from './sql-column-ir';
3
5
  import { SqlSchemaIRNode } from './sql-schema-ir-node';
4
6
  import { SqlTableIR, type SqlTableIRInput } from './sql-table-ir';
@@ -17,8 +19,15 @@ export interface SqlSchemaIRInput {
17
19
  * The constructor normalises nested `SqlTableIR` instances so
18
20
  * downstream walks see a uniform AST regardless of whether the input
19
21
  * was a plain-data literal or already-constructed class instances.
22
+ *
23
+ * Implements `DiffableNode` as the root of a flat (single-schema) diff
24
+ * tree: `id` is the fixed sentinel `'database'` (roots have no siblings),
25
+ * `isEqualTo` is identity (a container has no own attributes), and
26
+ * `children()` yields the table nodes.
20
27
  */
21
- export class SqlSchemaIR extends SqlSchemaIRNode {
28
+ export class SqlSchemaIR extends SqlSchemaIRNode implements DiffableNode {
29
+ override readonly nodeKind = RelationalSchemaNodeKind.schema;
30
+
22
31
  readonly tables: Readonly<Record<string, SqlTableIR>>;
23
32
  declare readonly annotations?: SqlAnnotations;
24
33
 
@@ -35,4 +44,16 @@ export class SqlSchemaIR extends SqlSchemaIRNode {
35
44
  if (input.annotations !== undefined) this.annotations = input.annotations;
36
45
  freezeNode(this);
37
46
  }
47
+
48
+ get id(): string {
49
+ return 'database';
50
+ }
51
+
52
+ isEqualTo(other: DiffableNode): boolean {
53
+ return this.id === other.id;
54
+ }
55
+
56
+ children(): readonly DiffableNode[] {
57
+ return Object.values(this.tables);
58
+ }
38
59
  }
@@ -1,5 +1,7 @@
1
+ import type { DiffableNode } from '@prisma-next/framework-components/control';
1
2
  import { freezeNode } from '@prisma-next/framework-components/ir';
2
3
  import { PrimaryKey, type PrimaryKeyInput } from './primary-key';
4
+ import { RelationalSchemaNodeKind } from './schema-node-kinds';
3
5
  import { SqlCheckConstraintIR, type SqlCheckConstraintIRInput } from './sql-check-constraint-ir';
4
6
  import { type SqlAnnotations, SqlColumnIR, type SqlColumnIRInput } from './sql-column-ir';
5
7
  import { SqlForeignKeyIR, type SqlForeignKeyIRInput } from './sql-foreign-key-ir';
@@ -32,8 +34,17 @@ export interface SqlTableIRInput {
32
34
  * walks see a uniform AST regardless of whether the input was a
33
35
  * plain-data literal (from introspection) or already-constructed
34
36
  * class instances.
37
+ *
38
+ * Implements `DiffableNode` so a flat (single-schema) tree is directly
39
+ * diffable: `id` is the table name; `isEqualTo` is identity (the table's
40
+ * structural drift is entirely expressed by its children); `children()`
41
+ * yields every column, the primary key (when present), every foreign key,
42
+ * unique, index, and check constraint — the same composition and order as
43
+ * the Postgres table node, minus policies.
35
44
  */
36
- export class SqlTableIR extends SqlSchemaIRNode {
45
+ export class SqlTableIR extends SqlSchemaIRNode implements DiffableNode {
46
+ override readonly nodeKind = RelationalSchemaNodeKind.table;
47
+
37
48
  readonly name: string;
38
49
  readonly columns: Readonly<Record<string, SqlColumnIR>>;
39
50
  readonly foreignKeys: ReadonlyArray<SqlForeignKeyIR>;
@@ -79,4 +90,23 @@ export class SqlTableIR extends SqlSchemaIRNode {
79
90
  }
80
91
  freezeNode(this);
81
92
  }
93
+
94
+ get id(): string {
95
+ return this.name;
96
+ }
97
+
98
+ isEqualTo(other: DiffableNode): boolean {
99
+ return this.id === other.id;
100
+ }
101
+
102
+ children(): readonly DiffableNode[] {
103
+ return [
104
+ ...Object.values(this.columns),
105
+ ...(this.primaryKey ? [this.primaryKey] : []),
106
+ ...this.foreignKeys,
107
+ ...this.uniques,
108
+ ...this.indexes,
109
+ ...(this.checks ?? []),
110
+ ];
111
+ }
82
112
  }
@@ -1,6 +1,9 @@
1
+ import type { DiffableNode } from '@prisma-next/framework-components/control';
1
2
  import { freezeNode } from '@prisma-next/framework-components/ir';
3
+ import { blindCast } from '@prisma-next/utils/casts';
4
+ import { RelationalSchemaNodeKind } from './schema-node-kinds';
2
5
  import type { SqlAnnotations } from './sql-column-ir';
3
- import { SqlSchemaIRNode } from './sql-schema-ir-node';
6
+ import { assertNode, SqlSchemaIRNode } from './sql-schema-ir-node';
4
7
 
5
8
  export interface SqlUniqueIRInput {
6
9
  readonly columns: readonly string[];
@@ -11,8 +14,17 @@ export interface SqlUniqueIRInput {
11
14
  /**
12
15
  * Schema IR node for a table-level unique constraint as observed by
13
16
  * introspection.
17
+ *
18
+ * Implements `DiffableNode` so a unique constraint is directly a table's
19
+ * diff-tree child. Unique constraints are frequently unnamed, so `id` is
20
+ * derived from the column tuple rather than `name` — the column tuple is
21
+ * also what makes two unique constraints the same constraint, so it doubles
22
+ * as the pairing key. There are no further attributes to compare once
23
+ * columns are equal (the differ pairs on `id`), so `isEqualTo` is identity.
14
24
  */
15
- export class SqlUniqueIR extends SqlSchemaIRNode {
25
+ export class SqlUniqueIR extends SqlSchemaIRNode implements DiffableNode {
26
+ override readonly nodeKind = RelationalSchemaNodeKind.unique;
27
+
16
28
  readonly columns: readonly string[];
17
29
  declare readonly name?: string;
18
30
  declare readonly annotations?: SqlAnnotations;
@@ -24,4 +36,25 @@ export class SqlUniqueIR extends SqlSchemaIRNode {
24
36
  if (input.annotations !== undefined) this.annotations = input.annotations;
25
37
  freezeNode(this);
26
38
  }
39
+
40
+ get id(): string {
41
+ return `unique:${this.columns.join(',')}`;
42
+ }
43
+
44
+ children(): readonly DiffableNode[] {
45
+ return [];
46
+ }
47
+
48
+ static is(node: SqlSchemaIRNode): node is SqlUniqueIR {
49
+ return node.nodeKind === RelationalSchemaNodeKind.unique;
50
+ }
51
+
52
+ isEqualTo(other: DiffableNode): boolean {
53
+ const node = blindCast<
54
+ SqlSchemaIRNode,
55
+ 'every diff-tree node the differ pairs is a SqlSchemaIRNode'
56
+ >(other);
57
+ assertNode(node, 'SqlUniqueIR', SqlUniqueIR.is);
58
+ return this.id === node.id;
59
+ }
27
60
  }
package/src/types.ts CHANGED
@@ -10,10 +10,19 @@
10
10
  */
11
11
 
12
12
  export { PrimaryKey, type PrimaryKeyInput } from './ir/primary-key';
13
+ export {
14
+ RelationalSchemaNodeKind,
15
+ relationalNodeEntityKind,
16
+ relationalNodeGranularity,
17
+ } from './ir/schema-node-kinds';
13
18
  export {
14
19
  SqlCheckConstraintIR,
15
20
  type SqlCheckConstraintIRInput,
16
21
  } from './ir/sql-check-constraint-ir';
22
+ export {
23
+ SqlColumnDefaultIR,
24
+ type SqlColumnDefaultIRInput,
25
+ } from './ir/sql-column-default-ir';
17
26
  export {
18
27
  type SqlAnnotations,
19
28
  SqlColumnIR,
@@ -26,7 +35,7 @@ export {
26
35
  } from './ir/sql-foreign-key-ir';
27
36
  export { SqlIndexIR, type SqlIndexIRInput } from './ir/sql-index-ir';
28
37
  export { SqlSchemaIR, type SqlSchemaIRInput } from './ir/sql-schema-ir';
29
- export { SqlSchemaIRNode } from './ir/sql-schema-ir-node';
38
+ export { assertNode, SqlSchemaIRNode } from './ir/sql-schema-ir-node';
30
39
  export { SqlTableIR, type SqlTableIRInput } from './ir/sql-table-ir';
31
40
  export { SqlUniqueIR, type SqlUniqueIRInput } from './ir/sql-unique-ir';
32
41
 
@@ -1,220 +0,0 @@
1
- import { IRNodeBase, freezeNode } from "@prisma-next/framework-components/ir";
2
- //#region src/ir/sql-schema-ir-node.ts
3
- /**
4
- * SQL Schema IR node base. Carries the family-level
5
- * `kind = 'sql-schema-ir'` discriminator and inherits the framework's
6
- * `freezeNode` affordance.
7
- *
8
- * SQL Schema IR represents the actual database state as discovered by
9
- * introspection (the parallel to SQL Contract IR, which represents the
10
- * desired state). Like the Contract side, today's Schema IR has no
11
- * polymorphic dispatch — verifiers and planners walk by structural
12
- * position, not by inspecting `kind` — so a single family-level
13
- * discriminator is sufficient. Future per-leaf overrides land cleanly
14
- * the same way as on the Contract side.
15
- *
16
- * The discriminator is installed as a non-enumerable own property,
17
- * matching the SqlNode pattern. This keeps `JSON.stringify(node)`
18
- * canonical (no `kind` field), keeps `toEqual({...})` test assertions
19
- * against pre-lift flat shapes passing, and keeps `node.kind` readable
20
- * for future polymorphic dispatch.
21
- */
22
- var SqlSchemaIRNode = class extends IRNodeBase {
23
- kind;
24
- constructor() {
25
- super();
26
- Object.defineProperty(this, "kind", {
27
- value: "sql-schema-ir",
28
- writable: false,
29
- enumerable: false,
30
- configurable: false
31
- });
32
- }
33
- };
34
- //#endregion
35
- //#region src/ir/primary-key.ts
36
- /**
37
- * Primary-key Schema IR node. Mirrors the Contract IR `PrimaryKey`
38
- * shape (same `columns` + optional `name`) so verification can compare
39
- * intent and actual structurally. Defined here independently to avoid
40
- * a sql-schema-ir -> sql-contract dependency.
41
- */
42
- var PrimaryKey = class extends SqlSchemaIRNode {
43
- columns;
44
- constructor(input) {
45
- super();
46
- this.columns = input.columns;
47
- if (input.name !== void 0) this.name = input.name;
48
- freezeNode(this);
49
- }
50
- };
51
- //#endregion
52
- //#region src/ir/sql-check-constraint-ir.ts
53
- /**
54
- * Schema IR node for a table-level check constraint that restricts a
55
- * column to a set of permitted values (an enum-style `IN (...)` check).
56
- *
57
- * Carries the **resolved values** rather than a raw SQL predicate so
58
- * callers can compare value-sets without parsing SQL.
59
- */
60
- var SqlCheckConstraintIR = class extends SqlSchemaIRNode {
61
- name;
62
- column;
63
- permittedValues;
64
- constructor(input) {
65
- super();
66
- this.name = input.name;
67
- this.column = input.column;
68
- this.permittedValues = Object.freeze([...input.permittedValues]);
69
- freezeNode(this);
70
- }
71
- };
72
- //#endregion
73
- //#region src/ir/sql-column-ir.ts
74
- /**
75
- * Schema IR node for a single column on a table, as observed by
76
- * introspection. Unlike the Contract IR `StorageColumn`, this carries
77
- * the column's `name` (Schema IR columns are returned as arrays from
78
- * introspection queries; the parent table re-keys them into a record
79
- * for downstream consumers).
80
- */
81
- var SqlColumnIR = class extends SqlSchemaIRNode {
82
- name;
83
- nativeType;
84
- nullable;
85
- constructor(input) {
86
- super();
87
- this.name = input.name;
88
- this.nativeType = input.nativeType;
89
- this.nullable = input.nullable;
90
- if (input.default !== void 0) this.default = input.default;
91
- if (input.annotations !== void 0) this.annotations = input.annotations;
92
- freezeNode(this);
93
- }
94
- };
95
- //#endregion
96
- //#region src/ir/sql-foreign-key-ir.ts
97
- /**
98
- * Schema IR node for a foreign-key constraint as observed by
99
- * introspection. The `referencedTable` / `referencedColumns` field
100
- * names match the introspection vocabulary (`pg_constraint.confkey`,
101
- * etc.) and intentionally differ from the Contract IR's nested
102
- * `references: { table, columns }` shape so that the verifier's
103
- * structural comparison stays explicit about which side it's reading.
104
- */
105
- var SqlForeignKeyIR = class extends SqlSchemaIRNode {
106
- columns;
107
- referencedTable;
108
- referencedColumns;
109
- constructor(input) {
110
- super();
111
- this.columns = input.columns;
112
- this.referencedTable = input.referencedTable;
113
- this.referencedColumns = input.referencedColumns;
114
- if (input.referencedSchema !== void 0) this.referencedSchema = input.referencedSchema;
115
- if (input.name !== void 0) this.name = input.name;
116
- if (input.onDelete !== void 0) this.onDelete = input.onDelete;
117
- if (input.onUpdate !== void 0) this.onUpdate = input.onUpdate;
118
- if (input.annotations !== void 0) this.annotations = input.annotations;
119
- freezeNode(this);
120
- }
121
- };
122
- //#endregion
123
- //#region src/ir/sql-index-ir.ts
124
- /**
125
- * Schema IR node for a secondary index as observed by introspection.
126
- * Unlike the Contract IR `Index`, the Schema IR carries an explicit
127
- * `unique` field — introspection sees the underlying index regardless
128
- * of whether the user expressed it as `@@index` or `@@unique`, and the
129
- * verifier needs to distinguish them when comparing to the Contract.
130
- */
131
- var SqlIndexIR = class extends SqlSchemaIRNode {
132
- columns;
133
- unique;
134
- constructor(input) {
135
- super();
136
- this.columns = input.columns;
137
- this.unique = input.unique;
138
- if (input.name !== void 0) this.name = input.name;
139
- if (input.type !== void 0) this.type = input.type;
140
- if (input.options !== void 0) this.options = input.options;
141
- if (input.annotations !== void 0) this.annotations = input.annotations;
142
- freezeNode(this);
143
- }
144
- };
145
- //#endregion
146
- //#region src/ir/sql-unique-ir.ts
147
- /**
148
- * Schema IR node for a table-level unique constraint as observed by
149
- * introspection.
150
- */
151
- var SqlUniqueIR = class extends SqlSchemaIRNode {
152
- columns;
153
- constructor(input) {
154
- super();
155
- this.columns = [...input.columns];
156
- if (input.name !== void 0) this.name = input.name;
157
- if (input.annotations !== void 0) this.annotations = input.annotations;
158
- freezeNode(this);
159
- }
160
- };
161
- //#endregion
162
- //#region src/ir/sql-table-ir.ts
163
- /**
164
- * Schema IR node for a single table as observed by introspection.
165
- *
166
- * Unlike the Contract IR `StorageTable`, this carries the table's
167
- * `name` — introspection queries return tables as arrays and the
168
- * verifier keys them into `SqlSchemaIR.tables` afterwards, so the name
169
- * stays on the table object for downstream call sites that walk
170
- * `Object.values(schema.tables)`.
171
- *
172
- * The constructor normalises nested IR-class fields so downstream
173
- * walks see a uniform AST regardless of whether the input was a
174
- * plain-data literal (from introspection) or already-constructed
175
- * class instances.
176
- */
177
- var SqlTableIR = class extends SqlSchemaIRNode {
178
- name;
179
- columns;
180
- foreignKeys;
181
- uniques;
182
- indexes;
183
- constructor(input) {
184
- super();
185
- this.name = input.name;
186
- this.columns = Object.freeze(Object.fromEntries(Object.entries(input.columns).map(([key, col]) => [key, col instanceof SqlColumnIR ? col : new SqlColumnIR(col)])));
187
- this.foreignKeys = Object.freeze(input.foreignKeys.map((fk) => fk instanceof SqlForeignKeyIR ? fk : new SqlForeignKeyIR(fk)));
188
- this.uniques = Object.freeze(input.uniques.map((u) => u instanceof SqlUniqueIR ? u : new SqlUniqueIR(u)));
189
- this.indexes = Object.freeze(input.indexes.map((i) => i instanceof SqlIndexIR ? i : new SqlIndexIR(i)));
190
- if (input.primaryKey !== void 0) this.primaryKey = input.primaryKey instanceof PrimaryKey ? input.primaryKey : new PrimaryKey(input.primaryKey);
191
- if (input.annotations !== void 0) this.annotations = input.annotations;
192
- if (input.checks !== void 0 && input.checks.length > 0) this.checks = Object.freeze(input.checks.map((c) => c instanceof SqlCheckConstraintIR ? c : new SqlCheckConstraintIR(c)));
193
- freezeNode(this);
194
- }
195
- };
196
- //#endregion
197
- //#region src/ir/sql-schema-ir.ts
198
- /**
199
- * Root Schema IR node representing the complete database schema as
200
- * observed by introspection. Target-agnostic; used by both verifiers
201
- * (compare against intended Contract storage) and migration planners
202
- * (derive operations needed to reconcile).
203
- *
204
- * The constructor normalises nested `SqlTableIR` instances so
205
- * downstream walks see a uniform AST regardless of whether the input
206
- * was a plain-data literal or already-constructed class instances.
207
- */
208
- var SqlSchemaIR = class extends SqlSchemaIRNode {
209
- tables;
210
- constructor(input) {
211
- super();
212
- this.tables = Object.freeze(Object.fromEntries(Object.entries(input.tables).map(([key, t]) => [key, t instanceof SqlTableIR ? t : new SqlTableIR(t)])));
213
- if (input.annotations !== void 0) this.annotations = input.annotations;
214
- freezeNode(this);
215
- }
216
- };
217
- //#endregion
218
- export { SqlForeignKeyIR as a, PrimaryKey as c, SqlIndexIR as i, SqlSchemaIRNode as l, SqlTableIR as n, SqlColumnIR as o, SqlUniqueIR as r, SqlCheckConstraintIR as s, SqlSchemaIR as t };
219
-
220
- //# sourceMappingURL=types-C0WFfEkA.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types-C0WFfEkA.mjs","names":[],"sources":["../src/ir/sql-schema-ir-node.ts","../src/ir/primary-key.ts","../src/ir/sql-check-constraint-ir.ts","../src/ir/sql-column-ir.ts","../src/ir/sql-foreign-key-ir.ts","../src/ir/sql-index-ir.ts","../src/ir/sql-unique-ir.ts","../src/ir/sql-table-ir.ts","../src/ir/sql-schema-ir.ts"],"sourcesContent":["import { IRNodeBase } from '@prisma-next/framework-components/ir';\n\n/**\n * SQL Schema IR node base. Carries the family-level\n * `kind = 'sql-schema-ir'` discriminator and inherits the framework's\n * `freezeNode` affordance.\n *\n * SQL Schema IR represents the actual database state as discovered by\n * introspection (the parallel to SQL Contract IR, which represents the\n * desired state). Like the Contract side, today's Schema IR has no\n * polymorphic dispatch — verifiers and planners walk by structural\n * position, not by inspecting `kind` — so a single family-level\n * discriminator is sufficient. Future per-leaf overrides land cleanly\n * the same way as on the Contract side.\n *\n * The discriminator is installed as a non-enumerable own property,\n * matching the SqlNode pattern. This keeps `JSON.stringify(node)`\n * canonical (no `kind` field), keeps `toEqual({...})` test assertions\n * against pre-lift flat shapes passing, and keeps `node.kind` readable\n * for future polymorphic dispatch.\n */\nexport abstract class SqlSchemaIRNode extends IRNodeBase {\n readonly kind?: string;\n\n constructor() {\n super();\n Object.defineProperty(this, 'kind', {\n value: 'sql-schema-ir',\n writable: false,\n enumerable: false,\n configurable: false,\n });\n }\n}\n","import { freezeNode } from '@prisma-next/framework-components/ir';\nimport { SqlSchemaIRNode } from './sql-schema-ir-node';\n\nexport interface PrimaryKeyInput {\n readonly columns: readonly string[];\n readonly name?: string;\n}\n\n/**\n * Primary-key Schema IR node. Mirrors the Contract IR `PrimaryKey`\n * shape (same `columns` + optional `name`) so verification can compare\n * intent and actual structurally. Defined here independently to avoid\n * a sql-schema-ir -> sql-contract dependency.\n */\nexport class PrimaryKey extends SqlSchemaIRNode {\n readonly columns: readonly string[];\n declare readonly name?: string;\n\n constructor(input: PrimaryKeyInput) {\n super();\n this.columns = input.columns;\n if (input.name !== undefined) this.name = input.name;\n freezeNode(this);\n }\n}\n","import { freezeNode } from '@prisma-next/framework-components/ir';\nimport { SqlSchemaIRNode } from './sql-schema-ir-node';\n\nexport interface SqlCheckConstraintIRInput {\n /** Constraint name as stored in the database catalog. */\n readonly name: string;\n /** Column the check restricts. */\n readonly column: string;\n /** Permitted values the column must be IN. */\n readonly permittedValues: readonly string[];\n}\n\n/**\n * Schema IR node for a table-level check constraint that restricts a\n * column to a set of permitted values (an enum-style `IN (...)` check).\n *\n * Carries the **resolved values** rather than a raw SQL predicate so\n * callers can compare value-sets without parsing SQL.\n */\nexport class SqlCheckConstraintIR extends SqlSchemaIRNode {\n readonly name: string;\n readonly column: string;\n readonly permittedValues: readonly string[];\n\n constructor(input: SqlCheckConstraintIRInput) {\n super();\n this.name = input.name;\n this.column = input.column;\n this.permittedValues = Object.freeze([...input.permittedValues]);\n freezeNode(this);\n }\n}\n","import { freezeNode } from '@prisma-next/framework-components/ir';\nimport { SqlSchemaIRNode } from './sql-schema-ir-node';\n\n/**\n * Namespaced annotations for extensibility. Each namespace\n * (e.g. `pg`, `pgvector`) owns its annotations subtree.\n */\nexport type SqlAnnotations = {\n readonly [namespace: string]: unknown;\n};\n\nexport interface SqlColumnIRInput {\n readonly name: string;\n readonly nativeType: string;\n readonly nullable: boolean;\n /** Raw database default expression (e.g. `'hello'::text`, `nextval('seq')`). */\n readonly default?: string;\n readonly annotations?: SqlAnnotations;\n}\n\n/**\n * Schema IR node for a single column on a table, as observed by\n * introspection. Unlike the Contract IR `StorageColumn`, this carries\n * the column's `name` (Schema IR columns are returned as arrays from\n * introspection queries; the parent table re-keys them into a record\n * for downstream consumers).\n */\nexport class SqlColumnIR extends SqlSchemaIRNode {\n readonly name: string;\n readonly nativeType: string;\n readonly nullable: boolean;\n declare readonly default?: string;\n declare readonly annotations?: SqlAnnotations;\n\n constructor(input: SqlColumnIRInput) {\n super();\n this.name = input.name;\n this.nativeType = input.nativeType;\n this.nullable = input.nullable;\n if (input.default !== undefined) this.default = input.default;\n if (input.annotations !== undefined) this.annotations = input.annotations;\n freezeNode(this);\n }\n}\n","import { freezeNode } from '@prisma-next/framework-components/ir';\nimport type { SqlAnnotations } from './sql-column-ir';\nimport { SqlSchemaIRNode } from './sql-schema-ir-node';\n\nexport type SqlReferentialAction = 'noAction' | 'restrict' | 'cascade' | 'setNull' | 'setDefault';\n\nexport interface SqlForeignKeyIRInput {\n readonly columns: readonly string[];\n readonly referencedTable: string;\n readonly referencedColumns: readonly string[];\n /** Schema (namespace) of the referenced table — populated by adapters that introspect cross-schema FKs. */\n readonly referencedSchema?: string;\n readonly name?: string;\n readonly onDelete?: SqlReferentialAction;\n readonly onUpdate?: SqlReferentialAction;\n readonly annotations?: SqlAnnotations;\n}\n\n/**\n * Schema IR node for a foreign-key constraint as observed by\n * introspection. The `referencedTable` / `referencedColumns` field\n * names match the introspection vocabulary (`pg_constraint.confkey`,\n * etc.) and intentionally differ from the Contract IR's nested\n * `references: { table, columns }` shape so that the verifier's\n * structural comparison stays explicit about which side it's reading.\n */\nexport class SqlForeignKeyIR extends SqlSchemaIRNode {\n readonly columns: readonly string[];\n readonly referencedTable: string;\n readonly referencedColumns: readonly string[];\n declare readonly referencedSchema?: string;\n declare readonly name?: string;\n declare readonly onDelete?: SqlReferentialAction;\n declare readonly onUpdate?: SqlReferentialAction;\n declare readonly annotations?: SqlAnnotations;\n\n constructor(input: SqlForeignKeyIRInput) {\n super();\n this.columns = input.columns;\n this.referencedTable = input.referencedTable;\n this.referencedColumns = input.referencedColumns;\n if (input.referencedSchema !== undefined) this.referencedSchema = input.referencedSchema;\n if (input.name !== undefined) this.name = input.name;\n if (input.onDelete !== undefined) this.onDelete = input.onDelete;\n if (input.onUpdate !== undefined) this.onUpdate = input.onUpdate;\n if (input.annotations !== undefined) this.annotations = input.annotations;\n freezeNode(this);\n }\n}\n","import { freezeNode } from '@prisma-next/framework-components/ir';\nimport type { SqlAnnotations } from './sql-column-ir';\nimport { SqlSchemaIRNode } from './sql-schema-ir-node';\n\nexport interface SqlIndexIRInput {\n readonly columns: readonly string[];\n readonly unique: boolean;\n readonly name?: string;\n readonly type?: string;\n readonly options?: Record<string, unknown>;\n readonly annotations?: SqlAnnotations;\n}\n\n/**\n * Schema IR node for a secondary index as observed by introspection.\n * Unlike the Contract IR `Index`, the Schema IR carries an explicit\n * `unique` field — introspection sees the underlying index regardless\n * of whether the user expressed it as `@@index` or `@@unique`, and the\n * verifier needs to distinguish them when comparing to the Contract.\n */\nexport class SqlIndexIR extends SqlSchemaIRNode {\n readonly columns: readonly string[];\n readonly unique: boolean;\n declare readonly name?: string;\n declare readonly type?: string;\n declare readonly options?: Record<string, unknown>;\n declare readonly annotations?: SqlAnnotations;\n\n constructor(input: SqlIndexIRInput) {\n super();\n this.columns = input.columns;\n this.unique = input.unique;\n if (input.name !== undefined) this.name = input.name;\n if (input.type !== undefined) this.type = input.type;\n if (input.options !== undefined) this.options = input.options;\n if (input.annotations !== undefined) this.annotations = input.annotations;\n freezeNode(this);\n }\n}\n","import { freezeNode } from '@prisma-next/framework-components/ir';\nimport type { SqlAnnotations } from './sql-column-ir';\nimport { SqlSchemaIRNode } from './sql-schema-ir-node';\n\nexport interface SqlUniqueIRInput {\n readonly columns: readonly string[];\n readonly name?: string;\n readonly annotations?: SqlAnnotations;\n}\n\n/**\n * Schema IR node for a table-level unique constraint as observed by\n * introspection.\n */\nexport class SqlUniqueIR extends SqlSchemaIRNode {\n readonly columns: readonly string[];\n declare readonly name?: string;\n declare readonly annotations?: SqlAnnotations;\n\n constructor(input: SqlUniqueIRInput) {\n super();\n this.columns = [...input.columns];\n if (input.name !== undefined) this.name = input.name;\n if (input.annotations !== undefined) this.annotations = input.annotations;\n freezeNode(this);\n }\n}\n","import { freezeNode } from '@prisma-next/framework-components/ir';\nimport { PrimaryKey, type PrimaryKeyInput } from './primary-key';\nimport { SqlCheckConstraintIR, type SqlCheckConstraintIRInput } from './sql-check-constraint-ir';\nimport { type SqlAnnotations, SqlColumnIR, type SqlColumnIRInput } from './sql-column-ir';\nimport { SqlForeignKeyIR, type SqlForeignKeyIRInput } from './sql-foreign-key-ir';\nimport { SqlIndexIR, type SqlIndexIRInput } from './sql-index-ir';\nimport { SqlSchemaIRNode } from './sql-schema-ir-node';\nimport { SqlUniqueIR, type SqlUniqueIRInput } from './sql-unique-ir';\n\nexport interface SqlTableIRInput {\n readonly name: string;\n readonly columns: Record<string, SqlColumnIR | SqlColumnIRInput>;\n readonly foreignKeys: ReadonlyArray<SqlForeignKeyIR | SqlForeignKeyIRInput>;\n readonly uniques: ReadonlyArray<SqlUniqueIR | SqlUniqueIRInput>;\n readonly indexes: ReadonlyArray<SqlIndexIR | SqlIndexIRInput>;\n readonly primaryKey?: PrimaryKey | PrimaryKeyInput;\n readonly annotations?: SqlAnnotations;\n /** Optional check constraints for enum-restricted columns. Omitted when none present. */\n readonly checks?: ReadonlyArray<SqlCheckConstraintIR | SqlCheckConstraintIRInput>;\n}\n\n/**\n * Schema IR node for a single table as observed by introspection.\n *\n * Unlike the Contract IR `StorageTable`, this carries the table's\n * `name` — introspection queries return tables as arrays and the\n * verifier keys them into `SqlSchemaIR.tables` afterwards, so the name\n * stays on the table object for downstream call sites that walk\n * `Object.values(schema.tables)`.\n *\n * The constructor normalises nested IR-class fields so downstream\n * walks see a uniform AST regardless of whether the input was a\n * plain-data literal (from introspection) or already-constructed\n * class instances.\n */\nexport class SqlTableIR extends SqlSchemaIRNode {\n readonly name: string;\n readonly columns: Readonly<Record<string, SqlColumnIR>>;\n readonly foreignKeys: ReadonlyArray<SqlForeignKeyIR>;\n readonly uniques: ReadonlyArray<SqlUniqueIR>;\n readonly indexes: ReadonlyArray<SqlIndexIR>;\n declare readonly primaryKey?: PrimaryKey;\n declare readonly annotations?: SqlAnnotations;\n declare readonly checks?: ReadonlyArray<SqlCheckConstraintIR>;\n\n constructor(input: SqlTableIRInput) {\n super();\n this.name = input.name;\n this.columns = Object.freeze(\n Object.fromEntries(\n Object.entries(input.columns).map(([key, col]) => [\n key,\n col instanceof SqlColumnIR ? col : new SqlColumnIR(col),\n ]),\n ),\n );\n this.foreignKeys = Object.freeze(\n input.foreignKeys.map((fk) => (fk instanceof SqlForeignKeyIR ? fk : new SqlForeignKeyIR(fk))),\n );\n this.uniques = Object.freeze(\n input.uniques.map((u) => (u instanceof SqlUniqueIR ? u : new SqlUniqueIR(u))),\n );\n this.indexes = Object.freeze(\n input.indexes.map((i) => (i instanceof SqlIndexIR ? i : new SqlIndexIR(i))),\n );\n if (input.primaryKey !== undefined) {\n this.primaryKey =\n input.primaryKey instanceof PrimaryKey\n ? input.primaryKey\n : new PrimaryKey(input.primaryKey);\n }\n if (input.annotations !== undefined) this.annotations = input.annotations;\n if (input.checks !== undefined && input.checks.length > 0) {\n this.checks = Object.freeze(\n input.checks.map((c) =>\n c instanceof SqlCheckConstraintIR ? c : new SqlCheckConstraintIR(c),\n ),\n );\n }\n freezeNode(this);\n }\n}\n","import { freezeNode } from '@prisma-next/framework-components/ir';\nimport type { SqlAnnotations } from './sql-column-ir';\nimport { SqlSchemaIRNode } from './sql-schema-ir-node';\nimport { SqlTableIR, type SqlTableIRInput } from './sql-table-ir';\n\nexport interface SqlSchemaIRInput {\n readonly tables: Record<string, SqlTableIR | SqlTableIRInput>;\n readonly annotations?: SqlAnnotations;\n}\n\n/**\n * Root Schema IR node representing the complete database schema as\n * observed by introspection. Target-agnostic; used by both verifiers\n * (compare against intended Contract storage) and migration planners\n * (derive operations needed to reconcile).\n *\n * The constructor normalises nested `SqlTableIR` instances so\n * downstream walks see a uniform AST regardless of whether the input\n * was a plain-data literal or already-constructed class instances.\n */\nexport class SqlSchemaIR extends SqlSchemaIRNode {\n readonly tables: Readonly<Record<string, SqlTableIR>>;\n declare readonly annotations?: SqlAnnotations;\n\n constructor(input: SqlSchemaIRInput) {\n super();\n this.tables = Object.freeze(\n Object.fromEntries(\n Object.entries(input.tables).map(([key, t]) => [\n key,\n t instanceof SqlTableIR ? t : new SqlTableIR(t),\n ]),\n ),\n );\n if (input.annotations !== undefined) this.annotations = input.annotations;\n freezeNode(this);\n }\n}\n"],"mappings":"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"}