@aws-amplify/api-graphql 4.0.1-api-v6-models.8035dfc.0 → 4.0.1-api-v6-models.3eb7748.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.
@@ -0,0 +1,12 @@
1
+ import { ResourcesConfig } from '@aws-amplify/core';
2
+ type GraphQLConfig = Exclude<ResourcesConfig['API'], undefined>['GraphQL'];
3
+ type ModelIntrospectionSchema = Exclude<Exclude<GraphQLConfig, undefined>['modelIntrospection'], undefined>;
4
+ type Model = ModelIntrospectionSchema['models'][string];
5
+ /**
6
+ * Given an introspection schema model, returns all owner fields.
7
+ *
8
+ * @param model Model from an introspection schema
9
+ * @returns List of owner field names
10
+ */
11
+ export declare function resolveOwnerFields(model: Model): string[];
12
+ export {};
@@ -0,0 +1,59 @@
1
+ import { __values } from "tslib";
2
+ /**
3
+ * Given an introspection schema model, returns all owner fields.
4
+ *
5
+ * @param model Model from an introspection schema
6
+ * @returns List of owner field names
7
+ */
8
+ export function resolveOwnerFields(model) {
9
+ var e_1, _a, e_2, _b;
10
+ var ownerFields = new Set();
11
+ try {
12
+ for (var _c = __values(model.attributes || []), _d = _c.next(); !_d.done; _d = _c.next()) {
13
+ var attr = _d.value;
14
+ if (isAuthAttribute(attr)) {
15
+ try {
16
+ for (var _e = (e_2 = void 0, __values(attr.properties.rules)), _f = _e.next(); !_f.done; _f = _e.next()) {
17
+ var rule = _f.value;
18
+ if (rule.allow === 'owner') {
19
+ ownerFields.add(rule.ownerField || 'owner');
20
+ }
21
+ }
22
+ }
23
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
24
+ finally {
25
+ try {
26
+ if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
27
+ }
28
+ finally { if (e_2) throw e_2.error; }
29
+ }
30
+ }
31
+ }
32
+ }
33
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
34
+ finally {
35
+ try {
36
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
37
+ }
38
+ finally { if (e_1) throw e_1.error; }
39
+ }
40
+ return Array.from(ownerFields);
41
+ }
42
+ /**
43
+ * Type guard that identifies an auth attribute with an attached rules list that
44
+ * specifies an `allow` attribute at a minimum.
45
+ *
46
+ * @param attribute Any object. Ideally a model introspection schema model attribute
47
+ * @returns True if given object is an auth attribute
48
+ */
49
+ function isAuthAttribute(attribute) {
50
+ var _a, _b;
51
+ if ((attribute === null || attribute === void 0 ? void 0 : attribute.type) === 'auth') {
52
+ if (typeof (attribute === null || attribute === void 0 ? void 0 : attribute.properties) === 'object') {
53
+ if (Array.isArray((_a = attribute === null || attribute === void 0 ? void 0 : attribute.properties) === null || _a === void 0 ? void 0 : _a.rules)) {
54
+ return ((_b = attribute === null || attribute === void 0 ? void 0 : attribute.properties) === null || _b === void 0 ? void 0 : _b.rules).every(function (rule) { return !!rule.allow; });
55
+ }
56
+ }
57
+ }
58
+ return false;
59
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aws-amplify/api-graphql",
3
- "version": "4.0.1-api-v6-models.8035dfc.0+8035dfc",
3
+ "version": "4.0.1-api-v6-models.3eb7748.0+3eb7748",
4
4
  "description": "Api-graphql category of aws-amplify",
5
5
  "main": "./lib/index.js",
6
6
  "module": "./lib-esm/index.js",
@@ -52,15 +52,14 @@
52
52
  ],
53
53
  "dependencies": {
54
54
  "@aws-amplify/amplify-api-next-types-alpha": "^0.2.0",
55
- "@aws-amplify/api-rest": "4.0.1-api-v6-models.8035dfc.0+8035dfc",
56
- "@aws-amplify/auth": "6.0.1-api-v6-models.8035dfc.0+8035dfc",
57
- "@aws-amplify/core": "6.0.1-api-v6-models.8035dfc.0+8035dfc",
55
+ "@aws-amplify/api-rest": "4.0.1-api-v6-models.3eb7748.0+3eb7748",
56
+ "@aws-amplify/auth": "6.0.1-api-v6-models.3eb7748.0+3eb7748",
57
+ "@aws-amplify/core": "6.0.1-api-v6-models.3eb7748.0+3eb7748",
58
58
  "@aws-sdk/types": "3.387.0",
59
59
  "graphql": "15.8.0",
60
60
  "rxjs": "^7.8.1",
61
61
  "tslib": "^2.6.1",
62
- "url": "0.11.0",
63
- "uuid": "^3.2.1"
62
+ "url": "0.11.0"
64
63
  },
65
64
  "size-limit": [
66
65
  {
@@ -127,5 +126,5 @@
127
126
  "<rootDir>/__tests__"
128
127
  ]
129
128
  },
130
- "gitHead": "8035dfc20dda8f7b4d116616e89e72d889ceb5f1"
129
+ "gitHead": "3eb7748aee2fcdea705c93904d1f30ff596649fa"
131
130
  }
@@ -3,20 +3,20 @@
3
3
  import { Observable, SubscriptionLike } from 'rxjs';
4
4
  import { GraphQLError } from 'graphql';
5
5
  import * as url from 'url';
6
- import { v4 as uuid } from 'uuid';
7
6
  import { Buffer } from 'buffer';
8
- import { Hub, fetchAuthSession } from '@aws-amplify/core';
7
+ import { Hub, fetchAuthSession, ConsoleLogger } from '@aws-amplify/core';
9
8
  import { signRequest } from '@aws-amplify/core/internals/aws-client-utils';
10
9
  import {
11
10
  GraphQLAuthMode,
12
11
  CustomUserAgentDetails,
13
- Logger,
14
12
  NonRetryableError,
15
13
  USER_AGENT_HEADER,
16
14
  getAmplifyUserAgent,
17
15
  isNonRetryableError,
18
16
  jitteredExponentialRetry,
19
17
  DocumentType,
18
+ amplifyUuid,
19
+ AmplifyUrl,
20
20
  } from '@aws-amplify/core/internals/utils';
21
21
 
22
22
  import {
@@ -47,7 +47,7 @@ import {
47
47
  ReconnectionMonitor,
48
48
  } from '../../utils/ReconnectionMonitor';
49
49
 
50
- const logger = new Logger('AWSAppSyncRealTimeProvider');
50
+ const logger = new ConsoleLogger('AWSAppSyncRealTimeProvider');
51
51
 
52
52
  const dispatchApiEvent = payload => {
53
53
  Hub.dispatch('api', payload, 'PubSub', AMPLIFY_SYMBOL);
@@ -210,7 +210,7 @@ export class AWSAppSyncRealTimeProvider {
210
210
  observer.complete();
211
211
  } else {
212
212
  let subscriptionStartActive = false;
213
- const subscriptionId = uuid();
213
+ const subscriptionId = amplifyUuid();
214
214
  const startSubscription = () => {
215
215
  if (!subscriptionStartActive) {
216
216
  subscriptionStartActive = true;
@@ -968,7 +968,7 @@ export class AWSAppSyncRealTimeProvider {
968
968
  {
969
969
  headers: request.headers,
970
970
  method: request.method,
971
- url: new URL(request.url),
971
+ url: new AmplifyUrl(request.url),
972
972
  body: request.data,
973
973
  },
974
974
  {
@@ -1,5 +1,7 @@
1
1
  // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
+ import { resolveOwnerFields } from '../utils/resolveOwnerFields';
4
+
3
5
  type ListArgs = { selectionSet?: string[]; filter?: {} };
4
6
 
5
7
  const connectionType = {
@@ -152,6 +154,9 @@ export const graphQLOperationsInfo = {
152
154
  UPDATE: { operationPrefix: 'update' as const, usePlural: false },
153
155
  DELETE: { operationPrefix: 'delete' as const, usePlural: false },
154
156
  LIST: { operationPrefix: 'list' as const, usePlural: true },
157
+ ONCREATE: { operationPrefix: 'onCreate' as const, usePlural: false },
158
+ ONUPDATE: { operationPrefix: 'onUpdate' as const, usePlural: false },
159
+ ONDELETE: { operationPrefix: 'onDelete' as const, usePlural: false },
155
160
  };
156
161
  export type ModelOperation = keyof typeof graphQLOperationsInfo;
157
162
 
@@ -162,10 +167,18 @@ const graphQLDocumentsCache = new Map<string, Map<ModelOperation, string>>();
162
167
  const SELECTION_SET_ALL_NESTED = '*';
163
168
 
164
169
  function defaultSelectionSetForModel(modelDefinition: any): string[] {
170
+ // fields that are explicitly part of the graphql schema; not
171
+ // inferred from owner auth rules.
165
172
  const { fields } = modelDefinition;
166
- return Object.values<any>(fields)
173
+ const explicitFields = Object.values<any>(fields)
167
174
  .map(({ type, name }) => typeof type === 'string' && name) // Default selection set omits model fields
168
175
  .filter(Boolean);
176
+
177
+ // fields used for owner auth rules that may or may not also
178
+ // be explicit on the model.
179
+ const ownerFields = resolveOwnerFields(modelDefinition);
180
+
181
+ return Array.from(new Set(explicitFields.concat(ownerFields)));
169
182
  }
170
183
 
171
184
  const FIELD_IR = '';
@@ -365,7 +378,7 @@ export function generateGraphQLDocument(
365
378
  }
366
379
 
367
380
  const graphQLFieldName = `${operationPrefix}${usePlural ? pluralName : name}`;
368
- let graphQLOperationType: 'mutation' | 'query' | undefined;
381
+ let graphQLOperationType: 'mutation' | 'query' | 'subscription' | undefined;
369
382
  let graphQLSelectionSet: string | undefined;
370
383
  let graphQLArguments: Record<string, any> | undefined;
371
384
 
@@ -410,6 +423,15 @@ export function generateGraphQLDocument(
410
423
  graphQLOperationType ?? (graphQLOperationType = 'query');
411
424
  graphQLSelectionSet ??
412
425
  (graphQLSelectionSet = `items { ${selectionSetFields} }`);
426
+ case 'ONCREATE':
427
+ case 'ONUPDATE':
428
+ case 'ONDELETE':
429
+ graphQLArguments ??
430
+ (graphQLArguments = {
431
+ filter: `ModelSubscription${name}FilterInput`,
432
+ });
433
+ graphQLOperationType ?? (graphQLOperationType = 'subscription');
434
+ graphQLSelectionSet ?? (graphQLSelectionSet = selectionSetFields);
413
435
  }
414
436
 
415
437
  const graphQLDocument = `${graphQLOperationType}${
@@ -488,6 +510,9 @@ export function buildGraphQLVariables(
488
510
  }
489
511
  break;
490
512
  case 'LIST':
513
+ case 'ONCREATE':
514
+ case 'ONUPDATE':
515
+ case 'ONDELETE':
491
516
  if (arg?.filter) {
492
517
  variables = { filter: arg.filter };
493
518
  }
@@ -9,12 +9,12 @@ import {
9
9
  OperationTypeNode,
10
10
  } from 'graphql';
11
11
  import { Observable } from 'rxjs';
12
- import { AmplifyClassV6 } from '@aws-amplify/core';
12
+ import { AmplifyClassV6, ConsoleLogger } from '@aws-amplify/core';
13
13
  import {
14
14
  GraphQLAuthMode,
15
15
  CustomUserAgentDetails,
16
- ConsoleLogger as Logger,
17
16
  getAmplifyUserAgent,
17
+ AmplifyUrl,
18
18
  } from '@aws-amplify/core/internals/utils';
19
19
  import {
20
20
  GraphQLAuthError,
@@ -33,7 +33,7 @@ import { resolveConfig, resolveLibraryOptions } from '../utils';
33
33
 
34
34
  const USER_AGENT_HEADER = 'x-amz-user-agent';
35
35
 
36
- const logger = new Logger('GraphQLAPI');
36
+ const logger = new ConsoleLogger('GraphQLAPI');
37
37
 
38
38
  export const graphqlOperation = (
39
39
  query,
@@ -304,7 +304,7 @@ export class InternalGraphQLAPIClass {
304
304
  let response;
305
305
  try {
306
306
  const { body: responseBody } = await this._api.post({
307
- url: new URL(endpoint),
307
+ url: new AmplifyUrl(endpoint),
308
308
  options: {
309
309
  headers,
310
310
  body,
@@ -10,7 +10,8 @@ import {
10
10
  flattenItems,
11
11
  } from './APIClient';
12
12
  import { ClientGenerationParams } from './types';
13
- import { V6Client } from '../types';
13
+ import { V6Client, GraphqlSubscriptionResult } from '../types';
14
+ import { Observable, map } from 'rxjs';
14
15
 
15
16
  export function generateModelsProperty<T extends Record<any, any> = never>(
16
17
  client: V6Client,
@@ -102,6 +103,32 @@ export function generateModelsProperty<T extends Record<any, any> = never>(
102
103
  }
103
104
  }
104
105
  };
106
+ } else if (['ONCREATE', 'ONUPDATE', 'ONDELETE'].includes(operation)) {
107
+ models[name][operationPrefix] = (arg?: any, options?: any) => {
108
+ const query = generateGraphQLDocument(
109
+ modelIntrospection.models,
110
+ name,
111
+ operation
112
+ );
113
+ const variables = buildGraphQLVariables(
114
+ model,
115
+ operation,
116
+ arg,
117
+ modelIntrospection
118
+ );
119
+
120
+ const observable = client.graphql({
121
+ query,
122
+ variables,
123
+ }) as GraphqlSubscriptionResult<object>;
124
+
125
+ return observable.pipe(
126
+ map(value => {
127
+ const [key] = Object.keys(value.data);
128
+ return value.data[key];
129
+ })
130
+ );
131
+ };
105
132
  } else {
106
133
  models[name][operationPrefix] = async (arg?: any, options?: any) => {
107
134
  const query = generateGraphQLDocument(
@@ -0,0 +1,65 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { ResourcesConfig } from '@aws-amplify/core';
4
+
5
+ type GraphQLConfig = Exclude<ResourcesConfig['API'], undefined>['GraphQL'];
6
+ type ModelIntrospectionSchema = Exclude<
7
+ Exclude<GraphQLConfig, undefined>['modelIntrospection'],
8
+ undefined
9
+ >;
10
+ type Model = ModelIntrospectionSchema['models'][string];
11
+
12
+ type AuthAttribute = {
13
+ type: 'auth';
14
+ properties: {
15
+ rules: AuthRule[];
16
+ };
17
+ };
18
+
19
+ /**
20
+ * Only the portions of an Auth rule we care about.
21
+ */
22
+ type AuthRule = {
23
+ allow: string;
24
+ ownerField?: string;
25
+ };
26
+
27
+ /**
28
+ * Given an introspection schema model, returns all owner fields.
29
+ *
30
+ * @param model Model from an introspection schema
31
+ * @returns List of owner field names
32
+ */
33
+ export function resolveOwnerFields(model: Model): string[] {
34
+ const ownerFields = new Set<string>();
35
+ for (const attr of model.attributes || []) {
36
+ if (isAuthAttribute(attr)) {
37
+ for (const rule of attr.properties.rules) {
38
+ if (rule.allow === 'owner') {
39
+ ownerFields.add(rule.ownerField || 'owner');
40
+ }
41
+ }
42
+ }
43
+ }
44
+ return Array.from(ownerFields);
45
+ }
46
+
47
+ /**
48
+ * Type guard that identifies an auth attribute with an attached rules list that
49
+ * specifies an `allow` attribute at a minimum.
50
+ *
51
+ * @param attribute Any object. Ideally a model introspection schema model attribute
52
+ * @returns True if given object is an auth attribute
53
+ */
54
+ function isAuthAttribute(attribute: any): attribute is AuthAttribute {
55
+ if (attribute?.type === 'auth') {
56
+ if (typeof attribute?.properties === 'object') {
57
+ if (Array.isArray(attribute?.properties?.rules)) {
58
+ return (attribute?.properties?.rules as Array<any>).every(
59
+ rule => !!rule.allow
60
+ );
61
+ }
62
+ }
63
+ }
64
+ return false;
65
+ }