@aws-amplify/data-schema 0.16.2 → 0.17.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.
Files changed (30) hide show
  1. package/dist/cjs/runtime/internals/operations/custom.js +33 -5
  2. package/dist/cjs/runtime/internals/operations/custom.js.map +1 -1
  3. package/dist/cjs/runtime/internals/operations/get.js +36 -6
  4. package/dist/cjs/runtime/internals/operations/get.js.map +1 -1
  5. package/dist/cjs/runtime/internals/operations/indexQuery.js +39 -11
  6. package/dist/cjs/runtime/internals/operations/indexQuery.js.map +1 -1
  7. package/dist/cjs/runtime/internals/operations/list.js +50 -6
  8. package/dist/cjs/runtime/internals/operations/list.js.map +1 -1
  9. package/dist/cjs/runtime/internals/operations/utils.js +42 -0
  10. package/dist/cjs/runtime/internals/operations/utils.js.map +1 -0
  11. package/dist/esm/Authorization.d.ts +2 -2
  12. package/dist/esm/ModelRelationalField.d.ts +1 -1
  13. package/dist/esm/runtime/internals/operations/custom.mjs +33 -5
  14. package/dist/esm/runtime/internals/operations/custom.mjs.map +1 -1
  15. package/dist/esm/runtime/internals/operations/get.mjs +36 -6
  16. package/dist/esm/runtime/internals/operations/get.mjs.map +1 -1
  17. package/dist/esm/runtime/internals/operations/indexQuery.mjs +39 -11
  18. package/dist/esm/runtime/internals/operations/indexQuery.mjs.map +1 -1
  19. package/dist/esm/runtime/internals/operations/list.mjs +50 -6
  20. package/dist/esm/runtime/internals/operations/list.mjs.map +1 -1
  21. package/dist/esm/runtime/internals/operations/utils.d.ts +8 -0
  22. package/dist/esm/runtime/internals/operations/utils.mjs +38 -0
  23. package/dist/esm/runtime/internals/operations/utils.mjs.map +1 -0
  24. package/dist/meta/cjs.tsbuildinfo +1 -1
  25. package/package.json +1 -1
  26. package/src/runtime/internals/operations/custom.ts +44 -5
  27. package/src/runtime/internals/operations/get.ts +47 -7
  28. package/src/runtime/internals/operations/indexQuery.ts +43 -11
  29. package/src/runtime/internals/operations/list.ts +63 -7
  30. package/src/runtime/internals/operations/utils.ts +35 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aws-amplify/data-schema",
3
- "version": "0.16.2",
3
+ "version": "0.17.0",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -27,6 +27,8 @@ import {
27
27
  selectionSetIRToString,
28
28
  } from '../APIClient';
29
29
 
30
+ import { handleSingularGraphQlError } from './utils';
31
+
30
32
  type CustomOperationOptions = AuthModeParams & ListArgs;
31
33
 
32
34
  // these are the 4 possible sets of arguments custom operations methods can receive
@@ -417,12 +419,49 @@ async function _op(
417
419
  return { data: null, extensions };
418
420
  }
419
421
  } catch (error: any) {
420
- if (error.errors) {
421
- // graphql errors pass through
422
- return error as any;
422
+ /**
423
+ * The `data` type returned by `error` here could be:
424
+ * 1) `null`
425
+ * 2) an empty object
426
+ * 3) "populated" but with a `null` value `{ getPost: null }`
427
+ * 4) an actual record `{ getPost: { id: '1', title: 'Hello, World!' } }`
428
+ */
429
+ const { data, errors } = error;
430
+
431
+ /**
432
+ * `data` is not `null`, and is not an empty object:
433
+ */
434
+ if (data && Object.keys(data).length !== 0 && errors) {
435
+ const [key] = Object.keys(data);
436
+ const flattenedResult = flattenItems(data)[key];
437
+
438
+ /**
439
+ * `flattenedResult` could be `null` here (e.g. `data: { getPost: null }`)
440
+ * if `flattenedResult`, result is an actual record:
441
+ */
442
+ if (flattenedResult) {
443
+ // TODO: custom selection set. current selection set is default selection set only
444
+ // custom selection set requires data-schema-type + runtime updates above.
445
+ const [initialized] = returnTypeModelName
446
+ ? initializeModel(
447
+ client,
448
+ returnTypeModelName,
449
+ [flattenedResult],
450
+ modelIntrospection,
451
+ auth.authMode,
452
+ auth.authToken,
453
+ !!context,
454
+ )
455
+ : [flattenedResult];
456
+
457
+ return { data: initialized, errors };
458
+ } else {
459
+ // was `data: { getPost: null }`)
460
+ return handleSingularGraphQlError(error);
461
+ }
423
462
  } else {
424
- // non-graphql errors re re-thrown
425
- throw error;
463
+ // `data` is `null`:
464
+ return handleSingularGraphQlError(error);
426
465
  }
427
466
  }
428
467
  }
@@ -25,6 +25,8 @@ import {
25
25
  initializeModel,
26
26
  } from '../APIClient';
27
27
 
28
+ import { handleSingularGraphQlError } from './utils';
29
+
28
30
  export function getFactory(
29
31
  client: BaseClient,
30
32
  modelIntrospection: ModelIntrospectionSchema,
@@ -90,9 +92,9 @@ async function _get(
90
92
  modelIntrospection,
91
93
  );
92
94
 
93
- try {
94
- const auth = authModeParams(client, getInternals, options);
95
+ const auth = authModeParams(client, getInternals, options);
95
96
 
97
+ try {
96
98
  const headers = getCustomHeaders(client, getInternals, options?.headers);
97
99
 
98
100
  const { data, extensions } = context
@@ -139,12 +141,50 @@ async function _get(
139
141
  return { data: null, extensions };
140
142
  }
141
143
  } catch (error: any) {
142
- if (error.errors) {
143
- // graphql errors pass through
144
- return error as any;
144
+ /**
145
+ * The `data` type returned by `error` here could be:
146
+ * 1) `null`
147
+ * 2) an empty object
148
+ * 3) "populated" but with a `null` value `{ getPost: null }`
149
+ * 4) an actual record `{ getPost: { id: '1', title: 'Hello, World!' } }`
150
+ */
151
+ const { data, errors } = error;
152
+
153
+ /**
154
+ * `data` is not `null`, and is not an empty object:
155
+ */
156
+ if (data && Object.keys(data).length !== 0 && errors) {
157
+ const [key] = Object.keys(data);
158
+ const flattenedResult = flattenItems(data)[key];
159
+
160
+ /**
161
+ * `flattenedResult` could be `null` here (e.g. `data: { getPost: null }`)
162
+ * if `flattenedResult`, result is an actual record:
163
+ */
164
+ if (flattenedResult) {
165
+ if (options?.selectionSet) {
166
+ return { data: flattenedResult, errors };
167
+ } else {
168
+ // TODO: refactor to avoid destructuring here
169
+ const [initialized] = initializeModel(
170
+ client,
171
+ name,
172
+ [flattenedResult],
173
+ modelIntrospection,
174
+ auth.authMode,
175
+ auth.authToken,
176
+ !!context,
177
+ );
178
+
179
+ return { data: initialized, errors };
180
+ }
181
+ } else {
182
+ // was `data: { getPost: null }`)
183
+ return handleSingularGraphQlError(error);
184
+ }
145
185
  } else {
146
- // non-graphql errors re re-thrown
147
- throw error;
186
+ // `data` is `null`:
187
+ return handleSingularGraphQlError(error);
148
188
  }
149
189
  }
150
190
  }
@@ -21,6 +21,8 @@ import {
21
21
  initializeModel,
22
22
  } from '../APIClient';
23
23
 
24
+ import { handleListGraphQlError } from './utils';
25
+
24
26
  export interface IndexMeta {
25
27
  queryField: string;
26
28
  pk: string;
@@ -97,16 +99,6 @@ function processGraphQlResponse(
97
99
  };
98
100
  }
99
101
 
100
- function handleGraphQlError(error: any) {
101
- if (error.errors) {
102
- // graphql errors pass through
103
- return error as any;
104
- } else {
105
- // non-graphql errors re re-thrown
106
- throw error;
107
- }
108
- }
109
-
110
102
  async function _indexQuery(
111
103
  client: BaseClient,
112
104
  modelIntrospection: ModelIntrospectionSchema,
@@ -173,6 +165,46 @@ async function _indexQuery(
173
165
  );
174
166
  }
175
167
  } catch (error: any) {
176
- return handleGraphQlError(error);
168
+ /**
169
+ * The `data` type returned by `error` here could be:
170
+ * 1) `null`
171
+ * 2) an empty object
172
+ * 3) "populated" but with a `null` value:
173
+ * `data: { listByExampleId: null }`
174
+ * 4) an actual record:
175
+ * `data: { listByExampleId: items: [{ id: '1', ...etc } }]`
176
+ */
177
+ const { data, errors } = error;
178
+
179
+ // `data` is not `null`, and is not an empty object:
180
+ if (data !== undefined && Object.keys(data).length !== 0 && errors) {
181
+ const [key] = Object.keys(data);
182
+
183
+ if (data[key]?.items) {
184
+ const flattenedResult = flattenItems(data)[key];
185
+
186
+ /**
187
+ * Check exists since `flattenedResult` could be `null`.
188
+ * if `flattenedResult` exists, result is an actual record.
189
+ */
190
+ if (flattenedResult) {
191
+ return {
192
+ data: args?.selectionSet
193
+ ? flattenedResult
194
+ : modelInitializer(flattenedResult),
195
+ nextToken: data[key]?.nextToken,
196
+ };
197
+ }
198
+ }
199
+
200
+ // response is of type `data: { listByExampleId: null }`
201
+ return {
202
+ data: data[key],
203
+ nextToken: data[key]?.nextToken,
204
+ };
205
+ } else {
206
+ // `data` is `null` or an empty object:
207
+ return handleListGraphQlError(error);
208
+ }
177
209
  }
178
210
  }
@@ -22,6 +22,8 @@ import {
22
22
  initializeModel,
23
23
  } from '../APIClient';
24
24
 
25
+ import { handleListGraphQlError } from './utils';
26
+
25
27
  export function listFactory(
26
28
  client: BaseClient,
27
29
  modelIntrospection: ModelIntrospectionSchema,
@@ -68,9 +70,9 @@ async function _list(
68
70
  modelIntrospection,
69
71
  );
70
72
 
71
- try {
72
- const auth = authModeParams(client, getInternals, args);
73
+ const auth = authModeParams(client, getInternals, args);
73
74
 
75
+ try {
74
76
  const headers = getCustomHeaders(client, getInternals, args?.headers);
75
77
 
76
78
  const { data, extensions } = contextSpec
@@ -132,12 +134,66 @@ async function _list(
132
134
  };
133
135
  }
134
136
  } catch (error: any) {
135
- if (error.errors) {
136
- // graphql errors pass through
137
- return error as any;
137
+ /**
138
+ * The `data` type returned by `error` here could be:
139
+ * 1) `null`
140
+ * 2) an empty object
141
+ * 3) "populated" but with a `null` value `data: { listPosts: null }`
142
+ * 4) actual records `data: { listPosts: items: [{ id: '1', ...etc }] }`
143
+ */
144
+ const { data, errors } = error;
145
+
146
+ // `data` is not `null`, and is not an empty object:
147
+ if (data !== undefined && Object.keys(data).length !== 0 && errors) {
148
+ const [key] = Object.keys(data);
149
+
150
+ if (data[key]?.items) {
151
+ const flattenedResult = flattenItems(data)[key];
152
+
153
+ /**
154
+ * Check exists since `flattenedResult` could be `null`.
155
+ * if `flattenedResult` exists, result is an actual record.
156
+ */
157
+ if (flattenedResult) {
158
+ // don't init if custom selection set
159
+ if (args?.selectionSet) {
160
+ return {
161
+ data: flattenedResult,
162
+ nextToken: data[key]?.nextToken,
163
+ errors,
164
+ };
165
+ } else {
166
+ const initialized = initializeModel(
167
+ client,
168
+ name,
169
+ flattenedResult,
170
+ modelIntrospection,
171
+ auth.authMode,
172
+ auth.authToken,
173
+ !!contextSpec,
174
+ );
175
+
176
+ // data is full record w/out selection set:
177
+ return {
178
+ data: initialized,
179
+ nextToken: data[key]?.nextToken,
180
+ errors,
181
+ };
182
+ }
183
+ }
184
+
185
+ return {
186
+ data: data[key],
187
+ nextToken: data[key]?.nextToken,
188
+ errors,
189
+ };
190
+ } else {
191
+ // response is of type `data: { getPost: null }`)
192
+ return handleListGraphQlError(error);
193
+ }
138
194
  } else {
139
- // non-graphql errors re re-thrown
140
- throw error;
195
+ // `data` is `null` or an empty object:
196
+ return handleListGraphQlError(error);
141
197
  }
142
198
  }
143
199
  }
@@ -0,0 +1,35 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // import { GraphQLFormattedError } from '@aws-amplify/data-schema-types';
4
+
5
+ /**
6
+ * Handle errors for list return types (list and index query operations)
7
+ */
8
+ export function handleListGraphQlError(error: any) {
9
+ if (error?.errors) {
10
+ // graphql errors pass through
11
+ return {
12
+ ...error,
13
+ data: [],
14
+ } as any;
15
+ } else {
16
+ // non-graphql errors are re-thrown
17
+ throw error;
18
+ }
19
+ }
20
+
21
+ /**
22
+ * Handle errors for singular return types (create, get, update, delete operations)
23
+ */
24
+ export function handleSingularGraphQlError(error: any) {
25
+ if (error.errors) {
26
+ // graphql errors pass through
27
+ return {
28
+ ...error,
29
+ data: null,
30
+ } as any;
31
+ } else {
32
+ // non-graphql errors are re-thrown
33
+ throw error;
34
+ }
35
+ }