@aws-amplify/data-schema 1.3.10 → 1.4.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.
- package/dist/cjs/ModelType.js +5 -0
- package/dist/cjs/ModelType.js.map +1 -1
- package/dist/cjs/SchemaProcessor.js +58 -1
- package/dist/cjs/SchemaProcessor.js.map +1 -1
- package/dist/cjs/runtime/addSchemaToClient.js +1 -0
- package/dist/cjs/runtime/addSchemaToClient.js.map +1 -1
- package/dist/cjs/runtime/addSchemaToClientWithInstance.js +1 -0
- package/dist/cjs/runtime/addSchemaToClientWithInstance.js.map +1 -1
- package/dist/cjs/runtime/internals/APIClient.js +63 -42
- package/dist/cjs/runtime/internals/APIClient.js.map +1 -1
- package/dist/cjs/runtime/internals/cancellation.js +48 -0
- package/dist/cjs/runtime/internals/cancellation.js.map +1 -0
- package/dist/cjs/runtime/internals/clientUtils.js +45 -3
- package/dist/cjs/runtime/internals/clientUtils.js.map +1 -1
- package/dist/cjs/runtime/internals/index.js +3 -1
- package/dist/cjs/runtime/internals/index.js.map +1 -1
- package/dist/cjs/runtime/internals/operations/custom.js +91 -85
- package/dist/cjs/runtime/internals/operations/custom.js.map +1 -1
- package/dist/cjs/runtime/internals/operations/get.js +71 -65
- package/dist/cjs/runtime/internals/operations/get.js.map +1 -1
- package/dist/cjs/runtime/internals/operations/indexQuery.js +66 -60
- package/dist/cjs/runtime/internals/operations/indexQuery.js.map +1 -1
- package/dist/cjs/runtime/internals/operations/list.js +90 -84
- package/dist/cjs/runtime/internals/operations/list.js.map +1 -1
- package/dist/cjs/runtime/internals/server/generateModelsProperty.js +3 -3
- package/dist/cjs/runtime/internals/server/generateModelsProperty.js.map +1 -1
- package/dist/cjs/runtime/internals/utils/clientProperties/generateModelsProperty.js +3 -3
- package/dist/cjs/runtime/internals/utils/clientProperties/generateModelsProperty.js.map +1 -1
- package/dist/cjs/runtime/utils/index.js +3 -1
- package/dist/cjs/runtime/utils/index.js.map +1 -1
- package/dist/cjs/runtime/utils/selfAwareAsync.js +40 -0
- package/dist/cjs/runtime/utils/selfAwareAsync.js.map +1 -0
- package/dist/esm/Authorization.d.ts +1 -1
- package/dist/esm/ClientSchema/Core/ClientModel.d.ts +20 -1
- package/dist/esm/ClientSchema/utilities/ResolveField.d.ts +5 -1
- package/dist/esm/ModelType.d.ts +6 -0
- package/dist/esm/ModelType.mjs +5 -0
- package/dist/esm/ModelType.mjs.map +1 -1
- package/dist/esm/SchemaProcessor.mjs +58 -1
- package/dist/esm/SchemaProcessor.mjs.map +1 -1
- package/dist/esm/runtime/addSchemaToClient.mjs +2 -0
- package/dist/esm/runtime/addSchemaToClient.mjs.map +1 -1
- package/dist/esm/runtime/addSchemaToClientWithInstance.mjs +2 -0
- package/dist/esm/runtime/addSchemaToClientWithInstance.mjs.map +1 -1
- package/dist/esm/runtime/bridge-types.d.ts +2 -2
- package/dist/esm/runtime/client/index.d.ts +6 -6
- package/dist/esm/runtime/internals/APIClient.d.ts +2 -2
- package/dist/esm/runtime/internals/APIClient.mjs +64 -42
- package/dist/esm/runtime/internals/APIClient.mjs.map +1 -1
- package/dist/esm/runtime/internals/cancellation.d.ts +10 -0
- package/dist/esm/runtime/internals/cancellation.mjs +44 -0
- package/dist/esm/runtime/internals/cancellation.mjs.map +1 -0
- package/dist/esm/runtime/internals/clientUtils.d.ts +78 -1
- package/dist/esm/runtime/internals/clientUtils.mjs +45 -3
- package/dist/esm/runtime/internals/clientUtils.mjs.map +1 -1
- package/dist/esm/runtime/internals/index.d.ts +1 -0
- package/dist/esm/runtime/internals/index.mjs +1 -0
- package/dist/esm/runtime/internals/index.mjs.map +1 -1
- package/dist/esm/runtime/internals/operations/custom.d.ts +1 -1
- package/dist/esm/runtime/internals/operations/custom.mjs +91 -85
- package/dist/esm/runtime/internals/operations/custom.mjs.map +1 -1
- package/dist/esm/runtime/internals/operations/get.d.ts +1 -1
- package/dist/esm/runtime/internals/operations/get.mjs +71 -65
- package/dist/esm/runtime/internals/operations/get.mjs.map +1 -1
- package/dist/esm/runtime/internals/operations/indexQuery.d.ts +1 -1
- package/dist/esm/runtime/internals/operations/indexQuery.mjs +66 -60
- package/dist/esm/runtime/internals/operations/indexQuery.mjs.map +1 -1
- package/dist/esm/runtime/internals/operations/list.d.ts +1 -1
- package/dist/esm/runtime/internals/operations/list.mjs +90 -84
- package/dist/esm/runtime/internals/operations/list.mjs.map +1 -1
- package/dist/esm/runtime/internals/server/generateModelsProperty.mjs +4 -4
- package/dist/esm/runtime/internals/server/generateModelsProperty.mjs.map +1 -1
- package/dist/esm/runtime/internals/utils/clientProperties/generateModelsProperty.mjs +4 -4
- package/dist/esm/runtime/internals/utils/clientProperties/generateModelsProperty.mjs.map +1 -1
- package/dist/esm/runtime/utils/index.d.ts +1 -0
- package/dist/esm/runtime/utils/index.mjs +1 -0
- package/dist/esm/runtime/utils/index.mjs.map +1 -1
- package/dist/esm/runtime/utils/selfAwareAsync.d.ts +19 -0
- package/dist/esm/runtime/utils/selfAwareAsync.mjs +37 -0
- package/dist/esm/runtime/utils/selfAwareAsync.mjs.map +1 -0
- package/dist/meta/cjs.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/ClientSchema/Core/ClientModel.ts +29 -0
- package/src/ClientSchema/utilities/ResolveField.ts +26 -6
- package/src/ModelType.ts +31 -0
- package/src/SchemaProcessor.ts +77 -2
- package/src/runtime/addSchemaToClient.ts +2 -0
- package/src/runtime/addSchemaToClientWithInstance.ts +2 -0
- package/src/runtime/bridge-types.ts +2 -2
- package/src/runtime/client/index.ts +207 -184
- package/src/runtime/internals/APIClient.ts +67 -23
- package/src/runtime/internals/cancellation.ts +57 -0
- package/src/runtime/internals/clientUtils.ts +61 -1
- package/src/runtime/internals/index.ts +1 -0
- package/src/runtime/internals/operations/custom.ts +117 -109
- package/src/runtime/internals/operations/get.ts +111 -95
- package/src/runtime/internals/operations/indexQuery.ts +100 -94
- package/src/runtime/internals/operations/list.ts +132 -119
- package/src/runtime/internals/server/generateModelsProperty.ts +31 -28
- package/src/runtime/internals/utils/clientProperties/generateModelsProperty.ts +36 -33
- package/src/runtime/utils/index.ts +1 -0
- package/src/runtime/utils/selfAwareAsync.ts +39 -0
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
|
|
4
3
|
import type {
|
|
5
4
|
ModelAttribute,
|
|
6
5
|
SchemaModel,
|
|
7
6
|
SecondaryIndexAttribute,
|
|
7
|
+
ModelIntrospectionSchema,
|
|
8
8
|
} from '../bridge-types';
|
|
9
|
+
import { graphQLOperationsInfo } from './APIClient';
|
|
9
10
|
|
|
10
11
|
const attributeIsSecondaryIndex = (
|
|
11
12
|
attr: ModelAttribute,
|
|
@@ -35,3 +36,62 @@ export const getSecondaryIndexesFromSchemaModel = (model: SchemaModel) => {
|
|
|
35
36
|
|
|
36
37
|
return idxs || [];
|
|
37
38
|
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* returns graphQLOperationsInfo, but filters out operations that were disabled via model().disableOperations([...])
|
|
42
|
+
*/
|
|
43
|
+
export const excludeDisabledOps = (
|
|
44
|
+
mis: ModelIntrospectionSchema,
|
|
45
|
+
modelName: string,
|
|
46
|
+
) => {
|
|
47
|
+
/* Example model attributes in MIS {
|
|
48
|
+
"type": "model",
|
|
49
|
+
"properties": {
|
|
50
|
+
"subscriptions": null,
|
|
51
|
+
"mutations": { "delete": null }
|
|
52
|
+
} }*/
|
|
53
|
+
const modelAttrs = mis.models[modelName].attributes?.find(
|
|
54
|
+
(attr) => attr.type === 'model',
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const coarseToFineDict: Record<string, string[]> = {
|
|
58
|
+
queries: ['list', 'get', 'observeQuery'],
|
|
59
|
+
mutations: ['create', 'update', 'delete'],
|
|
60
|
+
subscriptions: ['onCreate', 'onUpdate', 'onDelete'],
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const disabledOps: string[] = [];
|
|
64
|
+
|
|
65
|
+
if (!modelAttrs) {
|
|
66
|
+
return graphQLOperationsInfo;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (modelAttrs.properties) {
|
|
70
|
+
for (const [key, value] of Object.entries(modelAttrs.properties)) {
|
|
71
|
+
if (value === null) {
|
|
72
|
+
// coarse-grained disable, e.g. "subscriptions": null,
|
|
73
|
+
disabledOps.push(...coarseToFineDict[key]);
|
|
74
|
+
} else if (value instanceof Object) {
|
|
75
|
+
// fine-grained, e.g. "mutations": { "delete": null }
|
|
76
|
+
disabledOps.push(...Object.keys(value));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// observeQuery only exists on the client side, so can't be explicitly disabled via schema builder.
|
|
82
|
+
// It's unusable without `list`
|
|
83
|
+
if (disabledOps.includes('list')) {
|
|
84
|
+
disabledOps.push('observeQuery');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// graphQLOperationsInfo keys are in caps
|
|
88
|
+
const disabledOpsUpper = disabledOps.map((op) => op.toUpperCase());
|
|
89
|
+
|
|
90
|
+
const filteredGraphQLOperations = Object.fromEntries(
|
|
91
|
+
Object.entries(graphQLOperationsInfo).filter(
|
|
92
|
+
([key]) => !disabledOpsUpper.includes(key),
|
|
93
|
+
),
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
return filteredGraphQLOperations;
|
|
97
|
+
};
|
|
@@ -10,3 +10,4 @@ export { generateModelsProperty } from './utils/clientProperties/generateModelsP
|
|
|
10
10
|
export { isGraphQLResponseWithErrors } from './utils/runtimeTypeGuards/isGraphQLResponseWithErrors';
|
|
11
11
|
export { isApiGraphQLConfig } from './utils/runtimeTypeGuards/isApiGraphQLProviderConfig';
|
|
12
12
|
export { isConfigureEventWithResourceConfig } from './utils/runtimeTypeGuards/isConfigureEventWithResourceConfig';
|
|
13
|
+
export { upgradeClientCancellation } from './cancellation';
|
|
@@ -27,6 +27,9 @@ import {
|
|
|
27
27
|
} from '../APIClient';
|
|
28
28
|
|
|
29
29
|
import { handleSingularGraphQlError } from './utils';
|
|
30
|
+
import { selfAwareAsync } from '../../utils';
|
|
31
|
+
|
|
32
|
+
import { extendCancellability } from '../cancellation';
|
|
30
33
|
|
|
31
34
|
type CustomOperationOptions = AuthModeParams & ListArgs;
|
|
32
35
|
|
|
@@ -360,7 +363,7 @@ function operationVariables(
|
|
|
360
363
|
* @param context SSR context if relevant.
|
|
361
364
|
* @returns Result from the graphql request, model-instantiated when relevant.
|
|
362
365
|
*/
|
|
363
|
-
|
|
366
|
+
function _op(
|
|
364
367
|
client: BaseClient,
|
|
365
368
|
modelIntrospection: ModelIntrospectionSchema,
|
|
366
369
|
operationType: 'query' | 'mutation',
|
|
@@ -370,114 +373,63 @@ async function _op(
|
|
|
370
373
|
options?: AuthModeParams & ListArgs,
|
|
371
374
|
context?: AmplifyServer.ContextSpec,
|
|
372
375
|
) {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
376
|
+
return selfAwareAsync(async (resultPromise) => {
|
|
377
|
+
const { name: operationName } = operation;
|
|
378
|
+
const auth = authModeParams(client, getInternals, options);
|
|
379
|
+
const headers = getCustomHeaders(client, getInternals, options?.headers);
|
|
380
|
+
const outerArgsString = outerArguments(operation);
|
|
381
|
+
const innerArgsString = innerArguments(operation);
|
|
382
|
+
const selectionSet = operationSelectionSet(modelIntrospection, operation);
|
|
383
|
+
|
|
384
|
+
const returnTypeModelName = hasStringField(operation.type, 'model')
|
|
385
|
+
? operation.type.model
|
|
386
|
+
: undefined;
|
|
387
|
+
|
|
388
|
+
const query = `
|
|
385
389
|
${operationType.toLocaleLowerCase()}${outerArgsString} {
|
|
386
390
|
${operationName}${innerArgsString} ${selectionSet}
|
|
387
391
|
}
|
|
388
392
|
`;
|
|
389
393
|
|
|
390
|
-
|
|
394
|
+
const variables = operationVariables(operation, args);
|
|
395
|
+
|
|
396
|
+
try {
|
|
397
|
+
const basePromise = context
|
|
398
|
+
? ((client as BaseSSRClient).graphql(
|
|
399
|
+
context,
|
|
400
|
+
{
|
|
401
|
+
...auth,
|
|
402
|
+
query,
|
|
403
|
+
variables,
|
|
404
|
+
},
|
|
405
|
+
headers,
|
|
406
|
+
) as Promise<GraphQLResult>)
|
|
407
|
+
: ((client as BaseBrowserClient).graphql(
|
|
408
|
+
{
|
|
409
|
+
...auth,
|
|
410
|
+
query,
|
|
411
|
+
variables,
|
|
412
|
+
},
|
|
413
|
+
headers,
|
|
414
|
+
) as Promise<GraphQLResult>);
|
|
415
|
+
|
|
416
|
+
const extendedPromise = extendCancellability(basePromise, resultPromise);
|
|
417
|
+
const { data, extensions } = await extendedPromise;
|
|
418
|
+
|
|
419
|
+
// flatten response
|
|
420
|
+
if (data) {
|
|
421
|
+
const [key] = Object.keys(data);
|
|
422
|
+
|
|
423
|
+
const isArrayResult = Array.isArray(data[key]);
|
|
424
|
+
|
|
425
|
+
// TODO: when adding support for custom selection set, flattening will need
|
|
426
|
+
// to occur recursively. For now, it's expected that related models are not
|
|
427
|
+
// present in the result. Only FK's are present. Any related model properties
|
|
428
|
+
// should be replaced with lazy loaders under the current implementation.
|
|
429
|
+
const flattenedResult = isArrayResult
|
|
430
|
+
? data[key].filter((x: any) => x)
|
|
431
|
+
: data[key];
|
|
391
432
|
|
|
392
|
-
try {
|
|
393
|
-
const { data, extensions } = context
|
|
394
|
-
? ((await (client as BaseSSRClient).graphql(
|
|
395
|
-
context,
|
|
396
|
-
{
|
|
397
|
-
...auth,
|
|
398
|
-
query,
|
|
399
|
-
variables,
|
|
400
|
-
},
|
|
401
|
-
headers,
|
|
402
|
-
)) as GraphQLResult)
|
|
403
|
-
: ((await (client as BaseBrowserClient).graphql(
|
|
404
|
-
{
|
|
405
|
-
...auth,
|
|
406
|
-
query,
|
|
407
|
-
variables,
|
|
408
|
-
},
|
|
409
|
-
headers,
|
|
410
|
-
)) as GraphQLResult);
|
|
411
|
-
|
|
412
|
-
// flatten response
|
|
413
|
-
if (data) {
|
|
414
|
-
const [key] = Object.keys(data);
|
|
415
|
-
|
|
416
|
-
const isArrayResult = Array.isArray(data[key]);
|
|
417
|
-
|
|
418
|
-
// TODO: when adding support for custom selection set, flattening will need
|
|
419
|
-
// to occur recursively. For now, it's expected that related models are not
|
|
420
|
-
// present in the result. Only FK's are present. Any related model properties
|
|
421
|
-
// should be replaced with lazy loaders under the current implementation.
|
|
422
|
-
const flattenedResult = isArrayResult
|
|
423
|
-
? data[key].filter((x: any) => x)
|
|
424
|
-
: data[key];
|
|
425
|
-
|
|
426
|
-
// TODO: custom selection set. current selection set is default selection set only
|
|
427
|
-
// custom selection set requires data-schema-type + runtime updates above.
|
|
428
|
-
const initialized = returnTypeModelName
|
|
429
|
-
? initializeModel(
|
|
430
|
-
client,
|
|
431
|
-
returnTypeModelName,
|
|
432
|
-
isArrayResult ? flattenedResult : [flattenedResult],
|
|
433
|
-
modelIntrospection,
|
|
434
|
-
auth.authMode,
|
|
435
|
-
auth.authToken,
|
|
436
|
-
!!context,
|
|
437
|
-
)
|
|
438
|
-
: flattenedResult;
|
|
439
|
-
|
|
440
|
-
return {
|
|
441
|
-
data:
|
|
442
|
-
!isArrayResult && Array.isArray(initialized)
|
|
443
|
-
? initialized.shift()
|
|
444
|
-
: initialized,
|
|
445
|
-
extensions,
|
|
446
|
-
};
|
|
447
|
-
} else {
|
|
448
|
-
return { data: null, extensions };
|
|
449
|
-
}
|
|
450
|
-
} catch (error: any) {
|
|
451
|
-
/**
|
|
452
|
-
* The `data` type returned by `error` here could be:
|
|
453
|
-
* 1) `null`
|
|
454
|
-
* 2) an empty object
|
|
455
|
-
* 3) "populated" but with a `null` value `{ getPost: null }`
|
|
456
|
-
* 4) an actual record `{ getPost: { id: '1', title: 'Hello, World!' } }`
|
|
457
|
-
*/
|
|
458
|
-
const { data, errors } = error;
|
|
459
|
-
|
|
460
|
-
/**
|
|
461
|
-
* `data` is not `null`, and is not an empty object:
|
|
462
|
-
*/
|
|
463
|
-
if (data && Object.keys(data).length !== 0 && errors) {
|
|
464
|
-
const [key] = Object.keys(data);
|
|
465
|
-
|
|
466
|
-
const isArrayResult = Array.isArray(data[key]);
|
|
467
|
-
|
|
468
|
-
// TODO: when adding support for custom selection set, flattening will need
|
|
469
|
-
// to occur recursively. For now, it's expected that related models are not
|
|
470
|
-
// present in the result. Only FK's are present. Any related model properties
|
|
471
|
-
// should be replaced with lazy loaders under the current implementation.
|
|
472
|
-
const flattenedResult = isArrayResult
|
|
473
|
-
? data[key].filter((x: any) => x)
|
|
474
|
-
: data[key];
|
|
475
|
-
|
|
476
|
-
/**
|
|
477
|
-
* `flattenedResult` could be `null` here (e.g. `data: { getPost: null }`)
|
|
478
|
-
* if `flattenedResult`, result is an actual record:
|
|
479
|
-
*/
|
|
480
|
-
if (flattenedResult) {
|
|
481
433
|
// TODO: custom selection set. current selection set is default selection set only
|
|
482
434
|
// custom selection set requires data-schema-type + runtime updates above.
|
|
483
435
|
const initialized = returnTypeModelName
|
|
@@ -497,17 +449,73 @@ async function _op(
|
|
|
497
449
|
!isArrayResult && Array.isArray(initialized)
|
|
498
450
|
? initialized.shift()
|
|
499
451
|
: initialized,
|
|
500
|
-
|
|
452
|
+
extensions,
|
|
501
453
|
};
|
|
502
454
|
} else {
|
|
503
|
-
|
|
455
|
+
return { data: null, extensions };
|
|
456
|
+
}
|
|
457
|
+
} catch (error: any) {
|
|
458
|
+
/**
|
|
459
|
+
* The `data` type returned by `error` here could be:
|
|
460
|
+
* 1) `null`
|
|
461
|
+
* 2) an empty object
|
|
462
|
+
* 3) "populated" but with a `null` value `{ getPost: null }`
|
|
463
|
+
* 4) an actual record `{ getPost: { id: '1', title: 'Hello, World!' } }`
|
|
464
|
+
*/
|
|
465
|
+
const { data, errors } = error;
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* `data` is not `null`, and is not an empty object:
|
|
469
|
+
*/
|
|
470
|
+
if (data && Object.keys(data).length !== 0 && errors) {
|
|
471
|
+
const [key] = Object.keys(data);
|
|
472
|
+
|
|
473
|
+
const isArrayResult = Array.isArray(data[key]);
|
|
474
|
+
|
|
475
|
+
// TODO: when adding support for custom selection set, flattening will need
|
|
476
|
+
// to occur recursively. For now, it's expected that related models are not
|
|
477
|
+
// present in the result. Only FK's are present. Any related model properties
|
|
478
|
+
// should be replaced with lazy loaders under the current implementation.
|
|
479
|
+
const flattenedResult = isArrayResult
|
|
480
|
+
? data[key].filter((x: any) => x)
|
|
481
|
+
: data[key];
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* `flattenedResult` could be `null` here (e.g. `data: { getPost: null }`)
|
|
485
|
+
* if `flattenedResult`, result is an actual record:
|
|
486
|
+
*/
|
|
487
|
+
if (flattenedResult) {
|
|
488
|
+
// TODO: custom selection set. current selection set is default selection set only
|
|
489
|
+
// custom selection set requires data-schema-type + runtime updates above.
|
|
490
|
+
const initialized = returnTypeModelName
|
|
491
|
+
? initializeModel(
|
|
492
|
+
client,
|
|
493
|
+
returnTypeModelName,
|
|
494
|
+
isArrayResult ? flattenedResult : [flattenedResult],
|
|
495
|
+
modelIntrospection,
|
|
496
|
+
auth.authMode,
|
|
497
|
+
auth.authToken,
|
|
498
|
+
!!context,
|
|
499
|
+
)
|
|
500
|
+
: flattenedResult;
|
|
501
|
+
|
|
502
|
+
return {
|
|
503
|
+
data:
|
|
504
|
+
!isArrayResult && Array.isArray(initialized)
|
|
505
|
+
? initialized.shift()
|
|
506
|
+
: initialized,
|
|
507
|
+
errors,
|
|
508
|
+
};
|
|
509
|
+
} else {
|
|
510
|
+
// was `data: { getPost: null }`)
|
|
511
|
+
return handleSingularGraphQlError(error);
|
|
512
|
+
}
|
|
513
|
+
} else {
|
|
514
|
+
// `data` is `null`:
|
|
504
515
|
return handleSingularGraphQlError(error);
|
|
505
516
|
}
|
|
506
|
-
} else {
|
|
507
|
-
// `data` is `null`:
|
|
508
|
-
return handleSingularGraphQlError(error);
|
|
509
517
|
}
|
|
510
|
-
}
|
|
518
|
+
});
|
|
511
519
|
}
|
|
512
520
|
|
|
513
521
|
/**
|
|
@@ -26,6 +26,9 @@ import {
|
|
|
26
26
|
} from '../APIClient';
|
|
27
27
|
|
|
28
28
|
import { handleSingularGraphQlError } from './utils';
|
|
29
|
+
import { selfAwareAsync } from '../../utils';
|
|
30
|
+
|
|
31
|
+
import { extendCancellability } from '../cancellation';
|
|
29
32
|
|
|
30
33
|
export function getFactory(
|
|
31
34
|
client: BaseClient,
|
|
@@ -35,7 +38,7 @@ export function getFactory(
|
|
|
35
38
|
getInternals: ClientInternalsGetter,
|
|
36
39
|
useContext = false,
|
|
37
40
|
) {
|
|
38
|
-
const getWithContext =
|
|
41
|
+
const getWithContext = (
|
|
39
42
|
contextSpec: AmplifyServer.ContextSpec & GraphQLOptions,
|
|
40
43
|
arg?: any,
|
|
41
44
|
options?: any,
|
|
@@ -52,7 +55,7 @@ export function getFactory(
|
|
|
52
55
|
);
|
|
53
56
|
};
|
|
54
57
|
|
|
55
|
-
const get =
|
|
58
|
+
const get = (arg?: any, options?: any) => {
|
|
56
59
|
return _get(
|
|
57
60
|
client,
|
|
58
61
|
modelIntrospection,
|
|
@@ -67,7 +70,7 @@ export function getFactory(
|
|
|
67
70
|
return useContext ? getWithContext : get;
|
|
68
71
|
}
|
|
69
72
|
|
|
70
|
-
|
|
73
|
+
function _get(
|
|
71
74
|
client: BaseClient,
|
|
72
75
|
modelIntrospection: ModelIntrospectionSchema,
|
|
73
76
|
model: SchemaModel,
|
|
@@ -77,95 +80,62 @@ async function _get(
|
|
|
77
80
|
getInternals: ClientInternalsGetter,
|
|
78
81
|
context?: AmplifyServer.ContextSpec,
|
|
79
82
|
) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
return { data: flattenedResult, extensions };
|
|
128
|
-
} else {
|
|
129
|
-
// TODO: refactor to avoid destructuring here
|
|
130
|
-
const [initialized] = initializeModel(
|
|
131
|
-
client,
|
|
132
|
-
name,
|
|
133
|
-
[flattenedResult],
|
|
83
|
+
return selfAwareAsync(async (resultPromise) => {
|
|
84
|
+
const { name } = model;
|
|
85
|
+
|
|
86
|
+
const query = generateGraphQLDocument(
|
|
87
|
+
modelIntrospection,
|
|
88
|
+
name,
|
|
89
|
+
operation,
|
|
90
|
+
options,
|
|
91
|
+
);
|
|
92
|
+
const variables = buildGraphQLVariables(
|
|
93
|
+
model,
|
|
94
|
+
operation,
|
|
95
|
+
arg,
|
|
96
|
+
modelIntrospection,
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const auth = authModeParams(client, getInternals, options);
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
const headers = getCustomHeaders(client, getInternals, options?.headers);
|
|
103
|
+
|
|
104
|
+
const basePromise = context
|
|
105
|
+
? ((client as BaseSSRClient).graphql(
|
|
106
|
+
context,
|
|
107
|
+
{
|
|
108
|
+
...auth,
|
|
109
|
+
query,
|
|
110
|
+
variables,
|
|
111
|
+
},
|
|
112
|
+
headers,
|
|
113
|
+
) as Promise<GraphQLResult>)
|
|
114
|
+
: ((client as BaseBrowserClient).graphql(
|
|
115
|
+
{
|
|
116
|
+
...auth,
|
|
117
|
+
query,
|
|
118
|
+
variables,
|
|
119
|
+
},
|
|
120
|
+
headers,
|
|
121
|
+
) as Promise<GraphQLResult>);
|
|
122
|
+
|
|
123
|
+
const extendedPromise = extendCancellability(basePromise, resultPromise);
|
|
124
|
+
const { data, extensions } = await extendedPromise;
|
|
125
|
+
|
|
126
|
+
// flatten response
|
|
127
|
+
if (data) {
|
|
128
|
+
const [key] = Object.keys(data);
|
|
129
|
+
const flattenedResult = flattenItems(
|
|
134
130
|
modelIntrospection,
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
!!context,
|
|
131
|
+
name,
|
|
132
|
+
data[key],
|
|
138
133
|
);
|
|
139
134
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
} catch (error: any) {
|
|
146
|
-
/**
|
|
147
|
-
* The `data` type returned by `error` here could be:
|
|
148
|
-
* 1) `null`
|
|
149
|
-
* 2) an empty object
|
|
150
|
-
* 3) "populated" but with a `null` value `{ getPost: null }`
|
|
151
|
-
* 4) an actual record `{ getPost: { id: '1', title: 'Hello, World!' } }`
|
|
152
|
-
*/
|
|
153
|
-
const { data, errors } = error;
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* `data` is not `null`, and is not an empty object:
|
|
157
|
-
*/
|
|
158
|
-
if (data && Object.keys(data).length !== 0 && errors) {
|
|
159
|
-
const [key] = Object.keys(data);
|
|
160
|
-
const flattenedResult = flattenItems(modelIntrospection, name, data[key]);
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* `flattenedResult` could be `null` here (e.g. `data: { getPost: null }`)
|
|
164
|
-
* if `flattenedResult`, result is an actual record:
|
|
165
|
-
*/
|
|
166
|
-
if (flattenedResult) {
|
|
167
|
-
if (options?.selectionSet) {
|
|
168
|
-
return { data: flattenedResult, errors };
|
|
135
|
+
if (flattenedResult === null) {
|
|
136
|
+
return { data: null, extensions };
|
|
137
|
+
} else if (options?.selectionSet) {
|
|
138
|
+
return { data: flattenedResult, extensions };
|
|
169
139
|
} else {
|
|
170
140
|
// TODO: refactor to avoid destructuring here
|
|
171
141
|
const [initialized] = initializeModel(
|
|
@@ -178,15 +148,61 @@ async function _get(
|
|
|
178
148
|
!!context,
|
|
179
149
|
);
|
|
180
150
|
|
|
181
|
-
return { data: initialized,
|
|
151
|
+
return { data: initialized, extensions };
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
return { data: null, extensions };
|
|
155
|
+
}
|
|
156
|
+
} catch (error: any) {
|
|
157
|
+
/**
|
|
158
|
+
* The `data` type returned by `error` here could be:
|
|
159
|
+
* 1) `null`
|
|
160
|
+
* 2) an empty object
|
|
161
|
+
* 3) "populated" but with a `null` value `{ getPost: null }`
|
|
162
|
+
* 4) an actual record `{ getPost: { id: '1', title: 'Hello, World!' } }`
|
|
163
|
+
*/
|
|
164
|
+
const { data, errors } = error;
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* `data` is not `null`, and is not an empty object:
|
|
168
|
+
*/
|
|
169
|
+
if (data && Object.keys(data).length !== 0 && errors) {
|
|
170
|
+
const [key] = Object.keys(data);
|
|
171
|
+
const flattenedResult = flattenItems(
|
|
172
|
+
modelIntrospection,
|
|
173
|
+
name,
|
|
174
|
+
data[key],
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* `flattenedResult` could be `null` here (e.g. `data: { getPost: null }`)
|
|
179
|
+
* if `flattenedResult`, result is an actual record:
|
|
180
|
+
*/
|
|
181
|
+
if (flattenedResult) {
|
|
182
|
+
if (options?.selectionSet) {
|
|
183
|
+
return { data: flattenedResult, errors };
|
|
184
|
+
} else {
|
|
185
|
+
// TODO: refactor to avoid destructuring here
|
|
186
|
+
const [initialized] = initializeModel(
|
|
187
|
+
client,
|
|
188
|
+
name,
|
|
189
|
+
[flattenedResult],
|
|
190
|
+
modelIntrospection,
|
|
191
|
+
auth.authMode,
|
|
192
|
+
auth.authToken,
|
|
193
|
+
!!context,
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
return { data: initialized, errors };
|
|
197
|
+
}
|
|
198
|
+
} else {
|
|
199
|
+
// was `data: { getPost: null }`)
|
|
200
|
+
return handleSingularGraphQlError(error);
|
|
182
201
|
}
|
|
183
202
|
} else {
|
|
184
|
-
//
|
|
203
|
+
// `data` is `null`:
|
|
185
204
|
return handleSingularGraphQlError(error);
|
|
186
205
|
}
|
|
187
|
-
} else {
|
|
188
|
-
// `data` is `null`:
|
|
189
|
-
return handleSingularGraphQlError(error);
|
|
190
206
|
}
|
|
191
|
-
}
|
|
207
|
+
});
|
|
192
208
|
}
|