@aws-amplify/api-graphql 4.0.1-api-v6-models.9351bcf.0 → 4.0.1-api-v6-models.58f2536.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/internals/server/package.json +8 -0
- package/lib/GraphQLAPI.d.ts +1 -1
- package/lib/GraphQLAPI.js +23 -28
- package/lib/Providers/AWSAppSyncRealTimeProvider/index.js +467 -582
- package/lib/index.js +1 -1
- package/lib/internals/APIClient.d.ts +16 -1
- package/lib/internals/APIClient.js +232 -206
- package/lib/internals/InternalGraphQLAPI.d.ts +1 -1
- package/lib/internals/InternalGraphQLAPI.js +205 -247
- package/lib/internals/generateClient.js +14 -13
- package/lib/internals/generateModelsProperty.js +19 -312
- package/lib/internals/operations/get.d.ts +2 -0
- package/lib/internals/operations/get.js +59 -0
- package/lib/internals/operations/list.d.ts +2 -0
- package/lib/internals/operations/list.js +71 -0
- package/lib/internals/operations/observeQuery.d.ts +2 -0
- package/lib/internals/operations/observeQuery.js +119 -0
- package/lib/internals/operations/subscription.d.ts +1 -0
- package/lib/internals/operations/subscription.js +27 -0
- package/lib/internals/server/generateClient.d.ts +11 -0
- package/lib/internals/server/generateClient.js +30 -0
- package/lib/internals/server/generateModelsProperty.d.ts +3 -0
- package/lib/internals/server/generateModelsProperty.js +45 -0
- package/lib/internals/server/index.d.ts +1 -0
- package/lib/internals/server/index.js +7 -0
- package/lib/internals/v6.js +3 -3
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types/index.d.ts +36 -4
- package/lib/utils/ConnectionStateMonitor.js +51 -64
- package/lib/utils/ReachabilityMonitor/index.js +2 -2
- package/lib/utils/ReachabilityMonitor/index.native.js +4 -6
- package/lib/utils/ReconnectionMonitor.js +20 -24
- package/lib/utils/errors/APIError.js +7 -11
- package/lib/utils/errors/assertValidationError.js +4 -4
- package/lib/utils/errors/validation.js +5 -6
- package/lib/utils/findIndexByFields.js +4 -9
- package/lib/utils/resolveConfig.js +9 -10
- package/lib/utils/resolveLibraryOptions.js +4 -5
- package/lib/utils/resolveOwnerFields.js +10 -33
- package/lib/utils/resolvePKFields.js +2 -3
- package/lib-esm/GraphQLAPI.d.ts +1 -1
- package/lib-esm/GraphQLAPI.js +23 -29
- package/lib-esm/Providers/AWSAppSyncRealTimeProvider/index.js +459 -575
- package/lib-esm/Providers/constants.js +10 -10
- package/lib-esm/internals/APIClient.d.ts +16 -1
- package/lib-esm/internals/APIClient.js +230 -205
- package/lib-esm/internals/InternalGraphQLAPI.d.ts +1 -1
- package/lib-esm/internals/InternalGraphQLAPI.js +201 -244
- package/lib-esm/internals/generateClient.js +11 -10
- package/lib-esm/internals/generateModelsProperty.js +19 -312
- package/lib-esm/internals/operations/get.d.ts +2 -0
- package/lib-esm/internals/operations/get.js +55 -0
- package/lib-esm/internals/operations/list.d.ts +2 -0
- package/lib-esm/internals/operations/list.js +67 -0
- package/lib-esm/internals/operations/observeQuery.d.ts +2 -0
- package/lib-esm/internals/operations/observeQuery.js +115 -0
- package/lib-esm/internals/operations/subscription.d.ts +1 -0
- package/lib-esm/internals/operations/subscription.js +23 -0
- package/lib-esm/internals/server/generateClient.d.ts +11 -0
- package/lib-esm/internals/server/generateClient.js +26 -0
- package/lib-esm/internals/server/generateModelsProperty.d.ts +3 -0
- package/lib-esm/internals/server/generateModelsProperty.js +41 -0
- package/lib-esm/internals/server/index.d.ts +1 -0
- package/lib-esm/internals/server/index.js +3 -0
- package/lib-esm/internals/v6.js +1 -1
- package/lib-esm/tsconfig.tsbuildinfo +1 -1
- package/lib-esm/types/index.d.ts +36 -4
- package/lib-esm/types/index.js +3 -3
- package/lib-esm/utils/ConnectionStateMonitor.js +49 -63
- package/lib-esm/utils/ReachabilityMonitor/index.js +1 -1
- package/lib-esm/utils/ReachabilityMonitor/index.native.js +1 -3
- package/lib-esm/utils/ReconnectionMonitor.js +19 -24
- package/lib-esm/utils/errors/APIError.js +6 -11
- package/lib-esm/utils/errors/assertValidationError.js +2 -2
- package/lib-esm/utils/errors/validation.js +5 -6
- package/lib-esm/utils/findIndexByFields.js +4 -9
- package/lib-esm/utils/resolveConfig.js +8 -9
- package/lib-esm/utils/resolveLibraryOptions.js +4 -5
- package/lib-esm/utils/resolveOwnerFields.js +10 -33
- package/lib-esm/utils/resolvePKFields.js +2 -3
- package/package.json +8 -7
- package/src/GraphQLAPI.ts +6 -2
- package/src/Providers/AWSAppSyncRealTimeProvider/index.ts +6 -5
- package/src/internals/APIClient.ts +122 -35
- package/src/internals/InternalGraphQLAPI.ts +35 -10
- package/src/internals/generateClient.ts +0 -1
- package/src/internals/generateModelsProperty.ts +27 -340
- package/src/internals/operations/get.ts +121 -0
- package/src/internals/operations/list.ts +111 -0
- package/src/internals/operations/observeQuery.ts +140 -0
- package/src/internals/operations/subscription.ts +59 -0
- package/src/internals/server/generateClient.ts +45 -0
- package/src/internals/server/generateModelsProperty.ts +70 -0
- package/src/internals/server/index.ts +4 -0
- package/src/types/index.ts +65 -9
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { resolveOwnerFields } from '../utils/resolveOwnerFields';
|
|
4
4
|
import { GraphQLAuthMode } from '@aws-amplify/core/internals/utils';
|
|
5
|
+
import { V6Client, __authMode, __authToken } from '../types';
|
|
6
|
+
import { AmplifyServer } from '@aws-amplify/core/internals/adapter-core';
|
|
5
7
|
|
|
6
8
|
type ListArgs = { selectionSet?: string[]; filter?: {} };
|
|
7
9
|
|
|
@@ -49,7 +51,8 @@ export function initializeModel(
|
|
|
49
51
|
result: any[],
|
|
50
52
|
modelIntrospection: any,
|
|
51
53
|
authMode: GraphQLAuthMode | undefined,
|
|
52
|
-
authToken: string | undefined
|
|
54
|
+
authToken: string | undefined,
|
|
55
|
+
context = false
|
|
53
56
|
): any[] {
|
|
54
57
|
const introModel = modelIntrospection.models[modelName];
|
|
55
58
|
const introModelFields = introModel.fields;
|
|
@@ -91,21 +94,45 @@ export function initializeModel(
|
|
|
91
94
|
{}
|
|
92
95
|
);
|
|
93
96
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
97
|
+
if (context) {
|
|
98
|
+
initializedRelationalFields[field] = (
|
|
99
|
+
contextSpec: AmplifyServer.ContextSpec,
|
|
100
|
+
options?: LazyLoadOptions
|
|
101
|
+
) => {
|
|
102
|
+
if (record[targetNames[0]]) {
|
|
103
|
+
return client.models[relatedModelName].get(
|
|
104
|
+
contextSpec,
|
|
105
|
+
{
|
|
106
|
+
[relatedModelPKFieldName]: record[targetNames[0]],
|
|
107
|
+
...sortKeyValues,
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
authMode: options?.authMode || authMode,
|
|
111
|
+
authToken: options?.authToken || authToken,
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
return undefined;
|
|
116
|
+
};
|
|
117
|
+
} else {
|
|
118
|
+
initializedRelationalFields[field] = (
|
|
119
|
+
options?: LazyLoadOptions
|
|
120
|
+
) => {
|
|
121
|
+
if (record[targetNames[0]]) {
|
|
122
|
+
return client.models[relatedModelName].get(
|
|
123
|
+
{
|
|
124
|
+
[relatedModelPKFieldName]: record[targetNames[0]],
|
|
125
|
+
...sortKeyValues,
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
authMode: options?.authMode || authMode,
|
|
129
|
+
authToken: options?.authToken || authToken,
|
|
130
|
+
}
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
return undefined;
|
|
134
|
+
};
|
|
135
|
+
}
|
|
109
136
|
|
|
110
137
|
break;
|
|
111
138
|
case connectionType.HAS_MANY:
|
|
@@ -125,6 +152,61 @@ export function initializeModel(
|
|
|
125
152
|
return { [field]: { eq: record[parentSK[idx - 1]] } };
|
|
126
153
|
});
|
|
127
154
|
|
|
155
|
+
if (context) {
|
|
156
|
+
initializedRelationalFields[field] = (
|
|
157
|
+
contextSpec: AmplifyServer.ContextSpec,
|
|
158
|
+
options?: LazyLoadOptions
|
|
159
|
+
) => {
|
|
160
|
+
if (record[parentPk]) {
|
|
161
|
+
return client.models[relatedModelName].list(contextSpec, {
|
|
162
|
+
filter: { and: hasManyFilter },
|
|
163
|
+
authMode: options?.authMode || authMode,
|
|
164
|
+
authToken: options?.authToken || authToken,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
return [];
|
|
168
|
+
};
|
|
169
|
+
} else {
|
|
170
|
+
initializedRelationalFields[field] = (
|
|
171
|
+
options?: LazyLoadOptions
|
|
172
|
+
) => {
|
|
173
|
+
if (record[parentPk]) {
|
|
174
|
+
return client.models[relatedModelName].list({
|
|
175
|
+
filter: { and: hasManyFilter },
|
|
176
|
+
authMode: options?.authMode || authMode,
|
|
177
|
+
authToken: options?.authToken || authToken,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
return [];
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const hasManyFilter = connectionFields.map((field, idx) => {
|
|
188
|
+
if (idx === 0) {
|
|
189
|
+
return { [field]: { eq: record[parentPk] } };
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return { [field]: { eq: record[parentSK[idx - 1]] } };
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
if (context) {
|
|
196
|
+
initializedRelationalFields[field] = (
|
|
197
|
+
contextSpec: AmplifyServer.ContextSpec,
|
|
198
|
+
options?: LazyLoadOptions
|
|
199
|
+
) => {
|
|
200
|
+
if (record[parentPk]) {
|
|
201
|
+
return client.models[relatedModelName].list(contextSpec, {
|
|
202
|
+
filter: { and: hasManyFilter },
|
|
203
|
+
authMode: options?.authMode || authMode,
|
|
204
|
+
authToken: options?.authToken || authToken,
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
return [];
|
|
208
|
+
};
|
|
209
|
+
} else {
|
|
128
210
|
initializedRelationalFields[field] = (
|
|
129
211
|
options?: LazyLoadOptions
|
|
130
212
|
) => {
|
|
@@ -137,27 +219,8 @@ export function initializeModel(
|
|
|
137
219
|
}
|
|
138
220
|
return [];
|
|
139
221
|
};
|
|
140
|
-
break;
|
|
141
222
|
}
|
|
142
223
|
|
|
143
|
-
const hasManyFilter = connectionFields.map((field, idx) => {
|
|
144
|
-
if (idx === 0) {
|
|
145
|
-
return { [field]: { eq: record[parentPk] } };
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return { [field]: { eq: record[parentSK[idx - 1]] } };
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
initializedRelationalFields[field] = (options?: LazyLoadOptions) => {
|
|
152
|
-
if (record[parentPk]) {
|
|
153
|
-
return client.models[relatedModelName].list({
|
|
154
|
-
filter: { and: hasManyFilter },
|
|
155
|
-
authMode: options?.authMode || authMode,
|
|
156
|
-
authToken: options?.authToken || authToken,
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
return [];
|
|
160
|
-
};
|
|
161
224
|
break;
|
|
162
225
|
default:
|
|
163
226
|
break;
|
|
@@ -622,3 +685,27 @@ export function normalizeMutationInput(
|
|
|
622
685
|
|
|
623
686
|
return normalized;
|
|
624
687
|
}
|
|
688
|
+
|
|
689
|
+
type AuthModeParams = {
|
|
690
|
+
authMode?: GraphQLAuthMode;
|
|
691
|
+
authToken?: string;
|
|
692
|
+
};
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* Produces a parameter object that can contains auth mode/token overrides
|
|
696
|
+
* only if present in either `options` (first) or configured on the `client`
|
|
697
|
+
* as a fallback.
|
|
698
|
+
*
|
|
699
|
+
* @param client Configured client from `generateClient`
|
|
700
|
+
* @param options Args/Options obect from call site.
|
|
701
|
+
* @returns
|
|
702
|
+
*/
|
|
703
|
+
export function authModeParams(
|
|
704
|
+
client: V6Client,
|
|
705
|
+
options: AuthModeParams = {}
|
|
706
|
+
): AuthModeParams {
|
|
707
|
+
return {
|
|
708
|
+
authMode: options.authMode || client[__authMode],
|
|
709
|
+
authToken: options.authToken || client[__authToken],
|
|
710
|
+
};
|
|
711
|
+
}
|
|
@@ -45,6 +45,10 @@ export const graphqlOperation = (
|
|
|
45
45
|
authToken,
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
+
const isAmplifyInstance = (amplify): amplify is AmplifyClassV6 => {
|
|
49
|
+
return typeof amplify !== 'function';
|
|
50
|
+
};
|
|
51
|
+
|
|
48
52
|
/**
|
|
49
53
|
* Export Cloud Logic APIs
|
|
50
54
|
*/
|
|
@@ -163,7 +167,9 @@ export class InternalGraphQLAPIClass {
|
|
|
163
167
|
* @returns An Observable if the query is a subscription query, else a promise of the graphql result.
|
|
164
168
|
*/
|
|
165
169
|
graphql<T = any>(
|
|
166
|
-
amplify:
|
|
170
|
+
amplify:
|
|
171
|
+
| AmplifyClassV6
|
|
172
|
+
| ((fn: (amplify: any) => Promise<any>) => Promise<AmplifyClassV6>),
|
|
167
173
|
{ query: paramQuery, variables = {}, authMode, authToken }: GraphQLOptions,
|
|
168
174
|
additionalHeaders?: { [key: string]: string },
|
|
169
175
|
customUserAgentDetails?: CustomUserAgentDetails
|
|
@@ -190,13 +196,32 @@ export class InternalGraphQLAPIClass {
|
|
|
190
196
|
case 'query':
|
|
191
197
|
case 'mutation':
|
|
192
198
|
const abortController = new AbortController();
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
199
|
+
|
|
200
|
+
let responsePromise: Promise<GraphQLResult<T>>;
|
|
201
|
+
|
|
202
|
+
if (isAmplifyInstance(amplify)) {
|
|
203
|
+
responsePromise = this._graphql<T>(
|
|
204
|
+
amplify,
|
|
205
|
+
{ query, variables, authMode },
|
|
206
|
+
headers,
|
|
207
|
+
abortController,
|
|
208
|
+
customUserAgentDetails
|
|
209
|
+
);
|
|
210
|
+
} else {
|
|
211
|
+
const wrapper = amplifyInstance =>
|
|
212
|
+
this._graphql<T>(
|
|
213
|
+
amplifyInstance,
|
|
214
|
+
{ query, variables, authMode },
|
|
215
|
+
headers,
|
|
216
|
+
abortController,
|
|
217
|
+
customUserAgentDetails
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
responsePromise = amplify(wrapper) as unknown as Promise<
|
|
221
|
+
GraphQLResult<T>
|
|
222
|
+
>;
|
|
223
|
+
}
|
|
224
|
+
|
|
200
225
|
this._api.updateRequestToBeCancellable(
|
|
201
226
|
responsePromise,
|
|
202
227
|
abortController
|
|
@@ -204,7 +229,7 @@ export class InternalGraphQLAPIClass {
|
|
|
204
229
|
return responsePromise;
|
|
205
230
|
case 'subscription':
|
|
206
231
|
return this._graphqlSubscribe(
|
|
207
|
-
amplify,
|
|
232
|
+
amplify as AmplifyClassV6,
|
|
208
233
|
{ query, variables, authMode },
|
|
209
234
|
headers,
|
|
210
235
|
customUserAgentDetails
|
|
@@ -321,7 +346,7 @@ export class InternalGraphQLAPIClass {
|
|
|
321
346
|
// If the exception is because user intentionally
|
|
322
347
|
// cancelled the request, do not modify the exception
|
|
323
348
|
// so that clients can identify the exception correctly.
|
|
324
|
-
if (this.
|
|
349
|
+
if (this.isCancelError(err)) {
|
|
325
350
|
throw err;
|
|
326
351
|
}
|
|
327
352
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
import { AmplifyClassV6 } from '@aws-amplify/core';
|
|
4
3
|
import { graphql, cancel, isCancelError } from './v6';
|
|
5
4
|
import { generateModelsProperty } from './generateModelsProperty';
|
|
6
5
|
import { V6Client, __amplify, __authMode, __authToken } from '../types';
|
|
@@ -1,48 +1,14 @@
|
|
|
1
1
|
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { ModelTypes } from '@aws-amplify/amplify-api-next-types-alpha';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
initializeModel,
|
|
7
|
-
generateGraphQLDocument,
|
|
8
|
-
buildGraphQLVariables,
|
|
9
|
-
graphQLOperationsInfo,
|
|
10
|
-
ModelOperation,
|
|
11
|
-
flattenItems,
|
|
12
|
-
} from './APIClient';
|
|
4
|
+
import { graphQLOperationsInfo, ModelOperation } from './APIClient';
|
|
13
5
|
import { ClientGenerationParams } from './types';
|
|
14
|
-
import {
|
|
15
|
-
V6Client,
|
|
16
|
-
GraphqlSubscriptionResult,
|
|
17
|
-
__authMode,
|
|
18
|
-
__authToken,
|
|
19
|
-
} from '../types';
|
|
20
|
-
import { findIndexByFields, resolvePKFields } from '../utils';
|
|
21
|
-
import { Observable, map } from 'rxjs';
|
|
6
|
+
import { V6Client, __authMode, __authToken } from '../types';
|
|
22
7
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Produces a parameter object that can contains auth mode/token overrides
|
|
30
|
-
* only if present in either `options` (first) or configured on the `client`
|
|
31
|
-
* as a fallback.
|
|
32
|
-
*
|
|
33
|
-
* @param client Configured client from `generateClient`
|
|
34
|
-
* @param options Args/Options obect from call site.
|
|
35
|
-
* @returns
|
|
36
|
-
*/
|
|
37
|
-
function authModeParams(
|
|
38
|
-
client: V6Client,
|
|
39
|
-
options: AuthModeParams = {}
|
|
40
|
-
): AuthModeParams {
|
|
41
|
-
return {
|
|
42
|
-
authMode: options.authMode || client[__authMode],
|
|
43
|
-
authToken: options.authToken || client[__authToken],
|
|
44
|
-
};
|
|
45
|
-
}
|
|
8
|
+
import { listFactory } from './operations/list';
|
|
9
|
+
import { getFactory } from './operations/get';
|
|
10
|
+
import { subscriptionFactory } from './operations/subscription';
|
|
11
|
+
import { observeQueryFactory } from './operations/observeQuery';
|
|
46
12
|
|
|
47
13
|
export function generateModelsProperty<T extends Record<any, any> = never>(
|
|
48
14
|
client: V6Client,
|
|
@@ -56,8 +22,8 @@ export function generateModelsProperty<T extends Record<any, any> = never>(
|
|
|
56
22
|
return {} as any;
|
|
57
23
|
}
|
|
58
24
|
|
|
59
|
-
|
|
60
|
-
|
|
25
|
+
const SUBSCRIPTION_OPS = ['ONCREATE', 'ONUPDATE', 'ONDELETE'];
|
|
26
|
+
|
|
61
27
|
for (const model of Object.values(modelIntrospection.models)) {
|
|
62
28
|
const { name } = model as any;
|
|
63
29
|
|
|
@@ -68,306 +34,27 @@ export function generateModelsProperty<T extends Record<any, any> = never>(
|
|
|
68
34
|
const operation = key as ModelOperation;
|
|
69
35
|
|
|
70
36
|
if (operation === 'LIST') {
|
|
71
|
-
models[name][operationPrefix] =
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
try {
|
|
86
|
-
const auth = authModeParams(client, args);
|
|
87
|
-
|
|
88
|
-
const { data, extensions } = (await client.graphql({
|
|
89
|
-
...auth,
|
|
90
|
-
query,
|
|
91
|
-
variables,
|
|
92
|
-
})) as any;
|
|
93
|
-
|
|
94
|
-
// flatten response
|
|
95
|
-
if (data !== undefined) {
|
|
96
|
-
const [key] = Object.keys(data);
|
|
97
|
-
|
|
98
|
-
if (data[key].items) {
|
|
99
|
-
const flattenedResult = flattenItems(data)[key];
|
|
100
|
-
|
|
101
|
-
// don't init if custom selection set
|
|
102
|
-
if (args?.selectionSet) {
|
|
103
|
-
return {
|
|
104
|
-
data: flattenedResult,
|
|
105
|
-
nextToken: data[key].nextToken,
|
|
106
|
-
extensions,
|
|
107
|
-
};
|
|
108
|
-
} else {
|
|
109
|
-
const initialized = initializeModel(
|
|
110
|
-
client,
|
|
111
|
-
name,
|
|
112
|
-
flattenedResult,
|
|
113
|
-
modelIntrospection,
|
|
114
|
-
auth.authMode,
|
|
115
|
-
auth.authToken
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
return {
|
|
119
|
-
data: initialized,
|
|
120
|
-
nextToken: data[key].nextToken,
|
|
121
|
-
extensions,
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return {
|
|
127
|
-
data: data[key],
|
|
128
|
-
nextToken: data[key].nextToken,
|
|
129
|
-
extensions,
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
} catch (error) {
|
|
133
|
-
if (error.errors) {
|
|
134
|
-
// graphql errors pass through
|
|
135
|
-
return error as any;
|
|
136
|
-
} else {
|
|
137
|
-
// non-graphql errors re re-thrown
|
|
138
|
-
throw error;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
} else if (['ONCREATE', 'ONUPDATE', 'ONDELETE'].includes(operation)) {
|
|
143
|
-
models[name][operationPrefix] = (args?: any) => {
|
|
144
|
-
const query = generateGraphQLDocument(
|
|
145
|
-
modelIntrospection.models,
|
|
146
|
-
name,
|
|
147
|
-
operation
|
|
148
|
-
);
|
|
149
|
-
const variables = buildGraphQLVariables(
|
|
150
|
-
model,
|
|
151
|
-
operation,
|
|
152
|
-
args,
|
|
153
|
-
modelIntrospection
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
const auth = authModeParams(client, args);
|
|
157
|
-
|
|
158
|
-
const observable = client.graphql({
|
|
159
|
-
...auth,
|
|
160
|
-
query,
|
|
161
|
-
variables,
|
|
162
|
-
}) as GraphqlSubscriptionResult<object>;
|
|
163
|
-
|
|
164
|
-
return observable.pipe(
|
|
165
|
-
map(value => {
|
|
166
|
-
const [key] = Object.keys(value.data);
|
|
167
|
-
const [initialized] = initializeModel(
|
|
168
|
-
client,
|
|
169
|
-
name,
|
|
170
|
-
[value.data[key]],
|
|
171
|
-
modelIntrospection,
|
|
172
|
-
auth.authMode,
|
|
173
|
-
auth.authToken
|
|
174
|
-
);
|
|
175
|
-
return initialized;
|
|
176
|
-
})
|
|
177
|
-
);
|
|
178
|
-
};
|
|
37
|
+
models[name][operationPrefix] = listFactory(
|
|
38
|
+
client,
|
|
39
|
+
modelIntrospection,
|
|
40
|
+
model
|
|
41
|
+
);
|
|
42
|
+
} else if (SUBSCRIPTION_OPS.includes(operation)) {
|
|
43
|
+
models[name][operationPrefix] = subscriptionFactory(
|
|
44
|
+
client,
|
|
45
|
+
modelIntrospection,
|
|
46
|
+
model,
|
|
47
|
+
operation
|
|
48
|
+
);
|
|
179
49
|
} else if (operation === 'OBSERVE_QUERY') {
|
|
180
|
-
models[name][operationPrefix] = (
|
|
181
|
-
new Observable(subscriber => {
|
|
182
|
-
// what we'll be sending to our subscribers
|
|
183
|
-
const items: object[] = [];
|
|
184
|
-
|
|
185
|
-
// To enqueue subscription messages while we collect our initial
|
|
186
|
-
// result set.
|
|
187
|
-
const messageQueue = [] as {
|
|
188
|
-
type: 'create' | 'update' | 'delete';
|
|
189
|
-
item: object;
|
|
190
|
-
}[];
|
|
191
|
-
|
|
192
|
-
// operation to take when message(s) arrive.
|
|
193
|
-
// this operation will be swapped out once initial "sync" is complete
|
|
194
|
-
// to immediately ingest messsages.
|
|
195
|
-
let receiveMessages = (...messages: typeof messageQueue) => {
|
|
196
|
-
return messageQueue.push(...messages);
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
// start subscriptions
|
|
200
|
-
const onCreateSub = models[name].onCreate(arg).subscribe({
|
|
201
|
-
next(item) {
|
|
202
|
-
receiveMessages({ item, type: 'create' });
|
|
203
|
-
},
|
|
204
|
-
error(error) {
|
|
205
|
-
subscriber.error({ type: 'onCreate', error });
|
|
206
|
-
},
|
|
207
|
-
});
|
|
208
|
-
const onUpdateSub = models[name].onUpdate(arg).subscribe({
|
|
209
|
-
next(item) {
|
|
210
|
-
receiveMessages({ item, type: 'update' });
|
|
211
|
-
},
|
|
212
|
-
error(error) {
|
|
213
|
-
subscriber.error({ type: 'onUpdate', error });
|
|
214
|
-
},
|
|
215
|
-
});
|
|
216
|
-
const onDeleteSub = models[name].onDelete(arg).subscribe({
|
|
217
|
-
next(item) {
|
|
218
|
-
receiveMessages({ item, type: 'delete' });
|
|
219
|
-
},
|
|
220
|
-
error(error) {
|
|
221
|
-
subscriber.error({ type: 'onDelete', error });
|
|
222
|
-
},
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
// consumes a list of messages and sends a snapshot
|
|
226
|
-
function ingestMessages(messages: typeof messageQueue) {
|
|
227
|
-
for (const message of messages) {
|
|
228
|
-
const idx = findIndexByFields(
|
|
229
|
-
message.item,
|
|
230
|
-
items,
|
|
231
|
-
pkFields as any
|
|
232
|
-
);
|
|
233
|
-
switch (message.type) {
|
|
234
|
-
case 'create':
|
|
235
|
-
if (idx < 0) items.push(message.item);
|
|
236
|
-
break;
|
|
237
|
-
case 'update':
|
|
238
|
-
if (idx >= 0) items[idx] = message.item;
|
|
239
|
-
break;
|
|
240
|
-
case 'delete':
|
|
241
|
-
if (idx >= 0) items.splice(idx, 1);
|
|
242
|
-
break;
|
|
243
|
-
default:
|
|
244
|
-
console.error(
|
|
245
|
-
'Unrecognized message in observeQuery.',
|
|
246
|
-
message
|
|
247
|
-
);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
subscriber.next({
|
|
251
|
-
items,
|
|
252
|
-
isSynced: true,
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
const pkFields = resolvePKFields(model);
|
|
257
|
-
|
|
258
|
-
// initial results
|
|
259
|
-
(async () => {
|
|
260
|
-
let firstPage = true;
|
|
261
|
-
let nextToken: string | null = null;
|
|
262
|
-
while (!subscriber.closed && (firstPage || nextToken)) {
|
|
263
|
-
firstPage = false;
|
|
264
|
-
|
|
265
|
-
const {
|
|
266
|
-
data: page,
|
|
267
|
-
errors,
|
|
268
|
-
nextToken: _nextToken,
|
|
269
|
-
} = await models[name].list({ ...arg, nextToken });
|
|
270
|
-
nextToken = _nextToken;
|
|
271
|
-
|
|
272
|
-
items.push(...page);
|
|
273
|
-
|
|
274
|
-
// if there are no more pages and no items we already know about
|
|
275
|
-
// that need to be merged in from sub, we're "synced"
|
|
276
|
-
const isSynced =
|
|
277
|
-
messageQueue.length === 0 &&
|
|
278
|
-
(nextToken === null || nextToken === undefined);
|
|
279
|
-
|
|
280
|
-
subscriber.next({
|
|
281
|
-
items,
|
|
282
|
-
isSynced,
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
if (Array.isArray(errors)) {
|
|
286
|
-
for (const error of errors) {
|
|
287
|
-
subscriber.error(error);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// play through the queue
|
|
293
|
-
if (messageQueue.length > 0) {
|
|
294
|
-
ingestMessages(messageQueue);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// switch the queue to write directly to the items collection
|
|
298
|
-
receiveMessages = (...messages: typeof messageQueue) => {
|
|
299
|
-
ingestMessages(messages);
|
|
300
|
-
return items.length;
|
|
301
|
-
};
|
|
302
|
-
})();
|
|
303
|
-
|
|
304
|
-
// when subscriber unsubscribes, tear down internal subs
|
|
305
|
-
return () => {
|
|
306
|
-
// 1. tear down internal subs
|
|
307
|
-
onCreateSub.unsubscribe();
|
|
308
|
-
onUpdateSub.unsubscribe();
|
|
309
|
-
onDeleteSub.unsubscribe();
|
|
310
|
-
|
|
311
|
-
// 2. there is no need to explicitly stop paging. instead, we
|
|
312
|
-
// just check `subscriber.closed` above before fetching each page.
|
|
313
|
-
};
|
|
314
|
-
});
|
|
50
|
+
models[name][operationPrefix] = observeQueryFactory(models, model);
|
|
315
51
|
} else {
|
|
316
|
-
models[name][operationPrefix] =
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
);
|
|
323
|
-
const variables = buildGraphQLVariables(
|
|
324
|
-
model,
|
|
325
|
-
operation,
|
|
326
|
-
arg,
|
|
327
|
-
modelIntrospection
|
|
328
|
-
);
|
|
329
|
-
|
|
330
|
-
try {
|
|
331
|
-
const auth = authModeParams(client, options);
|
|
332
|
-
const { data, extensions } = (await client.graphql({
|
|
333
|
-
...auth,
|
|
334
|
-
query,
|
|
335
|
-
variables,
|
|
336
|
-
})) as any;
|
|
337
|
-
|
|
338
|
-
// flatten response
|
|
339
|
-
if (data !== undefined) {
|
|
340
|
-
const [key] = Object.keys(data);
|
|
341
|
-
const flattenedResult = flattenItems(data)[key];
|
|
342
|
-
|
|
343
|
-
if (options?.selectionSet) {
|
|
344
|
-
return { data: flattenedResult, extensions };
|
|
345
|
-
} else {
|
|
346
|
-
// TODO: refactor to avoid destructuring here
|
|
347
|
-
const [initialized] = initializeModel(
|
|
348
|
-
client,
|
|
349
|
-
name,
|
|
350
|
-
[flattenedResult],
|
|
351
|
-
modelIntrospection,
|
|
352
|
-
auth.authMode,
|
|
353
|
-
auth.authToken
|
|
354
|
-
);
|
|
355
|
-
|
|
356
|
-
return { data: initialized, extensions };
|
|
357
|
-
}
|
|
358
|
-
} else {
|
|
359
|
-
return { data: null, extensions };
|
|
360
|
-
}
|
|
361
|
-
} catch (error) {
|
|
362
|
-
if (error.errors) {
|
|
363
|
-
// graphql errors pass through
|
|
364
|
-
return error as any;
|
|
365
|
-
} else {
|
|
366
|
-
// non-graphql errors re re-thrown
|
|
367
|
-
throw error;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
};
|
|
52
|
+
models[name][operationPrefix] = getFactory(
|
|
53
|
+
client,
|
|
54
|
+
modelIntrospection,
|
|
55
|
+
model,
|
|
56
|
+
operation
|
|
57
|
+
);
|
|
371
58
|
}
|
|
372
59
|
}
|
|
373
60
|
);
|