@aws-amplify/data-schema 0.18.2 → 0.18.3
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/cjs/SchemaProcessor.js +24 -5
- package/dist/cjs/SchemaProcessor.js.map +1 -1
- package/dist/cjs/runtime/internals/APIClient.js +6 -2
- package/dist/cjs/runtime/internals/APIClient.js.map +1 -1
- package/dist/esm/ModelType.d.ts +20 -5
- package/dist/esm/SchemaProcessor.mjs +24 -5
- package/dist/esm/SchemaProcessor.mjs.map +1 -1
- package/dist/esm/runtime/client/index.d.ts +14 -11
- package/dist/esm/runtime/internals/APIClient.mjs +6 -2
- package/dist/esm/runtime/internals/APIClient.mjs.map +1 -1
- package/dist/meta/cjs.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/ModelType.ts +44 -14
- package/src/SchemaProcessor.ts +39 -3
- package/src/runtime/client/index.ts +45 -14
- package/src/runtime/internals/APIClient.ts +11 -2
package/package.json
CHANGED
package/src/ModelType.ts
CHANGED
|
@@ -10,7 +10,7 @@ import type {
|
|
|
10
10
|
ModelRelationalFieldParamShape,
|
|
11
11
|
} from './ModelRelationalField';
|
|
12
12
|
import { AllowModifier, Authorization, allow } from './Authorization';
|
|
13
|
-
import { RefType } from './RefType';
|
|
13
|
+
import { RefType, RefTypeParamShape } from './RefType';
|
|
14
14
|
import { EnumType, EnumTypeParamShape } from './EnumType';
|
|
15
15
|
import { CustomType, CustomTypeParamShape } from './CustomType';
|
|
16
16
|
import {
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
import { SecondaryIndexToIR } from './MappedTypes/MapSecondaryIndexes';
|
|
22
22
|
|
|
23
23
|
const brandName = 'modelType';
|
|
24
|
+
export type deferredRefResolvingPrefix = 'deferredRefResolving:';
|
|
24
25
|
|
|
25
26
|
type ModelFields = Record<
|
|
26
27
|
string,
|
|
@@ -57,14 +58,41 @@ export type ModelTypeParamShape = {
|
|
|
57
58
|
authorization: Authorization<any, any, any>[];
|
|
58
59
|
};
|
|
59
60
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Extract fields that are eligible to be PK or SK fields with their resolved type.
|
|
63
|
+
*
|
|
64
|
+
* Eligible fields include:
|
|
65
|
+
* 1. ModelField that contains string or number
|
|
66
|
+
* 2. inline EnumType
|
|
67
|
+
* 3. RefType that refers to a top level defined EnumType (this is enforced by
|
|
68
|
+
* validation that happens in the Schema Processor)
|
|
69
|
+
*
|
|
70
|
+
* NOTE: at this point, there is no way to resolve the type from a RefType as
|
|
71
|
+
* we don't have access to the NonModelType at this location. So we generate am
|
|
72
|
+
* indicator string, and resolve its corresponding type later in
|
|
73
|
+
* packages/data-schema/src/runtime/client/index.ts
|
|
74
|
+
*/
|
|
75
|
+
type ExtractSecondaryIndexIRFields<T extends ModelTypeParamShape> = {
|
|
76
|
+
[FieldProp in keyof T['fields'] as T['fields'][FieldProp] extends ModelField<
|
|
77
|
+
infer R,
|
|
78
|
+
any,
|
|
79
|
+
any
|
|
80
|
+
>
|
|
81
|
+
? NonNullable<R> extends string | number
|
|
82
|
+
? FieldProp
|
|
83
|
+
: never
|
|
84
|
+
: T['fields'][FieldProp] extends EnumType<EnumTypeParamShape>
|
|
85
|
+
? FieldProp
|
|
86
|
+
: T['fields'][FieldProp] extends RefType<RefTypeParamShape, any, any>
|
|
87
|
+
? FieldProp
|
|
88
|
+
: never]: T['fields'][FieldProp] extends ModelField<infer R, any, any>
|
|
89
|
+
? R
|
|
90
|
+
: T['fields'][FieldProp] extends EnumType<infer R>
|
|
91
|
+
? R['values'][number]
|
|
92
|
+
: T['fields'][FieldProp] extends RefType<infer R, any, any>
|
|
93
|
+
? `${deferredRefResolvingPrefix}${R['link']}`
|
|
94
|
+
: never;
|
|
95
|
+
};
|
|
68
96
|
|
|
69
97
|
type ExtractType<T extends ModelTypeParamShape> = {
|
|
70
98
|
[FieldProp in keyof T['fields'] as T['fields'][FieldProp] extends ModelField<
|
|
@@ -189,9 +217,9 @@ export type ModelType<
|
|
|
189
217
|
identifier: ID,
|
|
190
218
|
): ModelType<SetTypeSubArg<T, 'identifier', ID>, K | 'identifier'>;
|
|
191
219
|
secondaryIndexes<
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
220
|
+
const SecondaryIndexFields = ExtractSecondaryIndexIRFields<T>,
|
|
221
|
+
const SecondaryIndexPKPool extends string = keyof SecondaryIndexFields &
|
|
222
|
+
string,
|
|
195
223
|
const Indexes extends readonly ModelIndexType<
|
|
196
224
|
string,
|
|
197
225
|
string,
|
|
@@ -201,7 +229,7 @@ export type ModelType<
|
|
|
201
229
|
>[] = readonly [],
|
|
202
230
|
const IndexesIR extends readonly any[] = SecondaryIndexToIR<
|
|
203
231
|
Indexes,
|
|
204
|
-
|
|
232
|
+
SecondaryIndexFields
|
|
205
233
|
>,
|
|
206
234
|
>(
|
|
207
235
|
callback: (
|
|
@@ -218,7 +246,9 @@ export type ModelType<
|
|
|
218
246
|
K | 'secondaryIndexes'
|
|
219
247
|
>;
|
|
220
248
|
authorization<AuthRuleType extends Authorization<any, any, any>>(
|
|
221
|
-
callback: (
|
|
249
|
+
callback: (
|
|
250
|
+
allow: Omit<AllowModifier, 'resource'>,
|
|
251
|
+
) => AuthRuleType | AuthRuleType[],
|
|
222
252
|
): ModelType<
|
|
223
253
|
SetTypeSubArg<T, 'authorization', AuthRuleType[]>,
|
|
224
254
|
K | 'authorization'
|
package/src/SchemaProcessor.ts
CHANGED
|
@@ -220,7 +220,10 @@ function modelFieldToGql(fieldDef: ModelFieldDef) {
|
|
|
220
220
|
return field;
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
function refFieldToGql(
|
|
223
|
+
function refFieldToGql(
|
|
224
|
+
fieldDef: RefFieldDef,
|
|
225
|
+
secondaryIndexes: string[] = [],
|
|
226
|
+
): string {
|
|
224
227
|
const { link, valueRequired, array, arrayRequired } = fieldDef;
|
|
225
228
|
|
|
226
229
|
let field = link;
|
|
@@ -237,6 +240,20 @@ function refFieldToGql(fieldDef: RefFieldDef): string {
|
|
|
237
240
|
field += '!';
|
|
238
241
|
}
|
|
239
242
|
|
|
243
|
+
for (const index of secondaryIndexes) {
|
|
244
|
+
field += ` ${index}`;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return field;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function enumFieldToGql(enumName: string, secondaryIndexes: string[] = []) {
|
|
251
|
+
let field = enumName;
|
|
252
|
+
|
|
253
|
+
for (const index of secondaryIndexes) {
|
|
254
|
+
field += ` ${index}`;
|
|
255
|
+
}
|
|
256
|
+
|
|
240
257
|
return field;
|
|
241
258
|
}
|
|
242
259
|
|
|
@@ -764,7 +781,7 @@ function processFields(
|
|
|
764
781
|
);
|
|
765
782
|
} else if (isRefField(fieldDef)) {
|
|
766
783
|
gqlFields.push(
|
|
767
|
-
`${fieldName}: ${refFieldToGql(fieldDef.data)}${fieldAuth}`,
|
|
784
|
+
`${fieldName}: ${refFieldToGql(fieldDef.data, secondaryIndexes[fieldName])}${fieldAuth}`,
|
|
768
785
|
);
|
|
769
786
|
} else if (isEnumType(fieldDef)) {
|
|
770
787
|
// The inline enum type name should be `<TypeName><FieldName>` to avoid
|
|
@@ -773,7 +790,9 @@ function processFields(
|
|
|
773
790
|
|
|
774
791
|
models.push([enumName, fieldDef]);
|
|
775
792
|
|
|
776
|
-
gqlFields.push(
|
|
793
|
+
gqlFields.push(
|
|
794
|
+
`${fieldName}: ${enumFieldToGql(enumName, secondaryIndexes[fieldName])}`,
|
|
795
|
+
);
|
|
777
796
|
} else if (isCustomType(fieldDef)) {
|
|
778
797
|
// The inline CustomType name should be `<TypeName><FieldName>` to avoid
|
|
779
798
|
// CustomType name conflicts
|
|
@@ -830,6 +849,8 @@ const secondaryIndexDefaultQueryField = (
|
|
|
830
849
|
const transformedSecondaryIndexesForModel = (
|
|
831
850
|
modelName: string,
|
|
832
851
|
secondaryIndexes: readonly InternalModelIndexType[],
|
|
852
|
+
modelFields: Record<string, ModelField<any, any>>,
|
|
853
|
+
getRefType: ReturnType<typeof getRefTypeForSchema>,
|
|
833
854
|
): TransformedSecondaryIndexes => {
|
|
834
855
|
const indexDirectiveWithAttributes = (
|
|
835
856
|
partitionKey: string,
|
|
@@ -837,6 +858,19 @@ const transformedSecondaryIndexesForModel = (
|
|
|
837
858
|
indexName: string,
|
|
838
859
|
queryField: string,
|
|
839
860
|
): string => {
|
|
861
|
+
for (const keyName of [partitionKey, ...sortKeys]) {
|
|
862
|
+
const field = modelFields[keyName];
|
|
863
|
+
|
|
864
|
+
if (isRefField(field)) {
|
|
865
|
+
const { def } = getRefType(field.data.link, modelName);
|
|
866
|
+
if (!isEnumType(def)) {
|
|
867
|
+
throw new Error(
|
|
868
|
+
`The ref field \`${keyName}\` used in the secondary index of \`${modelName}\` should refer to an enum type. \`${field.data.link}\` is not a enum type.`,
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
|
|
840
874
|
if (!sortKeys.length && !indexName && !queryField) {
|
|
841
875
|
return `@index(queryField: "${secondaryIndexDefaultQueryField(
|
|
842
876
|
modelName,
|
|
@@ -1172,6 +1206,8 @@ const schemaPreprocessor = (
|
|
|
1172
1206
|
const transformedSecondaryIndexes = transformedSecondaryIndexesForModel(
|
|
1173
1207
|
typeName,
|
|
1174
1208
|
typeDef.data.secondaryIndexes,
|
|
1209
|
+
fields,
|
|
1210
|
+
getRefType,
|
|
1175
1211
|
);
|
|
1176
1212
|
|
|
1177
1213
|
const { authString, authFields } = calculateAuth(mostRelevantAuthRules);
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
IsEmptyStringOrNever,
|
|
12
12
|
} from '@aws-amplify/data-schema-types';
|
|
13
13
|
import type { Observable } from 'rxjs';
|
|
14
|
+
import { deferredRefResolvingPrefix } from '../../ModelType';
|
|
14
15
|
|
|
15
16
|
// temporarily export symbols from `data-schema-types` because in case part of the
|
|
16
17
|
// problem with the runtime -> data-schema migration comes down to a mismatch
|
|
@@ -445,17 +446,17 @@ type SizeFilter = {
|
|
|
445
446
|
/**
|
|
446
447
|
* Filters options that can be used on string-like fields.
|
|
447
448
|
*/
|
|
448
|
-
type StringFilter = {
|
|
449
|
+
type StringFilter<T extends string = string> = {
|
|
449
450
|
attributeExists?: boolean;
|
|
450
451
|
beginsWith?: string;
|
|
451
452
|
between?: [string, string];
|
|
452
453
|
contains?: string;
|
|
453
|
-
eq?:
|
|
454
|
+
eq?: T;
|
|
454
455
|
ge?: string;
|
|
455
456
|
gt?: string;
|
|
456
457
|
le?: string;
|
|
457
458
|
lt?: string;
|
|
458
|
-
ne?:
|
|
459
|
+
ne?: T;
|
|
459
460
|
notContains?: string;
|
|
460
461
|
size?: SizeFilter;
|
|
461
462
|
};
|
|
@@ -499,8 +500,14 @@ export type ModelTypesClient<
|
|
|
499
500
|
ModelName extends string,
|
|
500
501
|
Model extends Record<string, unknown>,
|
|
501
502
|
ModelMeta extends ModelMetaShape,
|
|
503
|
+
Enums extends Record<string, string>,
|
|
502
504
|
FlatModel extends Record<string, unknown> = ResolvedModel<Model>,
|
|
503
|
-
> = IndexQueryMethodsFromIR<
|
|
505
|
+
> = IndexQueryMethodsFromIR<
|
|
506
|
+
ModelMeta['secondaryIndexes'],
|
|
507
|
+
ModelName,
|
|
508
|
+
Model,
|
|
509
|
+
Enums
|
|
510
|
+
> & {
|
|
504
511
|
create: (
|
|
505
512
|
model: Prettify<CreateModelInput<Model, ModelMeta>>,
|
|
506
513
|
options?: {
|
|
@@ -595,8 +602,14 @@ type ModelTypesSSRCookies<
|
|
|
595
602
|
ModelName extends string,
|
|
596
603
|
Model extends Record<string, unknown>,
|
|
597
604
|
ModelMeta extends ModelMetaShape,
|
|
605
|
+
Enums extends Record<string, string>,
|
|
598
606
|
FlatModel extends Record<string, unknown> = ResolvedModel<Model>,
|
|
599
|
-
> = IndexQueryMethodsFromIR<
|
|
607
|
+
> = IndexQueryMethodsFromIR<
|
|
608
|
+
ModelMeta['secondaryIndexes'],
|
|
609
|
+
ModelName,
|
|
610
|
+
Model,
|
|
611
|
+
Enums
|
|
612
|
+
> & {
|
|
600
613
|
create: (
|
|
601
614
|
model: Prettify<CreateModelInput<Model, ModelMeta>>,
|
|
602
615
|
options?: {
|
|
@@ -648,8 +661,14 @@ type ModelTypesSSRRequest<
|
|
|
648
661
|
ModelName extends string,
|
|
649
662
|
Model extends Record<string, unknown>,
|
|
650
663
|
ModelMeta extends ModelMetaShape,
|
|
664
|
+
Enums extends Record<string, string>,
|
|
651
665
|
FlatModel extends Record<string, unknown> = ResolvedModel<Model>,
|
|
652
|
-
> = IndexQueryMethodsFromIR<
|
|
666
|
+
> = IndexQueryMethodsFromIR<
|
|
667
|
+
ModelMeta['secondaryIndexes'],
|
|
668
|
+
ModelName,
|
|
669
|
+
Model,
|
|
670
|
+
Enums
|
|
671
|
+
> & {
|
|
653
672
|
create: (
|
|
654
673
|
// TODO: actual type
|
|
655
674
|
contextSpec: any,
|
|
@@ -724,19 +743,22 @@ export type ModelTypes<
|
|
|
724
743
|
? ModelTypesClient<
|
|
725
744
|
ModelName,
|
|
726
745
|
Schema[ModelName]['type'],
|
|
727
|
-
ModelMeta[ModelName]
|
|
746
|
+
ModelMeta[ModelName],
|
|
747
|
+
ModelMeta['enums']
|
|
728
748
|
>
|
|
729
749
|
: Context extends 'COOKIES'
|
|
730
750
|
? ModelTypesSSRCookies<
|
|
731
751
|
ModelName,
|
|
732
752
|
Schema[ModelName]['type'],
|
|
733
|
-
ModelMeta[ModelName]
|
|
753
|
+
ModelMeta[ModelName],
|
|
754
|
+
ModelMeta['enums']
|
|
734
755
|
>
|
|
735
756
|
: Context extends 'REQUEST'
|
|
736
757
|
? ModelTypesSSRRequest<
|
|
737
758
|
ModelName,
|
|
738
759
|
Schema[ModelName]['type'],
|
|
739
|
-
ModelMeta[ModelName]
|
|
760
|
+
ModelMeta[ModelName],
|
|
761
|
+
ModelMeta['enums']
|
|
740
762
|
>
|
|
741
763
|
: never
|
|
742
764
|
: never
|
|
@@ -874,6 +896,7 @@ type IndexQueryMethodsFromIR<
|
|
|
874
896
|
SecondaryIdxTuple extends SecondaryIndexIrShape[],
|
|
875
897
|
ModelName extends string,
|
|
876
898
|
Model extends Record<string, unknown>,
|
|
899
|
+
Enums extends Record<string, string>,
|
|
877
900
|
Res = unknown, // defaulting `unknown` because it gets absorbed in an intersection, e.g. `{a: 1} & unknown` => `{a: 1}`
|
|
878
901
|
> = SecondaryIdxTuple extends [
|
|
879
902
|
infer A extends SecondaryIndexIrShape,
|
|
@@ -883,7 +906,8 @@ type IndexQueryMethodsFromIR<
|
|
|
883
906
|
B,
|
|
884
907
|
ModelName,
|
|
885
908
|
Model,
|
|
886
|
-
|
|
909
|
+
Enums,
|
|
910
|
+
IndexQueryMethodSignature<A, ModelName, Model, Enums> & Res
|
|
887
911
|
>
|
|
888
912
|
: Res;
|
|
889
913
|
|
|
@@ -891,6 +915,7 @@ type IndexQueryMethodSignature<
|
|
|
891
915
|
Idx extends SecondaryIndexIrShape,
|
|
892
916
|
ModelName extends string,
|
|
893
917
|
Model extends Record<string, unknown>,
|
|
918
|
+
Enums extends Record<string, string>,
|
|
894
919
|
> = Record<
|
|
895
920
|
IsEmptyStringOrNever<Idx['queryField']> extends false
|
|
896
921
|
? Idx['queryField']
|
|
@@ -899,10 +924,16 @@ type IndexQueryMethodSignature<
|
|
|
899
924
|
FlatModel extends Record<string, unknown> = ResolvedModel<Model>,
|
|
900
925
|
SelectionSet extends ReadonlyArray<ModelPath<FlatModel>> = never[],
|
|
901
926
|
>(
|
|
902
|
-
input:
|
|
903
|
-
[
|
|
904
|
-
?
|
|
905
|
-
:
|
|
927
|
+
input: {
|
|
928
|
+
[PKField in keyof Idx['pk']]: Idx['pk'][PKField] extends `${deferredRefResolvingPrefix}${infer R}`
|
|
929
|
+
? Enums[R]
|
|
930
|
+
: Idx['pk'][PKField];
|
|
931
|
+
} & {
|
|
932
|
+
[SKField in keyof Idx['sk']]+?: number extends Idx['sk'][SKField]
|
|
933
|
+
? NumericFilter
|
|
934
|
+
: Idx['sk'][SKField] extends `${deferredRefResolvingPrefix}${infer R}`
|
|
935
|
+
? StringFilter<Enums[R]>
|
|
936
|
+
: StringFilter<Idx['sk'][SKField] & string>;
|
|
906
937
|
},
|
|
907
938
|
options?: {
|
|
908
939
|
filter?: ModelFilter<Model>;
|
|
@@ -692,14 +692,23 @@ export function generateGraphQLDocument(
|
|
|
692
692
|
graphQLFieldName = queryField;
|
|
693
693
|
|
|
694
694
|
const skQueryArgs = sk.reduce((acc: Record<string, any>, fieldName) => {
|
|
695
|
-
const fieldType =
|
|
695
|
+
const fieldType = Object.prototype.hasOwnProperty.call(
|
|
696
|
+
fields[fieldName].type,
|
|
697
|
+
'enum',
|
|
698
|
+
)
|
|
699
|
+
? 'String' // AppSync schema sets `ModelStringKeyConditionInput` as the type of the enum field that's used as SK
|
|
700
|
+
: fields[fieldName].type;
|
|
696
701
|
acc[fieldName] = `Model${fieldType}KeyConditionInput`;
|
|
697
702
|
|
|
698
703
|
return acc;
|
|
699
704
|
}, {});
|
|
700
705
|
|
|
701
706
|
indexQueryArgs = {
|
|
702
|
-
[pk]: `${
|
|
707
|
+
[pk]: `${
|
|
708
|
+
Object.prototype.hasOwnProperty.call(fields[pk].type, 'enum')
|
|
709
|
+
? (fields[pk].type as any).enum // AppSync schema sets enum type as the type of the enum fields that's used as PK
|
|
710
|
+
: fields[pk].type
|
|
711
|
+
}!`,
|
|
703
712
|
...skQueryArgs,
|
|
704
713
|
};
|
|
705
714
|
} else {
|