@aws-amplify/data-schema 1.24.0 → 1.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import type { deferredRefResolvingPrefix, ModelTypeParamShape, ModelDefaultIdentifier, DisableOperationsOptions } from '../../ModelType';
2
2
  import type { ClientSchemaProperty } from './ClientSchemaProperty';
3
3
  import type { Authorization, ImpliedAuthFields } from '../../Authorization';
4
- import type { SchemaMetadata, ResolveFields } from '../utilities';
4
+ import type { SchemaMetadata, ResolveFields, FlatResolveFields } from '../utilities';
5
5
  import type { IsEmptyStringOrNever, UnionToIntersection, Equal, Prettify } from '@aws-amplify/data-schema-types';
6
6
  import type { ModelField } from '../../ModelField';
7
7
  import type { ModelRelationshipField } from '../../ModelRelationshipField';
@@ -20,6 +20,8 @@ export interface ClientModel<Bag extends Record<string, unknown>, Metadata exten
20
20
  secondaryIndexes: IndexQueryMethodsFromIR<Bag, T['secondaryIndexes'], K>;
21
21
  __meta: {
22
22
  listOptionsPkParams: ListOptionsPkParams<Bag, T>;
23
+ rawType: T;
24
+ flatModel: FlatClientFields<Bag, Metadata, false, T, K>;
23
25
  disabledOperations: DisabledOpsToMap<T['disabledOperations']>;
24
26
  };
25
27
  }
@@ -42,6 +44,7 @@ type DisabledOpsToMap<Ops extends ReadonlyArray<DisableOperationsOptions>> = {
42
44
  [Op in Ops[number] as Op extends 'queries' ? 'list' | 'get' | 'observeQuery' : Op extends 'mutations' ? 'create' | 'update' | 'delete' : Op extends 'subscriptions' ? 'onCreate' | 'onUpdate' | 'onDelete' | 'observeQuery' : Op extends 'list' ? 'list' | 'observeQuery' : Op]: true;
43
45
  };
44
46
  type ClientFields<Bag extends Record<string, unknown>, Metadata extends SchemaMetadata<any>, IsRDS extends boolean, T extends ModelTypeParamShape> = ResolveFields<Bag, T['fields']> & If<Not<IsRDS>, ImplicitIdentifier<T>> & AuthFields<Metadata, T> & Omit<SystemFields<IsRDS>, keyof ResolveFields<Bag, T['fields']>>;
47
+ type FlatClientFields<Bag extends Record<string, unknown>, Metadata extends SchemaMetadata<any>, IsRDS extends boolean, T extends ModelTypeParamShape, ModelName extends keyof Bag & string> = FlatResolveFields<Bag, T['fields'], ModelName> & If<Not<IsRDS>, ImplicitIdentifier<T>> & AuthFields<Metadata, T> & Omit<SystemFields<IsRDS>, keyof ResolveFields<Bag, T['fields']>>;
45
48
  type SystemFields<IsRDS extends boolean> = IsRDS extends false ? {
46
49
  readonly createdAt: string;
47
50
  readonly updatedAt: string;
@@ -5,6 +5,8 @@ import { CustomType } from '../../CustomType';
5
5
  import { RefType, RefTypeParamShape } from '../../RefType';
6
6
  import { ResolveRef } from './ResolveRef';
7
7
  import { LazyLoader } from '../../runtime';
8
+ import type { ModelTypeParamShape } from '../../ModelType';
9
+ type ExtendsNever<T> = [T] extends [never] ? true : false;
8
10
  /**
9
11
  * Takes a `ReturnType<typeof a.model()>` and turns it into a client-consumable type. Fields
10
12
  * definitions (e.g., `a.string()`) are turned into the client facing types (e.g., `string`),
@@ -19,14 +21,42 @@ export type ResolveFields<Bag extends Record<string, any>, T> = ShallowPretty<{
19
21
  } & {
20
22
  [K in keyof T as IsRequired<T[K]> extends true ? never : K]+?: ResolveIndividualField<Bag, T[K]>;
21
23
  }>;
24
+ export type FlatResolveFields<Bag extends Record<string, any>, T, FlatModelName extends keyof Bag & string = never> = ShallowPretty<{
25
+ [K in keyof T]: ResolveIndividualField<Bag, T[K], FlatModelName>;
26
+ }>;
22
27
  type ShallowPretty<T> = {
23
28
  [K in keyof T]: T[K];
24
29
  };
25
- export type ResolveIndividualField<Bag extends Record<string, any>, T> = T extends BaseModelField<infer FieldShape> ? FieldShape : T extends RefType<infer RefShape, any, any> ? ResolveRef<RefShape, Bag> : T extends ModelRelationshipField<infer RelationshipShape, any, any, any> ? ResolveRelationship<Bag, RelationshipShape> : T extends CustomType<infer CT> ? ResolveFields<Bag, CT['fields']> | null : T extends EnumType<infer values> ? values[number] | null : never;
30
+ export type ResolveIndividualField<Bag extends Record<string, any>, T, FlatModelName extends keyof Bag & string = never> = T extends BaseModelField<infer FieldShape> ? FieldShape : T extends RefType<infer RefShape, any, any> ? ResolveRef<RefShape, Bag> : T extends ModelRelationshipField<infer RelationshipShape, any, any, any> ? ResolveRelationship<Bag, RelationshipShape, FlatModelName> : T extends CustomType<infer CT> ? ResolveFields<Bag, CT['fields']> | null : T extends EnumType<infer values> ? values[number] | null : never;
26
31
  /**
27
- * Resolves to never if the related model has disabled list or get ops for hasOne/hasMany or belongsTo respectively
32
+ * This mapped type eliminates redundant recursive types when
33
+ * generating the ['__meta']['flatModel'] type that serves as the
34
+ * basis for custom selection set path type generation
35
+ *
36
+ * It drops belongsTo relational fields that match the source model
37
+ *
38
+ * For example, assuming the typical Post->Comment bi-directional hasMany relationship,
39
+ * The generated structure will be
40
+ * {
41
+ * id: string;
42
+ * title: string;
43
+ * createdAt: string;
44
+ * updatedAt: string;
45
+ * comments: {
46
+ * id: string;
47
+ * createdAt: string;
48
+ * updatedAt: string;
49
+ * content: string;
50
+ * postId: string;
51
+ * ~~post~~ is dropped because data would be the same as top level object
52
+ * }[]
53
+ * }
54
+ *
28
55
  */
29
- type ResolveRelationship<Bag extends Record<string, any>, RelationshipShape extends ModelRelationshipFieldParamShape> = DependentLazyLoaderOpIsAvailable<Bag, RelationshipShape> extends true ? LazyLoader<RelationshipShape['valueRequired'] extends true ? Bag[RelationshipShape['relatedModel']]['type'] : Bag[RelationshipShape['relatedModel']]['type'] | null, RelationshipShape['array']> : never;
56
+ type ShortCircuitBiDirectionalRelationship<Model extends Record<string, any>, ParentModelName extends string, Raw extends ModelTypeParamShape['fields']> = {
57
+ [Field in keyof Model as Field extends keyof Raw ? Raw[Field] extends ModelRelationshipField<infer RelationshipShape, any, any, any> ? RelationshipShape['relationshipType'] extends 'belongsTo' ? RelationshipShape['relatedModel'] extends ParentModelName ? never : Field : Field : Field : Field]: Model[Field];
58
+ };
59
+ type ResolveRelationship<Bag extends Record<string, any>, RelationshipShape extends ModelRelationshipFieldParamShape, ParentModelName extends keyof Bag & string = never> = ExtendsNever<ParentModelName> extends true ? DependentLazyLoaderOpIsAvailable<Bag, RelationshipShape> extends true ? LazyLoader<RelationshipShape['valueRequired'] extends true ? Bag[RelationshipShape['relatedModel']]['type'] : Bag[RelationshipShape['relatedModel']]['type'] | null, RelationshipShape['array']> : never : RelationshipShape['array'] extends true ? Array<ShortCircuitBiDirectionalRelationship<Bag[RelationshipShape['relatedModel']]['__meta']['flatModel'], ParentModelName, Bag[RelationshipShape['relatedModel']]['__meta']['rawType']['fields']>> : ShortCircuitBiDirectionalRelationship<Bag[RelationshipShape['relatedModel']]['__meta']['flatModel'], ParentModelName, Bag[RelationshipShape['relatedModel']]['__meta']['rawType']['fields']>;
30
60
  type DependentLazyLoaderOpIsAvailable<Bag extends Record<string, any>, RelationshipShape extends ModelRelationshipFieldParamShape> = RelationshipShape['relationshipType'] extends 'hasOne' | 'hasMany' ? 'list' extends keyof Bag[RelationshipShape['relatedModel']]['__meta']['disabledOperations'] ? false : true : 'get' extends keyof Bag[RelationshipShape['relatedModel']]['__meta']['disabledOperations'] ? false : true;
31
61
  type IsRequired<T> = T extends BaseModelField<infer FieldShape> ? null extends FieldShape ? false : true : T extends RefType<infer RefShape, any, any> ? IsRefRequired<RefShape> : T extends ModelRelationshipField<any, any, any, any> ? true : T extends CustomType<any> | EnumType<any> ? false : never;
32
62
  type IsRefRequired<T extends RefTypeParamShape> = T['array'] extends true ? T['arrayRequired'] : T['valueRequired'];
@@ -139,59 +139,13 @@ type FlattenArrays<T> = {
139
139
  * and especially for bi-directional relationships which are infinitely recursable by their nature
140
140
  *
141
141
  */
142
- export type ModelPath<FlatModel extends Record<string, unknown>, Depth extends number = 5, // think of this as the initialization expr. in a for loop (e.g. `let depth = 5`)
142
+ type ModelPathInner<FlatModel extends Record<string, unknown>, Depth extends number = 5, // think of this as the initialization expr. in a for loop (e.g. `let depth = 5`)
143
143
  RecursionLoop extends number[] = [-1, 0, 1, 2, 3, 4], Field = keyof FlatModel> = {
144
144
  done: Field extends string ? `${Field}.*` : never;
145
- recur: Field extends string ? NonNullable<UnwrapArray<FlatModel[Field]>> extends Record<string, unknown> ? `${Field}.${ModelPath<NonNullable<UnwrapArray<FlatModel[Field]>>, RecursionLoop[Depth]>}` | `${Field}.*` : `${Field}` : never;
145
+ recur: Field extends string ? NonNullable<UnwrapArray<FlatModel[Field]>> extends Record<string, unknown> ? `${Field}.${ModelPathInner<NonNullable<UnwrapArray<FlatModel[Field]>>, RecursionLoop[Depth]>}` | `${Field}.*` : `${Field}` : never;
146
146
  }[Depth extends -1 ? 'done' : 'recur'];
147
- /**
148
- * Flattens model instance type and unwraps async functions into resolved GraphQL shape
149
- *
150
- * This type is used for generating the base shape for custom selection set input and its return value
151
- * Uses same pattern as above to limit recursion depth to maximum usable for selection set.
152
- *
153
- * @example
154
- * ### Given
155
- * ```ts
156
- * Model = {
157
- title: string;
158
- comments: () => ListReturnValue<({
159
- content: string;
160
- readonly id: string;
161
- readonly createdAt: string;
162
- readonly updatedAt: string;
163
- } | null | undefined)[]>;
164
- readonly id: string;
165
- readonly createdAt: string;
166
- readonly updatedAt: string;
167
- description?: string | ... 1 more ... | undefined;
168
- }
169
- * ```
170
- * ### Returns
171
- * ```ts
172
- * {
173
- title: string;
174
- comments: {
175
- content: string;
176
- readonly id: string;
177
- readonly createdAt: string;
178
- readonly updatedAt: string;
179
- }[];
180
- readonly id: string;
181
- readonly createdAt: string;
182
- readonly updatedAt: string;
183
- description: string | null | undefined;
184
- }
185
- *
186
- * ```
187
- */
188
- type ResolvedModel<Model extends Record<string, unknown>, Depth extends number = 7, RecursionLoop extends number[] = [-1, 0, 1, 2, 3, 4, 5, 6]> = {
189
- done: NonRelationshipFields<Model>;
190
- recur: {
191
- [Field in keyof Model]: Model[Field] extends (...args: any) => ListReturnValue<infer M> ? NonNullable<M> extends Record<string, any> ? ResolvedModel<NonNullable<M>, RecursionLoop[Depth]>[] : never : Model[Field] extends (...args: any) => SingularReturnValue<infer M> ? NonNullable<M> extends Record<string, any> ? ResolvedModel<NonNullable<M>, RecursionLoop[Depth]> : never : Model[Field];
192
- };
193
- }[Depth extends -1 ? 'done' : 'recur'];
194
- export type SelectionSet<Model extends Record<string, unknown>, Path extends ReadonlyArray<ModelPath<FlatModel>>, FlatModel extends Record<string, unknown> = ResolvedModel<Model>> = WithOptionalsAsNullishOnly<CustomSelectionSetReturnValue<FlatModel, Path[number]>>;
147
+ export type ModelPath<FlatModel extends Record<string, unknown>> = ModelPathInner<FlatModel>;
148
+ export type SelectionSet<Model, Path extends ReadonlyArray<ModelPath<FlatModel>>, FlatModel extends Record<string, unknown> = Model extends ClientSchemaByEntityTypeBaseShape['models'][string] ? Model['__meta']['flatModel'] : Record<string, any>> = Model extends ClientSchemaByEntityTypeBaseShape['models'][string] ? WithOptionalsAsNullishOnly<CustomSelectionSetReturnValue<FlatModel, Path[number]>> : any;
195
149
  /**
196
150
  * See: https://spec.graphql.org/draft/#sec-Errors
197
151
  */
@@ -299,7 +253,7 @@ interface ClientSecondaryIndexField {
299
253
  type IndexQueryMethods<Model extends ClientSchemaByEntityTypeBaseShape['models'][string], Context extends ContextType = 'CLIENT'> = {
300
254
  [K in keyof Select<Model['secondaryIndexes'], ClientSecondaryIndexField>]: IndexQueryMethod<Model, Select<Model['secondaryIndexes'], ClientSecondaryIndexField>[K], Context>;
301
255
  };
302
- type IndexQueryMethod<Model extends ClientSchemaByEntityTypeBaseShape['models'][string], Method extends ClientSecondaryIndexField, Context extends ContextType = 'CLIENT', FlatModel extends Record<string, unknown> = ResolvedModel<Model['type']>> = Context extends 'CLIENT' | 'COOKIES' ? <SelectionSet extends ReadonlyArray<ModelPath<FlatModel>> = never[]>(input: Method['input'], options?: {
256
+ type IndexQueryMethod<Model extends ClientSchemaByEntityTypeBaseShape['models'][string], Method extends ClientSecondaryIndexField, Context extends ContextType = 'CLIENT', FlatModel extends Record<string, unknown> = Model['__meta']['flatModel']> = Context extends 'CLIENT' | 'COOKIES' ? <SelectionSet extends ReadonlyArray<ModelPath<FlatModel>> = never[]>(input: Method['input'], options?: {
303
257
  filter?: ModelFilter<Model>;
304
258
  sortDirection?: ModelSortDirection;
305
259
  limit?: number;
@@ -318,7 +272,7 @@ type IndexQueryMethod<Model extends ClientSchemaByEntityTypeBaseShape['models'][
318
272
  authToken?: string;
319
273
  headers?: CustomHeaders;
320
274
  }) => ListReturnValue<Prettify<ReturnValue<Model, FlatModel, SelectionSet>>>;
321
- type ModelTypesClient<Model extends ClientSchemaByEntityTypeBaseShape['models'][string], FlatModel extends Record<string, unknown> = ResolvedModel<Model['type']>> = IndexQueryMethods<Model> & Omit<{
275
+ type ModelTypesClient<Model extends ClientSchemaByEntityTypeBaseShape['models'][string], FlatModel extends Record<string, unknown> = Model['__meta']['flatModel']> = IndexQueryMethods<Model> & Omit<{
322
276
  create<SelectionSet extends ReadonlyArray<ModelPath<FlatModel>> = never[]>(model: Model['createType'], options?: {
323
277
  selectionSet?: SelectionSet;
324
278
  authMode?: AuthMode;
@@ -380,7 +334,7 @@ type ModelTypesClient<Model extends ClientSchemaByEntityTypeBaseShape['models'][
380
334
  authToken?: string;
381
335
  }): ObserveQueryReturnValue<Prettify<ReturnValue<Model, FlatModel, SelectionSet>>>;
382
336
  }, keyof Model['__meta']['disabledOperations']>;
383
- type ModelTypesSSRCookies<Model extends ClientSchemaByEntityTypeBaseShape['models'][string], FlatModel extends Record<string, unknown> = ResolvedModel<Model['type']>> = IndexQueryMethods<Model> & Omit<{
337
+ type ModelTypesSSRCookies<Model extends ClientSchemaByEntityTypeBaseShape['models'][string], FlatModel extends Record<string, unknown> = Model['__meta']['flatModel']> = IndexQueryMethods<Model> & Omit<{
384
338
  create<SelectionSet extends ReadonlyArray<ModelPath<FlatModel>> = never[]>(model: Model['createType'], options?: {
385
339
  selectionSet?: SelectionSet;
386
340
  authMode?: AuthMode;
@@ -416,7 +370,7 @@ type ModelTypesSSRCookies<Model extends ClientSchemaByEntityTypeBaseShape['model
416
370
  headers?: CustomHeaders;
417
371
  }): ListReturnValue<Prettify<ReturnValue<Model, FlatModel, SelectionSet>>>;
418
372
  }, keyof Model['__meta']['disabledOperations']>;
419
- type ModelTypesSSRRequest<Model extends ClientSchemaByEntityTypeBaseShape['models'][string], FlatModel extends Record<string, unknown> = ResolvedModel<Model['type']>> = IndexQueryMethods<Model, 'REQUEST'> & Omit<{
373
+ type ModelTypesSSRRequest<Model extends ClientSchemaByEntityTypeBaseShape['models'][string], FlatModel extends Record<string, unknown> = Model['__meta']['flatModel']> = IndexQueryMethods<Model, 'REQUEST'> & Omit<{
420
374
  create<SelectionSet extends ReadonlyArray<ModelPath<FlatModel>> = never[]>(contextSpec: AmplifyServer.ContextSpec, model: Model['createType'], options?: {
421
375
  selectionSet?: SelectionSet;
422
376
  authMode?: AuthMode;