@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.
- package/lib/Providers/AWSAppSyncRealTimeProvider/index.js +3 -4
- package/lib/internals/APIClient.d.ts +12 -0
- package/lib/internals/APIClient.js +24 -1
- package/lib/internals/InternalGraphQLAPI.js +3 -2
- package/lib/internals/generateModelsProperty.js +15 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/utils/resolveOwnerFields.d.ts +12 -0
- package/lib/utils/resolveOwnerFields.js +63 -0
- package/lib-esm/Providers/AWSAppSyncRealTimeProvider/index.js +5 -6
- package/lib-esm/internals/APIClient.d.ts +12 -0
- package/lib-esm/internals/APIClient.js +24 -1
- package/lib-esm/internals/InternalGraphQLAPI.js +4 -3
- package/lib-esm/internals/generateModelsProperty.js +15 -0
- package/lib-esm/tsconfig.tsbuildinfo +1 -1
- package/lib-esm/utils/resolveOwnerFields.d.ts +12 -0
- package/lib-esm/utils/resolveOwnerFields.js +59 -0
- package/package.json +6 -7
- package/src/Providers/AWSAppSyncRealTimeProvider/index.ts +6 -6
- package/src/internals/APIClient.ts +27 -2
- package/src/internals/InternalGraphQLAPI.ts +4 -4
- package/src/internals/generateModelsProperty.ts +28 -1
- package/src/utils/resolveOwnerFields.ts +65 -0
|
@@ -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.
|
|
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.
|
|
56
|
-
"@aws-amplify/auth": "6.0.1-api-v6-models.
|
|
57
|
-
"@aws-amplify/core": "6.0.1-api-v6-models.
|
|
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": "
|
|
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
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
+
}
|