UNPKG

29.1 kBJavaScriptView Raw
1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3import { __assign, __awaiter, __generator, __rest } from "tslib";
4import { ConsoleLogger as Logger, ClientDevice, Credentials, Signer, Hub, getAmplifyUserAgent, transferKeyToLowerCase, transferKeyToUpperCase, } from '@aws-amplify/core';
5import { PinpointClient, PutEventsCommand, UpdateEndpointCommand, } from '@aws-sdk/client-pinpoint';
6import { Cache } from '@aws-amplify/cache';
7import { v1 as uuid } from 'uuid';
8import EventsBuffer from './EventBuffer';
9var AMPLIFY_SYMBOL = (typeof Symbol !== 'undefined' && typeof Symbol.for === 'function'
10 ? Symbol.for('amplify_default')
11 : '@@amplify_default');
12var dispatchAnalyticsEvent = function (event, data) {
13 Hub.dispatch('analytics', { event: event, data: data }, 'Analytics', AMPLIFY_SYMBOL);
14};
15var logger = new Logger('AWSPinpointProvider');
16var RETRYABLE_CODES = [429, 500];
17var ACCEPTED_CODES = [202];
18var FORBIDDEN_CODE = 403;
19var MOBILE_SERVICE_NAME = 'mobiletargeting';
20var EXPIRED_TOKEN_CODE = 'ExpiredTokenException';
21var UPDATE_ENDPOINT = '_update_endpoint';
22var SESSION_START = '_session.start';
23var SESSION_STOP = '_session.stop';
24var BEACON_SUPPORTED = typeof navigator !== 'undefined' &&
25 navigator &&
26 typeof navigator.sendBeacon === 'function';
27// events buffer
28var BUFFER_SIZE = 1000;
29var FLUSH_SIZE = 100;
30var FLUSH_INTERVAL = 5 * 1000; // 5s
31var RESEND_LIMIT = 5;
32// params: { event: {name: , .... }, timeStamp, config, resendLimits }
33var AWSPinpointProvider = /** @class */ (function () {
34 function AWSPinpointProvider(config) {
35 this._endpointGenerating = true;
36 this._endpointUpdateInProgress = false;
37 this._buffer = null;
38 this._endpointBuffer = [];
39 this._config = config ? config : {};
40 this._config.bufferSize = this._config.bufferSize || BUFFER_SIZE;
41 this._config.flushSize = this._config.flushSize || FLUSH_SIZE;
42 this._config.flushInterval = this._config.flushInterval || FLUSH_INTERVAL;
43 this._config.resendLimit = this._config.resendLimit || RESEND_LIMIT;
44 this._clientInfo = ClientDevice.clientInfo();
45 }
46 /**
47 * get the category of the plugin
48 */
49 AWSPinpointProvider.prototype.getCategory = function () {
50 return AWSPinpointProvider.category;
51 };
52 /**
53 * get provider name of the plugin
54 */
55 AWSPinpointProvider.prototype.getProviderName = function () {
56 return AWSPinpointProvider.providerName;
57 };
58 /**
59 * configure the plugin
60 * @param {Object} config - configuration
61 */
62 AWSPinpointProvider.prototype.configure = function (config) {
63 var _this = this;
64 logger.debug('configure Analytics', config);
65 var conf = config || {};
66 this._config = Object.assign({}, this._config, conf);
67 // If autoSessionRecord is enabled, we need to wait for the endpoint to be
68 // updated before sending any events. See `sendEvents` in `Analytics.ts`
69 this._endpointGenerating = !!config['autoSessionRecord'];
70 if (this._config.appId && !this._config.disabled) {
71 if (!this._config.endpointId) {
72 var cacheKey = this.getProviderName() + '_' + this._config.appId;
73 this._getEndpointId(cacheKey)
74 .then(function (endpointId) {
75 logger.debug('setting endpoint id from the cache', endpointId);
76 _this._config.endpointId = endpointId;
77 dispatchAnalyticsEvent('pinpointProvider_configured', null);
78 })
79 .catch(function (err) {
80 logger.debug('Failed to generate endpointId', err);
81 });
82 }
83 else {
84 dispatchAnalyticsEvent('pinpointProvider_configured', null);
85 }
86 }
87 else {
88 this._flushBuffer();
89 }
90 return this._config;
91 };
92 /**
93 * record an event
94 * @param {Object} params - the params of an event
95 */
96 AWSPinpointProvider.prototype.record = function (params, handlers) {
97 return __awaiter(this, void 0, void 0, function () {
98 var credentials, timestamp;
99 return __generator(this, function (_a) {
100 switch (_a.label) {
101 case 0:
102 logger.debug('_public record', params);
103 return [4 /*yield*/, this._getCredentials()];
104 case 1:
105 credentials = _a.sent();
106 if (!credentials || !this._config.appId || !this._config.region) {
107 logger.debug('cannot send events without credentials, applicationId or region');
108 return [2 /*return*/, handlers.reject(new Error('No credentials, applicationId or region'))];
109 }
110 this._initClients(credentials);
111 timestamp = new Date().getTime();
112 // attach the session and eventId
113 this._generateSession(params);
114 params.event.eventId = uuid();
115 Object.assign(params, { timestamp: timestamp, config: this._config });
116 if (params.event.immediate) {
117 return [2 /*return*/, this._send(params, handlers)];
118 }
119 else {
120 this._putToBuffer(params, handlers);
121 }
122 return [2 /*return*/];
123 }
124 });
125 });
126 };
127 AWSPinpointProvider.prototype._sendEndpointUpdate = function (endpointObject) {
128 return __awaiter(this, void 0, void 0, function () {
129 var next;
130 return __generator(this, function (_a) {
131 switch (_a.label) {
132 case 0:
133 if (this._endpointUpdateInProgress) {
134 this._endpointBuffer.push(endpointObject);
135 return [2 /*return*/];
136 }
137 this._endpointUpdateInProgress = true;
138 return [4 /*yield*/, this._updateEndpoint(endpointObject)];
139 case 1:
140 _a.sent();
141 next = this._endpointBuffer.shift();
142 this._endpointUpdateInProgress = false;
143 next && this._sendEndpointUpdate(next);
144 return [2 /*return*/];
145 }
146 });
147 });
148 };
149 /**
150 * @private
151 * @param params - params for event recording
152 * Put events into buffer
153 */
154 AWSPinpointProvider.prototype._putToBuffer = function (params, handlers) {
155 if (params.event.name === UPDATE_ENDPOINT) {
156 this._sendEndpointUpdate({ params: params, handlers: handlers });
157 return;
158 }
159 this._buffer && this._buffer.push({ params: params, handlers: handlers });
160 };
161 AWSPinpointProvider.prototype._generateSession = function (params) {
162 this._sessionId = this._sessionId || uuid();
163 var event = params.event;
164 switch (event.name) {
165 case SESSION_START:
166 // refresh the session id and session start time
167 this._sessionStartTimestamp = new Date().getTime();
168 this._sessionId = uuid();
169 event.session = {
170 Id: this._sessionId,
171 StartTimestamp: new Date(this._sessionStartTimestamp).toISOString(),
172 };
173 break;
174 case SESSION_STOP:
175 var stopTimestamp = new Date().getTime();
176 this._sessionStartTimestamp =
177 this._sessionStartTimestamp || new Date().getTime();
178 this._sessionId = this._sessionId || uuid();
179 event.session = {
180 Id: this._sessionId,
181 Duration: stopTimestamp - this._sessionStartTimestamp,
182 StartTimestamp: new Date(this._sessionStartTimestamp).toISOString(),
183 StopTimestamp: new Date(stopTimestamp).toISOString(),
184 };
185 this._sessionId = undefined;
186 this._sessionStartTimestamp = undefined;
187 break;
188 default:
189 this._sessionStartTimestamp =
190 this._sessionStartTimestamp || new Date().getTime();
191 this._sessionId = this._sessionId || uuid();
192 event.session = {
193 Id: this._sessionId,
194 StartTimestamp: new Date(this._sessionStartTimestamp).toISOString(),
195 };
196 }
197 };
198 AWSPinpointProvider.prototype._send = function (params, handlers) {
199 return __awaiter(this, void 0, void 0, function () {
200 var event;
201 return __generator(this, function (_a) {
202 event = params.event;
203 switch (event.name) {
204 case UPDATE_ENDPOINT:
205 return [2 /*return*/, this._updateEndpoint({ params: params, handlers: handlers })];
206 case SESSION_STOP:
207 return [2 /*return*/, this._pinpointSendStopSession(params, handlers)];
208 default:
209 return [2 /*return*/, this._pinpointPutEvents(params, handlers)];
210 }
211 return [2 /*return*/];
212 });
213 });
214 };
215 AWSPinpointProvider.prototype._generateBatchItemContext = function (params) {
216 var _a;
217 var event = params.event, timestamp = params.timestamp, config = params.config;
218 var name = event.name, attributes = event.attributes, metrics = event.metrics, eventId = event.eventId, session = event.session;
219 var appId = config.appId, endpointId = config.endpointId;
220 var endpointContext = {};
221 var eventParams = {
222 ApplicationId: appId,
223 EventsRequest: {
224 BatchItem: {},
225 },
226 };
227 var endpointObj = {};
228 endpointObj.Endpoint = endpointContext;
229 endpointObj.Events = (_a = {},
230 _a[eventId] = {
231 EventType: name,
232 Timestamp: new Date(timestamp).toISOString(),
233 Attributes: attributes,
234 Metrics: metrics,
235 Session: session,
236 },
237 _a);
238 eventParams.EventsRequest.BatchItem[endpointId] = endpointObj;
239 return eventParams;
240 };
241 AWSPinpointProvider.prototype._pinpointPutEvents = function (params, handlers) {
242 return __awaiter(this, void 0, void 0, function () {
243 var eventId, endpointId, eventParams, command, data, _a, _b, _c, _d, StatusCode, Message, err_1;
244 return __generator(this, function (_e) {
245 switch (_e.label) {
246 case 0:
247 eventId = params.event.eventId, endpointId = params.config.endpointId;
248 eventParams = this._generateBatchItemContext(params);
249 command = new PutEventsCommand(eventParams);
250 _e.label = 1;
251 case 1:
252 _e.trys.push([1, 3, , 4]);
253 return [4 /*yield*/, this.pinpointClient.send(command)];
254 case 2:
255 data = _e.sent();
256 _a = data, _b = endpointId, _c = eventId, _d = _a.EventsResponse.Results[_b].EventsItemResponse[_c], StatusCode = _d.StatusCode, Message = _d.Message;
257 if (ACCEPTED_CODES.includes(StatusCode)) {
258 logger.debug('record event success. ', data);
259 return [2 /*return*/, handlers.resolve(data)];
260 }
261 else {
262 if (RETRYABLE_CODES.includes(StatusCode)) {
263 this._retry(params, handlers);
264 }
265 else {
266 logger.error("Event " + eventId + " is not accepted, the error is " + Message);
267 return [2 /*return*/, handlers.reject(data)];
268 }
269 }
270 return [3 /*break*/, 4];
271 case 3:
272 err_1 = _e.sent();
273 this._eventError(err_1);
274 return [2 /*return*/, handlers.reject(err_1)];
275 case 4: return [2 /*return*/];
276 }
277 });
278 });
279 };
280 AWSPinpointProvider.prototype._pinpointSendStopSession = function (params, handlers) {
281 if (!BEACON_SUPPORTED) {
282 this._pinpointPutEvents(params, handlers);
283 return;
284 }
285 var eventParams = this._generateBatchItemContext(params);
286 var region = this._config.region;
287 var ApplicationId = eventParams.ApplicationId, EventsRequest = eventParams.EventsRequest;
288 var accessInfo = {
289 secret_key: this._config.credentials.secretAccessKey,
290 access_key: this._config.credentials.accessKeyId,
291 session_token: this._config.credentials.sessionToken,
292 };
293 var url = "https://pinpoint." + region + ".amazonaws.com/v1/apps/" + ApplicationId + "/events/legacy";
294 var body = JSON.stringify(EventsRequest);
295 var method = 'POST';
296 var request = {
297 url: url,
298 body: body,
299 method: method,
300 };
301 var serviceInfo = { region: region, service: MOBILE_SERVICE_NAME };
302 var requestUrl = Signer.signUrl(request, accessInfo, serviceInfo, null);
303 var success = navigator.sendBeacon(requestUrl, body);
304 if (success) {
305 return handlers.resolve('sendBeacon success');
306 }
307 return handlers.reject('sendBeacon failure');
308 };
309 AWSPinpointProvider.prototype._retry = function (params, handlers) {
310 var resendLimit = params.config.resendLimit;
311 // For backward compatibility
312 params.resendLimit =
313 typeof params.resendLimit === 'number' ? params.resendLimit : resendLimit;
314 if (params.resendLimit-- > 0) {
315 logger.debug("resending event " + params.eventName + " with " + params.resendLimit + " retry times left");
316 this._pinpointPutEvents(params, handlers);
317 }
318 else {
319 logger.debug("retry times used up for event " + params.eventName);
320 }
321 };
322 AWSPinpointProvider.prototype._updateEndpoint = function (endpointObject) {
323 return __awaiter(this, void 0, void 0, function () {
324 var params, handlers, config, event, appId, endpointId, request, update_params, command, data, err_2, failureData;
325 return __generator(this, function (_a) {
326 switch (_a.label) {
327 case 0:
328 params = endpointObject.params, handlers = endpointObject.handlers;
329 config = params.config, event = params.event;
330 appId = config.appId, endpointId = config.endpointId;
331 request = this._endpointRequest(config, transferKeyToLowerCase(event, [], ['attributes', 'userAttributes', 'Attributes', 'UserAttributes']));
332 update_params = {
333 ApplicationId: appId,
334 EndpointId: endpointId,
335 EndpointRequest: request,
336 };
337 _a.label = 1;
338 case 1:
339 _a.trys.push([1, 3, , 4]);
340 command = new UpdateEndpointCommand(update_params);
341 return [4 /*yield*/, this.pinpointClient.send(command)];
342 case 2:
343 data = _a.sent();
344 logger.debug('updateEndpoint success', data);
345 this._endpointGenerating = false;
346 this._resumeBuffer();
347 handlers.resolve(data);
348 return [2 /*return*/];
349 case 3:
350 err_2 = _a.sent();
351 failureData = {
352 err: err_2,
353 update_params: update_params,
354 endpointObject: endpointObject,
355 };
356 return [2 /*return*/, this._handleEndpointUpdateFailure(failureData)];
357 case 4: return [2 /*return*/];
358 }
359 });
360 });
361 };
362 AWSPinpointProvider.prototype._handleEndpointUpdateFailure = function (failureData) {
363 return __awaiter(this, void 0, void 0, function () {
364 var err, endpointObject, statusCode, exponential;
365 return __generator(this, function (_a) {
366 err = failureData.err, endpointObject = failureData.endpointObject;
367 statusCode = err.$metadata && err.$metadata.httpStatusCode;
368 logger.debug('updateEndpoint error', err);
369 switch (statusCode) {
370 case FORBIDDEN_CODE:
371 return [2 /*return*/, this._handleEndpointUpdateForbidden(failureData)];
372 default:
373 if (RETRYABLE_CODES.includes(statusCode)) {
374 exponential = true;
375 return [2 /*return*/, this._retryEndpointUpdate(endpointObject, exponential)];
376 }
377 logger.error('updateEndpoint failed', err);
378 endpointObject.handlers.reject(err);
379 }
380 return [2 /*return*/];
381 });
382 });
383 };
384 AWSPinpointProvider.prototype._handleEndpointUpdateForbidden = function (failureData) {
385 var err = failureData.err, endpointObject = failureData.endpointObject;
386 var code = err.code, retryable = err.retryable;
387 if (code !== EXPIRED_TOKEN_CODE && !retryable) {
388 return endpointObject.handlers.reject(err);
389 }
390 this._retryEndpointUpdate(endpointObject);
391 };
392 AWSPinpointProvider.prototype._retryEndpointUpdate = function (endpointObject, exponential) {
393 if (exponential === void 0) { exponential = false; }
394 logger.debug('_retryEndpointUpdate', endpointObject);
395 var params = endpointObject.params;
396 // TODO: implement retry with exp back off once exp function is available
397 var resendLimit = params.config.resendLimit;
398 params.resendLimit =
399 typeof params.resendLimit === 'number' ? params.resendLimit : resendLimit;
400 if (params.resendLimit-- > 0) {
401 logger.debug("resending endpoint update " + params.event.eventId + " with " + params.resendLimit + " retry attempts remaining");
402 // insert at the front of endpointBuffer
403 this._endpointBuffer.length
404 ? this._endpointBuffer.unshift(endpointObject)
405 : this._updateEndpoint(endpointObject);
406 return;
407 }
408 logger.warn("resending endpoint update " + params.event.eventId + " failed after " + params.config.resendLimit + " attempts");
409 if (this._endpointGenerating) {
410 logger.error('Initial endpoint update failed. ');
411 }
412 };
413 /**
414 * @private
415 * @param config
416 * Init the clients
417 */
418 AWSPinpointProvider.prototype._initClients = function (credentials) {
419 return __awaiter(this, void 0, void 0, function () {
420 var identityId, region;
421 return __generator(this, function (_a) {
422 logger.debug('init clients');
423 if (this.pinpointClient &&
424 this._config.credentials &&
425 this._config.credentials.sessionToken === credentials.sessionToken &&
426 this._config.credentials.identityId === credentials.identityId) {
427 logger.debug('no change for aws credentials, directly return from init');
428 return [2 /*return*/];
429 }
430 identityId = this._config.credentials
431 ? this._config.credentials.identityId
432 : null;
433 this._config.credentials = credentials;
434 region = this._config.region;
435 logger.debug('init clients with credentials', credentials);
436 this.pinpointClient = new PinpointClient({
437 region: region,
438 credentials: credentials,
439 customUserAgent: getAmplifyUserAgent(),
440 });
441 // TODO: remove this middleware once a long term fix is implemented by aws-sdk-js team.
442 this.pinpointClient.middlewareStack.addRelativeTo(function (next) { return function (args) {
443 delete args.request.headers['amz-sdk-invocation-id'];
444 delete args.request.headers['amz-sdk-request'];
445 return next(args);
446 }; }, {
447 step: 'finalizeRequest',
448 relation: 'after',
449 toMiddleware: 'retryMiddleware',
450 });
451 if (this._bufferExists() && identityId === credentials.identityId) {
452 // if the identity has remained the same, pass the updated client to the buffer
453 this._updateBufferClient();
454 }
455 else {
456 // otherwise flush the buffer and instantiate a new one
457 // this will cause the old buffer to send any remaining events
458 // with the old credentials and then stop looping and shortly thereafter get picked up by GC
459 this._initBuffer();
460 }
461 this._customizePinpointClientReq();
462 return [2 /*return*/];
463 });
464 });
465 };
466 AWSPinpointProvider.prototype._bufferExists = function () {
467 return this._buffer && this._buffer instanceof EventsBuffer;
468 };
469 AWSPinpointProvider.prototype._initBuffer = function () {
470 if (this._bufferExists()) {
471 this._flushBuffer();
472 }
473 this._buffer = new EventsBuffer(this.pinpointClient, this._config);
474 // if the first endpoint update hasn't yet resolved pause the buffer to
475 // prevent race conditions. It will be resumed as soon as that request succeeds
476 if (this._endpointGenerating) {
477 this._buffer.pause();
478 }
479 };
480 AWSPinpointProvider.prototype._updateBufferClient = function () {
481 if (this._bufferExists()) {
482 this._buffer.updateClient(this.pinpointClient);
483 }
484 };
485 AWSPinpointProvider.prototype._flushBuffer = function () {
486 if (this._bufferExists()) {
487 this._buffer.flush();
488 this._buffer = null;
489 }
490 };
491 AWSPinpointProvider.prototype._resumeBuffer = function () {
492 if (this._bufferExists()) {
493 this._buffer.resume();
494 }
495 };
496 AWSPinpointProvider.prototype._customizePinpointClientReq = function () {
497 // TODO FIXME: Find a middleware to do this with AWS V3 SDK
498 // if (Platform.isReactNative) {
499 // this.pinpointClient.customizeRequests(request => {
500 // request.on('build', req => {
501 // req.httpRequest.headers['user-agent'] = Platform.userAgent;
502 // });
503 // });
504 // }
505 };
506 AWSPinpointProvider.prototype._getEndpointId = function (cacheKey) {
507 return __awaiter(this, void 0, void 0, function () {
508 var endpointId, ttl, expiration;
509 return __generator(this, function (_a) {
510 switch (_a.label) {
511 case 0: return [4 /*yield*/, Cache.getItem(cacheKey)];
512 case 1:
513 endpointId = _a.sent();
514 logger.debug('endpointId from cache', endpointId, 'type', typeof endpointId);
515 if (!endpointId) {
516 endpointId = uuid();
517 ttl = 1000 * 60 * 60 * 24 * 365 * 100;
518 expiration = new Date().getTime() + ttl;
519 Cache.setItem(cacheKey, endpointId, {
520 expires: expiration,
521 priority: 1,
522 });
523 }
524 return [2 /*return*/, endpointId];
525 }
526 });
527 });
528 };
529 /**
530 * EndPoint request
531 * @return {Object} - The request of updating endpoint
532 */
533 AWSPinpointProvider.prototype._endpointRequest = function (config, event) {
534 var credentials = config.credentials;
535 var clientInfo = this._clientInfo || {};
536 var clientContext = config.clientContext || {};
537 // for now we have three different ways for default endpoint configurations
538 // clientInfo
539 // clientContext (deprecated)
540 // config.endpoint
541 var defaultEndpointConfig = config.endpoint || {};
542 var demographicByClientInfo = {
543 appVersion: clientInfo.appVersion,
544 make: clientInfo.make,
545 model: clientInfo.model,
546 modelVersion: clientInfo.version,
547 platform: clientInfo.platform,
548 };
549 // for backward compatibility
550 var clientId = clientContext.clientId, appTitle = clientContext.appTitle, appVersionName = clientContext.appVersionName, appVersionCode = clientContext.appVersionCode, appPackageName = clientContext.appPackageName, demographicByClientContext = __rest(clientContext, ["clientId", "appTitle", "appVersionName", "appVersionCode", "appPackageName"]);
551 var channelType = event.address
552 ? clientInfo.platform === 'android'
553 ? 'GCM'
554 : 'APNS'
555 : undefined;
556 var tmp = __assign(__assign(__assign({ channelType: channelType, requestId: uuid(), effectiveDate: new Date().toISOString() }, defaultEndpointConfig), event), { attributes: __assign(__assign({}, defaultEndpointConfig.attributes), event.attributes), demographic: __assign(__assign(__assign(__assign({}, demographicByClientInfo), demographicByClientContext), defaultEndpointConfig.demographic), event.demographic), location: __assign(__assign({}, defaultEndpointConfig.location), event.location), metrics: __assign(__assign({}, defaultEndpointConfig.metrics), event.metrics), user: {
557 userId: event.userId ||
558 defaultEndpointConfig.userId ||
559 credentials.identityId,
560 userAttributes: __assign(__assign({}, defaultEndpointConfig.userAttributes), event.userAttributes),
561 } });
562 // eliminate unnecessary params
563 var userId = tmp.userId, userAttributes = tmp.userAttributes, name = tmp.name, session = tmp.session, eventId = tmp.eventId, immediate = tmp.immediate, ret = __rest(tmp, ["userId", "userAttributes", "name", "session", "eventId", "immediate"]);
564 return transferKeyToUpperCase(ret, [], ['metrics', 'userAttributes', 'attributes']);
565 };
566 AWSPinpointProvider.prototype._eventError = function (err) {
567 logger.error('record event failed.', err);
568 logger.warn("Please ensure you have updated your Pinpoint IAM Policy " +
569 "with the Action: \"mobiletargeting:PutEvents\" " +
570 "in order to record events");
571 };
572 AWSPinpointProvider.prototype._getCredentials = function () {
573 return __awaiter(this, void 0, void 0, function () {
574 var credentials, err_3;
575 return __generator(this, function (_a) {
576 switch (_a.label) {
577 case 0:
578 _a.trys.push([0, 2, , 3]);
579 return [4 /*yield*/, Credentials.get()];
580 case 1:
581 credentials = _a.sent();
582 if (!credentials)
583 return [2 /*return*/, null];
584 logger.debug('set credentials for analytics', credentials);
585 return [2 /*return*/, Credentials.shear(credentials)];
586 case 2:
587 err_3 = _a.sent();
588 logger.debug('ensure credentials error', err_3);
589 return [2 /*return*/, null];
590 case 3: return [2 /*return*/];
591 }
592 });
593 });
594 };
595 AWSPinpointProvider.category = 'Analytics';
596 AWSPinpointProvider.providerName = 'AWSPinpoint';
597 return AWSPinpointProvider;
598}());
599export { AWSPinpointProvider };
600//# sourceMappingURL=AWSPinpointProvider.js.map
\No newline at end of file