@prisma-next/sql-contract 0.16.0-dev.3 → 0.16.0-dev.30
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 +1 -1
- package/dist/canonicalization-hooks.d.mts.map +1 -1
- package/dist/canonicalization-hooks.mjs +10 -0
- package/dist/canonicalization-hooks.mjs.map +1 -1
- package/dist/contract-errors-CPZcBw8G.mjs +9 -0
- package/dist/contract-errors-CPZcBw8G.mjs.map +1 -0
- package/dist/contract-view.d.mts +1 -1
- package/dist/{entity-kinds-CVg6HzG2.mjs → entity-kinds-CdHJQGi0.mjs} +11 -6
- package/dist/entity-kinds-CdHJQGi0.mjs.map +1 -0
- package/dist/entity-kinds.d.mts +1 -1
- package/dist/entity-kinds.d.mts.map +1 -1
- package/dist/entity-kinds.mjs +1 -1
- package/dist/factories.d.mts +10 -4
- package/dist/factories.d.mts.map +1 -1
- package/dist/factories.mjs +11 -3
- package/dist/factories.mjs.map +1 -1
- package/dist/foreign-key-materialization.d.mts +7 -6
- package/dist/foreign-key-materialization.d.mts.map +1 -1
- package/dist/foreign-key-materialization.mjs +12 -9
- package/dist/foreign-key-materialization.mjs.map +1 -1
- package/dist/index-naming-DsnarUVW.mjs +43 -0
- package/dist/index-naming-DsnarUVW.mjs.map +1 -0
- package/dist/index-naming.d.mts +25 -0
- package/dist/index-naming.d.mts.map +1 -0
- package/dist/index-naming.mjs +2 -0
- package/dist/index-type-validation.d.mts +2 -2
- package/dist/index-type-validation.mjs +3 -3
- package/dist/index-type-validation.mjs.map +1 -1
- package/dist/index-types-DPVhsW0v.d.mts.map +1 -1
- package/dist/index-types.mjs +3 -2
- package/dist/index-types.mjs.map +1 -1
- package/dist/resolve-storage-table.d.mts +2 -2
- package/dist/resolve-storage-table.d.mts.map +1 -1
- package/dist/resolve-storage-table.mjs +5 -4
- package/dist/resolve-storage-table.mjs.map +1 -1
- package/dist/sql-index-Wzbj2nbH.d.mts +79 -0
- package/dist/sql-index-Wzbj2nbH.d.mts.map +1 -0
- package/dist/{sql-storage-BIErcfFA.d.mts → sql-storage-DjqU3XXV.d.mts} +2 -2
- package/dist/{sql-storage-BIErcfFA.d.mts.map → sql-storage-DjqU3XXV.d.mts.map} +1 -1
- package/dist/{storage-table-DBpYBmty.mjs → storage-table-DKTrkwZt.mjs} +30 -6
- package/dist/storage-table-DKTrkwZt.mjs.map +1 -0
- package/dist/{storage-table-mNGckl3_.d.mts → storage-table-zrxIuCJ3.d.mts} +3 -2
- package/dist/storage-table-zrxIuCJ3.d.mts.map +1 -0
- package/dist/{storage-value-set-3BKuha5q.mjs → storage-value-set-DdL4oin-.mjs} +2 -2
- package/dist/{storage-value-set-3BKuha5q.mjs.map → storage-value-set-DdL4oin-.mjs.map} +1 -1
- package/dist/{types-lpzJtKpv.d.mts → types-Bxa1Pyzg.d.mts} +5 -4
- package/dist/types-Bxa1Pyzg.d.mts.map +1 -0
- package/dist/types.d.mts +5 -4
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs +4 -3
- package/dist/types.mjs.map +1 -1
- package/dist/unique-constraint-Bp-q-mr-.d.mts +31 -0
- package/dist/unique-constraint-Bp-q-mr-.d.mts.map +1 -0
- package/dist/validators.d.mts +15 -7
- package/dist/validators.d.mts.map +1 -1
- package/dist/validators.mjs +14 -10
- package/dist/validators.mjs.map +1 -1
- package/package.json +9 -8
- package/src/canonicalization-hooks.ts +4 -0
- package/src/contract-errors.ts +14 -0
- package/src/entity-kinds.ts +4 -1
- package/src/exports/index-naming.ts +1 -0
- package/src/factories.ts +19 -2
- package/src/foreign-key-materialization.ts +18 -11
- package/src/index-naming.ts +65 -0
- package/src/index-type-validation.ts +3 -3
- package/src/index-types.ts +11 -2
- package/src/ir/sql-index.ts +94 -11
- package/src/ir/sql-storage.ts +2 -1
- package/src/ir/storage-entry-schemas.ts +6 -2
- package/src/ir/storage-table.ts +2 -1
- package/src/resolve-storage-table.ts +4 -1
- package/src/validators.ts +25 -9
- package/dist/entity-kinds-CVg6HzG2.mjs.map +0 -1
- package/dist/storage-table-DBpYBmty.mjs.map +0 -1
- package/dist/storage-table-mNGckl3_.d.mts.map +0 -1
- package/dist/types-lpzJtKpv.d.mts.map +0 -1
- package/dist/unique-constraint-WHfanEUq.d.mts +0 -54
- package/dist/unique-constraint-WHfanEUq.d.mts.map +0 -1
package/src/index-types.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Type } from 'arktype';
|
|
2
|
+
import { contractError } from './contract-errors';
|
|
2
3
|
|
|
3
4
|
export interface IndexTypeEntry<TOptions = unknown> {
|
|
4
5
|
readonly type: string;
|
|
@@ -34,7 +35,11 @@ class IndexTypeBuilderImpl<TMap extends IndexTypeMap> implements IndexTypeBuilde
|
|
|
34
35
|
entry: { readonly options: Type<TOpts> },
|
|
35
36
|
): IndexTypeBuilder<TMap & Record<TLit, { readonly options: TOpts }>> {
|
|
36
37
|
if (this.entries.some((e) => e.type === typeLiteral)) {
|
|
37
|
-
throw
|
|
38
|
+
throw contractError(
|
|
39
|
+
'CONTRACT.PACK_CONTRIBUTION_INVALID',
|
|
40
|
+
`Index type "${typeLiteral}" is already declared in this builder`,
|
|
41
|
+
{ meta: { indexType: typeLiteral } },
|
|
42
|
+
);
|
|
38
43
|
}
|
|
39
44
|
return new IndexTypeBuilderImpl<TMap & Record<TLit, { readonly options: TOpts }>>([
|
|
40
45
|
...this.entries,
|
|
@@ -58,7 +63,11 @@ class IndexTypeRegistryImpl implements IndexTypeRegistry {
|
|
|
58
63
|
|
|
59
64
|
register(entry: IndexTypeEntry): void {
|
|
60
65
|
if (this.entries.has(entry.type)) {
|
|
61
|
-
throw
|
|
66
|
+
throw contractError(
|
|
67
|
+
'CONTRACT.PACK_CONTRIBUTION_INVALID',
|
|
68
|
+
`Index type "${entry.type}" is already registered`,
|
|
69
|
+
{ meta: { indexType: entry.type } },
|
|
70
|
+
);
|
|
62
71
|
}
|
|
63
72
|
this.entries.set(entry.type, entry);
|
|
64
73
|
}
|
package/src/ir/sql-index.ts
CHANGED
|
@@ -1,15 +1,68 @@
|
|
|
1
|
+
import { ContractValidationError } from '@prisma-next/contract/contract-validation-error';
|
|
1
2
|
import { freezeNode } from '@prisma-next/framework-components/ir';
|
|
3
|
+
import { formatWireName, parseWireName } from '@prisma-next/sql-schema-ir/naming';
|
|
2
4
|
import { SqlNode } from './sql-node';
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
/**
|
|
7
|
+
* An index's element structure — exactly one of a column tuple or an opaque
|
|
8
|
+
* expression, made unrepresentable-otherwise at the type level. No
|
|
9
|
+
* discriminant is stored: the JSON shape stays flat (`columns` or
|
|
10
|
+
* `expression`, never both), and the runtime xor guard in the constructor
|
|
11
|
+
* remains as the backstop for JSON loads that bypass this input type.
|
|
12
|
+
*/
|
|
13
|
+
export type IndexElements =
|
|
14
|
+
| {
|
|
15
|
+
/** Column-tuple elements. */
|
|
16
|
+
readonly columns: readonly string[];
|
|
17
|
+
readonly expression?: never;
|
|
18
|
+
}
|
|
19
|
+
| {
|
|
20
|
+
readonly columns?: never;
|
|
21
|
+
/**
|
|
22
|
+
* Opaque SQL: the entire element list between the parens of CREATE
|
|
23
|
+
* INDEX — one string, never parsed.
|
|
24
|
+
*/
|
|
25
|
+
readonly expression: string;
|
|
26
|
+
};
|
|
10
27
|
|
|
11
28
|
/**
|
|
12
|
-
*
|
|
29
|
+
* Construction input for {@link Index}. Internal seam (built by lowering and
|
|
30
|
+
* FK materialization, not by end users), so every non-element key is
|
|
31
|
+
* required and absence is stated explicitly as `undefined` — matching the
|
|
32
|
+
* `SqlIndexIRInput` convention.
|
|
33
|
+
*/
|
|
34
|
+
export type IndexInput = IndexElements & {
|
|
35
|
+
/** Full wire name (managed) or verbatim physical name (exact). Always present. */
|
|
36
|
+
readonly name: string;
|
|
37
|
+
/**
|
|
38
|
+
* The managed-mode name prefix — its PRESENCE is the naming-mode
|
|
39
|
+
* discriminator (there is no stored enum). Present ⇔ managed: the
|
|
40
|
+
* toolchain owns the physical name and `name === formatWireName(prefix,
|
|
41
|
+
* <8hex content hash>)`, so the author chooses the prefix but never the
|
|
42
|
+
* whole name. Absent ⇔ exact: `name` is an adopted verbatim physical name
|
|
43
|
+
* (PSL `map:`) whose identity the author owns entirely.
|
|
44
|
+
*/
|
|
45
|
+
readonly prefix: string | undefined;
|
|
46
|
+
/** Opaque SQL: partial-index predicate (WHERE body, without the keyword). */
|
|
47
|
+
readonly where: string | undefined;
|
|
48
|
+
/** Rendered as CREATE UNIQUE INDEX. */
|
|
49
|
+
readonly unique: boolean;
|
|
50
|
+
readonly type: string | undefined;
|
|
51
|
+
readonly options: Record<string, unknown> | undefined;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* SQL Contract IR node for a table-level secondary index, name-identified:
|
|
56
|
+
* `name` is the full physical name; a present `prefix` marks the index as
|
|
57
|
+
* managed (`name` is `formatWireName(prefix, <8hex>)`), an absent `prefix`
|
|
58
|
+
* marks it exact (the name is adopted verbatim).
|
|
59
|
+
*
|
|
60
|
+
* `expression`, `where`, and `unique` are genuine SQL-family attributes —
|
|
61
|
+
* functional and partial indexes are standard SQL supported natively by
|
|
62
|
+
* Postgres and SQLite alike, and the family IR must be able to represent
|
|
63
|
+
* anything any SQL target can introspect. A target declining to AUTHOR them
|
|
64
|
+
* (SQLite's rejection at namespace construction) is a capability decision,
|
|
65
|
+
* not evidence of target-specificity.
|
|
13
66
|
*
|
|
14
67
|
* Note that this class shadows the global TypeScript `Index` lib type
|
|
15
68
|
* at the family-shared name; consumer files that need both should
|
|
@@ -17,15 +70,45 @@ export interface IndexInput {
|
|
|
17
70
|
* `import { Index as SqlIndexNode } from '@prisma-next/sql-contract/types'`).
|
|
18
71
|
*/
|
|
19
72
|
export class Index extends SqlNode {
|
|
20
|
-
readonly
|
|
21
|
-
|
|
73
|
+
readonly name: string;
|
|
74
|
+
readonly unique: boolean;
|
|
75
|
+
/** See {@link IndexInput.prefix} — presence is the naming-mode discriminator. */
|
|
76
|
+
declare readonly prefix?: string;
|
|
77
|
+
declare readonly columns?: readonly string[];
|
|
78
|
+
declare readonly expression?: string;
|
|
79
|
+
declare readonly where?: string;
|
|
22
80
|
declare readonly type?: string;
|
|
23
81
|
declare readonly options?: Record<string, unknown>;
|
|
24
82
|
|
|
25
83
|
constructor(input: IndexInput) {
|
|
26
84
|
super();
|
|
27
|
-
|
|
28
|
-
|
|
85
|
+
if (input.name === undefined || input.name.length === 0) {
|
|
86
|
+
throw new ContractValidationError(
|
|
87
|
+
'Index: every index carries a full physical name; an expression index must be explicitly named (a default name cannot be derived from an expression).',
|
|
88
|
+
'storage',
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
if ((input.columns === undefined) === (input.expression === undefined)) {
|
|
92
|
+
throw new ContractValidationError(
|
|
93
|
+
`Index "${input.name}": exactly one of columns or expression must be set.`,
|
|
94
|
+
'storage',
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
if (input.prefix !== undefined) {
|
|
98
|
+
const parsed = parseWireName(input.name);
|
|
99
|
+
if (parsed === undefined || parsed.prefix !== input.prefix) {
|
|
100
|
+
throw new ContractValidationError(
|
|
101
|
+
`Index "${input.name}": prefix "${input.prefix}" does not match the wire name (expected "${formatWireName(input.prefix, '<8hex>')}").`,
|
|
102
|
+
'storage',
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
this.name = input.name;
|
|
107
|
+
this.unique = input.unique;
|
|
108
|
+
if (input.prefix !== undefined) this.prefix = input.prefix;
|
|
109
|
+
if (input.columns !== undefined) this.columns = input.columns;
|
|
110
|
+
if (input.expression !== undefined) this.expression = input.expression;
|
|
111
|
+
if (input.where !== undefined) this.where = input.where;
|
|
29
112
|
if (input.type !== undefined) this.type = input.type;
|
|
30
113
|
if (input.options !== undefined) this.options = input.options;
|
|
31
114
|
freezeNode(this);
|
package/src/ir/sql-storage.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
NamespaceBase,
|
|
8
8
|
type Storage,
|
|
9
9
|
} from '@prisma-next/framework-components/ir';
|
|
10
|
+
import { InternalError } from '@prisma-next/utils/internal-error';
|
|
10
11
|
import { SqlNode } from './sql-node';
|
|
11
12
|
import type { StorageTable } from './storage-table';
|
|
12
13
|
import {
|
|
@@ -197,7 +198,7 @@ function normaliseTypeEntry(name: string, entry: SqlStorageTypeEntry): StorageTy
|
|
|
197
198
|
rawKind === undefined
|
|
198
199
|
? 'missing `kind` discriminator'
|
|
199
200
|
: `unrecognised \`kind\` discriminator ${JSON.stringify(rawKind)}`;
|
|
200
|
-
throw new
|
|
201
|
+
throw new InternalError(
|
|
201
202
|
`storage.types[${JSON.stringify(name)}] has ${kindDescription}; expected ${JSON.stringify('codec-instance')}. Untagged codec triples should be wrapped with toStorageTypeInstance(...) before construction.`,
|
|
202
203
|
);
|
|
203
204
|
}
|
|
@@ -75,8 +75,12 @@ const UniqueConstraintSchema = type.declare<UniqueConstraintInput>().type({
|
|
|
75
75
|
});
|
|
76
76
|
|
|
77
77
|
export const IndexSchema = type({
|
|
78
|
-
|
|
79
|
-
'
|
|
78
|
+
name: 'string',
|
|
79
|
+
'prefix?': 'string',
|
|
80
|
+
'columns?': type.string.array().readonly(),
|
|
81
|
+
'expression?': 'string',
|
|
82
|
+
'where?': 'string',
|
|
83
|
+
unique: 'boolean',
|
|
80
84
|
'type?': 'string',
|
|
81
85
|
'options?': 'Record<string, unknown>',
|
|
82
86
|
});
|
package/src/ir/storage-table.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ControlPolicy } from '@prisma-next/contract/types';
|
|
2
2
|
import { freezeNode } from '@prisma-next/framework-components/ir';
|
|
3
|
+
import { InternalError } from '@prisma-next/utils/internal-error';
|
|
3
4
|
import { CheckConstraint, type CheckConstraintInput } from './check-constraint';
|
|
4
5
|
import { ForeignKey, type ForeignKeyInput } from './foreign-key';
|
|
5
6
|
import { PrimaryKey, type PrimaryKeyInput } from './primary-key';
|
|
@@ -86,7 +87,7 @@ export class StorageTable extends SqlNode {
|
|
|
86
87
|
coordinate: string,
|
|
87
88
|
): asserts value is StorageTable {
|
|
88
89
|
if (!StorageTable.is(value)) {
|
|
89
|
-
throw new
|
|
90
|
+
throw new InternalError(`Expected a StorageTable at ${coordinate}`);
|
|
90
91
|
}
|
|
91
92
|
}
|
|
92
93
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { entityAt } from '@prisma-next/framework-components/ir';
|
|
2
|
+
import { contractError } from './contract-errors';
|
|
2
3
|
import type { SqlStorage } from './ir/sql-storage';
|
|
3
4
|
import type { StorageTable } from './ir/storage-table';
|
|
4
5
|
|
|
@@ -47,8 +48,10 @@ export function resolveStorageTable(
|
|
|
47
48
|
.map((match) => match.namespaceId)
|
|
48
49
|
.sort()
|
|
49
50
|
.join(', ');
|
|
50
|
-
throw
|
|
51
|
+
throw contractError(
|
|
52
|
+
'CONTRACT.TABLE_AMBIGUOUS',
|
|
51
53
|
`Storage table "${tableName}" is ambiguous across namespaces [${candidates}]; qualify it with a namespace coordinate.`,
|
|
54
|
+
{ meta: { tableName, candidates: matches.map((match) => match.namespaceId).sort() } },
|
|
52
55
|
);
|
|
53
56
|
}
|
|
54
57
|
|
package/src/validators.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import { blindCast } from '@prisma-next/utils/casts';
|
|
15
15
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
16
16
|
import { type Type, type } from 'arktype';
|
|
17
|
+
import { contractError } from './contract-errors';
|
|
17
18
|
import { composeSqlEntityKinds } from './entity-kinds';
|
|
18
19
|
|
|
19
20
|
export {
|
|
@@ -344,7 +345,7 @@ export function createSqlContractSchema(
|
|
|
344
345
|
'coreHash?': 'string',
|
|
345
346
|
profileHash: 'string',
|
|
346
347
|
'capabilities?': 'Record<string, Record<string, boolean>>',
|
|
347
|
-
'
|
|
348
|
+
'extensions?': 'Record<string, unknown>',
|
|
348
349
|
'meta?': ContractMetaSchema,
|
|
349
350
|
'defaultControlPolicy?': ControlPolicySchema,
|
|
350
351
|
'roots?': type({ '[string]': CrossReferenceSchema }),
|
|
@@ -376,16 +377,28 @@ const SqlContractSchema = createSqlContractSchema(DEFAULT_SQL_KINDS);
|
|
|
376
377
|
export function validateStorage(value: unknown): void {
|
|
377
378
|
const result = StorageSchema(value);
|
|
378
379
|
if (result instanceof type.errors) {
|
|
379
|
-
const
|
|
380
|
-
throw
|
|
380
|
+
const errors = result.map((p: { message: string }) => p.message);
|
|
381
|
+
throw contractError(
|
|
382
|
+
'CONTRACT.VALIDATION_FAILED',
|
|
383
|
+
`Storage validation failed: ${errors.join('; ')}`,
|
|
384
|
+
{
|
|
385
|
+
meta: { errors },
|
|
386
|
+
},
|
|
387
|
+
);
|
|
381
388
|
}
|
|
382
389
|
}
|
|
383
390
|
|
|
384
391
|
export function validateModel(value: unknown): unknown {
|
|
385
392
|
const result = ModelSchema(value);
|
|
386
393
|
if (result instanceof type.errors) {
|
|
387
|
-
const
|
|
388
|
-
throw
|
|
394
|
+
const errors = result.map((p: { message: string }) => p.message);
|
|
395
|
+
throw contractError(
|
|
396
|
+
'CONTRACT.VALIDATION_FAILED',
|
|
397
|
+
`Model validation failed: ${errors.join('; ')}`,
|
|
398
|
+
{
|
|
399
|
+
meta: { errors },
|
|
400
|
+
},
|
|
401
|
+
);
|
|
389
402
|
}
|
|
390
403
|
return result;
|
|
391
404
|
}
|
|
@@ -518,7 +531,7 @@ export function validateStorageSemantics(storage: SqlStorage): string[] {
|
|
|
518
531
|
|
|
519
532
|
const seenIndexDefinitions = new Set<string>();
|
|
520
533
|
for (const index of table.indexes) {
|
|
521
|
-
const duplicateColumn = findDuplicateValue(index.columns);
|
|
534
|
+
const duplicateColumn = findDuplicateValue(index.columns ?? []);
|
|
522
535
|
if (duplicateColumn !== undefined) {
|
|
523
536
|
errors.push(
|
|
524
537
|
`Namespace "${namespaceId}" table "${tableName}": index contains duplicate column "${duplicateColumn}"`,
|
|
@@ -526,13 +539,16 @@ export function validateStorageSemantics(storage: SqlStorage): string[] {
|
|
|
526
539
|
}
|
|
527
540
|
|
|
528
541
|
const signature = JSON.stringify({
|
|
529
|
-
columns: index.columns,
|
|
542
|
+
columns: index.columns ?? null,
|
|
543
|
+
expression: index.expression ?? null,
|
|
544
|
+
where: index.where ?? null,
|
|
545
|
+
unique: index.unique,
|
|
530
546
|
type: index.type ?? null,
|
|
531
547
|
options: sortOptions(index.options),
|
|
532
548
|
});
|
|
533
549
|
if (seenIndexDefinitions.has(signature)) {
|
|
534
550
|
errors.push(
|
|
535
|
-
`Namespace "${namespaceId}" table "${tableName}": duplicate index definition on columns [${index.columns.join(', ')}]`,
|
|
551
|
+
`Namespace "${namespaceId}" table "${tableName}": duplicate index definition on columns [${(index.columns ?? []).join(', ')}]`,
|
|
536
552
|
);
|
|
537
553
|
continue;
|
|
538
554
|
}
|
|
@@ -694,7 +710,7 @@ export function validateSqlStorageConsistency(contract: Contract<SqlStorage>): v
|
|
|
694
710
|
}
|
|
695
711
|
|
|
696
712
|
for (const index of table.indexes) {
|
|
697
|
-
for (const colName of index.columns) {
|
|
713
|
+
for (const colName of index.columns ?? []) {
|
|
698
714
|
if (!columnNames.has(colName)) {
|
|
699
715
|
throw new ContractValidationError(
|
|
700
716
|
`Namespace "${namespaceId}" table "${tableName}" index references non-existent column "${colName}"`,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"entity-kinds-CVg6HzG2.mjs","names":[],"sources":["../src/ir/storage-entry-schemas.ts","../src/entity-kinds.ts"],"sourcesContent":["import { type Type, type } from 'arktype';\nimport type { ForeignKeyInput, ReferentialAction } from './foreign-key';\nimport type { ForeignKeyReferenceInput } from './foreign-key-reference';\nimport type { PrimaryKeyInput } from './primary-key';\nimport type { UniqueConstraintInput } from './unique-constraint';\n\ntype ColumnDefaultLiteral = {\n readonly kind: 'literal';\n readonly value: string | number | boolean | Record<string, unknown> | unknown[] | null;\n};\ntype ColumnDefaultFunction = { readonly kind: 'function'; readonly expression: string };\n\nconst literalKindSchema = type(\"'literal'\");\nconst functionKindSchema = type(\"'function'\");\nconst ControlPolicySchema = type(\"'managed' | 'tolerated' | 'external' | 'observed'\");\n\nexport const ColumnDefaultLiteralSchema = type.declare<ColumnDefaultLiteral>().type({\n kind: literalKindSchema,\n value: 'string | number | boolean | null | unknown[] | Record<string, unknown>',\n});\n\nexport const ColumnDefaultFunctionSchema = type.declare<ColumnDefaultFunction>().type({\n kind: functionKindSchema,\n expression: 'string',\n});\n\nexport const ColumnDefaultSchema = ColumnDefaultLiteralSchema.or(ColumnDefaultFunctionSchema);\n\nconst StorageValueSetRefSchema = type({\n plane: \"'storage'\",\n namespaceId: 'string',\n entityKind: \"'valueSet'\",\n entityName: 'string',\n 'spaceId?': 'string',\n});\n\nconst StorageColumnSchema = type({\n '+': 'reject',\n nativeType: 'string',\n codecId: 'string',\n nullable: 'boolean',\n 'many?': 'boolean',\n 'typeParams?': 'Record<string, unknown>',\n 'typeRef?': 'string',\n 'default?': ColumnDefaultSchema,\n 'control?': ControlPolicySchema,\n 'valueSet?': StorageValueSetRefSchema,\n}).narrow((col, ctx) => {\n if (col.typeParams !== undefined && col.typeRef !== undefined) {\n return ctx.mustBe('a column with either typeParams or typeRef, not both');\n }\n return true;\n});\n\n/**\n * Storage value-set entry under `storage.namespaces[id].entries.valueSet[name]`.\n * Carries a `kind: 'valueSet'` discriminator (enumerable, survives JSON) and an\n * ordered `values` array of codec-encoded permitted values.\n */\nexport const StorageValueSetSchema = type({\n kind: \"'valueSet'\",\n values: type('string | number | boolean | null | unknown[] | Record<string, unknown>')\n .array()\n .readonly(),\n});\n\nconst PrimaryKeySchema = type.declare<PrimaryKeyInput>().type({\n columns: type.string.array().readonly(),\n 'name?': 'string',\n});\n\nconst UniqueConstraintSchema = type.declare<UniqueConstraintInput>().type({\n columns: type.string.array().readonly(),\n 'name?': 'string',\n});\n\nexport const IndexSchema = type({\n columns: type.string.array().readonly(),\n 'name?': 'string',\n 'type?': 'string',\n 'options?': 'Record<string, unknown>',\n});\n\nexport const ForeignKeyReferenceSchema = type({\n '+': 'reject',\n namespaceId: 'string',\n tableName: 'string',\n columns: type.string.array().readonly(),\n 'spaceId?': 'string',\n}) satisfies Type<ForeignKeyReferenceInput>;\n\nexport const ForeignKeySourceSchema = type({\n '+': 'reject',\n namespaceId: 'string',\n tableName: 'string',\n columns: type.string.array().readonly(),\n}) satisfies Type<ForeignKeyReferenceInput>;\n\nexport const ReferentialActionSchema = type\n .declare<ReferentialAction>()\n .type(\"'noAction' | 'restrict' | 'cascade' | 'setNull' | 'setDefault'\");\n\nexport const ForeignKeySchema = type.declare<ForeignKeyInput>().type({\n source: ForeignKeySourceSchema,\n target: ForeignKeyReferenceSchema,\n 'name?': 'string',\n 'onDelete?': ReferentialActionSchema,\n 'onUpdate?': ReferentialActionSchema,\n});\n\nexport const CheckConstraintSchema = type({\n '+': 'reject',\n name: 'string',\n column: 'string',\n valueSet: StorageValueSetRefSchema,\n});\n\nexport const StorageTableSchema = type({\n '+': 'reject',\n columns: type({ '[string]': StorageColumnSchema }),\n 'primaryKey?': PrimaryKeySchema,\n uniques: UniqueConstraintSchema.array().readonly(),\n indexes: IndexSchema.array().readonly(),\n foreignKeys: ForeignKeySchema.array().readonly(),\n 'control?': ControlPolicySchema,\n 'checks?': CheckConstraintSchema.array().readonly(),\n});\n","import type {\n AnyEntityKindDescriptor,\n EntityKindDescriptor,\n} from '@prisma-next/framework-components/ir';\nimport { StorageTableSchema, StorageValueSetSchema } from './ir/storage-entry-schemas';\nimport { StorageTable, type StorageTableInput } from './ir/storage-table';\nimport { StorageValueSet, type StorageValueSetInput } from './ir/storage-value-set';\n\nexport const tableEntityKind: EntityKindDescriptor<StorageTableInput, StorageTable> = {\n kind: 'table',\n schema: StorageTableSchema,\n construct: (input) => new StorageTable(input),\n};\n\nexport const valueSetEntityKind: EntityKindDescriptor<StorageValueSetInput, StorageValueSet> = {\n kind: 'valueSet',\n schema: StorageValueSetSchema,\n construct: (input) => new StorageValueSet(input),\n};\n\n/**\n * Assembles the `kind → descriptor` registry for SQL namespaces: the built-in\n * `table` and `valueSet` kinds plus any target `packKinds`. This builds the\n * lookup table — it does not touch contract data. `hydrateNamespaceEntities`\n * later consumes this registry to turn a namespace's raw entries into IR\n * instances, and `createSqlContractSchema` derives validation from the same\n * registry. Throws on a duplicate kind.\n */\nexport function composeSqlEntityKinds(\n packKinds: readonly AnyEntityKindDescriptor[] = [],\n): ReadonlyMap<string, AnyEntityKindDescriptor> {\n const kinds = new Map<string, AnyEntityKindDescriptor>([\n ['table', tableEntityKind],\n ['valueSet', valueSetEntityKind],\n ]);\n for (const descriptor of packKinds) {\n if (kinds.has(descriptor.kind)) {\n throw new Error(\n `composeSqlEntityKinds: duplicate entity kind \"${descriptor.kind}\" — each kind may be registered only once`,\n );\n }\n kinds.set(descriptor.kind, descriptor);\n }\n return kinds;\n}\n"],"mappings":";;;;AAYA,MAAM,oBAAoB,KAAK,WAAW;AAC1C,MAAM,qBAAqB,KAAK,YAAY;AAC5C,MAAM,sBAAsB,KAAK,mDAAmD;AAEpF,MAAa,6BAA6B,KAAK,QAA8B,CAAC,CAAC,KAAK;CAClF,MAAM;CACN,OAAO;AACT,CAAC;AAED,MAAa,8BAA8B,KAAK,QAA+B,CAAC,CAAC,KAAK;CACpF,MAAM;CACN,YAAY;AACd,CAAC;AAED,MAAa,sBAAsB,2BAA2B,GAAG,2BAA2B;AAE5F,MAAM,2BAA2B,KAAK;CACpC,OAAO;CACP,aAAa;CACb,YAAY;CACZ,YAAY;CACZ,YAAY;AACd,CAAC;AAED,MAAM,sBAAsB,KAAK;CAC/B,KAAK;CACL,YAAY;CACZ,SAAS;CACT,UAAU;CACV,SAAS;CACT,eAAe;CACf,YAAY;CACZ,YAAY;CACZ,YAAY;CACZ,aAAa;AACf,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ;CACtB,IAAI,IAAI,eAAe,KAAA,KAAa,IAAI,YAAY,KAAA,GAClD,OAAO,IAAI,OAAO,sDAAsD;CAE1E,OAAO;AACT,CAAC;;;;;;AAOD,MAAa,wBAAwB,KAAK;CACxC,MAAM;CACN,QAAQ,KAAK,wEAAwE,CAAC,CACnF,MAAM,CAAC,CACP,SAAS;AACd,CAAC;AAED,MAAM,mBAAmB,KAAK,QAAyB,CAAC,CAAC,KAAK;CAC5D,SAAS,KAAK,OAAO,MAAM,CAAC,CAAC,SAAS;CACtC,SAAS;AACX,CAAC;AAED,MAAM,yBAAyB,KAAK,QAA+B,CAAC,CAAC,KAAK;CACxE,SAAS,KAAK,OAAO,MAAM,CAAC,CAAC,SAAS;CACtC,SAAS;AACX,CAAC;AAED,MAAa,cAAc,KAAK;CAC9B,SAAS,KAAK,OAAO,MAAM,CAAC,CAAC,SAAS;CACtC,SAAS;CACT,SAAS;CACT,YAAY;AACd,CAAC;AAED,MAAa,4BAA4B,KAAK;CAC5C,KAAK;CACL,aAAa;CACb,WAAW;CACX,SAAS,KAAK,OAAO,MAAM,CAAC,CAAC,SAAS;CACtC,YAAY;AACd,CAAC;AAED,MAAa,yBAAyB,KAAK;CACzC,KAAK;CACL,aAAa;CACb,WAAW;CACX,SAAS,KAAK,OAAO,MAAM,CAAC,CAAC,SAAS;AACxC,CAAC;AAED,MAAa,0BAA0B,KACpC,QAA2B,CAAC,CAC5B,KAAK,gEAAgE;AAExE,MAAa,mBAAmB,KAAK,QAAyB,CAAC,CAAC,KAAK;CACnE,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,aAAa;CACb,aAAa;AACf,CAAC;AAED,MAAa,wBAAwB,KAAK;CACxC,KAAK;CACL,MAAM;CACN,QAAQ;CACR,UAAU;AACZ,CAAC;AAED,MAAa,qBAAqB,KAAK;CACrC,KAAK;CACL,SAAS,KAAK,EAAE,YAAY,oBAAoB,CAAC;CACjD,eAAe;CACf,SAAS,uBAAuB,MAAM,CAAC,CAAC,SAAS;CACjD,SAAS,YAAY,MAAM,CAAC,CAAC,SAAS;CACtC,aAAa,iBAAiB,MAAM,CAAC,CAAC,SAAS;CAC/C,YAAY;CACZ,WAAW,sBAAsB,MAAM,CAAC,CAAC,SAAS;AACpD,CAAC;;;ACtHD,MAAa,kBAAyE;CACpF,MAAM;CACN,QAAQ;CACR,YAAY,UAAU,IAAI,aAAa,KAAK;AAC9C;AAEA,MAAa,qBAAkF;CAC7F,MAAM;CACN,QAAQ;CACR,YAAY,UAAU,IAAI,gBAAgB,KAAK;AACjD;;;;;;;;;AAUA,SAAgB,sBACd,YAAgD,CAAC,GACH;CAC9C,MAAM,wBAAQ,IAAI,IAAqC,CACrD,CAAC,SAAS,eAAe,GACzB,CAAC,YAAY,kBAAkB,CACjC,CAAC;CACD,KAAK,MAAM,cAAc,WAAW;EAClC,IAAI,MAAM,IAAI,WAAW,IAAI,GAC3B,MAAM,IAAI,MACR,iDAAiD,WAAW,KAAK,0CACnE;EAEF,MAAM,IAAI,WAAW,MAAM,UAAU;CACvC;CACA,OAAO;AACT"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"storage-table-DBpYBmty.mjs","names":[],"sources":["../src/ir/sql-node.ts","../src/ir/check-constraint.ts","../src/ir/foreign-key-reference.ts","../src/ir/foreign-key.ts","../src/ir/primary-key.ts","../src/ir/sql-index.ts","../src/ir/storage-column.ts","../src/ir/unique-constraint.ts","../src/ir/storage-table.ts"],"sourcesContent":["import { IRNodeBase } from '@prisma-next/framework-components/ir';\n\n/**\n * SQL family IR node base. Carries the family-level `kind` discriminator\n * `'sql'` and inherits the framework's `freezeNode` affordance.\n *\n * Single family-level discriminator (not per-leaf) reflects the fact that\n * SQL IR has no polymorphic dispatch today — verifiers and serializers\n * walk by structural position (`storage.tables[name].columns[name]`),\n * not by inspecting `kind`. The abstract bar for per-leaf discriminators\n * isn't earned until a future polymorphic consumer arrives.\n *\n * `kind` is installed as a non-enumerable own property on every instance,\n * which keeps three things clean simultaneously:\n *\n * - `JSON.stringify(node)` produces the canonical pre-lift JSON envelope\n * shape (no `kind` field), so emitted contract.json files and the\n * `validateSqlContractFully` arktype schemas stay unchanged.\n * - Test assertions that use `toEqual({...})` against the pre-lift flat\n * shape continue to pass — only enumerable own properties are\n * compared.\n * - Direct access (`node.kind`) and runtime narrowing\n * (`if (node.kind === 'sql')`) still work, so future polymorphic\n * dispatch can begin reading `kind` without a runtime change.\n *\n * Future per-leaf overrides land cleanly: a class that gains a\n * polymorphic-dispatch consumer (e.g. an enum type instance walked\n * alongside other types) overrides `kind` with its narrower literal\n * at that leaf level. Per-leaf overrides will use enumerable kind\n * (matching the Mongo per-class-discriminator precedent) because they\n * encode dispatch-relevant information that callers need to see in\n * JSON envelopes; the family-level `'sql'` is uniform across all SQL\n * IR and carries no dispatch-relevant information.\n */\nexport abstract class SqlNode extends IRNodeBase {\n readonly kind?: string;\n\n constructor() {\n super();\n Object.defineProperty(this, 'kind', {\n value: 'sql',\n writable: false,\n enumerable: false,\n // configurable so per-leaf subclasses (e.g. StorageValueSet)\n // can override `kind` with their narrower\n // enumerable literal via a class-field initializer. SqlNode\n // itself never needs to mutate the property again, so\n // configurability has no surface impact at this layer.\n configurable: true,\n });\n }\n}\n","import type { ValueSetRef } from '@prisma-next/contract/types';\nimport { freezeNode } from '@prisma-next/framework-components/ir';\nimport { SqlNode } from './sql-node';\n\n/**\n * Hydration / construction input shape for {@link CheckConstraint}.\n * Mirrors the on-disk storage JSON envelope so the serializer hydration\n * walker can hand a validated literal straight to `new`.\n */\nexport interface CheckConstraintInput {\n readonly name: string;\n readonly column: string;\n readonly valueSet: ValueSetRef;\n}\n\n/**\n * SQL Contract IR node for a table-level check constraint that restricts\n * a column to the permitted values of a value-set.\n *\n * The constraint is **structured** (names a column and a value-set\n * reference), not a raw SQL expression. Each target renders its own DDL\n * from the structured form, keeping the contract target-agnostic.\n *\n * Construction is idempotent: passing an existing `CheckConstraint`\n * instance as input produces a new instance with identical fields.\n * The constructor does not use `instanceof` for input discrimination —\n * it reads plain named properties, which is sufficient since\n * `CheckConstraintInput` is a structural type.\n */\nexport class CheckConstraint extends SqlNode {\n readonly name: string;\n readonly column: string;\n readonly valueSet: ValueSetRef;\n\n constructor(input: CheckConstraintInput) {\n super();\n this.name = input.name;\n this.column = input.column;\n this.valueSet = input.valueSet;\n freezeNode(this);\n }\n}\n","import { asNamespaceId, type NamespaceId } from '@prisma-next/contract/types';\nimport { freezeNode } from '@prisma-next/framework-components/ir';\nimport { SqlNode } from './sql-node';\n\n/**\n * Input for a foreign-key reference (one side of a foreign-key declaration).\n *\n * When `spaceId` is absent the reference is local — the referenced table lives\n * in the same contract-space. When `spaceId` is present the reference is\n * cross-space — the referenced table lives in a different contract-space\n * identified by `spaceId`.\n *\n * Presence-based discrimination keeps local FK JSON byte-identical to\n * contracts authored before cross-space support was added.\n */\nexport interface ForeignKeyReferenceInput {\n readonly namespaceId: string;\n readonly tableName: string;\n readonly columns: readonly string[];\n readonly spaceId?: string;\n}\n\n/**\n * SQL Contract IR node for one side (source or target) of a foreign-key\n * declaration. Carries the full coordinate: namespace, table, and columns.\n *\n * Cross-space discrimination is based on `spaceId` presence: absent means\n * local (same contract-space); present means cross-space (the referenced\n * table lives in the contract-space identified by `spaceId`).\n *\n * For local references `spaceId` is absent from JSON, keeping the serialized\n * shape byte-identical to contracts authored before cross-space support was\n * added. For cross-space references `spaceId` appears in JSON so round-trips\n * are lossless.\n *\n * Use `UNBOUND_NAMESPACE_ID` from `@prisma-next/framework-components/ir`\n * as the sentinel `namespaceId` for single-namespace (unbound) references.\n */\nexport class ForeignKeyReference extends SqlNode {\n readonly namespaceId: NamespaceId;\n readonly tableName: string;\n readonly columns: readonly string[];\n declare readonly spaceId?: string;\n\n constructor(input: ForeignKeyReferenceInput) {\n super();\n this.namespaceId = asNamespaceId(input.namespaceId);\n this.tableName = input.tableName;\n this.columns = input.columns;\n if (input.spaceId !== undefined) this.spaceId = input.spaceId;\n freezeNode(this);\n }\n}\n","import { freezeNode } from '@prisma-next/framework-components/ir';\nimport { ForeignKeyReference, type ForeignKeyReferenceInput } from './foreign-key-reference';\nimport { SqlNode } from './sql-node';\n\nexport type ReferentialAction = 'noAction' | 'restrict' | 'cascade' | 'setNull' | 'setDefault';\n\nexport interface ForeignKeyInput {\n readonly source: ForeignKeyReference | ForeignKeyReferenceInput;\n readonly target: ForeignKeyReference | ForeignKeyReferenceInput;\n readonly name?: string;\n readonly onDelete?: ReferentialAction;\n readonly onUpdate?: ReferentialAction;\n}\n\n/**\n * SQL Contract IR node for a table-level foreign-key declaration — the\n * referential constraint only (source, target, `onDelete`/`onUpdate`).\n *\n * A persisted `foreignKeys[]` entry always denotes a real constraint: whether\n * to emit the constraint at all, and whether to back it with an index, are\n * authoring-time decisions (PSL `@relation(index:)`, TS `fk({ constraint,\n * index })`) resolved once at `contract emit` — a `constraint: false` FK\n * simply has no entry here, and a backing index (if any) is its own discrete,\n * named entry in the table's `indexes[]`.\n *\n * Each FK carries explicit `source` and `target` {@link ForeignKeyReference}\n * coordinates (namespace, table, columns). For single-namespace contracts the\n * sentinel `UNBOUND_NAMESPACE_ID` appears on both sides.\n *\n * The nested references are normalised to {@link ForeignKeyReference}\n * instances inside the constructor so downstream walks see a uniform AST\n * regardless of whether the input was a JSON literal or an already-constructed\n * class instance.\n */\nexport class ForeignKey extends SqlNode {\n readonly source: ForeignKeyReference;\n readonly target: ForeignKeyReference;\n declare readonly name?: string;\n declare readonly onDelete?: ReferentialAction;\n declare readonly onUpdate?: ReferentialAction;\n\n constructor(input: ForeignKeyInput) {\n super();\n this.source =\n input.source instanceof ForeignKeyReference\n ? input.source\n : new ForeignKeyReference(input.source);\n this.target =\n input.target instanceof ForeignKeyReference\n ? input.target\n : new ForeignKeyReference(input.target);\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 freezeNode(this);\n }\n}\n","import { freezeNode } from '@prisma-next/framework-components/ir';\nimport { SqlNode } from './sql-node';\n\nexport interface PrimaryKeyInput {\n readonly columns: readonly string[];\n readonly name?: string;\n}\n\n/**\n * SQL Contract IR node for a table's primary-key constraint.\n */\nexport class PrimaryKey extends SqlNode {\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 { SqlNode } from './sql-node';\n\nexport interface IndexInput {\n readonly columns: readonly string[];\n readonly name?: string;\n readonly type?: string;\n readonly options?: Record<string, unknown>;\n}\n\n/**\n * SQL Contract IR node for a table-level secondary index.\n *\n * Note that this class shadows the global TypeScript `Index` lib type\n * at the family-shared name; consumer files that need both should\n * alias one (e.g.\n * `import { Index as SqlIndexNode } from '@prisma-next/sql-contract/types'`).\n */\nexport class Index extends SqlNode {\n readonly columns: readonly string[];\n declare readonly name?: string;\n declare readonly type?: string;\n declare readonly options?: Record<string, unknown>;\n\n constructor(input: IndexInput) {\n super();\n this.columns = input.columns;\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 freezeNode(this);\n }\n}\n","import type { ColumnDefault, ControlPolicy, ValueSetRef } from '@prisma-next/contract/types';\nimport { freezeNode } from '@prisma-next/framework-components/ir';\nimport { SqlNode } from './sql-node';\n\n/**\n * Hydration / construction input shape for {@link StorageColumn}. Mirrors\n * the on-disk storage JSON envelope exactly so the family-base\n * serializer's hydration walker can hand an arktype-validated literal\n * straight to `new`.\n *\n * `typeParams` and `typeRef` remain mutually exclusive (one or the\n * other, not both); the constructor preserves whichever caller-side\n * choice the input encodes.\n */\nexport interface StorageColumnInput {\n readonly nativeType: string;\n readonly codecId: string;\n readonly nullable: boolean;\n readonly many?: boolean;\n readonly typeParams?: Record<string, unknown>;\n readonly typeRef?: string;\n readonly default?: ColumnDefault;\n readonly control?: ControlPolicy;\n readonly valueSet?: ValueSetRef;\n}\n\n/**\n * SQL Contract IR node for a single column entry in `StorageTable.columns`.\n *\n * Single concrete family-shared class — every SQL target reads the\n * same column shape today, so there is no per-target subclass. The\n * class type accepts any caller that constructs via\n * `new StorageColumn(input)`; literal construction sites must pass\n * through the constructor or the family-base hydration walker.\n *\n * The column's `name` is not on the class — columns are keyed by name\n * in the parent `StorageTable.columns: Record<string, StorageColumn>`\n * map, so a `name` field would be redundant with the key.\n */\nexport class StorageColumn extends SqlNode {\n readonly nativeType: string;\n readonly codecId: string;\n readonly nullable: boolean;\n declare readonly many?: boolean;\n declare readonly typeParams?: Record<string, unknown>;\n declare readonly typeRef?: string;\n declare readonly default?: ColumnDefault;\n declare readonly control?: ControlPolicy;\n declare readonly valueSet?: ValueSetRef;\n\n constructor(input: StorageColumnInput) {\n super();\n this.nativeType = input.nativeType;\n this.codecId = input.codecId;\n this.nullable = input.nullable;\n if (input.many !== undefined) this.many = input.many;\n if (input.typeParams !== undefined) this.typeParams = input.typeParams;\n if (input.typeRef !== undefined) this.typeRef = input.typeRef;\n if (input.default !== undefined) this.default = input.default;\n if (input.control !== undefined) this.control = input.control;\n if (input.valueSet !== undefined) this.valueSet = input.valueSet;\n freezeNode(this);\n }\n}\n","import { freezeNode } from '@prisma-next/framework-components/ir';\nimport { SqlNode } from './sql-node';\n\nexport interface UniqueConstraintInput {\n readonly columns: readonly string[];\n readonly name?: string;\n}\n\n/**\n * SQL Contract IR node for a table-level unique constraint.\n */\nexport class UniqueConstraint extends SqlNode {\n readonly columns: readonly string[];\n declare readonly name?: string;\n\n constructor(input: UniqueConstraintInput) {\n super();\n this.columns = input.columns;\n if (input.name !== undefined) this.name = input.name;\n freezeNode(this);\n }\n}\n","import type { ControlPolicy } from '@prisma-next/contract/types';\nimport { freezeNode } from '@prisma-next/framework-components/ir';\nimport { CheckConstraint, type CheckConstraintInput } from './check-constraint';\nimport { ForeignKey, type ForeignKeyInput } from './foreign-key';\nimport { PrimaryKey, type PrimaryKeyInput } from './primary-key';\nimport { Index, type IndexInput } from './sql-index';\nimport { SqlNode } from './sql-node';\nimport { StorageColumn, type StorageColumnInput } from './storage-column';\nimport { UniqueConstraint, type UniqueConstraintInput } from './unique-constraint';\n\nexport interface StorageTableInput {\n readonly columns: Record<string, StorageColumn | StorageColumnInput>;\n readonly primaryKey?: PrimaryKey | PrimaryKeyInput;\n readonly uniques: ReadonlyArray<UniqueConstraint | UniqueConstraintInput>;\n readonly indexes: ReadonlyArray<Index | IndexInput>;\n readonly foreignKeys: ReadonlyArray<ForeignKey | ForeignKeyInput>;\n readonly control?: ControlPolicy;\n readonly checks?: ReadonlyArray<CheckConstraint | CheckConstraintInput>;\n}\n\n/**\n * SQL Contract IR node for a single table entry in a namespace's\n * `tables` map.\n *\n * The constructor normalises nested IR-class fields (columns, primary\n * key, uniques, indexes, foreign keys) into the appropriate class\n * instances so downstream walks see a uniform AST regardless of whether\n * the input was a JSON literal or an already-constructed class.\n *\n * The table's `name` is not on the class — tables are keyed by name in\n * the parent namespace's `tables: Record<string, StorageTable>` map.\n */\nexport class StorageTable extends SqlNode {\n readonly columns: Readonly<Record<string, StorageColumn>>;\n readonly uniques: ReadonlyArray<UniqueConstraint>;\n readonly indexes: ReadonlyArray<Index>;\n readonly foreignKeys: ReadonlyArray<ForeignKey>;\n declare readonly primaryKey?: PrimaryKey;\n declare readonly control?: ControlPolicy;\n declare readonly checks?: ReadonlyArray<CheckConstraint>;\n\n constructor(input: StorageTableInput) {\n super();\n this.columns = Object.freeze(\n Object.fromEntries(\n Object.entries(input.columns).map(([name, col]) => [\n name,\n col instanceof StorageColumn ? col : new StorageColumn(col),\n ]),\n ),\n );\n if (input.primaryKey !== undefined) {\n this.primaryKey =\n input.primaryKey instanceof PrimaryKey\n ? input.primaryKey\n : new PrimaryKey(input.primaryKey);\n }\n this.uniques = Object.freeze(\n input.uniques.map((u) => (u instanceof UniqueConstraint ? u : new UniqueConstraint(u))),\n );\n this.indexes = Object.freeze(input.indexes.map((i) => (i instanceof Index ? i : new Index(i))));\n this.foreignKeys = Object.freeze(\n input.foreignKeys.map((fk) => (fk instanceof ForeignKey ? fk : new ForeignKey(fk))),\n );\n if (input.control !== undefined) this.control = input.control;\n if (input.checks !== undefined && input.checks.length > 0) {\n this.checks = Object.freeze(input.checks.map((cc) => new CheckConstraint(cc)));\n }\n freezeNode(this);\n }\n\n /**\n * Runtime guard that a namespace `table` entry is really a `StorageTable`.\n * The compiler already types the entry as `StorageTable`, but a\n * freshly-deserialized contract may carry plain JSON at that slot until\n * hydration; this duck-types the structural shape. Accepts `undefined` so\n * optional-chained entry lookups pass straight through.\n */\n static is(value: StorageTable | undefined): value is StorageTable {\n if (typeof value !== 'object' || value === null) return false;\n return 'columns' in value && 'uniques' in value && 'indexes' in value && 'foreignKeys' in value;\n }\n\n static assert(\n value: StorageTable | undefined,\n coordinate: string,\n ): asserts value is StorageTable {\n if (!StorageTable.is(value)) {\n throw new Error(`Expected a StorageTable at ${coordinate}`);\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"storage-table-mNGckl3_.d.mts","names":[],"sources":["../src/ir/check-constraint.ts","../src/ir/storage-column.ts","../src/ir/storage-table.ts"],"mappings":";;;;;;;;;;UASiB;WACN;WACA;WACA,UAAU;;;;;;;;;;;;;;;;cAiBR,wBAAwB;WAC1B;WACA;WACA,UAAU;cAEP,OAAO;;;;;;;;;;;;;;UCpBJ;WACN;WACA;WACA;WACA;WACA,aAAa;WACb;WACA,UAAU;WACV,UAAU;WACV,WAAW;;;;;;;;;;;;;;;cAgBT,sBAAsB;WACxB;WACA;WACA;WACQ;WACA,aAAa;WACb;WACA,UAAU;WACV,UAAU;WACV,WAAW;cAEhB,OAAO;;;;UCxCJ;WACN,SAAS,eAAe,gBAAgB;WACxC,aAAa,aAAa;WAC1B,SAAS,cAAc,mBAAmB;WAC1C,SAAS,cAAc,QAAQ;WAC/B,aAAa,cAAc,aAAa;WACxC,UAAU;WACV,SAAS,cAAc,kBAAkB;;;;;;;;;;;;;;cAevC,qBAAqB;WACvB,SAAS,SAAS,eAAe;WACjC,SAAS,cAAc;WACvB,SAAS,cAAc;WACvB,aAAa,cAAc;WACnB,aAAa;WACb,UAAU;WACV,SAAS,cAAc;cAE5B,OAAO;;;;;;;;SAqCZ,GAAG,OAAO,2BAA2B,SAAS;SAK9C,OACL,OAAO,0BACP,6BACS,SAAS"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types-lpzJtKpv.d.mts","names":[],"sources":["../src/types.ts"],"mappings":";;;;;;;;;UAIiB,yBAAyB,mCAChC,6BAA6B;EACrC,MAAM,MAAM,yBACV,aACA,8BACC;aAAmB,MAAM;;;KAgDlB;WACD;WACA,WAAW;WACX,WAAW;;KAGV;WACD;WACA;WACA;;KAGC;WACD;WACA;WACA,QAAQ,eAAe;;cAGrB;cACA;iBAEG,gBACd;EAAM;EAAkC;GACxC;EAAqB;EAAkC;;EACpD;EAAqB;;KASd,yBAAyB,eAAe,eAAe;KAEvD,iCAAiC,eAE3C,eAAe;KAGL,SACV,oBAAoB;EAAiB;KAAqB,uBAC1D,6BAA6B,0BAA0B,uBACvD,0BAA0B,yBAAyB,uBACnD,yBAAyB,yBAAyB,uBAClD,4BAA4B,iCAAiC,uBAC7D,iCAAiC,iCAAiC;WAEzD,YAAY;WACZ,qBAAqB;WACrB,kBAAkB;WAClB,iBAAiB;WACjB,oBAAoB;WACpB,yBAAyB;;KAGxB,aAAa,MAAM,qBAC3B,wBACA;WAAqB,kBAAkB;IACrC,UAAU;EAAiB;KACzB,IACA,wBACF;;;;;;;;;KAUM;WACG;WAA0B;WAAyB;;WACnD,iBAAiB;WAAuB;WAA0B;;WAElE;WACA,yBAAyB;WACzB;WACA;;;;;;;;;;KAWH;WACD;aAAuB;aAA0B;;;KAGhD;WACD,OAAO;WACP,UAAU,kBAAkB;;KAG3B,uBACV,YAAY;WAA0B;WAAyB;IAC/D,UAAU,eAAe,4BACvB;KAEQ,0BAA0B,eAAe;KAEzC,sBAAsB,MAAM,qBACpC,wBACA;WAAqB,2BAA2B;IAC9C,UAAU,0BACR,IACA,wBACF;KAEM;KAEA,qBAAqB,WAAW,aAAa,wBAC7C,KAAK,sBAAsB;KAG3B,4BAA4B,KAAK,iCAAiC,IAC1E,YAAY,EAAE,2BAA2B;KAGjC,mBAAmB,MAAM,qBACjC,wBACA;WAAqB,wBAAwB;IAC3C,UAAU,yBACR,IACA,wBACF;KAEM,kBAAkB,MAAM,qBAChC,wBACA;WAAqB,uBAAuB;IAC1C,UAAU,yBACR,IACA,wBACF;KAEM,qBAAqB,MAAM,qBACnC,wBACA;WAAqB,0BAA0B;IAC7C,UAAU,iCACR,IACA,wBACF;KAEM,0BAA0B,MAAM,qBACxC,wBACA;WAAqB,+BAA+B;IAClD,UAAU,iCACR,IACA,wBACF;KAEM,kBAAkB,KAAK,aAAa,4BAA4B;KAChE,2BAA2B,KAAK,sBAAsB,4BAA4B;KAClF,wBAAwB,KAAK,mBAAmB,4BAA4B;KAC5E,uBAAuB,KAAK,kBAAkB,4BAA4B;KAC1E,0BAA0B,KAAK,qBAAqB,4BAA4B;KAChF,+BAA+B,KAAK,0BAC9C,4BAA4B;KAGlB,kBAAkB,WAAW,cAAc,6BACnD,kBAAkB,aAClB,aAAa"}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { t as SqlNode } from "./sql-node-QXu33IeX.mjs";
|
|
2
|
-
//#region src/ir/primary-key.d.ts
|
|
3
|
-
interface PrimaryKeyInput {
|
|
4
|
-
readonly columns: readonly string[];
|
|
5
|
-
readonly name?: string;
|
|
6
|
-
}
|
|
7
|
-
/**
|
|
8
|
-
* SQL Contract IR node for a table's primary-key constraint.
|
|
9
|
-
*/
|
|
10
|
-
declare class PrimaryKey extends SqlNode {
|
|
11
|
-
readonly columns: readonly string[];
|
|
12
|
-
readonly name?: string;
|
|
13
|
-
constructor(input: PrimaryKeyInput);
|
|
14
|
-
}
|
|
15
|
-
//#endregion
|
|
16
|
-
//#region src/ir/sql-index.d.ts
|
|
17
|
-
interface IndexInput {
|
|
18
|
-
readonly columns: readonly string[];
|
|
19
|
-
readonly name?: string;
|
|
20
|
-
readonly type?: string;
|
|
21
|
-
readonly options?: Record<string, unknown>;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* SQL Contract IR node for a table-level secondary index.
|
|
25
|
-
*
|
|
26
|
-
* Note that this class shadows the global TypeScript `Index` lib type
|
|
27
|
-
* at the family-shared name; consumer files that need both should
|
|
28
|
-
* alias one (e.g.
|
|
29
|
-
* `import { Index as SqlIndexNode } from '@prisma-next/sql-contract/types'`).
|
|
30
|
-
*/
|
|
31
|
-
declare class Index extends SqlNode {
|
|
32
|
-
readonly columns: readonly string[];
|
|
33
|
-
readonly name?: string;
|
|
34
|
-
readonly type?: string;
|
|
35
|
-
readonly options?: Record<string, unknown>;
|
|
36
|
-
constructor(input: IndexInput);
|
|
37
|
-
}
|
|
38
|
-
//#endregion
|
|
39
|
-
//#region src/ir/unique-constraint.d.ts
|
|
40
|
-
interface UniqueConstraintInput {
|
|
41
|
-
readonly columns: readonly string[];
|
|
42
|
-
readonly name?: string;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* SQL Contract IR node for a table-level unique constraint.
|
|
46
|
-
*/
|
|
47
|
-
declare class UniqueConstraint extends SqlNode {
|
|
48
|
-
readonly columns: readonly string[];
|
|
49
|
-
readonly name?: string;
|
|
50
|
-
constructor(input: UniqueConstraintInput);
|
|
51
|
-
}
|
|
52
|
-
//#endregion
|
|
53
|
-
export { PrimaryKey as a, IndexInput as i, UniqueConstraintInput as n, PrimaryKeyInput as o, Index as r, UniqueConstraint as t };
|
|
54
|
-
//# sourceMappingURL=unique-constraint-WHfanEUq.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"unique-constraint-WHfanEUq.d.mts","names":[],"sources":["../src/ir/primary-key.ts","../src/ir/sql-index.ts","../src/ir/unique-constraint.ts"],"mappings":";;UAGiB;WACN;WACA;;;;;cAME,mBAAmB;WACrB;WACQ;cAEL,OAAO;;;;UCZJ;WACN;WACA;WACA;WACA,UAAU;;;;;;;;;;cAWR,cAAc;WAChB;WACQ;WACA;WACA,UAAU;cAEf,OAAO;;;;UCrBJ;WACN;WACA;;;;;cAME,yBAAyB;WAC3B;WACQ;cAEL,OAAO"}
|