@prisma-next/sql-contract-ts 0.5.0-dev.81 → 0.5.0-dev.82
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/contract-builder.d.mts +87 -55
- package/dist/contract-builder.d.mts.map +1 -1
- package/dist/contract-builder.mjs +24 -13
- package/dist/contract-builder.mjs.map +1 -1
- package/package.json +9 -9
- package/src/build-contract.ts +37 -5
- package/src/composed-authoring-helpers.ts +35 -1
- package/src/contract-definition.ts +2 -2
- package/src/contract-dsl.ts +72 -32
- package/src/contract-lowering.ts +4 -3
- package/src/contract-types.ts +33 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/sql-contract-ts",
|
|
3
|
-
"version": "0.5.0-dev.
|
|
3
|
+
"version": "0.5.0-dev.82",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
"arktype": "^2.1.29",
|
|
10
10
|
"pathe": "^2.0.3",
|
|
11
11
|
"ts-toolbelt": "^9.6.0",
|
|
12
|
-
"@prisma-next/config": "0.5.0-dev.
|
|
13
|
-
"@prisma-next/contract-authoring": "0.5.0-dev.
|
|
14
|
-
"@prisma-next/framework-components": "0.5.0-dev.
|
|
15
|
-
"@prisma-next/
|
|
16
|
-
"@prisma-next/
|
|
17
|
-
"@prisma-next/
|
|
12
|
+
"@prisma-next/config": "0.5.0-dev.82",
|
|
13
|
+
"@prisma-next/contract-authoring": "0.5.0-dev.82",
|
|
14
|
+
"@prisma-next/framework-components": "0.5.0-dev.82",
|
|
15
|
+
"@prisma-next/sql-contract": "0.5.0-dev.82",
|
|
16
|
+
"@prisma-next/utils": "0.5.0-dev.82",
|
|
17
|
+
"@prisma-next/contract": "0.5.0-dev.82"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"@types/pg": "8.20.0",
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"typescript": "5.9.3",
|
|
24
24
|
"vitest": "4.1.5",
|
|
25
25
|
"@prisma-next/test-utils": "0.0.1",
|
|
26
|
-
"@prisma-next/
|
|
27
|
-
"@prisma-next/
|
|
26
|
+
"@prisma-next/tsconfig": "0.0.0",
|
|
27
|
+
"@prisma-next/tsdown": "0.0.0"
|
|
28
28
|
},
|
|
29
29
|
"files": [
|
|
30
30
|
"dist",
|
package/src/build-contract.ts
CHANGED
|
@@ -17,6 +17,12 @@ import {
|
|
|
17
17
|
type StorageHashBase,
|
|
18
18
|
} from '@prisma-next/contract/types';
|
|
19
19
|
import type { CodecLookup } from '@prisma-next/framework-components/codec';
|
|
20
|
+
import { validateIndexTypes } from '@prisma-next/sql-contract/index-type-validation';
|
|
21
|
+
import {
|
|
22
|
+
createIndexTypeRegistry,
|
|
23
|
+
type IndexTypeMap,
|
|
24
|
+
type IndexTypeRegistration,
|
|
25
|
+
} from '@prisma-next/sql-contract/index-types';
|
|
20
26
|
import {
|
|
21
27
|
applyFkDefaults,
|
|
22
28
|
type SqlStorage,
|
|
@@ -63,11 +69,37 @@ function encodeColumnDefault(
|
|
|
63
69
|
};
|
|
64
70
|
}
|
|
65
71
|
|
|
66
|
-
function assertStorageSemantics(
|
|
67
|
-
|
|
72
|
+
function assertStorageSemantics(
|
|
73
|
+
definition: ContractDefinition,
|
|
74
|
+
contract: Contract<SqlStorage>,
|
|
75
|
+
): void {
|
|
76
|
+
const semanticErrors = validateStorageSemantics(contract.storage);
|
|
68
77
|
if (semanticErrors.length > 0) {
|
|
69
78
|
throw new Error(`Contract semantic validation failed: ${semanticErrors.join('; ')}`);
|
|
70
79
|
}
|
|
80
|
+
|
|
81
|
+
const indexTypeRegistry = createIndexTypeRegistry();
|
|
82
|
+
const packsToRegister: ReadonlyArray<{ readonly id?: string; readonly indexTypes?: unknown }> = [
|
|
83
|
+
definition.target,
|
|
84
|
+
...Object.values(definition.extensionPacks ?? {}),
|
|
85
|
+
];
|
|
86
|
+
for (const pack of packsToRegister) {
|
|
87
|
+
const registration = pack.indexTypes;
|
|
88
|
+
if (registration === undefined) continue;
|
|
89
|
+
if (
|
|
90
|
+
typeof registration !== 'object' ||
|
|
91
|
+
registration === null ||
|
|
92
|
+
!Array.isArray((registration as { entries?: unknown }).entries)
|
|
93
|
+
) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
`Pack "${pack.id ?? '<unknown>'}" declares "indexTypes" but its value is not an IndexTypeRegistration (expected an object with an "entries" array; got ${typeof registration}).`,
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
for (const entry of (registration as IndexTypeRegistration<IndexTypeMap>).entries) {
|
|
99
|
+
indexTypeRegistry.register(entry);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
validateIndexTypes(contract, indexTypeRegistry);
|
|
71
103
|
}
|
|
72
104
|
|
|
73
105
|
function assertKnownTargetModel(
|
|
@@ -277,8 +309,8 @@ export function buildSqlContractFromDefinition(
|
|
|
277
309
|
indexes: (semanticModel.indexes ?? []).map((i) => ({
|
|
278
310
|
columns: i.columns,
|
|
279
311
|
...ifDefined('name', i.name),
|
|
280
|
-
...ifDefined('
|
|
281
|
-
...ifDefined('
|
|
312
|
+
...ifDefined('type', i.type),
|
|
313
|
+
...ifDefined('options', i.options),
|
|
282
314
|
})),
|
|
283
315
|
foreignKeys,
|
|
284
316
|
...(semanticModel.id
|
|
@@ -447,7 +479,7 @@ export function buildSqlContractFromDefinition(
|
|
|
447
479
|
meta: {},
|
|
448
480
|
};
|
|
449
481
|
|
|
450
|
-
assertStorageSemantics(contract
|
|
482
|
+
assertStorageSemantics(definition, contract);
|
|
451
483
|
|
|
452
484
|
return contract;
|
|
453
485
|
}
|
|
@@ -26,7 +26,14 @@ import type {
|
|
|
26
26
|
TupleFromArgumentDescriptors,
|
|
27
27
|
UnionToIntersection,
|
|
28
28
|
} from './authoring-type-utils';
|
|
29
|
+
import type {
|
|
30
|
+
AnyRelationBuilder,
|
|
31
|
+
ContractModelBuilder,
|
|
32
|
+
IndexTypeMap,
|
|
33
|
+
ScalarFieldBuilder,
|
|
34
|
+
} from './contract-dsl';
|
|
29
35
|
import { buildFieldPreset, field, model, rel } from './contract-dsl';
|
|
36
|
+
import type { MergeExtensionIndexTypes } from './contract-types';
|
|
30
37
|
|
|
31
38
|
type ExtractTypeNamespaceFromPack<Pack> = Pack extends {
|
|
32
39
|
readonly authoring?: { readonly type?: infer Namespace extends AuthoringTypeNamespace };
|
|
@@ -93,6 +100,33 @@ type TypeHelpersFromNamespace<Namespace> = {
|
|
|
93
100
|
|
|
94
101
|
type CoreFieldHelpers = Pick<typeof field, 'column' | 'generated' | 'namedType'>;
|
|
95
102
|
|
|
103
|
+
type MergeAllPackIndexTypes<Family, Target, ExtensionPacks> = MergeExtensionIndexTypes<
|
|
104
|
+
{ readonly __family: Family; readonly __target: Target } & (ExtensionPacks extends Record<
|
|
105
|
+
string,
|
|
106
|
+
unknown
|
|
107
|
+
>
|
|
108
|
+
? ExtensionPacks
|
|
109
|
+
: Record<never, never>)
|
|
110
|
+
>;
|
|
111
|
+
|
|
112
|
+
type PackAwareModel<IndexTypes extends IndexTypeMap> = {
|
|
113
|
+
<
|
|
114
|
+
const ModelName extends string,
|
|
115
|
+
Fields extends Record<string, ScalarFieldBuilder>,
|
|
116
|
+
Relations extends Record<string, AnyRelationBuilder> = Record<never, never>,
|
|
117
|
+
>(
|
|
118
|
+
modelName: ModelName,
|
|
119
|
+
input: { readonly fields: Fields; readonly relations?: Relations },
|
|
120
|
+
): ContractModelBuilder<ModelName, Fields, Relations, undefined, undefined, IndexTypes>;
|
|
121
|
+
<
|
|
122
|
+
Fields extends Record<string, ScalarFieldBuilder>,
|
|
123
|
+
Relations extends Record<string, AnyRelationBuilder> = Record<never, never>,
|
|
124
|
+
>(input: {
|
|
125
|
+
readonly fields: Fields;
|
|
126
|
+
readonly relations?: Relations;
|
|
127
|
+
}): ContractModelBuilder<undefined, Fields, Relations, undefined, undefined, IndexTypes>;
|
|
128
|
+
};
|
|
129
|
+
|
|
96
130
|
export type ComposedAuthoringHelpers<
|
|
97
131
|
Family extends FamilyPackRef<string>,
|
|
98
132
|
Target extends TargetPackRef<'sql', string>,
|
|
@@ -104,7 +138,7 @@ export type ComposedAuthoringHelpers<
|
|
|
104
138
|
ExtractFieldNamespaceFromPack<Target> &
|
|
105
139
|
MergeExtensionFieldNamespaces<ExtensionPacks>
|
|
106
140
|
>;
|
|
107
|
-
readonly model:
|
|
141
|
+
readonly model: PackAwareModel<MergeAllPackIndexTypes<Family, Target, ExtensionPacks>>;
|
|
108
142
|
readonly rel: typeof rel;
|
|
109
143
|
readonly type: TypeHelpersFromNamespace<
|
|
110
144
|
ExtractTypeNamespaceFromPack<Family> &
|
|
@@ -29,8 +29,8 @@ export interface UniqueConstraintNode {
|
|
|
29
29
|
export interface IndexNode {
|
|
30
30
|
readonly columns: readonly string[];
|
|
31
31
|
readonly name?: string;
|
|
32
|
-
readonly
|
|
33
|
-
readonly
|
|
32
|
+
readonly type?: string;
|
|
33
|
+
readonly options?: Record<string, unknown>;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
export interface ForeignKeyNode {
|
package/src/contract-dsl.ts
CHANGED
|
@@ -465,7 +465,7 @@ export type RelationState =
|
|
|
465
465
|
| ManyToManyRelation;
|
|
466
466
|
|
|
467
467
|
type AnyRelationState = RelationState;
|
|
468
|
-
type AnyRelationBuilder = RelationBuilder<AnyRelationState>;
|
|
468
|
+
export type AnyRelationBuilder = RelationBuilder<AnyRelationState>;
|
|
469
469
|
|
|
470
470
|
type ApplyBelongsToRelationSqlSpec<
|
|
471
471
|
State extends RelationState,
|
|
@@ -537,11 +537,21 @@ type ConstraintOptions<Name extends string | undefined = string | undefined> = {
|
|
|
537
537
|
readonly name?: Name;
|
|
538
538
|
};
|
|
539
539
|
|
|
540
|
-
type
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
540
|
+
export type IndexTypeMap = Record<string, { readonly options: unknown }>;
|
|
541
|
+
|
|
542
|
+
type IndexInput<
|
|
543
|
+
Name extends string | undefined,
|
|
544
|
+
IndexTypes extends IndexTypeMap,
|
|
545
|
+
> = keyof IndexTypes extends never
|
|
546
|
+
? ConstraintOptions<Name>
|
|
547
|
+
:
|
|
548
|
+
| (ConstraintOptions<Name> & { readonly type?: never; readonly options?: never })
|
|
549
|
+
| {
|
|
550
|
+
readonly [K in keyof IndexTypes & string]: ConstraintOptions<Name> & {
|
|
551
|
+
readonly type: K;
|
|
552
|
+
readonly options: IndexTypes[K]['options'];
|
|
553
|
+
};
|
|
554
|
+
}[keyof IndexTypes & string];
|
|
545
555
|
|
|
546
556
|
type ForeignKeyOptions<Name extends string | undefined = string | undefined> =
|
|
547
557
|
ConstraintOptions<Name> & {
|
|
@@ -577,8 +587,8 @@ export type IndexConstraint<
|
|
|
577
587
|
readonly kind: 'index';
|
|
578
588
|
readonly fields: FieldNames;
|
|
579
589
|
readonly name?: Name;
|
|
580
|
-
readonly
|
|
581
|
-
readonly
|
|
590
|
+
readonly type?: string;
|
|
591
|
+
readonly options?: Record<string, unknown>;
|
|
582
592
|
};
|
|
583
593
|
|
|
584
594
|
export type ForeignKeyConstraint<
|
|
@@ -623,7 +633,7 @@ function normalizeTargetFieldRefInput(input: TargetFieldRef | readonly TargetFie
|
|
|
623
633
|
};
|
|
624
634
|
}
|
|
625
635
|
|
|
626
|
-
function createConstraintsDsl() {
|
|
636
|
+
function createConstraintsDsl<IndexTypes extends IndexTypeMap = Record<never, never>>() {
|
|
627
637
|
function ref<ModelName extends string, FieldName extends string>(
|
|
628
638
|
modelName: ModelName,
|
|
629
639
|
fieldName: FieldName,
|
|
@@ -674,24 +684,26 @@ function createConstraintsDsl() {
|
|
|
674
684
|
};
|
|
675
685
|
}
|
|
676
686
|
|
|
677
|
-
function index<FieldName extends string, Name extends string | undefined = undefined>(
|
|
678
|
-
field: ColumnRef<FieldName>,
|
|
679
|
-
options?: IndexOptions<Name>,
|
|
680
|
-
): IndexConstraint<readonly [FieldName], Name>;
|
|
681
687
|
function index<FieldNames extends readonly string[], Name extends string | undefined = undefined>(
|
|
682
688
|
fields: { readonly [K in keyof FieldNames]: ColumnRef<FieldNames[K] & string> },
|
|
683
|
-
options?:
|
|
689
|
+
options?: IndexInput<Name, IndexTypes>,
|
|
684
690
|
): IndexConstraint<FieldNames, Name>;
|
|
685
691
|
function index(
|
|
686
|
-
|
|
687
|
-
options?:
|
|
692
|
+
fields: readonly ColumnRef[],
|
|
693
|
+
options?: {
|
|
694
|
+
readonly name?: string;
|
|
695
|
+
readonly type?: string;
|
|
696
|
+
readonly options?: unknown;
|
|
697
|
+
},
|
|
688
698
|
): IndexConstraint {
|
|
689
699
|
return {
|
|
690
700
|
kind: 'index',
|
|
691
|
-
fields: normalizeFieldRefInput(
|
|
692
|
-
...(options?.name ? { name: options.name } : {}),
|
|
693
|
-
...(options?.
|
|
694
|
-
...(options?.
|
|
701
|
+
fields: normalizeFieldRefInput(fields),
|
|
702
|
+
...(options?.name !== undefined ? { name: options.name } : {}),
|
|
703
|
+
...(options?.type !== undefined ? { type: options.type } : {}),
|
|
704
|
+
...(options?.options !== undefined
|
|
705
|
+
? { options: options.options as Record<string, unknown> }
|
|
706
|
+
: {}),
|
|
695
707
|
};
|
|
696
708
|
}
|
|
697
709
|
|
|
@@ -776,9 +788,26 @@ type AttributeContext<Fields extends Record<string, ScalarFieldBuilder>> = {
|
|
|
776
788
|
readonly constraints: Pick<ConstraintsDsl, 'id' | 'unique'>;
|
|
777
789
|
};
|
|
778
790
|
|
|
779
|
-
type
|
|
791
|
+
type PackAwareIndex<IndexTypes extends IndexTypeMap> = <
|
|
792
|
+
FieldNames extends readonly string[],
|
|
793
|
+
Name extends string | undefined = undefined,
|
|
794
|
+
>(
|
|
795
|
+
fields: { readonly [K in keyof FieldNames]: ColumnRef<FieldNames[K] & string> },
|
|
796
|
+
options?: IndexInput<Name, IndexTypes>,
|
|
797
|
+
) => IndexConstraint<FieldNames, Name>;
|
|
798
|
+
|
|
799
|
+
type PackAwareSqlConstraints<IndexTypes extends IndexTypeMap> = {
|
|
800
|
+
readonly foreignKey: ConstraintsDsl['foreignKey'];
|
|
801
|
+
readonly ref: ConstraintsDsl['ref'];
|
|
802
|
+
readonly index: PackAwareIndex<IndexTypes>;
|
|
803
|
+
};
|
|
804
|
+
|
|
805
|
+
export type SqlContext<
|
|
806
|
+
Fields extends Record<string, ScalarFieldBuilder>,
|
|
807
|
+
IndexTypes extends IndexTypeMap = Record<never, never>,
|
|
808
|
+
> = {
|
|
780
809
|
readonly cols: FieldRefs<Fields>;
|
|
781
|
-
readonly constraints:
|
|
810
|
+
readonly constraints: PackAwareSqlConstraints<IndexTypes>;
|
|
782
811
|
};
|
|
783
812
|
|
|
784
813
|
function createFieldRefs<Fields extends Record<string, ScalarFieldBuilder>>(
|
|
@@ -829,8 +858,10 @@ function createAttributeConstraintsDsl(): AttributeContext<
|
|
|
829
858
|
};
|
|
830
859
|
}
|
|
831
860
|
|
|
832
|
-
function createSqlConstraintsDsl
|
|
833
|
-
|
|
861
|
+
function createSqlConstraintsDsl<
|
|
862
|
+
IndexTypes extends IndexTypeMap = Record<never, never>,
|
|
863
|
+
>(): SqlContext<Record<string, ScalarFieldBuilder>, IndexTypes>['constraints'] {
|
|
864
|
+
const constraints = createConstraintsDsl<IndexTypes>();
|
|
834
865
|
return {
|
|
835
866
|
index: constraints.index,
|
|
836
867
|
foreignKey: constraints.foreignKey,
|
|
@@ -946,12 +977,14 @@ export class ContractModelBuilder<
|
|
|
946
977
|
Relations extends Record<string, AnyRelationBuilder> = Record<never, never>,
|
|
947
978
|
AttributesSpec extends ModelAttributesSpec | undefined = undefined,
|
|
948
979
|
SqlSpec extends SqlStageSpec | undefined = undefined,
|
|
980
|
+
IndexTypes extends IndexTypeMap = Record<never, never>,
|
|
949
981
|
> {
|
|
950
982
|
declare readonly __name: ModelName;
|
|
951
983
|
declare readonly __fields: Fields;
|
|
952
984
|
declare readonly __relations: Relations;
|
|
953
985
|
declare readonly __attributes: AttributesSpec;
|
|
954
986
|
declare readonly __sql: SqlSpec;
|
|
987
|
+
declare readonly __indexTypes: IndexTypes;
|
|
955
988
|
readonly refs: ModelName extends string ? ModelTokenRefs<ModelName, Fields> : never;
|
|
956
989
|
|
|
957
990
|
constructor(
|
|
@@ -961,7 +994,7 @@ export class ContractModelBuilder<
|
|
|
961
994
|
readonly relations: Relations;
|
|
962
995
|
},
|
|
963
996
|
readonly attributesFactory?: StageInput<AttributeContext<Fields>, AttributesSpec>,
|
|
964
|
-
readonly sqlFactory?: StageInput<SqlContext<Fields>, SqlSpec>,
|
|
997
|
+
readonly sqlFactory?: StageInput<SqlContext<Fields, IndexTypes>, SqlSpec>,
|
|
965
998
|
) {
|
|
966
999
|
this.refs = (
|
|
967
1000
|
stageOne.modelName ? createModelTokenRefs(stageOne.modelName, stageOne.fields) : undefined
|
|
@@ -970,7 +1003,7 @@ export class ContractModelBuilder<
|
|
|
970
1003
|
|
|
971
1004
|
ref<FieldName extends keyof Fields & string>(
|
|
972
1005
|
this: ModelName extends string
|
|
973
|
-
? ContractModelBuilder<ModelName, Fields, Relations, AttributesSpec, SqlSpec>
|
|
1006
|
+
? ContractModelBuilder<ModelName, Fields, Relations, AttributesSpec, SqlSpec, IndexTypes>
|
|
974
1007
|
: never,
|
|
975
1008
|
fieldName: FieldName,
|
|
976
1009
|
): TargetFieldRef<ModelName & string, FieldName> {
|
|
@@ -989,7 +1022,14 @@ export class ContractModelBuilder<
|
|
|
989
1022
|
|
|
990
1023
|
relations<const NextRelations extends Record<string, AnyRelationBuilder>>(
|
|
991
1024
|
relations: NextRelations,
|
|
992
|
-
): ContractModelBuilder<
|
|
1025
|
+
): ContractModelBuilder<
|
|
1026
|
+
ModelName,
|
|
1027
|
+
Fields,
|
|
1028
|
+
Relations & NextRelations,
|
|
1029
|
+
AttributesSpec,
|
|
1030
|
+
SqlSpec,
|
|
1031
|
+
IndexTypes
|
|
1032
|
+
> {
|
|
993
1033
|
const duplicateRelationName = findDuplicateRelationName(this.stageOne.relations, relations);
|
|
994
1034
|
if (duplicateRelationName) {
|
|
995
1035
|
throw new Error(
|
|
@@ -1015,15 +1055,15 @@ export class ContractModelBuilder<
|
|
|
1015
1055
|
AttributeContext<Fields>,
|
|
1016
1056
|
ValidateAttributesStageSpec<Fields, SqlSpec, NextAttributesSpec>
|
|
1017
1057
|
>,
|
|
1018
|
-
): ContractModelBuilder<ModelName, Fields, Relations, NextAttributesSpec, SqlSpec> {
|
|
1058
|
+
): ContractModelBuilder<ModelName, Fields, Relations, NextAttributesSpec, SqlSpec, IndexTypes> {
|
|
1019
1059
|
return new ContractModelBuilder(this.stageOne, specOrFactory, this.sqlFactory);
|
|
1020
1060
|
}
|
|
1021
1061
|
|
|
1022
1062
|
sql<const NextSqlSpec extends SqlStageSpec>(
|
|
1023
|
-
specOrFactory: StageInput<SqlContext<Fields>, NextSqlSpec>,
|
|
1063
|
+
specOrFactory: StageInput<SqlContext<Fields, IndexTypes>, NextSqlSpec>,
|
|
1024
1064
|
): [ValidateSqlStageSpec<Fields, AttributesSpec, NextSqlSpec>] extends [never]
|
|
1025
|
-
? ContractModelBuilder<ModelName, Fields, Relations, AttributesSpec, never>
|
|
1026
|
-
: ContractModelBuilder<ModelName, Fields, Relations, AttributesSpec, NextSqlSpec> {
|
|
1065
|
+
? ContractModelBuilder<ModelName, Fields, Relations, AttributesSpec, never, IndexTypes>
|
|
1066
|
+
: ContractModelBuilder<ModelName, Fields, Relations, AttributesSpec, NextSqlSpec, IndexTypes> {
|
|
1027
1067
|
// Conditional return type cannot be verified by the implementation; the runtime value is always a valid ContractModelBuilder regardless of the validation outcome (validation is type-level only).
|
|
1028
1068
|
return new ContractModelBuilder(this.stageOne, this.attributesFactory, specOrFactory) as never;
|
|
1029
1069
|
}
|
|
@@ -1045,7 +1085,7 @@ export class ContractModelBuilder<
|
|
|
1045
1085
|
}
|
|
1046
1086
|
return buildStageSpec(this.sqlFactory, {
|
|
1047
1087
|
cols: createColumnRefs(this.stageOne.fields),
|
|
1048
|
-
constraints: createSqlConstraintsDsl()
|
|
1088
|
+
constraints: createSqlConstraintsDsl<IndexTypes>(),
|
|
1049
1089
|
});
|
|
1050
1090
|
}
|
|
1051
1091
|
}
|
package/src/contract-lowering.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ColumnTypeDescriptor } from '@prisma-next/framework-components/codec';
|
|
2
2
|
import type { StorageTypeInstance } from '@prisma-next/sql-contract/types';
|
|
3
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
3
4
|
import type {
|
|
4
5
|
ContractDefinition,
|
|
5
6
|
FieldNode,
|
|
@@ -573,9 +574,9 @@ function resolveModelNode(
|
|
|
573
574
|
})) satisfies readonly UniqueConstraintNode[];
|
|
574
575
|
const indexes = (spec.sqlSpec?.indexes ?? []).map((index) => ({
|
|
575
576
|
columns: mapFieldNamesToColumnNames(spec.modelName, index.fields, spec.fieldToColumn),
|
|
576
|
-
...(
|
|
577
|
-
...(
|
|
578
|
-
...(
|
|
577
|
+
...ifDefined('name', index.name),
|
|
578
|
+
...ifDefined('type', index.type),
|
|
579
|
+
...ifDefined('options', index.options),
|
|
579
580
|
})) satisfies readonly IndexNode[];
|
|
580
581
|
const foreignKeys = resolveForeignKeyNodes(spec, allSpecs);
|
|
581
582
|
const relations = Object.entries(spec.relations).map(([relationName, relationBuilder]) =>
|
package/src/contract-types.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
StorageHashBase,
|
|
6
6
|
} from '@prisma-next/contract/types';
|
|
7
7
|
import type { ExtensionPackRef, TargetPackRef } from '@prisma-next/framework-components/components';
|
|
8
|
+
import type { IndexTypeRegistration } from '@prisma-next/sql-contract/index-types';
|
|
8
9
|
import type {
|
|
9
10
|
ContractWithTypeMaps,
|
|
10
11
|
Index,
|
|
@@ -34,6 +35,28 @@ type MergeExtensionCodecTypesSafe<Packs> =
|
|
|
34
35
|
: MergeExtensionCodecTypes<Packs>
|
|
35
36
|
: Record<string, never>;
|
|
36
37
|
|
|
38
|
+
export type ExtractIndexTypesFromPack<P> = P extends {
|
|
39
|
+
readonly indexTypes: IndexTypeRegistration<infer M>;
|
|
40
|
+
}
|
|
41
|
+
? M
|
|
42
|
+
: Record<never, never>;
|
|
43
|
+
|
|
44
|
+
type AllIndexTypeLiterals<Packs> =
|
|
45
|
+
Packs extends Record<string, unknown>
|
|
46
|
+
? { [K in keyof Packs]: keyof ExtractIndexTypesFromPack<Packs[K]> }[keyof Packs] & string
|
|
47
|
+
: never;
|
|
48
|
+
|
|
49
|
+
export type MergeExtensionIndexTypes<Packs extends Record<string, unknown>> = {
|
|
50
|
+
readonly [Lit in AllIndexTypeLiterals<Packs>]: Extract<
|
|
51
|
+
{
|
|
52
|
+
[K in keyof Packs]: Lit extends keyof ExtractIndexTypesFromPack<Packs[K]>
|
|
53
|
+
? ExtractIndexTypesFromPack<Packs[K]>[Lit]
|
|
54
|
+
: never;
|
|
55
|
+
}[keyof Packs],
|
|
56
|
+
{ readonly options: unknown }
|
|
57
|
+
>;
|
|
58
|
+
};
|
|
59
|
+
|
|
37
60
|
export type MergeExtensionPackRefs<
|
|
38
61
|
Existing extends Record<string, unknown> | undefined,
|
|
39
62
|
Added extends Record<string, ExtensionPackRef<'sql', string>>,
|
|
@@ -64,6 +87,16 @@ type CodecTypesFromDefinition<Definition> = ExtractCodecTypesFromPack<
|
|
|
64
87
|
> &
|
|
65
88
|
MergeExtensionCodecTypesSafe<DefinitionExtensionPacks<Definition>>;
|
|
66
89
|
|
|
90
|
+
type DefinitionTarget<Definition> = Definition extends { readonly target: infer Target }
|
|
91
|
+
? Target
|
|
92
|
+
: never;
|
|
93
|
+
|
|
94
|
+
type AllPacks<Definition> = DefinitionExtensionPacks<Definition> & {
|
|
95
|
+
readonly __target: DefinitionTarget<Definition>;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export type IndexTypesFromDefinition<Definition> = MergeExtensionIndexTypes<AllPacks<Definition>>;
|
|
99
|
+
|
|
67
100
|
type DefinitionModels<Definition> = Definition extends {
|
|
68
101
|
readonly models?: unknown;
|
|
69
102
|
}
|