@aws-amplify/api-graphql 4.0.18-unstable.b758843.0 → 4.0.18

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.
Files changed (51) hide show
  1. package/dist/cjs/internals/APIClient.js +95 -34
  2. package/dist/cjs/internals/APIClient.js.map +1 -1
  3. package/dist/cjs/internals/generateClient.js +7 -0
  4. package/dist/cjs/internals/generateClient.js.map +1 -1
  5. package/dist/cjs/internals/generateCustomOperationsProperty.js +45 -0
  6. package/dist/cjs/internals/generateCustomOperationsProperty.js.map +1 -0
  7. package/dist/cjs/internals/operations/custom.js +289 -0
  8. package/dist/cjs/internals/operations/custom.js.map +1 -0
  9. package/dist/cjs/internals/operations/get.js +1 -1
  10. package/dist/cjs/internals/operations/get.js.map +1 -1
  11. package/dist/cjs/internals/operations/indexQuery.js +1 -1
  12. package/dist/cjs/internals/operations/indexQuery.js.map +1 -1
  13. package/dist/cjs/internals/operations/list.js +1 -1
  14. package/dist/cjs/internals/operations/list.js.map +1 -1
  15. package/dist/cjs/internals/operations/subscription.js +1 -1
  16. package/dist/cjs/internals/operations/subscription.js.map +1 -1
  17. package/dist/cjs/internals/server/generateClientWithAmplifyInstance.js +11 -1
  18. package/dist/cjs/internals/server/generateClientWithAmplifyInstance.js.map +1 -1
  19. package/dist/esm/internals/APIClient.d.ts +4 -4
  20. package/dist/esm/internals/APIClient.mjs +95 -34
  21. package/dist/esm/internals/APIClient.mjs.map +1 -1
  22. package/dist/esm/internals/generateClient.mjs +7 -0
  23. package/dist/esm/internals/generateClient.mjs.map +1 -1
  24. package/dist/esm/internals/generateCustomOperationsProperty.d.ts +8 -0
  25. package/dist/esm/internals/generateCustomOperationsProperty.mjs +41 -0
  26. package/dist/esm/internals/generateCustomOperationsProperty.mjs.map +1 -0
  27. package/dist/esm/internals/operations/custom.d.ts +60 -0
  28. package/dist/esm/internals/operations/custom.mjs +287 -0
  29. package/dist/esm/internals/operations/custom.mjs.map +1 -0
  30. package/dist/esm/internals/operations/get.mjs +1 -1
  31. package/dist/esm/internals/operations/get.mjs.map +1 -1
  32. package/dist/esm/internals/operations/indexQuery.mjs +1 -1
  33. package/dist/esm/internals/operations/indexQuery.mjs.map +1 -1
  34. package/dist/esm/internals/operations/list.mjs +1 -1
  35. package/dist/esm/internals/operations/list.mjs.map +1 -1
  36. package/dist/esm/internals/operations/subscription.mjs +1 -1
  37. package/dist/esm/internals/operations/subscription.mjs.map +1 -1
  38. package/dist/esm/internals/server/generateClientWithAmplifyInstance.mjs +12 -2
  39. package/dist/esm/internals/server/generateClientWithAmplifyInstance.mjs.map +1 -1
  40. package/dist/esm/types/index.d.ts +9 -1
  41. package/package.json +6 -6
  42. package/src/internals/APIClient.ts +138 -44
  43. package/src/internals/generateClient.ts +25 -1
  44. package/src/internals/generateCustomOperationsProperty.ts +89 -0
  45. package/src/internals/operations/custom.ts +382 -0
  46. package/src/internals/operations/get.ts +1 -1
  47. package/src/internals/operations/indexQuery.ts +1 -1
  48. package/src/internals/operations/list.ts +1 -1
  49. package/src/internals/operations/subscription.ts +3 -1
  50. package/src/internals/server/generateClientWithAmplifyInstance.ts +20 -1
  51. package/src/types/index.ts +11 -1
@@ -5,6 +5,7 @@ import {
5
5
  GraphQLAuthMode,
6
6
  ModelIntrospectionSchema,
7
7
  ModelFieldType,
8
+ NonModelFieldType,
8
9
  SchemaModel,
9
10
  SchemaModels,
10
11
  AssociationHasOne,
@@ -24,6 +25,7 @@ import {
24
25
  } from '../types';
25
26
  import { AmplifyServer } from '@aws-amplify/core/internals/adapter-core';
26
27
  import { CustomHeaders } from '@aws-amplify/data-schema-types';
28
+ import { SchemaNonModel } from '@aws-amplify/core/dist/esm/singleton/API/types';
27
29
  import type { IndexMeta } from './operations/indexQuery';
28
30
 
29
31
  type LazyLoadOptions = {
@@ -314,12 +316,13 @@ type OperationPrefix =
314
316
 
315
317
  const SELECTION_SET_WILDCARD = '*';
316
318
 
317
- function defaultSelectionSetForModel(modelDefinition: SchemaModel): string[] {
318
- // fields that are explicitly part of the graphql schema; not
319
- // inferred from owner auth rules.
320
- const { fields } = modelDefinition;
319
+ function defaultSelectionSetForNonModel(
320
+ nonModelDefinition: SchemaNonModel
321
+ ): string[] {
322
+ // fields that are explicitly part of the graphql schema;
323
+ const { fields } = nonModelDefinition;
321
324
  const explicitFields = Object.values<any>(fields)
322
- // Default selection set omits model fields
325
+ // Default selection set omits non-model fields
323
326
  .map(
324
327
  ({ type, name }) =>
325
328
  (typeof type === 'string' ||
@@ -328,6 +331,31 @@ function defaultSelectionSetForModel(modelDefinition: SchemaModel): string[] {
328
331
  )
329
332
  .filter(Boolean);
330
333
 
334
+ // fields used for owner auth rules that may or may not also
335
+ // be explicit on the model.
336
+
337
+ return Array.from(new Set(explicitFields));
338
+ }
339
+
340
+ function defaultSelectionSetForModel(modelDefinition: SchemaModel): string[] {
341
+ // fields that are explicitly part of the graphql schema; not
342
+ // inferred from owner auth rules.
343
+ const { fields } = modelDefinition;
344
+ const explicitFields = Object.values<any>(fields)
345
+ // Default selection set omits model fields
346
+ .map(({ type, name }) => {
347
+ if (typeof type === 'string') return name;
348
+
349
+ if (typeof type === 'object') {
350
+ if (typeof type?.enum === 'string') {
351
+ return name;
352
+ } else if (typeof type?.nonModel === 'string') {
353
+ return `${name}.${SELECTION_SET_WILDCARD}`;
354
+ }
355
+ }
356
+ })
357
+ .filter(Boolean);
358
+
331
359
  // fields used for owner auth rules that may or may not also
332
360
  // be explicit on the model.
333
361
  const ownerFields = resolveOwnerFields(modelDefinition);
@@ -357,44 +385,71 @@ const FIELD_IR = '';
357
385
  * ```
358
386
  */
359
387
  export function customSelectionSetToIR(
360
- modelDefinitions: SchemaModels,
388
+ modelInstrospection: ModelIntrospectionSchema,
361
389
  modelName: string,
362
390
  selectionSet: string[],
363
391
  ): Record<string, string | object> {
364
- const dotNotationToObject = (
365
- path: string,
366
- modelName: string,
367
- ): Record<string, any> => {
392
+ const dotNotationToObject = (path: string, modelOrNonModelName: string) => {
368
393
  const [fieldName, ...rest] = path.split('.');
369
394
 
370
- let result: Record<string, any> = {};
395
+ const nested = rest[0];
396
+ const modelDefinition = modelInstrospection.models[modelOrNonModelName];
371
397
 
372
- if (rest.length === 0) {
373
- result = { [fieldName]: FIELD_IR };
374
- } else {
375
- const nested = rest[0];
376
- const modelDefinition = modelDefinitions[modelName];
377
- const modelFields = modelDefinition.fields;
378
- const relatedModel = (modelFields[fieldName]?.type as ModelFieldType)
379
- ?.model;
380
-
381
- if (!relatedModel) {
382
- // TODO: may need to change this to support custom types
383
- throw Error(`${fieldName} is not a model field`);
398
+ const modelFields = modelDefinition?.fields;
399
+ const relatedModel = (modelFields?.[fieldName]?.type as ModelFieldType)
400
+ ?.model;
401
+
402
+ const relatedModelDefinition = modelInstrospection.models[relatedModel];
403
+ const relatedNonModel = (
404
+ modelFields?.[fieldName]?.type as NonModelFieldType
405
+ )?.nonModel;
406
+ const relatedNonModelDefinition =
407
+ modelInstrospection.nonModels[relatedNonModel];
408
+
409
+ const isModelOrNonModelOrField = relatedModelDefinition
410
+ ? 'model'
411
+ : relatedNonModelDefinition
412
+ ? 'nonModel'
413
+ : 'field';
414
+
415
+ if (isModelOrNonModelOrField === 'nonModel') {
416
+ let result: Record<string, any> = {};
417
+
418
+ if (!nested) {
419
+ throw Error(
420
+ `${fieldName} must declare a wildcard (*) or a field of custom type ${relatedNonModel}`
421
+ );
384
422
  }
385
423
 
386
424
  if (nested === SELECTION_SET_WILDCARD) {
387
- const relatedModelDefinition = modelDefinitions[relatedModel];
388
-
389
425
  result = {
390
- [fieldName]: defaultSelectionSetIR(relatedModelDefinition),
426
+ [fieldName]: nonModelsDefaultSelectionSetIR(
427
+ relatedNonModelDefinition
428
+ ),
391
429
  };
392
430
  } else {
393
- const exists = Boolean(modelFields[fieldName]);
394
- if (!exists) {
395
- throw Error(`${fieldName} is not a field of model ${modelName}`);
396
- }
431
+ result = {
432
+ [fieldName]: dotNotationToObject(rest.join('.'), relatedNonModel),
433
+ };
434
+ }
435
+
436
+ return result;
437
+ } else if (isModelOrNonModelOrField === 'model') {
438
+ let result: Record<string, any> = {};
439
+
440
+ if (!nested) {
441
+ throw Error(
442
+ `${fieldName} must declare a wildcard (*) or a field of model ${relatedModel}`
443
+ );
444
+ }
445
+
446
+ if (nested === SELECTION_SET_WILDCARD) {
447
+ const relatedModelDefinition = modelInstrospection.models[relatedModel];
397
448
 
449
+ result = {
450
+ [fieldName]: modelsDefaultSelectionSetIR(relatedModelDefinition),
451
+ };
452
+ } else {
398
453
  result = {
399
454
  [fieldName]: dotNotationToObject(rest.join('.'), relatedModel),
400
455
  };
@@ -407,9 +462,34 @@ export function customSelectionSetToIR(
407
462
  },
408
463
  };
409
464
  }
410
- }
411
465
 
412
- return result;
466
+ return result;
467
+ } else {
468
+ const modelField = modelFields?.[fieldName];
469
+
470
+ const nonModelDefinition =
471
+ modelInstrospection.nonModels[modelOrNonModelName];
472
+ const nonModelField = nonModelDefinition?.fields?.[fieldName];
473
+
474
+ if (!nonModelDefinition) {
475
+ const isOwnerField =
476
+ resolveOwnerFields(modelDefinition).includes(fieldName);
477
+
478
+ if (!modelField && !isOwnerField) {
479
+ throw Error(
480
+ `${fieldName} is not a field of model ${modelOrNonModelName}`
481
+ );
482
+ }
483
+ } else {
484
+ if (!nonModelField) {
485
+ throw Error(
486
+ `${fieldName} is not a field of custom type ${modelOrNonModelName}`
487
+ );
488
+ }
489
+ }
490
+
491
+ return { [fieldName]: FIELD_IR };
492
+ }
413
493
  };
414
494
 
415
495
  return selectionSet.reduce(
@@ -422,7 +502,7 @@ export function customSelectionSetToIR(
422
502
  );
423
503
  }
424
504
 
425
- const defaultSelectionSetIR = (relatedModelDefinition: SchemaModel) => {
505
+ const modelsDefaultSelectionSetIR = (relatedModelDefinition: SchemaModel) => {
426
506
  const defaultSelectionSet = defaultSelectionSetForModel(
427
507
  relatedModelDefinition,
428
508
  );
@@ -438,6 +518,24 @@ const defaultSelectionSetIR = (relatedModelDefinition: SchemaModel) => {
438
518
  return reduced;
439
519
  };
440
520
 
521
+ const nonModelsDefaultSelectionSetIR = (
522
+ relatedNonModelDefinition: SchemaNonModel
523
+ ) => {
524
+ const defaultSelectionSet = defaultSelectionSetForNonModel(
525
+ relatedNonModelDefinition
526
+ );
527
+
528
+ const reduced = defaultSelectionSet.reduce(
529
+ (acc: Record<string, any>, curVal) => {
530
+ acc[curVal] = FIELD_IR;
531
+ return acc;
532
+ },
533
+ {}
534
+ );
535
+
536
+ return reduced;
537
+ };
538
+
441
539
  /**
442
540
  * Stringifies selection set IR
443
541
  * * @example
@@ -510,20 +608,16 @@ function deepMergeSelectionSetObjects<T extends Record<string, any>>(
510
608
  }
511
609
 
512
610
  export function generateSelectionSet(
513
- modelDefinitions: SchemaModels,
611
+ modelInstrospection: ModelIntrospectionSchema,
514
612
  modelName: string,
515
613
  selectionSet?: string[],
516
614
  ) {
517
- const modelDefinition = modelDefinitions[modelName];
518
-
519
- if (!selectionSet) {
520
- return defaultSelectionSetForModel(modelDefinition).join(' ');
521
- }
615
+ const modelDefinition = modelInstrospection.models[modelName];
522
616
 
523
617
  const selSetIr = customSelectionSetToIR(
524
- modelDefinitions,
618
+ modelInstrospection,
525
619
  modelName,
526
- selectionSet,
620
+ selectionSet ?? defaultSelectionSetForModel(modelDefinition)
527
621
  );
528
622
  const selSetString = selectionSetIRToString(selSetIr);
529
623
 
@@ -531,13 +625,13 @@ export function generateSelectionSet(
531
625
  }
532
626
 
533
627
  export function generateGraphQLDocument(
534
- modelDefinitions: SchemaModels,
628
+ modelInstrospection: ModelIntrospectionSchema,
535
629
  modelName: string,
536
630
  modelOperation: ModelOperation,
537
631
  listArgs?: ListArgs | QueryArgs,
538
632
  indexMeta?: IndexMeta,
539
633
  ): string {
540
- const modelDefinition = modelDefinitions[modelName];
634
+ const modelDefinition = modelInstrospection.models[modelName];
541
635
 
542
636
  const {
543
637
  name,
@@ -584,7 +678,7 @@ export function generateGraphQLDocument(
584
678
  let graphQLArguments: Record<string, any> | undefined;
585
679
 
586
680
  const selectionSetFields = generateSelectionSet(
587
- modelDefinitions,
681
+ modelInstrospection,
588
682
  modelName,
589
683
  selectionSet as ListArgs['selectionSet'],
590
684
  );
@@ -1,11 +1,20 @@
1
1
  // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
  import { Hub } from '@aws-amplify/core';
4
- import { EnumTypes, ModelTypes } from '@aws-amplify/data-schema-types';
5
4
  import { graphql, cancel, isCancelError } from './v6';
5
+ import {
6
+ EnumTypes,
7
+ ModelTypes,
8
+ CustomQueries,
9
+ CustomMutations,
10
+ } from '@aws-amplify/data-schema-types';
6
11
  import { generateEnumsProperty } from './utils/generateEnumsProperty';
7
12
  import { generateModelsProperty } from './utils/generateModelsProperty';
8
13
  import { isApiGraphQLConfig } from './utils/isApiGraphQLProviderConfig';
14
+ import {
15
+ generateCustomQueriesProperty,
16
+ generateCustomMutationsProperty,
17
+ } from './generateCustomOperationsProperty';
9
18
  import {
10
19
  V6Client,
11
20
  __amplify,
@@ -38,6 +47,8 @@ export function generateClient<T extends Record<any, any> = never>(
38
47
  isCancelError,
39
48
  models: emptyProperty as ModelTypes<never>,
40
49
  enums: emptyProperty as EnumTypes<never>,
50
+ queries: emptyProperty as CustomQueries<never>,
51
+ mutations: emptyProperty as CustomMutations<never>,
41
52
  } as any;
42
53
 
43
54
  const apiGraphqlConfig = params.amplify.getConfig().API?.GraphQL;
@@ -45,6 +56,11 @@ export function generateClient<T extends Record<any, any> = never>(
45
56
  if (isApiGraphQLConfig(apiGraphqlConfig)) {
46
57
  client.models = generateModelsProperty<T>(client, apiGraphqlConfig);
47
58
  client.enums = generateEnumsProperty<T>(apiGraphqlConfig);
59
+ client.queries = generateCustomQueriesProperty<T>(client, apiGraphqlConfig);
60
+ client.mutations = generateCustomMutationsProperty<T>(
61
+ client,
62
+ apiGraphqlConfig,
63
+ );
48
64
  } else {
49
65
  // This happens when the `Amplify.configure()` call gets evaluated after the `generateClient()` call.
50
66
  //
@@ -75,6 +91,14 @@ const generateModelsPropertyOnAmplifyConfigure = (clientRef: any) => {
75
91
  if (isApiGraphQLConfig(apiGraphQLConfig)) {
76
92
  clientRef.models = generateModelsProperty(clientRef, apiGraphQLConfig);
77
93
  clientRef.enums = generateEnumsProperty(apiGraphQLConfig);
94
+ clientRef.queries = generateCustomQueriesProperty(
95
+ clientRef,
96
+ apiGraphQLConfig,
97
+ );
98
+ clientRef.mutations = generateCustomMutationsProperty(
99
+ clientRef,
100
+ apiGraphQLConfig,
101
+ );
78
102
  }
79
103
  });
80
104
  };
@@ -0,0 +1,89 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { CustomQueries, CustomMutations } from '@aws-amplify/data-schema-types';
4
+ import { V6Client, __authMode, __authToken, __amplify } from '../types';
5
+
6
+ import { customOpFactory } from './operations/custom';
7
+ import {
8
+ ModelIntrospectionSchema,
9
+ GraphQLProviderConfig,
10
+ } from '@aws-amplify/core/internals/utils';
11
+
12
+ type OpTypes = 'queries' | 'mutations';
13
+
14
+ type CustomOpsProperty<
15
+ T extends Record<any, any>,
16
+ OpType extends OpTypes,
17
+ > = OpType extends 'queries' ? CustomQueries<T> : CustomMutations<T>;
18
+
19
+ const operationTypeMap = {
20
+ queries: 'query',
21
+ mutations: 'mutation',
22
+ } as const;
23
+
24
+ export function generateCustomOperationsProperty<
25
+ T extends Record<any, any>,
26
+ OpType extends OpTypes,
27
+ >(
28
+ client: V6Client<Record<string, any>>,
29
+ config: GraphQLProviderConfig['GraphQL'],
30
+ operationsType: OpType,
31
+ ): OpType extends 'queries' ? CustomQueries<T> : CustomMutations<T> {
32
+ // some bundlers end up with `Amplify.configure` being called *after* generate client.
33
+ // if that occurs, we need to *not error* while we wait. handling for late configuration
34
+ // occurs in `generateClient()`. we do not need to subscribe to Hub events here.
35
+ if (!config) {
36
+ return {} as CustomOpsProperty<T, OpType>;
37
+ }
38
+
39
+ const modelIntrospection: ModelIntrospectionSchema | undefined =
40
+ config.modelIntrospection;
41
+
42
+ // model intro schema might be absent if there's not actually a configured GraphQL API
43
+ if (!modelIntrospection) {
44
+ return {} as CustomOpsProperty<T, OpType>;
45
+ }
46
+
47
+ // custom operations will be absent from model intro schema if no custom ops
48
+ // are present on the source schema.
49
+ const operations = modelIntrospection[operationsType];
50
+ if (!operations) {
51
+ return {} as CustomOpsProperty<T, OpType>;
52
+ }
53
+
54
+ const ops = {} as CustomOpsProperty<T, OpType>;
55
+ const useContext = client[__amplify] === null;
56
+ for (const operation of Object.values(operations)) {
57
+ (ops as any)[operation.name] = customOpFactory(
58
+ client,
59
+ modelIntrospection,
60
+ operationTypeMap[operationsType],
61
+ operation,
62
+ useContext
63
+ );
64
+ }
65
+
66
+ return ops;
67
+ }
68
+
69
+ export function generateCustomMutationsProperty<T extends Record<any, any>>(
70
+ client: V6Client<Record<string, any>>,
71
+ config: GraphQLProviderConfig['GraphQL'],
72
+ ) {
73
+ return generateCustomOperationsProperty<T, 'mutations'>(
74
+ client,
75
+ config,
76
+ 'mutations',
77
+ );
78
+ }
79
+
80
+ export function generateCustomQueriesProperty<T extends Record<any, any>>(
81
+ client: V6Client<Record<string, any>>,
82
+ config: GraphQLProviderConfig['GraphQL'],
83
+ ) {
84
+ return generateCustomOperationsProperty<T, 'queries'>(
85
+ client,
86
+ config,
87
+ 'queries',
88
+ );
89
+ }