@prisma-next/sql-contract 0.13.0 → 0.14.0-dev.10
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/{types-DqhaAjCH.mjs → entity-kinds-Cl36zL5j.mjs} +121 -205
- package/dist/entity-kinds-Cl36zL5j.mjs.map +1 -0
- package/dist/entity-kinds.d.mts +18 -0
- package/dist/entity-kinds.d.mts.map +1 -0
- package/dist/entity-kinds.mjs +2 -0
- package/dist/factories.d.mts +2 -2
- package/dist/factories.mjs +2 -1
- package/dist/factories.mjs.map +1 -1
- package/dist/index-type-validation.d.mts +1 -1
- package/dist/index-type-validation.mjs +9 -12
- package/dist/index-type-validation.mjs.map +1 -1
- package/dist/resolve-storage-table.d.mts +2 -1
- package/dist/resolve-storage-table.d.mts.map +1 -1
- package/dist/resolve-storage-table.mjs +11 -8
- package/dist/resolve-storage-table.mjs.map +1 -1
- package/dist/sql-storage-Dga0jwP2.d.mts +128 -0
- package/dist/sql-storage-Dga0jwP2.d.mts.map +1 -0
- package/dist/{sql-storage-CXf9xjAL.d.mts → storage-value-set-WnYsIFM8.d.mts} +8 -120
- package/dist/storage-value-set-WnYsIFM8.d.mts.map +1 -0
- package/dist/types-B-eiQXff.mjs +191 -0
- package/dist/types-B-eiQXff.mjs.map +1 -0
- package/dist/{types-DEnWD3xB.d.mts → types-B1N8w0I2.d.mts} +11 -62
- package/dist/types-B1N8w0I2.d.mts.map +1 -0
- package/dist/types.d.mts +4 -3
- package/dist/types.mjs +3 -2
- package/dist/validators.d.mts +75 -40
- package/dist/validators.d.mts.map +1 -1
- package/dist/validators.mjs +156 -184
- package/dist/validators.mjs.map +1 -1
- package/package.json +8 -7
- package/src/entity-kinds.ts +45 -0
- package/src/exports/entity-kinds.ts +5 -0
- package/src/exports/types.ts +2 -4
- package/src/index-type-validation.ts +2 -3
- package/src/ir/build-sql-namespace.ts +39 -32
- package/src/ir/sql-node.ts +2 -2
- package/src/ir/sql-storage.ts +22 -24
- package/src/ir/sql-unbound-namespace.ts +15 -3
- package/src/ir/storage-entry-schemas.ts +128 -0
- package/src/ir/storage-type-instance.ts +3 -3
- package/src/ir/storage-value-set.ts +6 -5
- package/src/resolve-storage-table.ts +12 -17
- package/src/types.ts +10 -10
- package/src/validators.ts +288 -225
- package/dist/sql-storage-CXf9xjAL.d.mts.map +0 -1
- package/dist/types-DEnWD3xB.d.mts.map +0 -1
- package/dist/types-DqhaAjCH.mjs.map +0 -1
- package/src/ir/postgres-enum-storage-entry.ts +0 -57
|
@@ -3,6 +3,8 @@ import {
|
|
|
3
3
|
NamespaceBase,
|
|
4
4
|
UNBOUND_NAMESPACE_ID,
|
|
5
5
|
} from '@prisma-next/framework-components/ir';
|
|
6
|
+
import { blindCast } from '@prisma-next/utils/casts';
|
|
7
|
+
import type { SqlNamespaceEntries } from './sql-storage';
|
|
6
8
|
import type { StorageTable } from './storage-table';
|
|
7
9
|
|
|
8
10
|
/**
|
|
@@ -40,9 +42,12 @@ export class SqlUnboundNamespace extends NamespaceBase {
|
|
|
40
42
|
static readonly instance: SqlUnboundNamespace = new SqlUnboundNamespace();
|
|
41
43
|
|
|
42
44
|
readonly id = UNBOUND_NAMESPACE_ID;
|
|
43
|
-
readonly entries:
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
readonly entries: SqlNamespaceEntries = Object.freeze({
|
|
46
|
+
table: blindCast<
|
|
47
|
+
Readonly<Record<string, StorageTable>>,
|
|
48
|
+
'empty frozen map is a valid Readonly<Record<string, StorageTable>>'
|
|
49
|
+
>(Object.freeze({})),
|
|
50
|
+
});
|
|
46
51
|
declare readonly kind: string;
|
|
47
52
|
|
|
48
53
|
private constructor() {
|
|
@@ -56,6 +61,13 @@ export class SqlUnboundNamespace extends NamespaceBase {
|
|
|
56
61
|
freezeNode(this);
|
|
57
62
|
}
|
|
58
63
|
|
|
64
|
+
get table(): Readonly<Record<string, StorageTable>> {
|
|
65
|
+
return blindCast<
|
|
66
|
+
Readonly<Record<string, StorageTable>>,
|
|
67
|
+
'entries[table] holds only StorageTable by construction'
|
|
68
|
+
>(this.entries['table']);
|
|
69
|
+
}
|
|
70
|
+
|
|
59
71
|
qualifyTable(tableName: string): string {
|
|
60
72
|
return `"${tableName}"`;
|
|
61
73
|
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { type Type, type } from 'arktype';
|
|
2
|
+
import type { ForeignKeyInput, ReferentialAction } from './foreign-key';
|
|
3
|
+
import type { ForeignKeyReferenceInput } from './foreign-key-reference';
|
|
4
|
+
import type { PrimaryKeyInput } from './primary-key';
|
|
5
|
+
import type { UniqueConstraintInput } from './unique-constraint';
|
|
6
|
+
|
|
7
|
+
type ColumnDefaultLiteral = {
|
|
8
|
+
readonly kind: 'literal';
|
|
9
|
+
readonly value: string | number | boolean | Record<string, unknown> | unknown[] | null;
|
|
10
|
+
};
|
|
11
|
+
type ColumnDefaultFunction = { readonly kind: 'function'; readonly expression: string };
|
|
12
|
+
|
|
13
|
+
const literalKindSchema = type("'literal'");
|
|
14
|
+
const functionKindSchema = type("'function'");
|
|
15
|
+
const ControlPolicySchema = type("'managed' | 'tolerated' | 'external' | 'observed'");
|
|
16
|
+
|
|
17
|
+
export const ColumnDefaultLiteralSchema = type.declare<ColumnDefaultLiteral>().type({
|
|
18
|
+
kind: literalKindSchema,
|
|
19
|
+
value: 'string | number | boolean | null | unknown[] | Record<string, unknown>',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export const ColumnDefaultFunctionSchema = type.declare<ColumnDefaultFunction>().type({
|
|
23
|
+
kind: functionKindSchema,
|
|
24
|
+
expression: 'string',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export const ColumnDefaultSchema = ColumnDefaultLiteralSchema.or(ColumnDefaultFunctionSchema);
|
|
28
|
+
|
|
29
|
+
const StorageValueSetRefSchema = type({
|
|
30
|
+
plane: "'storage'",
|
|
31
|
+
namespaceId: 'string',
|
|
32
|
+
entityKind: "'valueSet'",
|
|
33
|
+
entityName: 'string',
|
|
34
|
+
'spaceId?': 'string',
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const StorageColumnSchema = type({
|
|
38
|
+
'+': 'reject',
|
|
39
|
+
nativeType: 'string',
|
|
40
|
+
codecId: 'string',
|
|
41
|
+
nullable: 'boolean',
|
|
42
|
+
'typeParams?': 'Record<string, unknown>',
|
|
43
|
+
'typeRef?': 'string',
|
|
44
|
+
'default?': ColumnDefaultSchema,
|
|
45
|
+
'control?': ControlPolicySchema,
|
|
46
|
+
'valueSet?': StorageValueSetRefSchema,
|
|
47
|
+
}).narrow((col, ctx) => {
|
|
48
|
+
if (col.typeParams !== undefined && col.typeRef !== undefined) {
|
|
49
|
+
return ctx.mustBe('a column with either typeParams or typeRef, not both');
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Storage value-set entry under `storage.namespaces[id].entries.valueSet[name]`.
|
|
56
|
+
* Carries a `kind: 'valueSet'` discriminator (enumerable, survives JSON) and an
|
|
57
|
+
* ordered `values` array of codec-encoded permitted values.
|
|
58
|
+
*/
|
|
59
|
+
export const StorageValueSetSchema = type({
|
|
60
|
+
kind: "'valueSet'",
|
|
61
|
+
values: type('string | number | boolean | null | unknown[] | Record<string, unknown>')
|
|
62
|
+
.array()
|
|
63
|
+
.readonly(),
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const PrimaryKeySchema = type.declare<PrimaryKeyInput>().type({
|
|
67
|
+
columns: type.string.array().readonly(),
|
|
68
|
+
'name?': 'string',
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const UniqueConstraintSchema = type.declare<UniqueConstraintInput>().type({
|
|
72
|
+
columns: type.string.array().readonly(),
|
|
73
|
+
'name?': 'string',
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
export const IndexSchema = type({
|
|
77
|
+
columns: type.string.array().readonly(),
|
|
78
|
+
'name?': 'string',
|
|
79
|
+
'type?': 'string',
|
|
80
|
+
'options?': 'Record<string, unknown>',
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
export const ForeignKeyReferenceSchema = type({
|
|
84
|
+
'+': 'reject',
|
|
85
|
+
namespaceId: 'string',
|
|
86
|
+
tableName: 'string',
|
|
87
|
+
columns: type.string.array().readonly(),
|
|
88
|
+
'spaceId?': 'string',
|
|
89
|
+
}) satisfies Type<ForeignKeyReferenceInput>;
|
|
90
|
+
|
|
91
|
+
export const ForeignKeySourceSchema = type({
|
|
92
|
+
'+': 'reject',
|
|
93
|
+
namespaceId: 'string',
|
|
94
|
+
tableName: 'string',
|
|
95
|
+
columns: type.string.array().readonly(),
|
|
96
|
+
}) satisfies Type<ForeignKeyReferenceInput>;
|
|
97
|
+
|
|
98
|
+
export const ReferentialActionSchema = type
|
|
99
|
+
.declare<ReferentialAction>()
|
|
100
|
+
.type("'noAction' | 'restrict' | 'cascade' | 'setNull' | 'setDefault'");
|
|
101
|
+
|
|
102
|
+
export const ForeignKeySchema = type.declare<ForeignKeyInput>().type({
|
|
103
|
+
source: ForeignKeySourceSchema,
|
|
104
|
+
target: ForeignKeyReferenceSchema,
|
|
105
|
+
'name?': 'string',
|
|
106
|
+
'onDelete?': ReferentialActionSchema,
|
|
107
|
+
'onUpdate?': ReferentialActionSchema,
|
|
108
|
+
constraint: 'boolean',
|
|
109
|
+
index: 'boolean',
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
export const CheckConstraintSchema = type({
|
|
113
|
+
'+': 'reject',
|
|
114
|
+
name: 'string',
|
|
115
|
+
column: 'string',
|
|
116
|
+
valueSet: StorageValueSetRefSchema,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
export const StorageTableSchema = type({
|
|
120
|
+
'+': 'reject',
|
|
121
|
+
columns: type({ '[string]': StorageColumnSchema }),
|
|
122
|
+
'primaryKey?': PrimaryKeySchema,
|
|
123
|
+
uniques: UniqueConstraintSchema.array().readonly(),
|
|
124
|
+
indexes: IndexSchema.array().readonly(),
|
|
125
|
+
foreignKeys: ForeignKeySchema.array().readonly(),
|
|
126
|
+
'control?': ControlPolicySchema,
|
|
127
|
+
'checks?': CheckConstraintSchema.array().readonly(),
|
|
128
|
+
});
|
|
@@ -14,8 +14,8 @@ export const CODEC_INSTANCE_KIND = 'codec-instance' as const;
|
|
|
14
14
|
* in `SqlStorage.types`. These are plain object literals — there is no
|
|
15
15
|
* runtime IR class, the JSON envelope round-trips through the slot
|
|
16
16
|
* unchanged. The `kind: 'codec-instance'` discriminator is the dispatch
|
|
17
|
-
* key that distinguishes codec-typed entries from class-instance
|
|
18
|
-
*
|
|
17
|
+
* key that distinguishes codec-typed entries from any class-instance
|
|
18
|
+
* kinds a target pack contributes to the polymorphic slot.
|
|
19
19
|
*/
|
|
20
20
|
export interface StorageTypeInstance extends StorageType {
|
|
21
21
|
readonly kind: typeof CODEC_INSTANCE_KIND;
|
|
@@ -54,7 +54,7 @@ export function toStorageTypeInstance(input: StorageTypeInstanceInput): StorageT
|
|
|
54
54
|
/**
|
|
55
55
|
* Type-guard for codec-typed entries on the polymorphic
|
|
56
56
|
* `SqlStorage.types` slot. Distinguishes `StorageTypeInstance` from
|
|
57
|
-
* class-instance kinds
|
|
57
|
+
* any class-instance kinds a target pack contributes.
|
|
58
58
|
*/
|
|
59
59
|
export function isStorageTypeInstance(value: unknown): value is StorageTypeInstance {
|
|
60
60
|
if (typeof value !== 'object' || value === null) return false;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { JsonValue } from '@prisma-next/contract/types';
|
|
1
2
|
import { freezeNode } from '@prisma-next/framework-components/ir';
|
|
2
3
|
import { SqlNode } from './sql-node';
|
|
3
4
|
|
|
@@ -7,9 +8,9 @@ import { SqlNode } from './sql-node';
|
|
|
7
8
|
* walker can hand a validated literal straight to `new`.
|
|
8
9
|
*/
|
|
9
10
|
export interface StorageValueSetInput {
|
|
10
|
-
readonly kind: '
|
|
11
|
+
readonly kind: 'valueSet';
|
|
11
12
|
/** Ordered permitted values, codec-encoded. Declaration order is preserved. */
|
|
12
|
-
readonly values: readonly
|
|
13
|
+
readonly values: readonly JsonValue[];
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
/**
|
|
@@ -21,7 +22,7 @@ export interface StorageValueSetInput {
|
|
|
21
22
|
* column that references it already holds the codec; the value-set holds
|
|
22
23
|
* only the permitted values.
|
|
23
24
|
*
|
|
24
|
-
* The node's `kind` is enumerable (`'
|
|
25
|
+
* The node's `kind` is enumerable (`'valueSet'`) so the JSON envelope
|
|
25
26
|
* carries the discriminator and the serializer hydration walker can
|
|
26
27
|
* dispatch on it. This follows the per-leaf enumerable-kind convention
|
|
27
28
|
* established in the SQL-node comment (future polymorphic dispatch on
|
|
@@ -31,8 +32,8 @@ export interface StorageValueSetInput {
|
|
|
31
32
|
* the parent namespace's `valueSet: Record<string, StorageValueSet>` map.
|
|
32
33
|
*/
|
|
33
34
|
export class StorageValueSet extends SqlNode {
|
|
34
|
-
override readonly kind = '
|
|
35
|
-
readonly values: readonly
|
|
35
|
+
override readonly kind = 'valueSet' as const;
|
|
36
|
+
readonly values: readonly JsonValue[];
|
|
36
37
|
|
|
37
38
|
constructor(input: StorageValueSetInput) {
|
|
38
39
|
super();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { entityAt } from '@prisma-next/framework-components/ir';
|
|
2
|
+
import type { SqlStorage } from './ir/sql-storage';
|
|
2
3
|
import type { StorageTable } from './ir/storage-table';
|
|
3
4
|
|
|
4
5
|
export interface ResolvedStorageTable {
|
|
@@ -6,20 +7,6 @@ export interface ResolvedStorageTable {
|
|
|
6
7
|
readonly table: StorageTable;
|
|
7
8
|
}
|
|
8
9
|
|
|
9
|
-
function tableInNamespace(
|
|
10
|
-
namespace: SqlNamespace | undefined,
|
|
11
|
-
tableName: string,
|
|
12
|
-
): StorageTable | undefined {
|
|
13
|
-
if (namespace === undefined) {
|
|
14
|
-
return undefined;
|
|
15
|
-
}
|
|
16
|
-
const tables = namespace.entries.table;
|
|
17
|
-
if (!Object.hasOwn(tables, tableName)) {
|
|
18
|
-
return undefined;
|
|
19
|
-
}
|
|
20
|
-
return tables[tableName];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
10
|
/**
|
|
24
11
|
* Resolve a bare storage table name to its namespace coordinate and table IR.
|
|
25
12
|
*
|
|
@@ -35,13 +22,21 @@ export function resolveStorageTable(
|
|
|
35
22
|
namespaceId?: string,
|
|
36
23
|
): ResolvedStorageTable | undefined {
|
|
37
24
|
if (namespaceId !== undefined) {
|
|
38
|
-
const table =
|
|
25
|
+
const table = entityAt<StorageTable>(storage, {
|
|
26
|
+
namespaceId,
|
|
27
|
+
entityKind: 'table',
|
|
28
|
+
entityName: tableName,
|
|
29
|
+
});
|
|
39
30
|
return table === undefined ? undefined : { namespaceId, table };
|
|
40
31
|
}
|
|
41
32
|
|
|
42
33
|
const matches: ResolvedStorageTable[] = [];
|
|
43
34
|
for (const candidateNamespaceId of Object.keys(storage.namespaces)) {
|
|
44
|
-
const table =
|
|
35
|
+
const table = entityAt<StorageTable>(storage, {
|
|
36
|
+
namespaceId: candidateNamespaceId,
|
|
37
|
+
entityKind: 'table',
|
|
38
|
+
entityName: tableName,
|
|
39
|
+
});
|
|
45
40
|
if (table !== undefined) {
|
|
46
41
|
matches.push({ namespaceId: candidateNamespaceId, table });
|
|
47
42
|
}
|
package/src/types.ts
CHANGED
|
@@ -21,20 +21,16 @@ export {
|
|
|
21
21
|
ForeignKeyReference,
|
|
22
22
|
type ForeignKeyReferenceInput,
|
|
23
23
|
} from './ir/foreign-key-reference';
|
|
24
|
-
export {
|
|
25
|
-
isPostgresEnumStorageEntry,
|
|
26
|
-
POSTGRES_ENUM_KIND,
|
|
27
|
-
type PostgresEnumStorageEntry,
|
|
28
|
-
} from './ir/postgres-enum-storage-entry';
|
|
29
24
|
export { PrimaryKey, type PrimaryKeyInput } from './ir/primary-key';
|
|
30
25
|
export { Index, type IndexInput } from './ir/sql-index';
|
|
31
26
|
export { SqlNode } from './ir/sql-node';
|
|
32
27
|
export {
|
|
28
|
+
type SqlNamespace,
|
|
29
|
+
type SqlNamespaceEntries,
|
|
33
30
|
type SqlNamespaceTablesInput,
|
|
34
31
|
SqlStorage,
|
|
35
32
|
type SqlStorageInput,
|
|
36
33
|
type SqlStorageTypeEntry,
|
|
37
|
-
storageTableAt,
|
|
38
34
|
} from './ir/sql-storage';
|
|
39
35
|
export { SqlUnboundNamespace } from './ir/sql-unbound-namespace';
|
|
40
36
|
export { StorageColumn, type StorageColumnInput } from './ir/storage-column';
|
|
@@ -83,11 +79,15 @@ export function applyFkDefaults(
|
|
|
83
79
|
};
|
|
84
80
|
}
|
|
85
81
|
|
|
82
|
+
// Field-type maps nested by namespace coordinate: `[namespaceId][model][field]`.
|
|
83
|
+
// Shared by the output and input field-type maps and their extractors.
|
|
84
|
+
export type NamespacedFieldTypeMap = Record<string, Record<string, Record<string, unknown>>>;
|
|
85
|
+
|
|
86
86
|
export type TypeMaps<
|
|
87
87
|
TCodecTypes extends Record<string, { output: unknown }> = Record<string, never>,
|
|
88
88
|
TQueryOperationTypes extends Record<string, unknown> = Record<string, never>,
|
|
89
|
-
TFieldOutputTypes extends
|
|
90
|
-
TFieldInputTypes extends
|
|
89
|
+
TFieldOutputTypes extends NamespacedFieldTypeMap = Record<string, never>,
|
|
90
|
+
TFieldInputTypes extends NamespacedFieldTypeMap = Record<string, never>,
|
|
91
91
|
> = {
|
|
92
92
|
readonly codecTypes: TCodecTypes;
|
|
93
93
|
readonly queryOperationTypes: TQueryOperationTypes;
|
|
@@ -159,7 +159,7 @@ export type ExtractTypeMapsFromContract<T> = TypeMapsPhantomKey extends keyof T
|
|
|
159
159
|
export type FieldOutputTypesOf<T> = [T] extends [never]
|
|
160
160
|
? Record<string, never>
|
|
161
161
|
: T extends { readonly fieldOutputTypes: infer F }
|
|
162
|
-
? F extends
|
|
162
|
+
? F extends NamespacedFieldTypeMap
|
|
163
163
|
? F
|
|
164
164
|
: Record<string, never>
|
|
165
165
|
: Record<string, never>;
|
|
@@ -167,7 +167,7 @@ export type FieldOutputTypesOf<T> = [T] extends [never]
|
|
|
167
167
|
export type FieldInputTypesOf<T> = [T] extends [never]
|
|
168
168
|
? Record<string, never>
|
|
169
169
|
: T extends { readonly fieldInputTypes: infer F }
|
|
170
|
-
? F extends
|
|
170
|
+
? F extends NamespacedFieldTypeMap
|
|
171
171
|
? F
|
|
172
172
|
: Record<string, never>
|
|
173
173
|
: Record<string, never>;
|