@aws-amplify/datastore 5.0.1-api-v6-models.c1977f8.0 → 5.0.1-api-v6-models.891fe0d.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 (70) hide show
  1. package/lib/authModeStrategies/defaultAuthStrategy.js +1 -1
  2. package/lib/authModeStrategies/multiAuthStrategy.js +29 -105
  3. package/lib/datastore/datastore.js +887 -1370
  4. package/lib/index.js +1 -1
  5. package/lib/predicates/index.js +53 -102
  6. package/lib/predicates/next.js +310 -557
  7. package/lib/predicates/sort.js +24 -27
  8. package/lib/ssr/index.js +1 -1
  9. package/lib/storage/adapter/AsyncStorageAdapter.js +115 -449
  10. package/lib/storage/adapter/AsyncStorageDatabase.js +215 -480
  11. package/lib/storage/adapter/InMemoryStore.js +27 -101
  12. package/lib/storage/adapter/InMemoryStore.native.js +1 -1
  13. package/lib/storage/adapter/IndexedDBAdapter.js +441 -1002
  14. package/lib/storage/adapter/StorageAdapterBase.js +177 -396
  15. package/lib/storage/adapter/getDefaultAdapter/index.js +5 -6
  16. package/lib/storage/adapter/getDefaultAdapter/index.native.js +2 -2
  17. package/lib/storage/relationship.js +174 -260
  18. package/lib/storage/storage.js +244 -507
  19. package/lib/sync/datastoreConnectivity.js +29 -84
  20. package/lib/sync/datastoreReachability/index.js +1 -1
  21. package/lib/sync/datastoreReachability/index.native.js +2 -2
  22. package/lib/sync/index.js +512 -885
  23. package/lib/sync/merger.js +30 -133
  24. package/lib/sync/outbox.js +147 -302
  25. package/lib/sync/processors/errorMaps.js +30 -80
  26. package/lib/sync/processors/mutation.js +331 -579
  27. package/lib/sync/processors/subscription.js +268 -428
  28. package/lib/sync/processors/sync.js +276 -464
  29. package/lib/sync/utils.js +248 -393
  30. package/lib/tsconfig.tsbuildinfo +1 -1
  31. package/lib/types.js +16 -58
  32. package/lib/util.js +335 -575
  33. package/lib-esm/authModeStrategies/defaultAuthStrategy.js +1 -1
  34. package/lib-esm/authModeStrategies/multiAuthStrategy.js +27 -103
  35. package/lib-esm/datastore/datastore.js +874 -1359
  36. package/lib-esm/index.js +6 -6
  37. package/lib-esm/predicates/index.js +54 -104
  38. package/lib-esm/predicates/next.js +306 -555
  39. package/lib-esm/predicates/sort.js +24 -27
  40. package/lib-esm/ssr/index.js +1 -1
  41. package/lib-esm/storage/adapter/AsyncStorageAdapter.js +111 -446
  42. package/lib-esm/storage/adapter/AsyncStorageDatabase.js +212 -477
  43. package/lib-esm/storage/adapter/InMemoryStore.js +27 -102
  44. package/lib-esm/storage/adapter/IndexedDBAdapter.js +436 -997
  45. package/lib-esm/storage/adapter/StorageAdapterBase.js +172 -392
  46. package/lib-esm/storage/adapter/getDefaultAdapter/index.js +2 -3
  47. package/lib-esm/storage/adapter/getDefaultAdapter/index.native.js +1 -1
  48. package/lib-esm/storage/relationship.js +173 -260
  49. package/lib-esm/storage/storage.js +236 -499
  50. package/lib-esm/sync/datastoreConnectivity.js +26 -82
  51. package/lib-esm/sync/datastoreReachability/index.js +1 -1
  52. package/lib-esm/sync/datastoreReachability/index.native.js +1 -1
  53. package/lib-esm/sync/index.js +498 -872
  54. package/lib-esm/sync/merger.js +28 -131
  55. package/lib-esm/sync/outbox.js +143 -298
  56. package/lib-esm/sync/processors/errorMaps.js +32 -82
  57. package/lib-esm/sync/processors/mutation.js +324 -572
  58. package/lib-esm/sync/processors/subscription.js +258 -418
  59. package/lib-esm/sync/processors/sync.js +269 -457
  60. package/lib-esm/sync/utils.js +245 -390
  61. package/lib-esm/tsconfig.tsbuildinfo +1 -1
  62. package/lib-esm/types.js +16 -59
  63. package/lib-esm/util.js +335 -577
  64. package/package.json +12 -12
  65. package/src/datastore/datastore.ts +4 -3
  66. package/src/storage/adapter/getDefaultAdapter/index.ts +1 -3
  67. package/src/sync/processors/mutation.ts +1 -1
  68. package/src/sync/processors/sync.ts +1 -1
  69. package/src/sync/utils.ts +1 -1
  70. package/src/util.ts +44 -6
@@ -1,75 +1,3 @@
1
- var __assign = (this && this.__assign) || function () {
2
- __assign = Object.assign || function(t) {
3
- for (var s, i = 1, n = arguments.length; i < n; i++) {
4
- s = arguments[i];
5
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
- t[p] = s[p];
7
- }
8
- return t;
9
- };
10
- return __assign.apply(this, arguments);
11
- };
12
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
13
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
14
- return new (P || (P = Promise))(function (resolve, reject) {
15
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
16
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
17
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
18
- step((generator = generator.apply(thisArg, _arguments || [])).next());
19
- });
20
- };
21
- var __generator = (this && this.__generator) || function (thisArg, body) {
22
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
23
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
24
- function verb(n) { return function (v) { return step([n, v]); }; }
25
- function step(op) {
26
- if (f) throw new TypeError("Generator is already executing.");
27
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
28
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
29
- if (y = 0, t) op = [op[0] & 2, t.value];
30
- switch (op[0]) {
31
- case 0: case 1: t = op; break;
32
- case 4: _.label++; return { value: op[1], done: false };
33
- case 5: _.label++; y = op[1]; op = [0]; continue;
34
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
35
- default:
36
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
37
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
38
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
39
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
40
- if (t[2]) _.ops.pop();
41
- _.trys.pop(); continue;
42
- }
43
- op = body.call(thisArg, _);
44
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
45
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46
- }
47
- };
48
- var __read = (this && this.__read) || function (o, n) {
49
- var m = typeof Symbol === "function" && o[Symbol.iterator];
50
- if (!m) return o;
51
- var i = m.call(o), r, ar = [], e;
52
- try {
53
- while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
54
- }
55
- catch (error) { e = { error: error }; }
56
- finally {
57
- try {
58
- if (r && !r.done && (m = i["return"])) m.call(i);
59
- }
60
- finally { if (e) throw e.error; }
61
- }
62
- return ar;
63
- };
64
- var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
65
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
66
- if (ar || !(i in from)) {
67
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
68
- ar[i] = from[i];
69
- }
70
- }
71
- return to.concat(ar || Array.prototype.slice.call(from));
72
- };
73
1
  import { InternalAPI } from '@aws-amplify/api/internals';
74
2
  import { Hub, fetchAuthSession, ConsoleLogger, } from '@aws-amplify/core';
75
3
  import { Category, DataStoreAction, BackgroundProcessManager, } from '@aws-amplify/core/internals/utils';
@@ -80,7 +8,7 @@ import { ModelPredicateCreator } from '../../predicates';
80
8
  import { validatePredicate } from '../../util';
81
9
  import { getSubscriptionErrorType } from './errorMaps';
82
10
  import { CONTROL_MSG as PUBSUB_CONTROL_MSG } from '@aws-amplify/api-graphql';
83
- var logger = new ConsoleLogger('DataStore');
11
+ const logger = new ConsoleLogger('DataStore');
84
12
  export var CONTROL_MSG;
85
13
  (function (CONTROL_MSG) {
86
14
  CONTROL_MSG["CONNECTED"] = "CONNECTED";
@@ -91,12 +19,10 @@ export var USER_CREDENTIALS;
91
19
  USER_CREDENTIALS[USER_CREDENTIALS["unauth"] = 1] = "unauth";
92
20
  USER_CREDENTIALS[USER_CREDENTIALS["auth"] = 2] = "auth";
93
21
  })(USER_CREDENTIALS || (USER_CREDENTIALS = {}));
94
- var SubscriptionProcessor = /** @class */ (function () {
95
- function SubscriptionProcessor(schema, syncPredicates, amplifyConfig, authModeStrategy, errorHandler, amplifyContext) {
96
- if (amplifyConfig === void 0) { amplifyConfig = {}; }
97
- if (amplifyContext === void 0) { amplifyContext = {
98
- InternalAPI: InternalAPI,
99
- }; }
22
+ class SubscriptionProcessor {
23
+ constructor(schema, syncPredicates, amplifyConfig = {}, authModeStrategy, errorHandler, amplifyContext = {
24
+ InternalAPI,
25
+ }) {
100
26
  this.schema = schema;
101
27
  this.syncPredicates = syncPredicates;
102
28
  this.amplifyConfig = amplifyConfig;
@@ -107,18 +33,17 @@ var SubscriptionProcessor = /** @class */ (function () {
107
33
  this.buffer = [];
108
34
  this.runningProcesses = new BackgroundProcessManager();
109
35
  }
110
- SubscriptionProcessor.prototype.buildSubscription = function (namespace, model, transformerMutationType, userCredentials, oidcTokenPayload, authMode, filterArg) {
111
- if (filterArg === void 0) { filterArg = false; }
112
- var aws_appsync_authenticationType = this.amplifyConfig.aws_appsync_authenticationType;
113
- var _a = this.getAuthorizationInfo(model, userCredentials, aws_appsync_authenticationType, oidcTokenPayload, authMode) || {}, isOwner = _a.isOwner, ownerField = _a.ownerField, ownerValue = _a.ownerValue;
114
- var _b = __read(buildSubscriptionGraphQLOperation(namespace, model, transformerMutationType, isOwner, ownerField, filterArg), 3), opType = _b[0], opName = _b[1], query = _b[2];
115
- return { authMode: authMode, opType: opType, opName: opName, query: query, isOwner: isOwner, ownerField: ownerField, ownerValue: ownerValue };
116
- };
117
- SubscriptionProcessor.prototype.getAuthorizationInfo = function (model, userCredentials, defaultAuthType, oidcTokenPayload, authMode) {
118
- var rules = getAuthorizationRules(model);
36
+ buildSubscription(namespace, model, transformerMutationType, userCredentials, oidcTokenPayload, authMode, filterArg = false) {
37
+ const { aws_appsync_authenticationType } = this.amplifyConfig;
38
+ const { isOwner, ownerField, ownerValue } = this.getAuthorizationInfo(model, userCredentials, aws_appsync_authenticationType, oidcTokenPayload, authMode) || {};
39
+ const [opType, opName, query] = buildSubscriptionGraphQLOperation(namespace, model, transformerMutationType, isOwner, ownerField, filterArg);
40
+ return { authMode, opType, opName, query, isOwner, ownerField, ownerValue };
41
+ }
42
+ getAuthorizationInfo(model, userCredentials, defaultAuthType, oidcTokenPayload, authMode) {
43
+ const rules = getAuthorizationRules(model);
119
44
  // Return null if user doesn't have proper credentials for private API with IAM auth
120
- var iamPrivateAuth = authMode === 'iam' &&
121
- rules.find(function (rule) { return rule.authStrategy === 'private' && rule.provider === 'iam'; });
45
+ const iamPrivateAuth = authMode === 'iam' &&
46
+ rules.find(rule => rule.authStrategy === 'private' && rule.provider === 'iam');
122
47
  if (iamPrivateAuth && userCredentials === USER_CREDENTIALS.unauth) {
123
48
  return null;
124
49
  }
@@ -126,47 +51,42 @@ var SubscriptionProcessor = /** @class */ (function () {
126
51
  // if rule(s) have group authorization as well as if either the Cognito or
127
52
  // OIDC token has a groupClaim. If so, we are returning auth info before
128
53
  // any further owner-based auth checks.
129
- var groupAuthRules = rules.filter(function (rule) {
130
- return rule.authStrategy === 'groups' &&
131
- ['userPools', 'oidc'].includes(rule.provider);
132
- });
133
- var validGroup = (authMode === 'oidc' || authMode === 'userPool') &&
134
- groupAuthRules.find(function (groupAuthRule) {
54
+ const groupAuthRules = rules.filter(rule => rule.authStrategy === 'groups' &&
55
+ ['userPools', 'oidc'].includes(rule.provider));
56
+ const validGroup = (authMode === 'oidc' || authMode === 'userPool') &&
57
+ groupAuthRules.find(groupAuthRule => {
135
58
  // validate token against groupClaim
136
59
  if (oidcTokenPayload) {
137
- var oidcUserGroups = getUserGroupsFromToken(oidcTokenPayload, groupAuthRule);
138
- return __spreadArray([], __read(oidcUserGroups), false).find(function (userGroup) {
139
- return groupAuthRule.groups.find(function (group) { return group === userGroup; });
60
+ const oidcUserGroups = getUserGroupsFromToken(oidcTokenPayload, groupAuthRule);
61
+ return [...oidcUserGroups].find(userGroup => {
62
+ return groupAuthRule.groups.find(group => group === userGroup);
140
63
  });
141
64
  }
142
65
  });
143
66
  if (validGroup) {
144
67
  return {
145
- authMode: authMode,
68
+ authMode,
146
69
  isOwner: false,
147
70
  };
148
71
  }
149
- var ownerAuthInfo;
72
+ let ownerAuthInfo;
150
73
  if (ownerAuthInfo) {
151
74
  return ownerAuthInfo;
152
75
  }
153
76
  // Owner auth needs additional values to be returned in order to create the subscription with
154
77
  // the correct parameters so we are getting the owner value from the OIDC token via the
155
78
  // identityClaim from the auth rule.
156
- var oidcOwnerAuthRules = authMode === 'oidc' || authMode === 'userPool'
157
- ? rules.filter(function (rule) {
158
- return rule.authStrategy === 'owner' &&
159
- (rule.provider === 'oidc' || rule.provider === 'userPools');
160
- })
79
+ const oidcOwnerAuthRules = authMode === 'oidc' || authMode === 'userPool'
80
+ ? rules.filter(rule => rule.authStrategy === 'owner' &&
81
+ (rule.provider === 'oidc' || rule.provider === 'userPools'))
161
82
  : [];
162
- oidcOwnerAuthRules.forEach(function (ownerAuthRule) {
163
- var _a;
164
- var ownerValue = oidcTokenPayload[ownerAuthRule.identityClaim];
165
- var singleOwner = ((_a = model.fields[ownerAuthRule.ownerField]) === null || _a === void 0 ? void 0 : _a.isArray) !== true;
166
- var isOwnerArgRequired = singleOwner && !ownerAuthRule.areSubscriptionsPublic;
83
+ oidcOwnerAuthRules.forEach(ownerAuthRule => {
84
+ const ownerValue = oidcTokenPayload[ownerAuthRule.identityClaim];
85
+ const singleOwner = model.fields[ownerAuthRule.ownerField]?.isArray !== true;
86
+ const isOwnerArgRequired = singleOwner && !ownerAuthRule.areSubscriptionsPublic;
167
87
  if (ownerValue) {
168
88
  ownerAuthInfo = {
169
- authMode: authMode,
89
+ authMode,
170
90
  isOwner: isOwnerArgRequired,
171
91
  ownerField: ownerAuthRule.ownerField,
172
92
  ownerValue: String(ownerValue),
@@ -181,331 +101,255 @@ var SubscriptionProcessor = /** @class */ (function () {
181
101
  authMode: authMode || defaultAuthType,
182
102
  isOwner: false,
183
103
  };
184
- };
185
- SubscriptionProcessor.prototype.hubQueryCompletionListener = function (completed, capsule) {
186
- var event = capsule.payload.event;
104
+ }
105
+ hubQueryCompletionListener(completed, capsule) {
106
+ const { payload: { event }, } = capsule;
187
107
  if (event === PUBSUB_CONTROL_MSG.SUBSCRIPTION_ACK) {
188
108
  completed();
189
109
  }
190
- };
191
- SubscriptionProcessor.prototype.start = function () {
192
- var _this = this;
110
+ }
111
+ start() {
193
112
  this.runningProcesses =
194
113
  this.runningProcesses || new BackgroundProcessManager();
195
- var ctlObservable = new Observable(function (observer) {
196
- var promises = [];
114
+ const ctlObservable = new Observable(observer => {
115
+ const promises = [];
197
116
  // Creating subs for each model/operation combo so they can be unsubscribed
198
117
  // independently, since the auth retry behavior is asynchronous.
199
- var subscriptions = {};
200
- var oidcTokenPayload;
201
- var userCredentials = USER_CREDENTIALS.none;
202
- _this.runningProcesses.add(function () { return __awaiter(_this, void 0, void 0, function () {
203
- var credentials, err_1, session, err_2;
204
- var _this = this;
205
- var _a, _b, _c;
206
- return __generator(this, function (_d) {
207
- switch (_d.label) {
208
- case 0:
209
- _d.trys.push([0, 2, , 3]);
210
- return [4 /*yield*/, fetchAuthSession()];
211
- case 1:
212
- credentials = (_a = (_d.sent()).tokens) === null || _a === void 0 ? void 0 : _a.accessToken;
213
- userCredentials = credentials
214
- ? USER_CREDENTIALS.auth
215
- : USER_CREDENTIALS.unauth;
216
- return [3 /*break*/, 3];
217
- case 2:
218
- err_1 = _d.sent();
219
- return [3 /*break*/, 3];
220
- case 3:
221
- _d.trys.push([3, 6, , 7]);
222
- return [4 /*yield*/, fetchAuthSession()];
223
- case 4: return [4 /*yield*/, _d.sent()];
224
- case 5:
225
- session = _d.sent();
226
- oidcTokenPayload = (_c = (_b = session.tokens) === null || _b === void 0 ? void 0 : _b.idToken) === null || _c === void 0 ? void 0 : _c.payload;
227
- return [3 /*break*/, 7];
228
- case 6:
229
- err_2 = _d.sent();
230
- return [3 /*break*/, 7];
231
- case 7:
232
- Object.values(this.schema.namespaces).forEach(function (namespace) {
233
- Object.values(namespace.models)
234
- .filter(function (_a) {
235
- var syncable = _a.syncable;
236
- return syncable;
237
- })
238
- .forEach(function (modelDefinition) {
239
- return _this.runningProcesses.isOpen &&
240
- _this.runningProcesses.add(function () { return __awaiter(_this, void 0, void 0, function () {
241
- var modelAuthModes, readAuthModes, operations, operationAuthModeAttempts, predicatesGroup, addFilterArg, subscriptionRetry;
242
- var _a, _b, _c;
243
- var _this = this;
244
- return __generator(this, function (_d) {
245
- switch (_d.label) {
246
- case 0: return [4 /*yield*/, getModelAuthModes({
247
- authModeStrategy: this.authModeStrategy,
248
- defaultAuthMode: this.amplifyConfig.aws_appsync_authenticationType,
249
- modelName: modelDefinition.name,
250
- schema: this.schema,
251
- })];
252
- case 1:
253
- modelAuthModes = _d.sent();
254
- readAuthModes = modelAuthModes.READ;
255
- subscriptions = __assign(__assign({}, subscriptions), (_a = {}, _a[modelDefinition.name] = (_b = {},
256
- _b[TransformerMutationType.CREATE] = [],
257
- _b[TransformerMutationType.UPDATE] = [],
258
- _b[TransformerMutationType.DELETE] = [],
259
- _b), _a));
260
- operations = [
261
- TransformerMutationType.CREATE,
262
- TransformerMutationType.UPDATE,
263
- TransformerMutationType.DELETE,
264
- ];
265
- operationAuthModeAttempts = (_c = {},
266
- _c[TransformerMutationType.CREATE] = 0,
267
- _c[TransformerMutationType.UPDATE] = 0,
268
- _c[TransformerMutationType.DELETE] = 0,
269
- _c);
270
- predicatesGroup = ModelPredicateCreator.getPredicates(this.syncPredicates.get(modelDefinition), false);
271
- addFilterArg = predicatesGroup !== undefined;
272
- subscriptionRetry = function (operation, addFilter) {
273
- if (addFilter === void 0) { addFilter = addFilterArg; }
274
- return __awaiter(_this, void 0, void 0, function () {
275
- var _a, transformerMutationType, opName, query, isOwner, ownerField, ownerValue, authMode, authToken, variables, customUserAgentDetails, queryObservable, subscriptionReadyCallback;
276
- var _this = this;
277
- return __generator(this, function (_b) {
278
- switch (_b.label) {
279
- case 0:
280
- _a = this.buildSubscription(namespace, modelDefinition, operation, userCredentials, oidcTokenPayload, readAuthModes[operationAuthModeAttempts[operation]], addFilter), transformerMutationType = _a.opType, opName = _a.opName, query = _a.query, isOwner = _a.isOwner, ownerField = _a.ownerField, ownerValue = _a.ownerValue, authMode = _a.authMode;
281
- return [4 /*yield*/, getTokenForCustomAuth(authMode, this.amplifyConfig)];
282
- case 1:
283
- authToken = _b.sent();
284
- variables = {};
285
- customUserAgentDetails = {
286
- category: Category.DataStore,
287
- action: DataStoreAction.Subscribe,
288
- };
289
- if (addFilter && predicatesGroup) {
290
- variables['filter'] =
291
- predicateToGraphQLFilter(predicatesGroup);
292
- }
293
- if (isOwner) {
294
- if (!ownerValue) {
295
- observer.error('Owner field required, sign in is needed in order to perform this operation');
296
- return [2 /*return*/];
297
- }
298
- variables[ownerField] = ownerValue;
299
- }
300
- logger.debug("Attempting ".concat(operation, " subscription with authMode: ").concat(readAuthModes[operationAuthModeAttempts[operation]]));
301
- queryObservable = this.amplifyContext.InternalAPI.graphql(__assign(__assign({ query: query, variables: variables }, { authMode: authMode }), { authToken: authToken }), undefined, customUserAgentDetails);
302
- // TODO: consider onTerminate.then(() => API.cancel(...))
303
- subscriptions[modelDefinition.name][transformerMutationType].push(queryObservable.subscribe({
304
- next: function (result) {
305
- var data = result.data, errors = result.errors;
306
- if (Array.isArray(errors) && errors.length > 0) {
307
- var messages = errors.map(function (_a) {
308
- var message = _a.message;
309
- return message;
310
- });
311
- logger.warn("Skipping incoming subscription. Messages: ".concat(messages.join('\n')));
312
- _this.drainBuffer();
313
- return;
314
- }
315
- var predicatesGroup = ModelPredicateCreator.getPredicates(_this.syncPredicates.get(modelDefinition), false);
316
- // @ts-ignore
317
- var _a = data, _b = opName, record = _a[_b];
318
- // checking incoming subscription against syncPredicate.
319
- // once AppSync implements filters on subscriptions, we'll be
320
- // able to set these when establishing the subscription instead.
321
- // Until then, we'll need to filter inbound
322
- if (_this.passesPredicateValidation(record, predicatesGroup)) {
323
- _this.pushToBuffer(transformerMutationType, modelDefinition, record);
324
- }
325
- _this.drainBuffer();
326
- },
327
- error: function (subscriptionError) { return __awaiter(_this, void 0, void 0, function () {
328
- var _a, _b, _c, _d, message, isRTFError, e_1;
329
- var _e;
330
- return __generator(this, function (_f) {
331
- switch (_f.label) {
332
- case 0:
333
- _a = __read((_e = __read(subscriptionError.errors, 0), subscriptionError).errors, 1), _b = _a[0], _c = _b === void 0 ? {} : _b, _d = _c.message, message = _d === void 0 ? '' : _d;
334
- isRTFError =
335
- // only attempt catch if a filter variable was added to the subscription query
336
- addFilter &&
337
- this.catchRTFError(message, modelDefinition, predicatesGroup);
338
- // Catch RTF errors
339
- if (isRTFError) {
340
- // Unsubscribe and clear subscription array for model/operation
341
- subscriptions[modelDefinition.name][transformerMutationType].forEach(function (subscription) {
342
- return subscription.unsubscribe();
343
- });
344
- subscriptions[modelDefinition.name][transformerMutationType] = [];
345
- // retry subscription connection without filter
346
- subscriptionRetry(operation, false);
347
- return [2 /*return*/];
348
- }
349
- if (message.includes(PUBSUB_CONTROL_MSG.REALTIME_SUBSCRIPTION_INIT_ERROR) ||
350
- message.includes(PUBSUB_CONTROL_MSG.CONNECTION_FAILED)) {
351
- // Unsubscribe and clear subscription array for model/operation
352
- subscriptions[modelDefinition.name][transformerMutationType].forEach(function (subscription) {
353
- return subscription.unsubscribe();
354
- });
355
- subscriptions[modelDefinition.name][transformerMutationType] = [];
356
- operationAuthModeAttempts[operation]++;
357
- if (operationAuthModeAttempts[operation] >=
358
- readAuthModes.length) {
359
- // last auth mode retry. Continue with error
360
- logger.debug("".concat(operation, " subscription failed with authMode: ").concat(readAuthModes[operationAuthModeAttempts[operation] - 1]));
361
- }
362
- else {
363
- // retry with different auth mode. Do not trigger
364
- // observer error or error handler
365
- logger.debug("".concat(operation, " subscription failed with authMode: ").concat(readAuthModes[operationAuthModeAttempts[operation] - 1], ". Retrying with authMode: ").concat(readAuthModes[operationAuthModeAttempts[operation]]));
366
- subscriptionRetry(operation);
367
- return [2 /*return*/];
368
- }
369
- }
370
- logger.warn('subscriptionError', message);
371
- _f.label = 1;
372
- case 1:
373
- _f.trys.push([1, 3, , 4]);
374
- return [4 /*yield*/, this.errorHandler({
375
- recoverySuggestion: 'Ensure app code is up to date, auth directives exist and are correct on each model, and that server-side data has not been invalidated by a schema change. If the problem persists, search for or create an issue: https://github.com/aws-amplify/amplify-js/issues',
376
- localModel: null,
377
- message: message,
378
- model: modelDefinition.name,
379
- operation: operation,
380
- errorType: getSubscriptionErrorType(subscriptionError),
381
- process: ProcessName.subscribe,
382
- remoteModel: null,
383
- cause: subscriptionError,
384
- })];
385
- case 2:
386
- _f.sent();
387
- return [3 /*break*/, 4];
388
- case 3:
389
- e_1 = _f.sent();
390
- logger.error('Subscription error handler failed with:', e_1);
391
- return [3 /*break*/, 4];
392
- case 4:
393
- if (typeof subscriptionReadyCallback === 'function') {
394
- subscriptionReadyCallback();
395
- }
396
- if (message.includes('"errorType":"Unauthorized"') ||
397
- message.includes('"errorType":"OperationDisabled"')) {
398
- return [2 /*return*/];
399
- }
400
- observer.error(message);
401
- return [2 /*return*/];
402
- }
403
- });
404
- }); },
405
- }));
406
- promises.push((function () { return __awaiter(_this, void 0, void 0, function () {
407
- var boundFunction, removeBoundFunctionListener;
408
- var _this = this;
409
- return __generator(this, function (_a) {
410
- switch (_a.label) {
411
- case 0: return [4 /*yield*/, new Promise(function (res) {
412
- subscriptionReadyCallback = res;
413
- boundFunction = _this.hubQueryCompletionListener.bind(_this, res);
414
- removeBoundFunctionListener = Hub.listen('api', boundFunction);
415
- })];
416
- case 1:
417
- _a.sent();
418
- removeBoundFunctionListener();
419
- return [2 /*return*/];
420
- }
421
- });
422
- }); })());
423
- return [2 /*return*/];
424
- }
425
- });
426
- });
427
- };
428
- operations.forEach(function (op) { return subscriptionRetry(op); });
429
- return [2 /*return*/];
430
- }
431
- });
432
- }); });
433
- });
118
+ let subscriptions = {};
119
+ let oidcTokenPayload;
120
+ let userCredentials = USER_CREDENTIALS.none;
121
+ this.runningProcesses.add(async () => {
122
+ try {
123
+ // retrieving current AWS Credentials
124
+ const credentials = (await fetchAuthSession()).tokens?.accessToken;
125
+ userCredentials = credentials
126
+ ? USER_CREDENTIALS.auth
127
+ : USER_CREDENTIALS.unauth;
128
+ }
129
+ catch (err) {
130
+ // best effort to get AWS credentials
131
+ }
132
+ try {
133
+ // retrieving current token info from Cognito UserPools
134
+ const session = await await fetchAuthSession();
135
+ oidcTokenPayload = session.tokens?.idToken?.payload;
136
+ }
137
+ catch (err) {
138
+ // best effort to get jwt from Cognito
139
+ }
140
+ Object.values(this.schema.namespaces).forEach(namespace => {
141
+ Object.values(namespace.models)
142
+ .filter(({ syncable }) => syncable)
143
+ .forEach(modelDefinition => this.runningProcesses.isOpen &&
144
+ this.runningProcesses.add(async () => {
145
+ const modelAuthModes = await getModelAuthModes({
146
+ authModeStrategy: this.authModeStrategy,
147
+ defaultAuthMode: this.amplifyConfig.aws_appsync_authenticationType,
148
+ modelName: modelDefinition.name,
149
+ schema: this.schema,
434
150
  });
435
- this.runningProcesses.isOpen &&
436
- this.runningProcesses.add(function () {
437
- return Promise.all(promises).then(function () {
438
- observer.next(CONTROL_MSG.CONNECTED);
151
+ // subscriptions are created only based on the READ auth mode(s)
152
+ const readAuthModes = modelAuthModes.READ;
153
+ subscriptions = {
154
+ ...subscriptions,
155
+ [modelDefinition.name]: {
156
+ [TransformerMutationType.CREATE]: [],
157
+ [TransformerMutationType.UPDATE]: [],
158
+ [TransformerMutationType.DELETE]: [],
159
+ },
160
+ };
161
+ const operations = [
162
+ TransformerMutationType.CREATE,
163
+ TransformerMutationType.UPDATE,
164
+ TransformerMutationType.DELETE,
165
+ ];
166
+ const operationAuthModeAttempts = {
167
+ [TransformerMutationType.CREATE]: 0,
168
+ [TransformerMutationType.UPDATE]: 0,
169
+ [TransformerMutationType.DELETE]: 0,
170
+ };
171
+ const predicatesGroup = ModelPredicateCreator.getPredicates(this.syncPredicates.get(modelDefinition), false);
172
+ const addFilterArg = predicatesGroup !== undefined;
173
+ // Retry subscriptions that failed for one of the following reasons:
174
+ // 1. unauthorized - retry with next auth mode (if available)
175
+ // 2. RTF error - retry without sending filter arg. (filtering will fall back to clientside)
176
+ const subscriptionRetry = async (operation, addFilter = addFilterArg) => {
177
+ const { opType: transformerMutationType, opName, query, isOwner, ownerField, ownerValue, authMode, } = this.buildSubscription(namespace, modelDefinition, operation, userCredentials, oidcTokenPayload, readAuthModes[operationAuthModeAttempts[operation]], addFilter);
178
+ const authToken = await getTokenForCustomAuth(authMode, this.amplifyConfig);
179
+ const variables = {};
180
+ const customUserAgentDetails = {
181
+ category: Category.DataStore,
182
+ action: DataStoreAction.Subscribe,
183
+ };
184
+ if (addFilter && predicatesGroup) {
185
+ variables['filter'] =
186
+ predicateToGraphQLFilter(predicatesGroup);
187
+ }
188
+ if (isOwner) {
189
+ if (!ownerValue) {
190
+ observer.error('Owner field required, sign in is needed in order to perform this operation');
191
+ return;
192
+ }
193
+ variables[ownerField] = ownerValue;
194
+ }
195
+ logger.debug(`Attempting ${operation} subscription with authMode: ${readAuthModes[operationAuthModeAttempts[operation]]}`);
196
+ const queryObservable = this.amplifyContext.InternalAPI.graphql({
197
+ query,
198
+ variables,
199
+ ...{ authMode },
200
+ authToken,
201
+ }, undefined, customUserAgentDetails);
202
+ let subscriptionReadyCallback;
203
+ // TODO: consider onTerminate.then(() => API.cancel(...))
204
+ subscriptions[modelDefinition.name][transformerMutationType].push(queryObservable.subscribe({
205
+ next: result => {
206
+ const { data, errors } = result;
207
+ if (Array.isArray(errors) && errors.length > 0) {
208
+ const messages = errors.map(({ message }) => message);
209
+ logger.warn(`Skipping incoming subscription. Messages: ${messages.join('\n')}`);
210
+ this.drainBuffer();
211
+ return;
212
+ }
213
+ const predicatesGroup = ModelPredicateCreator.getPredicates(this.syncPredicates.get(modelDefinition), false);
214
+ // @ts-ignore
215
+ const { [opName]: record } = data;
216
+ // checking incoming subscription against syncPredicate.
217
+ // once AppSync implements filters on subscriptions, we'll be
218
+ // able to set these when establishing the subscription instead.
219
+ // Until then, we'll need to filter inbound
220
+ if (this.passesPredicateValidation(record, predicatesGroup)) {
221
+ this.pushToBuffer(transformerMutationType, modelDefinition, record);
222
+ }
223
+ this.drainBuffer();
224
+ },
225
+ error: async (subscriptionError) => {
226
+ const { errors: [{ message = '' } = {}], } = ({
227
+ errors: [],
228
+ } = subscriptionError);
229
+ const isRTFError =
230
+ // only attempt catch if a filter variable was added to the subscription query
231
+ addFilter &&
232
+ this.catchRTFError(message, modelDefinition, predicatesGroup);
233
+ // Catch RTF errors
234
+ if (isRTFError) {
235
+ // Unsubscribe and clear subscription array for model/operation
236
+ subscriptions[modelDefinition.name][transformerMutationType].forEach(subscription => subscription.unsubscribe());
237
+ subscriptions[modelDefinition.name][transformerMutationType] = [];
238
+ // retry subscription connection without filter
239
+ subscriptionRetry(operation, false);
240
+ return;
241
+ }
242
+ if (message.includes(PUBSUB_CONTROL_MSG.REALTIME_SUBSCRIPTION_INIT_ERROR) ||
243
+ message.includes(PUBSUB_CONTROL_MSG.CONNECTION_FAILED)) {
244
+ // Unsubscribe and clear subscription array for model/operation
245
+ subscriptions[modelDefinition.name][transformerMutationType].forEach(subscription => subscription.unsubscribe());
246
+ subscriptions[modelDefinition.name][transformerMutationType] = [];
247
+ operationAuthModeAttempts[operation]++;
248
+ if (operationAuthModeAttempts[operation] >=
249
+ readAuthModes.length) {
250
+ // last auth mode retry. Continue with error
251
+ logger.debug(`${operation} subscription failed with authMode: ${readAuthModes[operationAuthModeAttempts[operation] - 1]}`);
252
+ }
253
+ else {
254
+ // retry with different auth mode. Do not trigger
255
+ // observer error or error handler
256
+ logger.debug(`${operation} subscription failed with authMode: ${readAuthModes[operationAuthModeAttempts[operation] - 1]}. Retrying with authMode: ${readAuthModes[operationAuthModeAttempts[operation]]}`);
257
+ subscriptionRetry(operation);
258
+ return;
259
+ }
260
+ }
261
+ logger.warn('subscriptionError', message);
262
+ try {
263
+ await this.errorHandler({
264
+ recoverySuggestion: 'Ensure app code is up to date, auth directives exist and are correct on each model, and that server-side data has not been invalidated by a schema change. If the problem persists, search for or create an issue: https://github.com/aws-amplify/amplify-js/issues',
265
+ localModel: null,
266
+ message,
267
+ model: modelDefinition.name,
268
+ operation,
269
+ errorType: getSubscriptionErrorType(subscriptionError),
270
+ process: ProcessName.subscribe,
271
+ remoteModel: null,
272
+ cause: subscriptionError,
273
+ });
274
+ }
275
+ catch (e) {
276
+ logger.error('Subscription error handler failed with:', e);
277
+ }
278
+ if (typeof subscriptionReadyCallback === 'function') {
279
+ subscriptionReadyCallback();
280
+ }
281
+ if (message.includes('"errorType":"Unauthorized"') ||
282
+ message.includes('"errorType":"OperationDisabled"')) {
283
+ return;
284
+ }
285
+ observer.error(message);
286
+ },
287
+ }));
288
+ promises.push((async () => {
289
+ let boundFunction;
290
+ let removeBoundFunctionListener;
291
+ await new Promise(res => {
292
+ subscriptionReadyCallback = res;
293
+ boundFunction = this.hubQueryCompletionListener.bind(this, res);
294
+ removeBoundFunctionListener = Hub.listen('api', boundFunction);
439
295
  });
440
- });
441
- return [2 /*return*/];
442
- }
443
- });
444
- }); }, 'subscription processor new subscriber');
445
- return _this.runningProcesses.addCleaner(function () { return __awaiter(_this, void 0, void 0, function () {
446
- return __generator(this, function (_a) {
447
- Object.keys(subscriptions).forEach(function (modelName) {
448
- subscriptions[modelName][TransformerMutationType.CREATE].forEach(function (subscription) { return subscription.unsubscribe(); });
449
- subscriptions[modelName][TransformerMutationType.UPDATE].forEach(function (subscription) { return subscription.unsubscribe(); });
450
- subscriptions[modelName][TransformerMutationType.DELETE].forEach(function (subscription) { return subscription.unsubscribe(); });
451
- });
452
- return [2 /*return*/];
296
+ removeBoundFunctionListener();
297
+ })());
298
+ };
299
+ operations.forEach(op => subscriptionRetry(op));
300
+ }));
453
301
  });
454
- }); });
455
- });
456
- var dataObservable = new Observable(function (observer) {
457
- _this.dataObserver = observer;
458
- _this.drainBuffer();
459
- return _this.runningProcesses.addCleaner(function () { return __awaiter(_this, void 0, void 0, function () {
460
- return __generator(this, function (_a) {
461
- this.dataObserver = null;
462
- return [2 /*return*/];
302
+ this.runningProcesses.isOpen &&
303
+ this.runningProcesses.add(() => Promise.all(promises).then(() => {
304
+ observer.next(CONTROL_MSG.CONNECTED);
305
+ }));
306
+ }, 'subscription processor new subscriber');
307
+ return this.runningProcesses.addCleaner(async () => {
308
+ Object.keys(subscriptions).forEach(modelName => {
309
+ subscriptions[modelName][TransformerMutationType.CREATE].forEach(subscription => subscription.unsubscribe());
310
+ subscriptions[modelName][TransformerMutationType.UPDATE].forEach(subscription => subscription.unsubscribe());
311
+ subscriptions[modelName][TransformerMutationType.DELETE].forEach(subscription => subscription.unsubscribe());
463
312
  });
464
- }); });
313
+ });
465
314
  });
466
- return [ctlObservable, dataObservable];
467
- };
468
- SubscriptionProcessor.prototype.stop = function () {
469
- return __awaiter(this, void 0, void 0, function () {
470
- return __generator(this, function (_a) {
471
- switch (_a.label) {
472
- case 0: return [4 /*yield*/, this.runningProcesses.close()];
473
- case 1:
474
- _a.sent();
475
- return [4 /*yield*/, this.runningProcesses.open()];
476
- case 2:
477
- _a.sent();
478
- return [2 /*return*/];
479
- }
315
+ const dataObservable = new Observable(observer => {
316
+ this.dataObserver = observer;
317
+ this.drainBuffer();
318
+ return this.runningProcesses.addCleaner(async () => {
319
+ this.dataObserver = null;
480
320
  });
481
321
  });
482
- };
483
- SubscriptionProcessor.prototype.passesPredicateValidation = function (record, predicatesGroup) {
322
+ return [ctlObservable, dataObservable];
323
+ }
324
+ async stop() {
325
+ await this.runningProcesses.close();
326
+ await this.runningProcesses.open();
327
+ }
328
+ passesPredicateValidation(record, predicatesGroup) {
484
329
  if (!predicatesGroup) {
485
330
  return true;
486
331
  }
487
- var predicates = predicatesGroup.predicates, type = predicatesGroup.type;
332
+ const { predicates, type } = predicatesGroup;
488
333
  return validatePredicate(record, type, predicates);
489
- };
490
- SubscriptionProcessor.prototype.pushToBuffer = function (transformerMutationType, modelDefinition, data) {
334
+ }
335
+ pushToBuffer(transformerMutationType, modelDefinition, data) {
491
336
  this.buffer.push([transformerMutationType, modelDefinition, data]);
492
- };
493
- SubscriptionProcessor.prototype.drainBuffer = function () {
494
- var _this = this;
337
+ }
338
+ drainBuffer() {
495
339
  if (this.dataObserver) {
496
- this.buffer.forEach(function (data) { return _this.dataObserver.next(data); });
340
+ this.buffer.forEach(data => this.dataObserver.next(data));
497
341
  this.buffer = [];
498
342
  }
499
- };
343
+ }
500
344
  /**
501
345
  * @returns true if the service returned an RTF subscription error
502
346
  * @remarks logs a warning with remediation instructions
503
347
  *
504
348
  */
505
- SubscriptionProcessor.prototype.catchRTFError = function (message, modelDefinition, predicatesGroup) {
506
- var header = 'Backend subscriptions filtering error.\n' +
349
+ catchRTFError(message, modelDefinition, predicatesGroup) {
350
+ const header = 'Backend subscriptions filtering error.\n' +
507
351
  'Subscriptions filtering will be applied clientside.\n';
508
- var messageErrorTypeMap = {
352
+ const messageErrorTypeMap = {
509
353
  'UnknownArgument: Unknown field argument filter': RTFError.UnknownField,
510
354
  'Filters exceed maximum attributes limit': RTFError.MaxAttributes,
511
355
  'Filters combination exceed maximum limit': RTFError.MaxCombinations,
@@ -513,17 +357,13 @@ var SubscriptionProcessor = /** @class */ (function () {
513
357
  "The variables input contains a field name 'not'": RTFError.NotGroup,
514
358
  'The variables input contains a field that is not defined for input object type': RTFError.FieldNotInType,
515
359
  };
516
- var _a = __read(Object.entries(messageErrorTypeMap).find(function (_a) {
517
- var _b = __read(_a, 1), errorMsg = _b[0];
518
- return message.includes(errorMsg);
519
- }) || [], 2), _errorMsg = _a[0], errorType = _a[1];
360
+ const [_errorMsg, errorType] = Object.entries(messageErrorTypeMap).find(([errorMsg]) => message.includes(errorMsg)) || [];
520
361
  if (errorType !== undefined) {
521
- var remediationMessage = generateRTFRemediation(errorType, modelDefinition, predicatesGroup);
522
- logger.warn("".concat(header, "\n").concat(message, "\n").concat(remediationMessage));
362
+ const remediationMessage = generateRTFRemediation(errorType, modelDefinition, predicatesGroup);
363
+ logger.warn(`${header}\n${message}\n${remediationMessage}`);
523
364
  return true;
524
365
  }
525
366
  return false;
526
- };
527
- return SubscriptionProcessor;
528
- }());
367
+ }
368
+ }
529
369
  export { SubscriptionProcessor };