UNPKG

13.7 kBJavaScriptView Raw
1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3import { __awaiter, __generator } from "tslib";
4import { ConsoleLogger as Logger, Credentials, getAmplifyUserAgent, browserOrNode, } from '@aws-amplify/core';
5import { PersonalizeEventsClient, PutEventsCommand, } from '@aws-sdk/client-personalize-events';
6import { SessionInfoManager, MediaAutoTrack, } from './AmazonPersonalizeHelper';
7import get from 'lodash/get';
8import isEmpty from 'lodash/isEmpty';
9import isEqual from 'lodash/isEqual';
10var logger = new Logger('AmazonPersonalizeProvider');
11// events buffer
12var FLUSH_SIZE = 5;
13var FLUSH_SIZE_THRESHHOLD = 10;
14var FLUSH_INTERVAL = 5 * 1000; // 5s
15var IDENTIFY_EVENT = 'Identify';
16var AmazonPersonalizeProvider = /** @class */ (function () {
17 function AmazonPersonalizeProvider(config) {
18 this._buffer = [];
19 this._config = config ? config : {};
20 this._config.flushSize =
21 this._config.flushSize > 0 &&
22 this._config.flushSize <= FLUSH_SIZE_THRESHHOLD
23 ? this._config.flushSize
24 : FLUSH_SIZE;
25 this._config.flushInterval = this._config.flushInterval || FLUSH_INTERVAL;
26 this._sessionManager = new SessionInfoManager();
27 if (!isEmpty(this._config.trackingId)) {
28 this._sessionInfo = this._sessionManager.retrieveSessionInfo(this._config.trackingId);
29 }
30 this._isBrowser = browserOrNode().isBrowser;
31 // flush event buffer
32 this._setupTimer();
33 }
34 AmazonPersonalizeProvider.prototype._setupTimer = function () {
35 if (this._timer) {
36 clearInterval(this._timer);
37 }
38 var flushInterval = this._config.flushInterval;
39 var that = this;
40 this._timer = setInterval(function () {
41 that._sendFromBuffer();
42 }, flushInterval);
43 };
44 /**
45 * Record event
46 * @param eventType - type of the event action. e.g. "Click"
47 * @param properties - properties of the event
48 * @return Promise
49 */
50 AmazonPersonalizeProvider.prototype.record = function (params) {
51 return __awaiter(this, void 0, void 0, function () {
52 var credentials, _a, eventType, properties, requestParams, isLoaded;
53 return __generator(this, function (_b) {
54 switch (_b.label) {
55 case 0: return [4 /*yield*/, this._getCredentials()];
56 case 1:
57 credentials = _b.sent();
58 if (!credentials)
59 return [2 /*return*/, Promise.resolve(false)];
60 Object.assign(params, {
61 config: this._config,
62 credentials: credentials,
63 sentAt: new Date(),
64 });
65 _a = params.event, eventType = _a.eventType, properties = _a.properties;
66 if (eventType === IDENTIFY_EVENT) {
67 this._sessionManager.updateSessionInfo(properties && properties.userId ? properties.userId : '', this._sessionInfo);
68 return [2 /*return*/];
69 }
70 else if (!isEmpty(params.event.userId)) {
71 this._sessionManager.updateSessionInfo(params.event.userId, this._sessionInfo);
72 }
73 requestParams = this.generateRequestParams(params, this._sessionInfo);
74 if (!(eventType === 'MediaAutoTrack')) return [3 /*break*/, 7];
75 if (!this._isBrowser) return [3 /*break*/, 5];
76 if (!!isEmpty(get(requestParams, 'eventData.properties.domElementId', null))) return [3 /*break*/, 3];
77 return [4 /*yield*/, this.isElementFullyLoaded(this.loadElement, requestParams.eventData.properties['domElementId'], 500, 5)];
78 case 2:
79 isLoaded = _b.sent();
80 if (isLoaded) {
81 new MediaAutoTrack(requestParams, this);
82 }
83 else {
84 logger.debug('Cannot find the media element.');
85 }
86 return [3 /*break*/, 4];
87 case 3:
88 logger.debug("Missing domElementId field in 'properties' for MediaAutoTrack event type.");
89 _b.label = 4;
90 case 4: return [3 /*break*/, 6];
91 case 5:
92 logger.debug('MediaAutoTrack only for browser');
93 _b.label = 6;
94 case 6: return [2 /*return*/];
95 case 7: return [2 /*return*/, this.putToBuffer(requestParams)];
96 }
97 });
98 });
99 };
100 AmazonPersonalizeProvider.prototype.loadElement = function (domId) {
101 return new Promise(function (resolve, reject) {
102 if (document.getElementById(domId) &&
103 document.getElementById(domId).clientHeight) {
104 return resolve(true);
105 }
106 else {
107 return reject(true);
108 }
109 });
110 };
111 AmazonPersonalizeProvider.prototype.isElementFullyLoaded = function (operation, params, delay, times) {
112 var _this = this;
113 var wait = function (ms) { return new Promise(function (r) { return setTimeout(r, ms); }); };
114 return new Promise(function (resolve, reject) {
115 return operation(params)
116 .then(resolve)
117 .catch(function (reason) {
118 if (times - 1 > 0) {
119 return wait(delay)
120 .then(_this.isElementFullyLoaded.bind(null, operation, params, delay, times - 1))
121 .then(resolve)
122 .catch(reject);
123 }
124 return reject(reason);
125 });
126 });
127 };
128 /**
129 * get the category of the plugin
130 */
131 AmazonPersonalizeProvider.prototype.getCategory = function () {
132 return 'Analytics';
133 };
134 /**
135 * get provider name of the plugin
136 */
137 AmazonPersonalizeProvider.prototype.getProviderName = function () {
138 return 'AmazonPersonalize';
139 };
140 /**
141 * configure the plugin
142 * @param {Object} config - configuration
143 */
144 AmazonPersonalizeProvider.prototype.configure = function (config) {
145 logger.debug('configure Analytics', config);
146 var conf = config ? config : {};
147 this._config = Object.assign({}, this._config, conf);
148 if (!isEmpty(this._config.trackingId)) {
149 this._sessionInfo = this._sessionManager.retrieveSessionInfo(this._config.trackingId);
150 }
151 this._setupTimer();
152 return this._config;
153 };
154 /**
155 * Generate the requestParams from customer input params and sessionInfo
156 * @private
157 * @param eventData - customer input for event data
158 * @param api - api name
159 * @return RequestParams - wrapper object with all information required for make request
160 */
161 AmazonPersonalizeProvider.prototype.generateRequestParams = function (params, sessionInfo) {
162 var requestParams = {};
163 var _a = params.event, eventType = _a.eventType, properties = _a.properties;
164 requestParams.eventData = { eventType: eventType, properties: properties };
165 requestParams.sessionInfo = sessionInfo;
166 requestParams.sentAt = params.sentAt;
167 requestParams.credentials = params.credentials;
168 requestParams.config = params.config;
169 return requestParams;
170 };
171 /**
172 * record an event
173 * @param {Object} params - the params of an event
174 */
175 AmazonPersonalizeProvider.prototype._sendEvents = function (group) {
176 var groupLen = group.length;
177 if (groupLen === 0) {
178 logger.debug('events array is empty, directly return');
179 return;
180 }
181 var _a = group[0], config = _a.config, credentials = _a.credentials, sessionInfo = _a.sessionInfo;
182 var initClients = this._init(config, credentials);
183 if (!initClients)
184 return false;
185 if (groupLen > 0) {
186 var events = [];
187 for (var i = 0; i < groupLen; i += 1) {
188 var params = group.shift();
189 var eventPayload = this._generateSingleRecordPayload(params, sessionInfo);
190 events.push(eventPayload);
191 }
192 var payload_1 = {};
193 payload_1.trackingId = sessionInfo.trackingId;
194 payload_1.sessionId = sessionInfo.sessionId;
195 payload_1.userId = sessionInfo.userId;
196 payload_1.eventList = [];
197 events.forEach(function (event) {
198 // @ts-ignore
199 payload_1.eventList.push(event);
200 });
201 var command = new PutEventsCommand(payload_1);
202 this._personalize.send(command, function (err) {
203 if (err)
204 logger.debug('Failed to call putEvents in Personalize', err);
205 else
206 logger.debug('Put events');
207 });
208 }
209 };
210 /**
211 * Put event into buffer
212 * @private
213 * @param params - params for the event recording
214 */
215 AmazonPersonalizeProvider.prototype.putToBuffer = function (params) {
216 if (this._buffer.length < this._config.flushSize) {
217 this._buffer.push(params);
218 }
219 else {
220 this._buffer.push(params);
221 this._sendFromBuffer();
222 }
223 return Promise.resolve(true);
224 };
225 /**
226 * flush the buffer and batch sending the request
227 * @private
228 * @param eventsParams - the buffer for cache the payload
229 */
230 AmazonPersonalizeProvider.prototype._sendFromBuffer = function () {
231 var _this = this;
232 var size = this._buffer.length;
233 if (size <= 0)
234 return;
235 var eventsGroups = [];
236 var preCred = null;
237 var group = [];
238 for (var i = 0; i < size; i += 1) {
239 var currRequestParams = this._buffer.shift();
240 var cred = currRequestParams.credentials;
241 var sessionInfo = currRequestParams.sessionInfo;
242 if (i === 0) {
243 group.push(currRequestParams);
244 preCred = cred;
245 }
246 else {
247 if (isEqual(sessionInfo, this._sessionInfo) &&
248 cred.sessionToken === preCred.sessionToken &&
249 cred.identityId === preCred.identityId) {
250 logger.debug('no change for cred, put event in the same group');
251 group.push(currRequestParams);
252 }
253 else {
254 eventsGroups.push(group);
255 group = [];
256 group.push(currRequestParams);
257 preCred = cred;
258 this._sessionInfo = sessionInfo;
259 }
260 }
261 }
262 eventsGroups.push(group);
263 eventsGroups.map(function (group) {
264 _this._sendEvents(group);
265 });
266 };
267 /**
268 * Generate the record payload for single event
269 * @private
270 * @param params - RequestParams
271 */
272 AmazonPersonalizeProvider.prototype._generateSingleRecordPayload = function (params, sessionInfo) {
273 var eventData = params.eventData, sentAt = params.sentAt;
274 var trackPayload = {};
275 trackPayload.sentAt = sentAt;
276 trackPayload.properties =
277 eventData.properties && JSON.stringify(eventData.properties);
278 trackPayload.eventId =
279 this._sessionManager.getTimerKey() + sessionInfo.sessionId;
280 trackPayload.eventType = eventData.eventType;
281 return trackPayload;
282 };
283 /**
284 * Initialize the personalize client
285 * @private
286 * @param params - RequestParams
287 */
288 AmazonPersonalizeProvider.prototype._init = function (config, credentials) {
289 logger.debug('init clients');
290 if (this._personalize &&
291 this._config.credentials &&
292 this._config.credentials.sessionToken === credentials.sessionToken &&
293 this._config.credentials.identityId === credentials.identityId) {
294 logger.debug('no change for analytics config, directly return from init');
295 return true;
296 }
297 this._config.credentials = credentials;
298 var region = config.region;
299 logger.debug('initialize personalize with credentials', credentials);
300 this._personalize = new PersonalizeEventsClient({
301 region: region,
302 credentials: credentials,
303 customUserAgent: getAmplifyUserAgent(),
304 });
305 return true;
306 };
307 /**
308 * check if current credentials exists
309 * @private
310 */
311 AmazonPersonalizeProvider.prototype._getCredentials = function () {
312 var that = this;
313 return Credentials.get()
314 .then(function (credentials) {
315 if (!credentials)
316 return null;
317 logger.debug('set credentials for analytics', that._config.credentials);
318 return Credentials.shear(credentials);
319 })
320 .catch(function (err) {
321 logger.debug('ensure credentials error', err);
322 return null;
323 });
324 };
325 return AmazonPersonalizeProvider;
326}());
327export { AmazonPersonalizeProvider };
328//# sourceMappingURL=AmazonPersonalizeProvider.js.map
\No newline at end of file