comprodls-sdk 2.90.3-development → 2.91.0-thor

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 (42) hide show
  1. package/README.md +1 -137
  2. package/dist/comprodls-sdk.js +2917 -6291
  3. package/dist/comprodls-sdk.min.js +1 -1
  4. package/lib/comprodls.js +39 -57
  5. package/lib/config/index.js +172 -198
  6. package/lib/helpers/index.js +3 -2
  7. package/lib/helpers/lib/api/converter.js +1 -2
  8. package/lib/helpers/lib/api/index.js +19 -94
  9. package/lib/helpers/lib/errors.js +75 -80
  10. package/lib/helpers/lib/requestLayer.js +154 -0
  11. package/lib/helpers/lib/validator.js +65 -52
  12. package/lib/open_access/index.js +48 -53
  13. package/lib/services/analytics/index.js +286 -1014
  14. package/lib/services/attempts/index.js +38 -88
  15. package/lib/services/auth/index.js +324 -806
  16. package/lib/services/authextn/index.js +85 -247
  17. package/lib/services/datasyncmanager/index.js +10 -45
  18. package/lib/services/drive/index.js +20 -83
  19. package/lib/services/integrations/index.js +51 -126
  20. package/lib/services/invitations/index.js +20 -61
  21. package/lib/services/product/index.js +82 -85
  22. package/lib/services/pub/index.js +167 -235
  23. package/lib/services/pushX/index.js +195 -142
  24. package/lib/services/pushX/pubnubClientWrapper.js +399 -172
  25. package/lib/services/rules/index.js +14 -67
  26. package/lib/services/spaces/index.js +106 -289
  27. package/lib/services/spacesextn/index.js +44 -20
  28. package/lib/services/superuser/index.js +21 -36
  29. package/lib/services/taxonomy/index.js +27 -57
  30. package/lib/services/workflows/index.js +38 -97
  31. package/lib/services/xapi/index.js +7 -168
  32. package/lib/token/index.js +73 -67
  33. package/lib/token/validations.js +45 -48
  34. package/package.json +2 -3
  35. package/lib/helpers/lib/api/validations.js +0 -73
  36. package/lib/helpers/lib/utils.js +0 -24
  37. package/lib/services/activity/activity.js +0 -209
  38. package/lib/services/activity/attempt.js +0 -431
  39. package/lib/services/activity/index.js +0 -28
  40. package/lib/services/auth/classProduct.js +0 -37
  41. package/lib/services/collab/index.js +0 -468
  42. package/test.js +0 -38
@@ -1,5 +1,6 @@
1
- var pubNub = require("pubnub");
2
- var EventEmitter = require("events").EventEmitter;
1
+ var pubNub = require('pubnub');
2
+ var request = require('superagent');
3
+ var EventEmitter = require('events').EventEmitter;
3
4
  var helpers = require('../../helpers');
4
5
 
5
6
  var PUSHXError = helpers.errors.PUSHXError;
@@ -12,200 +13,426 @@ var CHANNEL_DELIMITER = '$';
12
13
  * implementation details - allowing future switch (to a different Saas provider).
13
14
  */
14
15
  module.exports = function () {
15
- "use strict";
16
+ 'use strict';
16
17
 
17
- /** ====== MODULE GLOBALS */
18
- var _pubnubClient; //SAAS provider client SDK (PubNub).
19
- var _eventEmitter = new EventEmitter();
20
- var _userOptions;
21
- var _globalSubscription = [];
22
- var _globalSubscriptionStatus = {};
23
- var bStatusSubscribed = false;
18
+ /** ====== MODULE GLOBALS */
19
+ var _pubnubClient; //SAAS provider client SDK (PubNub).
20
+ var _eventEmitter = new EventEmitter();
21
+ var _userOptions;
22
+ var _globalSubscription = [];
23
+ var _globalSubscriptionStatus = {};
24
+ var bStatusSubscribed = false;
25
+ /** ID of the setTimeout - used for Polling events when PubNub fails */
26
+ var _setTimeoutIDForPolling;
27
+ /** Timestamp from when the events need to be fetched */
28
+ var _startTimestampForPolling;
29
+ /** Counter for polling */
30
+ var _pollingCounter;
31
+ var bPollingInitiated = false;
24
32
 
25
- /** ###### END OF MODULE GLOBALS */
33
+ /** ###### END OF MODULE GLOBALS */
26
34
 
27
- /** ====== UTILITY FUNCTIONS */
35
+ /** ====== UTILITY FUNCTIONS */
28
36
 
29
37
 
30
- /**
31
- * Call this function to make a new client adaptor.
32
- This adapter exposes functions to send message, update user state etc.
33
- * @return (object) : client adapter.
34
- */
35
- var _constructClientAdaptor = function () {
36
- //Returning the adaptor (Plain Javascript object)
37
- return {
38
- "on": function (channelObj, handler) {
39
- var pubNubChannel;
40
- var channelContext = [];
41
-
42
- if((channelObj.orgid || channelObj.userid) || channelObj.accountid ||
43
- channelObj.productid || channelObj.classid)
44
- {
45
- if(channelObj.accountid) { channelContext.push('a-' + channelObj.accountid); }
46
- else {
47
- if(channelObj.orgid) { channelContext.push('o-' + channelObj.orgid); }
48
- if(channelObj.userid) { channelContext.push('u-' + channelObj.userid); }
49
- if(channelObj.productid) { channelContext.push('p-' + channelObj.productid); }
50
- if(channelObj.classid) { channelContext.push('c-' + channelObj.classid); }
51
- }
52
- pubNubChannel = channelContext.join(CHANNEL_DELIMITER) + CHANNEL_DELIMITER +
53
- channelObj.channel;
54
- if(!_globalSubscription.includes(pubNubChannel)) {
55
- _globalSubscription.push(pubNubChannel);
56
- _globalSubscriptionStatus[pubNubChannel] = {
57
- status: 'pending'
58
- };
59
- _eventEmitter.on(pubNubChannel, handler);
60
- _subscribeToPubNubChannels(pubNubChannel);
61
- }
62
- }
63
- else if(channelObj.channel === 'pushx_status' && ! bStatusSubscribed) {
64
- _eventEmitter.on(channelObj.channel, handler);
65
- bStatusSubscribed = true;
66
- }
67
- },
68
- "getMySubscriptionStatus": __getMySubscriptionStatus
69
- };
70
- };
38
+ /**
39
+ * Call this function to make a new client adaptor.
40
+ This adapter exposes functions to send message, update user state etc.
41
+ * @return (object) : client adapter.
42
+ */
43
+ var _constructClientAdaptor = function () {
44
+ //Returning the adaptor (Plain Javascript object)
45
+ return {
46
+ 'on': function (channelObj, handler) {
47
+ // If PubNub fails, we will fetch the events from this timestamp
48
+ _startTimestampForPolling = Date.now();
49
+
50
+ var pubNubChannel;
51
+ var channelContext = [];
71
52
 
72
- var _translatePubnubMessage = function (pubNubEventData) {
73
- var subscribedChannel = pubNubEventData.subscribedChannel;
74
- var message = pubNubEventData.message;
75
- _eventEmitter.emit(subscribedChannel, message);
53
+ if((channelObj.orgid || channelObj.userid) || channelObj.accountid ||
54
+ channelObj.productid || channelObj.classid)
55
+ {
56
+ if(channelObj.accountid) { channelContext.push('a-' + channelObj.accountid); }
57
+ else {
58
+ if(channelObj.orgid) { channelContext.push('o-' + channelObj.orgid); }
59
+ if(channelObj.userid) { channelContext.push('u-' + channelObj.userid); }
60
+ if(channelObj.productid) { channelContext.push('p-' + channelObj.productid); }
61
+ if(channelObj.classid) { channelContext.push('c-' + channelObj.classid); }
62
+ }
63
+ pubNubChannel = channelContext.join(CHANNEL_DELIMITER) + CHANNEL_DELIMITER +
64
+ channelObj.channel;
65
+ if(!_globalSubscription.includes(pubNubChannel)) {
66
+ _globalSubscription.push(pubNubChannel);
67
+ _globalSubscriptionStatus[pubNubChannel] = {
68
+ status: 'pending'
69
+ };
70
+ _eventEmitter.on(pubNubChannel, handler);
71
+ _subscribeToPubNubChannels(pubNubChannel);
72
+ }
73
+ }
74
+ else if(channelObj.channel === 'pushx_status' && ! bStatusSubscribed) {
75
+ _eventEmitter.on(channelObj.channel, handler);
76
+ bStatusSubscribed = true;
77
+ }
78
+
79
+ // Clean up the old events
80
+ _checkOldBubbledEvents();
81
+ },
82
+ 'getMySubscriptionStatus': __getMySubscriptionStatus
76
83
  };
84
+ };
85
+
86
+ var _translatePubnubMessage = function (pubNubEventData) {
87
+ var subscribedChannel = pubNubEventData.subscribedChannel;
88
+ var message = pubNubEventData.message;
89
+ _eventEmitter.emit(subscribedChannel, message);
90
+ };
91
+
92
+ var _translatePubnubStatus = function(status, options) {
93
+ var channels = [], error, successObj;
77
94
 
78
- var _translatePubnubStatus = function(status) {
79
- var channels = [], error, successObj;
80
- switch (status.category) {
81
- case "PNConnectedCategory":
82
- if(status.operation === "PNSubscribeOperation") {
83
- channels = status.subscribedChannels;
84
- for(var i in channels) {
85
- if(_globalSubscriptionStatus[channels[i]]) {
86
- _globalSubscriptionStatus[channels[i]].status = 'subscribed';
87
- }
88
- }
89
- successObj = {
90
- category: 'PUSHX',
91
- type: 'CHANNEL_SUBSCRIPTION',
92
- status: 'SUCCESS',
93
- message: 'Success: Subscribed successfully.',
94
- httpcode: 200,
95
- data: {
96
- payload: {
97
- channels: status.subscribedChannels
98
- },
99
- message: 'Success: Subscribed successfully.'
100
- }
101
- };
102
- _eventEmitter.emit('pushx_status', successObj);
103
- }
104
- break;
105
- case "PNAccessDeniedCategory":
106
- if(status.operation === "PNSubscribeOperation") {
107
- var errorData = {
108
- payload: JSON.parse(status.errorData.response.text).payload,
109
- message: 'Forbidden: Subscription failed.',
110
- errorDetails: {
111
- operation: status.operation,
112
- category: status.category,
113
- statusCode: status.statusCode
114
- }
115
- };
116
- channels = errorData.payload.channels;
117
- for(var j in channels) {
118
- if(_globalSubscriptionStatus[channels[j]]) {
119
- _globalSubscriptionStatus[channels[j]].status = 'error';
120
- _globalSubscriptionStatus[channels[j]].error = error;
121
- }
122
- }
123
- error = new PUSHXError(helpers.errors.ERROR_CATEGORY.PUSHX, errorData);
124
- _eventEmitter.emit('pushx_status', error);
125
- }
126
- break;
127
- case "PNBadRequestCategory":
128
- case "PNNetworkDownCategory":
129
- case "PNNetworkUpCategory":
130
- error = {
131
- message: "PushX Error", status: status.statusCode,
132
- pushXError: status
133
- };
134
- error = new PUSHXError(helpers.errors.ERROR_CATEGORY.PUSHX, error);
135
- _eventEmitter.emit('pushx_status', error);
136
- break;
95
+ // If polling has been initiated, ignore all punnub status
96
+ if (bPollingInitiated) return;
97
+
98
+ switch (status.category) {
99
+ case 'PNConnectedCategory':
100
+ if(status.operation === 'PNSubscribeOperation') {
101
+ channels = status.subscribedChannels;
102
+ for(var i in channels) {
103
+ if(_globalSubscriptionStatus[channels[i]]) {
104
+ _globalSubscriptionStatus[channels[i]].status = 'subscribed';
105
+ }
106
+ }
107
+ successObj = {
108
+ category: 'PUSHX',
109
+ type: 'CHANNEL_SUBSCRIPTION',
110
+ status: 'SUCCESS',
111
+ message: 'Success: Subscribed successfully.',
112
+ httpcode: 200,
113
+ data: {
114
+ payload: {
115
+ channels: status.subscribedChannels
116
+ },
117
+ message: 'Success: Subscribed successfully.'
118
+ }
119
+ };
120
+ _eventEmitter.emit('pushx_status', successObj);
137
121
  }
138
- };
122
+ break;
123
+ case 'PNAccessDeniedCategory':
124
+ if(status.operation === 'PNSubscribeOperation') {
125
+ var errorText = status.errorData.response && status.errorData.response.text;
126
+ var errorJSON = errorText ? JSON.parse(errorText) : undefined;
127
+ var errorData = {
128
+ payload: errorJSON && errorJSON.payload || status.errorData.payload,
129
+ message: 'Forbidden: Subscription failed.',
130
+ errorDetails: {
131
+ operation: status.operation,
132
+ category: status.category,
133
+ statusCode: status.statusCode
134
+ }
135
+ };
136
+ channels = errorData.payload.channels;
137
+ for(var j in channels) {
138
+ if(_globalSubscriptionStatus[channels[j]]) {
139
+ _globalSubscriptionStatus[channels[j]].status = 'error';
140
+ _globalSubscriptionStatus[channels[j]].error = error;
141
+ }
142
+ }
143
+ error = new PUSHXError(helpers.errors.ERROR_CATEGORY.PUSHX, errorData);
144
+ _eventEmitter.emit('pushx_status', error);
145
+ }
146
+ break;
147
+ case 'PNBadRequestCategory':
148
+ case 'PNNetworkDownCategory':
149
+ case 'PNNetworkUpCategory':
150
+ error = {
151
+ message: 'PushX Error', status: status.statusCode,
152
+ pushXError: status
153
+ };
154
+ error = new PUSHXError(helpers.errors.ERROR_CATEGORY.PUSHX, error);
155
+ _eventEmitter.emit('pushx_status', error);
156
+ break;
157
+ case 'PNNetworkIssuesCategory':
158
+ if(status.operation === 'PNSubscribeOperation') {
159
+ if(!options.accountId || !_userOptions.pollingEndpoint) {
160
+ error = {
161
+ message: 'Polling initiation error: Missing mandatory parameters to initiate polling operation - [accountId, pollingEndpoint]',
162
+ status: status.statusCode
163
+ };
164
+ error = new PUSHXError(helpers.errors.ERROR_CATEGORY.PUSHX, error);
165
+ _eventEmitter.emit('pushx_status', error);
166
+ break;
167
+ }
168
+ else {
169
+ /**
170
+ * Handle network issue category status for 'subscription' opreration
171
+ * Start the events polling here.
172
+ *
173
+ * The wrapper supports multiple channels, but the APP currently uses a single channel only.
174
+ * Polling will also limited to a single channel.
175
+ */
176
+ _pollingCounter = 0;
177
+ _pollForEvents();
178
+ bPollingInitiated = true;
179
+ }
180
+ }
181
+ else {
182
+ // Handle network issue category status for other operations like 'unsubscription'
183
+ }
184
+ break;
185
+ case 'PNReconnectedCategory':
186
+ // Handle reconnected category status.
187
+ break;
188
+ default:
189
+ // Emit error for other status-category received from pubnub
190
+ error = {
191
+ message: 'PushX Error: unexpected error',
192
+ status: status.statusCode,
193
+ pushXError: status
194
+ };
195
+ error = new PUSHXError(helpers.errors.ERROR_CATEGORY.PUSHX, error);
196
+ _eventEmitter.emit('pushx_status', error);
197
+ break;
198
+ }
199
+ };
139
200
 
140
- var __getMySubscriptionStatus = function() {
141
- return JSON.parse(JSON.stringify(_globalSubscriptionStatus));
142
- };
201
+ var __getMySubscriptionStatus = function() {
202
+ return JSON.parse(JSON.stringify(_globalSubscriptionStatus));
203
+ };
204
+
205
+ /**
206
+ * Sets up necessary subscriptions (Pub/Sub) to PUSH channels. To a large extent, subscriptions are
207
+ * driven the student's (instructor's) roster.
208
+ * @param {object} groups - Roster information, provided during initialization, wrapper.setup().
209
+ */
210
+ var _subscribeToPubNubChannels = function (channel) {
211
+ _pubnubClient.subscribe({ // Calling Pubnub SDK
212
+ 'channels': [channel]
213
+ });
214
+ };
215
+
216
+ /** ###### END OF UTILITY FUNCTIONS ############ */
217
+
218
+ /** ====== Client Wrapper Member functions ==> Mapped to Public Methods */
219
+
220
+ /**
221
+ * Initializes the library, and established a connection with the Saas/PUSH provider.
222
+ * Setup should be called only once i.e. ONE CONNECTION (on a page/tab) is allowed
223
+ * at a time. If called again, it will throw an error (failure callback).
224
+ *
225
+ * @param {object} userOptions - User auth key and pubnub credentials
226
+ * @returns PROMISE.
227
+ */
228
+ var __setup = function (userOptions) {
229
+
230
+ var pubnubConfig = userOptions.pubnub;
231
+ pubnubConfig.uuid = userOptions.userid;
232
+ var accountId = userOptions.accountid;
233
+ var token = userOptions.token;
234
+
235
+ if (!_pubnubClient && pubnubConfig) {
236
+ _pubnubClient = new pubNub(pubnubConfig); //Connect with PubNub SDK
237
+ _pubnubClient.setToken(token);
238
+ processSetup();
239
+ } else {
240
+ return new Error('Already Initialized');
241
+ }
143
242
 
144
243
  /**
145
- * Sets up necessary subscriptions (Pub/Sub) to PUSH channels. To a large extent, subscriptions are
146
- * driven the student's (instructor's) roster.
147
- * @param {object} groups - Roster information, provided during initialization, wrapper.setup().
244
+ * SYNC Function
148
245
  */
149
- var _subscribeToPubNubChannels = function (channel) {
150
- _pubnubClient.subscribe({ // Calling Pubnub SDK
151
- "channels": [channel]
152
- });
246
+ function processSetup() {
247
+ _userOptions = userOptions;
248
+ _pubnubClient.addListener({ //Setup Listeners (events will shows up after subscription)
249
+ 'message': function (data) {
250
+ _translatePubnubMessage(data);
251
+ },
252
+ 'status': function (status) {
253
+ var statusOptions = { accountId: accountId };
254
+ _translatePubnubStatus(status, statusOptions);
255
+ }
256
+ });
257
+ }
258
+ return _constructClientAdaptor();
259
+ }; //End of _setup()
260
+
261
+ var __cleanup = function () {
262
+ if (_pubnubClient) { //Skip cleanup if setup() was not called.
263
+ _pubnubClient.unsubscribeAll();
264
+ _pubnubClient.stop();
265
+ _globalSubscription = [];
266
+ bStatusSubscribed = false;
267
+ _globalSubscriptionStatus = {};
268
+ bPollingInitiated = false;
269
+ }
270
+ _pubnubClient = undefined;
271
+
272
+ // Clear the Polling
273
+ if (_setTimeoutIDForPolling) {
274
+ clearTimeout(_setTimeoutIDForPolling);
275
+ // Setting the start time to now to clear the old events
276
+ _startTimestampForPolling = Date.now();
277
+ _checkOldBubbledEvents();
278
+ _setTimeoutIDForPolling = undefined;
279
+ _pollingCounter = undefined;
280
+ _startTimestampForPolling = undefined;
281
+ }
282
+ };
283
+
284
+ /**
285
+ * Polling function
286
+ */
287
+ var _pollForEvents = function () {
288
+ // Setup request params
289
+ var params = {
290
+ accountid: _userOptions.accountid,
291
+ channelname: _globalSubscription[0],
292
+ starttime: _startTimestampForPolling,
293
+ endtime: Date.now()
153
294
  };
154
295
 
155
- /** ###### END OF UTILITY FUNCTIONS ############ */
296
+ // Safe check to avoid poll for events if the channel name or start time is not set
297
+ // This handles an edge condition where the clearTimeout doesn't work as expected
298
+ if (!params.channelname || !params.starttime) {
299
+ return;
300
+ }
156
301
 
157
- /** ====== Client Wrapper Member functions ==> Mapped to Public Methods */
302
+ var requestAPI = request.get(_userOptions.pollingEndpoint).query(params);
158
303
 
159
- /**
160
- * Initializes the library, and established a connection with the Saas/PUSH provider.
161
- * Setup should be called only once i.e. ONE CONNECTION (on a page/tab) is allowed
162
- * at a time. If called again, it will throw an error (failure callback).
163
- *
164
- * @param {object} userOptions - User auth key and pubnub credentials
165
- * @returns PROMISE.
166
- */
167
- var __setup = function (userOptions) {
168
- var pubnubConfig = userOptions.pubnub;
169
- pubnubConfig.uuid = userOptions.userid;
304
+ requestAPI
305
+ .end(function(error, response) {
306
+
307
+ if (!error) {
308
+ // Bubble the connected status
309
+ if (_pollingCounter === 0) {
310
+ // Set the status of the channel to subscribed
311
+ if(_globalSubscriptionStatus[_globalSubscription[0]]) {
312
+ _globalSubscriptionStatus[_globalSubscription[0]].status = 'subscribed';
313
+ }
314
+
315
+ var successObj = {
316
+ category: 'PUSHX',
317
+ type: 'CHANNEL_SUBSCRIPTION',
318
+ status: 'SUCCESS',
319
+ message: 'Success: Subscribed successfully.',
320
+ httpcode: 200,
321
+ data: {
322
+ payload: {
323
+ channels: _globalSubscription
324
+ },
325
+ message: 'Success: Subscribed successfully.'
326
+ }
327
+ };
328
+ _eventEmitter.emit('pushx_status', successObj);
329
+ }
330
+
331
+ // Bubble the received events
332
+ _bubblePolledEvents(response.body);
333
+
334
+ // Increase the counter
335
+ _pollingCounter++;
336
+ }
170
337
 
171
- if (!_pubnubClient && pubnubConfig) {
172
- _pubnubClient = new pubNub(pubnubConfig); //Connect with PubNub SDK
173
- processSetup();
338
+ // Polling will be done only for specific number of times
339
+ if (_pollingCounter > _userOptions.pollingIterations) {
340
+ var error = {
341
+ message: 'Polling error: Polling limit exceeded',
342
+ status: 429
343
+ };
344
+ error = new PUSHXError(helpers.errors.ERROR_CATEGORY.PUSHX, error);
345
+ _eventEmitter.emit('pushx_status', error);
346
+ } else {
347
+ var timeoutDelay;
348
+
349
+ // If the polling interval is provided, use that
350
+ if (_userOptions.pollingInterval) {
351
+ timeoutDelay = _userOptions.pollingInterval * 60 * 1000;
174
352
  } else {
175
- return new Error('Already Initialized');
353
+ // Else, use exponential backoff
354
+ timeoutDelay = parseInt(Math.pow(1.3, _pollingCounter) * 10 * 1000, 10);
176
355
  }
177
356
 
178
- /**
179
- * SYNC Function
180
- */
181
- function processSetup() {
182
- _userOptions = userOptions;
183
- _pubnubClient.addListener({ //Setup Listeners (events will shows up after subscription)
184
- "message": function (data) {
185
- _translatePubnubMessage(data);
186
- },
187
- "status": function (status) {
188
- _translatePubnubStatus(status);
189
- }
190
- });
357
+ // Set timeout for next poll
358
+ if (timeoutDelay) {
359
+ _setTimeoutIDForPolling = setTimeout(_pollForEvents, timeoutDelay);
191
360
  }
192
- return _constructClientAdaptor();
193
- }; //End of _setup()
194
-
195
- var __cleanup = function () {
196
- if (_pubnubClient) { //Skip cleanup if setup() was not called.
197
- _pubnubClient.unsubscribeAll();
198
- _pubnubClient.stop();
199
- _globalSubscription = [];
200
- bStatusSubscribed = false;
201
- _globalSubscriptionStatus = {};
361
+ }
362
+ });
363
+ };
364
+
365
+ /**
366
+ * Bubble the polled events to the FE APP
367
+ * @param {*} events - Events recieved from the polling endpoint
368
+ */
369
+ var _bubblePolledEvents = function (events) {
370
+ // Load the old events from the session storage
371
+ var oldEventData = _checkOldBubbledEvents();
372
+
373
+ var oldEvents = oldEventData.events;
374
+ var sessionStorageKey = oldEventData.key;
375
+
376
+ for (var i = 0; i < events.entities.length; i++) {
377
+ var event = events.entities[i];
378
+ var eventId = event.pk + '_' + event.sk;
379
+
380
+ // Check if the event is already emitted
381
+ if (!oldEvents[eventId]) {
382
+ oldEvents[eventId] = event.context.start_time;
383
+
384
+ // Emit the event
385
+ _eventEmitter.emit(_globalSubscription[0], event);
386
+ }
387
+ }
388
+
389
+ // Save the bubbled events to session storage
390
+ sessionStorage.setItem(sessionStorageKey, JSON.stringify(oldEvents));
391
+ };
392
+
393
+ /**
394
+ * Check the old bubbled events and remove the events that are older than the start timestamp
395
+ * @returns {object} - Object containing the key and the events
396
+ */
397
+ var _checkOldBubbledEvents = function () {
398
+ var sessionStorageKey = 'comprodls.old_pushx_events.' + _userOptions.userid + '.' + _globalSubscription[0];
399
+ var oldEvents = sessionStorage.getItem(sessionStorageKey);
400
+
401
+ if (oldEvents) {
402
+ try {
403
+ oldEvents = JSON.parse(oldEvents);
404
+ } catch (e) {
405
+ oldEvents = {};
202
406
  }
203
- _pubnubClient = undefined;
204
- };
205
407
 
206
- return { // Return public methods for the wrapper
207
- "setup": __setup,
208
- "cleanup": __cleanup
408
+ var oldEventIds = Object.keys(oldEvents);
409
+
410
+ // Remove the events that are older than the start timestamp
411
+ for (var i = 0; i < oldEventIds.length; i++) {
412
+ var oldEventId = oldEventIds[i];
413
+
414
+ if (oldEvents[oldEventId] < _startTimestampForPolling) {
415
+ delete oldEvents[oldEventId];
416
+ }
417
+ }
418
+
419
+ // If the number of events has changed, save the events
420
+ if (oldEventIds.length !== Object.keys(oldEvents).length) {
421
+ sessionStorage.setItem(sessionStorageKey, JSON.stringify(oldEvents));
422
+ }
423
+ } else {
424
+ oldEvents = {};
425
+ }
426
+
427
+ return {
428
+ key: sessionStorageKey,
429
+ events: oldEvents
209
430
  };
431
+ };
432
+
433
+ return { // Return public methods for the wrapper
434
+ 'setup': __setup,
435
+ 'cleanup': __cleanup
436
+ };
210
437
 
211
438
  }; //End of Client Wrapper module