@como/como-client 0.9.4 → 0.9.5

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 (3) hide show
  1. package/README.md +29 -2
  2. package/package.json +10 -8
  3. package/src/como.js +0 -1085
package/README.md CHANGED
@@ -6,10 +6,37 @@ A cross platform SDK for como backend API.
6
6
 
7
7
  - To run this project source code locally make sure you're running node 8.x.x or later.
8
8
  - To run the project example - `node ${workspaceFolder}/test.js`.
9
- - To run all unit tests run - `npm test`.
9
+ - Install dependencies with `corepack yarn install --frozen-lockfile`. Yarn is the
10
+ source of truth; the ignored local `package-lock.json` is not maintained.
11
+ - To build and run the offline dependency compatibility tests, run `npm test`.
12
+ This does not run the live QA example in `test.js`. The development test runner
13
+ requires Node 14 or later; this release was checked on Node 22.
10
14
  - To publish a new version to npm - `npm publish`. Make sure to increment the package version in `${workspaceFolder}/package.json`.
11
15
 
12
16
  ## Development in [vscode](https://code.visualstudio.com/)
13
17
 
14
18
  - The configuration is set in `${workspaceFolder}/.vscode/launch.json`
15
- - Use `Launch Program` pre-defined configuration to run.
19
+ - Use `Launch Program` pre-defined configuration to run.
20
+
21
+ ## Security release 0.9.5
22
+
23
+ - Axios is patched within the existing 0.x API line to `^0.34.0`.
24
+ - Mocha and Chai are development dependencies only, so consumers no longer
25
+ install the SDK's old Mocha 5 dependency tree, including its `inflight` path.
26
+ Build/test tooling can still have separate development-only advisories.
27
+ - `babel-runtime` is an explicit runtime dependency because the published
28
+ compiled files import it.
29
+ - The package entrypoint is `index.js`, which loads `lib/como.js`. `npm pack`
30
+ builds `lib/` through `prepack`; source-only `src/` paths are not published.
31
+ Existing `lib/como` and interceptor imports remain available.
32
+
33
+ The offline tests cover the service-consumed exports, HTTP JSON/redirect/error
34
+ handling, bearer-token refresh, credential updates, signed sign-on requests,
35
+ location state and resource URLs. They do not certify browser/mobile runtimes
36
+ or live authentication/CDN services.
37
+
38
+ Release this SDK before changing a consumer's registry dependency to `0.9.5`.
39
+ Do not commit a consumer lockfile referring to an unpublished registry version
40
+ or a machine-local sibling path. Review unrelated working-tree edits before
41
+ packing or publishing; a package includes the current source, not only staged
42
+ Git changes.
package/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "@como/como-client",
3
- "version": "0.9.4",
3
+ "version": "0.9.5",
4
4
  "description": "Client module for Como's loaylty API",
5
- "main": "src/como.js",
5
+ "main": "index.js",
6
+ "packageManager": "yarn@1.22.22",
6
7
  "scripts": {
7
- "test": "mocha",
8
- "prepublishOnly": "node_modules/babel-cli/bin/babel.js src --out-dir lib"
8
+ "build": "babel src --out-dir lib",
9
+ "test": "npm run build && mocha --timeout 10000 \"test/**/*.test.js\"",
10
+ "prepack": "npm run build",
11
+ "prepublishOnly": "npm run build"
9
12
  },
10
13
  "files": [
11
14
  "/lib",
@@ -26,11 +29,10 @@
26
29
  },
27
30
  "homepage": "https://github.com/ConduitMobileRND/como-client-lib#readme",
28
31
  "dependencies": {
29
- "axios": "^0.30.2",
30
- "chai": "^4.1.2",
32
+ "axios": "^0.34.0",
33
+ "babel-runtime": "^6.26.0",
31
34
  "json-stable-stringify": "1.0.1",
32
35
  "jssha": "^3.2.0",
33
- "mocha": "^5.2.0",
34
36
  "moment-timezone": "^0.5.35",
35
37
  "ramda": "^0.25.0"
36
38
  },
@@ -45,7 +47,7 @@
45
47
  "eslint": "^4.19.1",
46
48
  "eslint-config-airbnb-base": "^12.1.0",
47
49
  "eslint-plugin-import": "^2.12.0",
48
- "mocha": "^5.2.0",
50
+ "mocha": "^10.8.2",
49
51
  "supertest": "^3.1.0",
50
52
  "webpack": "^4.8.3",
51
53
  "webpack-cli": "^2.1.4"
package/src/como.js DELETED
@@ -1,1085 +0,0 @@
1
- const moment = require('moment-timezone');
2
- const ramda = require('ramda');
3
- const environmentConfig = require('./config/env');
4
- const APIService = require('./services');
5
- const comoExternalUrlTranslator = require('./utils/comoExternalUrlTranslator');
6
- const resourceNames = require('./constants/resourceNames');
7
- const urlsUtils = require('./utils/urls');
8
-
9
- const INITIAL_COMO_DATA = {
10
- env: environmentConfig,
11
- token: null,
12
- locationId: null,
13
- locationState: null,
14
- installationId: null,
15
- membership: null,
16
- assets: null,
17
- reCaptchaSiteKey: null,
18
- mainResources: {},
19
- };
20
-
21
- class Como {
22
- constructor() {
23
- this.comoData = {};
24
- }
25
-
26
- async refreshTokenIfNeeded() {
27
- const { refresher, expiresIn } = this.comoData;
28
- if (!refresher) {
29
- console.log('No refresh for %o', this.comoData);
30
- } else if (expiresIn && moment(expiresIn).subtract(60, 'seconds').isBefore(moment())) {
31
- await refresher();
32
- }
33
- }
34
-
35
-
36
- /**
37
- * Sign the user and returns guest token & refresh token.
38
- * Requires init.
39
- */
40
- // async signon(source) {
41
- // const { InitApi: api } = this.comoData;
42
- // try {
43
- // const data = await api.signOn(this.comoData.installationId, this.comoData.locationId, this.comoData.refreshToken, source);
44
- // if (data && data.config && data.config.loyaltyCDN) {
45
- // this.comoData.env_params.services_root_cdn = data.config.loyaltyCDN;
46
- // }
47
- // return data;
48
- // } catch (error) {
49
- // if (error.response && error.response.data) {
50
- // const { code, message } = error.response.data;
51
- // throw new Error(code || message);
52
- // }
53
- // throw error;
54
- // }
55
- // }
56
-
57
- /**
58
- *
59
- * @param {Object} environment Environemnt object
60
- * @param {string} environment.id Environment Id
61
- * @param {string} environment.locationId Location Id
62
- * @param {string} environment.installationId Unique installation id
63
- * @param {Object} credentials Member credentials (Optional)
64
- * @param {string} accessToken session id string (Optional)
65
- * @param {string} refreshToken refresh token string (Optional)
66
- * @param {string} expiresIn access token expiration date formatted (Optional)
67
- * @param {function} refreshCallback an event callback which fires each time user's tokens gets refreshed
68
- * @param {boolean} enableSignon if disabled signOn api call will not be fired. Enabled by default.
69
- */
70
- async init(environment, credentials, refreshCallback, enableSignon = true) {
71
- const isExists = (x => !ramda.isNil(x) && !ramda.isEmpty(x));
72
- const {
73
- id: environmentId, locationId, installationId, source, binaryVersion, phoenixVersion,
74
- } = environment;
75
- if (!isExists(environmentId) || !isExists(locationId) || !isExists(installationId)) {
76
- throw new Error(`missing parameters: ${environment}`);
77
- }
78
-
79
- this.comoData = {
80
- ...INITIAL_COMO_DATA,
81
- ...credentials,
82
- installationId,
83
- locationId,
84
- source,
85
- env_params: {
86
- ...INITIAL_COMO_DATA.env[environmentId],
87
- },
88
- tempTokenData: {},
89
- config: {},
90
- };
91
-
92
- const updateCredentials = (creds, isNew = false) => {
93
- this.updateLocalCreds(creds);
94
- if (refreshCallback && isNew) {
95
- refreshCallback(creds);
96
- }
97
- };
98
-
99
- const getCredentials = this.getCredentials.bind(this);
100
- const { gateway } = this.comoData.env_params;
101
- const { service, refresher, initService } = APIService
102
- .getService(gateway, installationId, getCredentials, updateCredentials, source, binaryVersion, phoenixVersion);
103
- this.comoData.api = service;
104
- this.comoData.initApi = initService;
105
- this.comoData.refresher = refresher;
106
-
107
- const { accessToken, refreshToken, expiresIn } = credentials;
108
- let credExist = isExists(accessToken) && isExists(refreshToken);
109
- const isExpired = credExist && expiresIn && moment(expiresIn).isBefore(moment());
110
- let refreshFailed = false;
111
- if (isExpired) {
112
- try {
113
- const data = await this.comoData.initApi.refreshToken(installationId, refreshToken || 'none', locationId, source);
114
- this.comoData.config = data.config;
115
- console.log(`signOn with isExpired true result:${JSON.stringify(data)}`);
116
- updateCredentials(data, true);
117
- } catch (e) {
118
- console.error(`Failed to refresh token, installationId:${installationId}, refreshToken:${this.comoData.refreshToken}, locationId:${locationId}, source:${source}`);
119
- // refresh failed - need to revoke and signOn again
120
- initService.logError({
121
- method: 'refreshToken', installationId, locationId, source, refreshToken, error: e.message,
122
- });
123
- refreshFailed = true;
124
- }
125
- }
126
- let interval = 0;
127
- if (refreshFailed || !credExist) {
128
- while (!credExist && interval < 3000) {
129
- try {
130
- const data = await this.comoData.initApi.signOn(installationId, locationId, source);
131
- this.comoData.config = data.config;
132
- console.log(`signOn with refreshFailed result:${JSON.stringify(data)}`);
133
- updateCredentials(data, true);
134
- credExist = true;
135
- } catch (e) {
136
- console.error(`Failed to signOn, installationId:${installationId}, locationId:${locationId}, source:${source},interval:${interval}, error:${e}`);
137
- interval += 1000;
138
- initService.logError({
139
- method: 'signOn no accessToken', accessToken, isExpired, refreshFailed, credExist, installationId, locationId, source, refreshToken, interval, error: e.message,
140
- });
141
- await new Promise(r => setTimeout(r, interval));
142
- }
143
- }
144
- } else if (!isExpired) {
145
- let signOnSuccessfully = false;
146
- while (!signOnSuccessfully && interval < 3000) {
147
- try {
148
- console.log(`signOn with installationId:${installationId}, locationId:${locationId}, source:${source},accessToken:${accessToken}`);
149
- const data = await this.comoData.initApi.signOn(installationId, locationId, source, accessToken);
150
- this.comoData.config = data.config;
151
- console.log(`signOn with result " ${JSON.stringify(data)}`);
152
- if (data && data.accessToken) {
153
- console.log('signOn- updating credentials');
154
- updateCredentials(data, true);
155
- }
156
- if (data && data.config && data.config.recaptchaSiteKey) {
157
- this.comoData.reCaptchaSiteKey = data.config.recaptchaSiteKey;
158
- }
159
- signOnSuccessfully = true;
160
- } catch (e) {
161
- console.error(`Failed signOn with accessToken, installationId:${installationId}, locationId:${locationId}, source:${source},accessToken:${accessToken}, error:${e.message}`);
162
- interval += 1000;
163
- initService.logError({
164
- method: 'signOn with credentials', accessToken, isExpired, refreshFailed, credExist, installationId, locationId, source, refreshToken, interval, error: e.message,
165
- });
166
- await new Promise(r => setTimeout(r, interval));
167
- }
168
- }
169
- }
170
- if (!this.comoData.token) {
171
- this.comoData.token = this.comoData.accessToken;
172
- }
173
- return this.getCredentials();
174
- }
175
-
176
- /**
177
- * Updates the como.js local credentials settings.
178
- * Used when making api calls to janua.
179
- *
180
- * @param {Object} credentials credentials to update.
181
- * @param {Object} accessToken access token to update.
182
- * @param {Object} refreshToken refresh token to update.
183
- * @param {Object} expiresIn access token expiry date to update.
184
- */
185
- updateLocalCreds(credentials = {}) {
186
- this.comoData.accessToken = credentials.accessToken;
187
- this.comoData.token = credentials.accessToken;
188
- this.comoData.refreshToken = credentials.refreshToken;
189
- this.comoData.expiresIn = credentials.expiresIn;
190
- if (credentials && credentials.config) {
191
- this.comoData.reCaptchaSiteKey = credentials.config.recaptchaSiteKey;
192
- if (credentials.config.recaptcha) {
193
- this.comoData.recaptchaConfig = credentials.config.recaptcha;
194
- }
195
- }
196
- }
197
-
198
- getExternalUrlByID(itemID, gpsData, assetID, accessibilityData) {
199
- const locationData = this.comoData.mainResources[resourceNames.LOCATION_DATA];
200
- if (locationData && locationData.WebViews && locationData.WebViews[0].item) {
201
- const possibleWebViews = locationData.WebViews[0].item.filter(u => u.id === itemID);
202
- const url = possibleWebViews && possibleWebViews[0] && possibleWebViews[0].url;
203
- return this.translateExternalUrl(url, gpsData, assetID, accessibilityData);
204
- }
205
- return null;
206
- }
207
-
208
- async translateExternalUrl(url, gpsData, assetID, accessibilityData, devicePlatform = 'notImplemented') {
209
- const legacyUrl = await this.getAppModulesLegacyBaseUrl();
210
- let externalUrl = url;
211
- if (externalUrl && externalUrl.startsWith(legacyUrl)) {
212
- externalUrl = externalUrl.replace(legacyUrl, this.comoData.env_params.app_modules_root);
213
- }
214
- const {
215
- api, locationId, token, env_params: env, membership, assets,
216
- } = this.comoData;
217
- const locationData = this.comoData.mainResources && this.comoData.mainResources[resourceNames.LOCATION_DATA];
218
- const apiObjects = { api, servicesRoot: env.services_root };
219
- const dataToUse = {
220
- locationId, token, membership, locationData, assets, gpsData, assetID, accessibilityData, devicePlatform,
221
- };
222
- const translatedData = await comoExternalUrlTranslator.translateUrl(externalUrl, apiObjects, dataToUse);
223
- if (translatedData.tempTokenData.temporaryToken) {
224
- this.comoData.tempTokenData[translatedData.tempTokenData.temporaryToken] = translatedData.tempTokenData.expirationDate;
225
- }
226
- return translatedData && translatedData.translatedUrl && translatedData.translatedUrl.length ? translatedData.translatedUrl : '';
227
- }
228
-
229
- async getFeedbackFormData() {
230
- const {
231
- locationId, env_params: env, api,
232
- } = this.comoData;
233
- return api.getFeedbackFormData(env.zapp_root, locationId);
234
- }
235
-
236
- /**
237
- *
238
- * @param {Object} form registration form values
239
- * @param {Object} verification flow
240
- * @param {string} reCaptchaToken
241
- * @param {Object} source(registration origin)
242
- */
243
- async register(form, verification, reCaptchaToken, source) {
244
- const { api } = this.comoData;
245
- try {
246
- const data = await api.register(form, verification, reCaptchaToken, source);
247
- return data;
248
- } catch (error) {
249
- if (error.response && error.response.data) {
250
- const { code, message } = error.response.data;
251
- throw new Error(code || message);
252
- }
253
- throw error;
254
- }
255
- }
256
-
257
- /**
258
- *
259
- * @param {string} verification flow (code & verification step)
260
- * @param {string} type verification type
261
- * @param {Object} form registration form values
262
- * @param {string} reCaptchaToken
263
- */
264
- async registerVerify(verification, type, form, reCaptchaToken) {
265
- const { api } = this.comoData;
266
- try {
267
- const data = await api.registerVerify(verification, type, form, reCaptchaToken);
268
- return data;
269
- } catch (error) {
270
- if (error.response && error.response.data) {
271
- const { code, message } = error.response.data;
272
- throw new Error(code || message);
273
- }
274
- throw error;
275
- }
276
- }
277
-
278
- /**
279
- *
280
- * @param {Object} form update form values
281
- * @param {string} reCaptchaToken
282
- * @param {string} verification
283
- * @param {string} source request source
284
- */
285
- async updateProfile(form, reCaptchaToken, verification, source) {
286
- const { api } = this.comoData;
287
- try {
288
- const data = await api.updateProfile(form, reCaptchaToken, verification, source);
289
- return data;
290
- } catch (error) {
291
- if (error.response && error.response.data) {
292
- const { code, message } = error.response.data;
293
- throw new Error(code || message);
294
- }
295
- throw error;
296
- }
297
- }
298
-
299
- /**
300
- *
301
- * @param {string} verificationCode code verification sent by 3rd party
302
- * @param {string} type verification type
303
- * @param {Object} form update form values
304
- * @param {string} reCaptchaToken
305
- * @param {string} source request source
306
- */
307
- async updateProfileVerify(verificationCode, type, form, reCaptchaToken, source) {
308
- const { api } = this.comoData;
309
- try {
310
- const data = await api.updateProfileVerify(verificationCode, type, form, reCaptchaToken, source);
311
- return data;
312
- } catch (error) {
313
- if (error.response && error.response.data) {
314
- const { code, message } = error.response.data;
315
- throw new Error(code || message);
316
- }
317
- throw error;
318
- }
319
- }
320
-
321
- /**
322
- * @param {string} language language code
323
- */
324
- async updateLanguage(language) {
325
- const { api } = this.comoData;
326
- try {
327
- const data = await api.updateLanguage(language);
328
- return data;
329
- } catch (error) {
330
- if (error.response && error.response.data) {
331
- const { code, message } = error.response.data;
332
- throw new Error(code || message);
333
- }
334
- throw error;
335
- }
336
- }
337
-
338
- /**
339
- *
340
- * @param {string} unsubscribeSms unsubscribe user at location
341
- * @param {string} PhoneNumber phone number to identify user
342
- */
343
- async unsubscribeSms(PhoneNumber) {
344
- const { api, locationId } = this.comoData;
345
- try {
346
- const identifier = { PhoneNumber };
347
- const data = await api.unsubscribeSms(locationId, identifier);
348
- return data;
349
- } catch (error) {
350
- if (error.response && error.response.data) {
351
- const { code, message } = error.response.data;
352
- throw new Error(code || message);
353
- }
354
- throw error;
355
- }
356
- }
357
-
358
- /**
359
- *
360
- * @param {string} unsubscribeWhatsapp unsubscribe user at location
361
- * @param {string} PhoneNumber phone number to identify user
362
- */
363
- async unsubscribeWhatsapp(PhoneNumber) {
364
- const { api, locationId } = this.comoData;
365
- try {
366
- const identifier = { PhoneNumber };
367
- const data = await api.unsubscribeWhatsapp(locationId, identifier);
368
- return data;
369
- } catch (error) {
370
- if (error.response && error.response.data) {
371
- const { code, message } = error.response.data;
372
- throw new Error(code || message);
373
- }
374
- throw error;
375
- }
376
- }
377
-
378
- /**
379
- *
380
- * @param {Object} identifier an object which identifies the user by its credentials
381
- * @param {string} type login type i.e PhoneNumber/Email/etc
382
- * @param {reCaptchaToken} reCaptcha token for login chalenge
383
- * @param {recaptchaTokenType} recaptcha token type - score/human
384
- * @param {devicePlatform} device platform i.e. ios/android
385
- * @param {boolean} isWhatsapp optional flag for whatsapp login flow
386
- */
387
- async login(identifier, type, reCaptchaToken, recaptchaTokenType, devicePlatform, isWhatsapp) {
388
- const { api } = this.comoData;
389
- try {
390
- const data = await api.logIn(type, identifier, reCaptchaToken, recaptchaTokenType, devicePlatform, isWhatsapp);
391
- return data;
392
- } catch (error) {
393
- if (error.response && error.response.data) {
394
- const { code, message, retryAfter } = error.response.data;
395
- const loginError = new Error(code || message);
396
- // When a request lands inside its OTP backoff the server states how long
397
- // to wait. Only code and message used to survive this rethrow, which left
398
- // the app inventing a countdown of its own.
399
- if (typeof retryAfter === 'number') { loginError.retryAfter = retryAfter; }
400
- throw loginError;
401
- }
402
- throw error;
403
- }
404
- }
405
-
406
- /**
407
- *
408
- * @param {Object} identifier key-value identifiers
409
- * @param {*} type login type i.e PhoneNumber/Email/etc
410
- * @param {*} code a 2-factor verification code sent to the client
411
- * @param {reCaptchaToken} reCaptcha token for login challenge
412
- * @param {recaptchaTokenType} recaptcha token type - score/human
413
- * @param {devicePlatform} device platform i.e. ios/android
414
- */
415
- async loginVerify(identifier, type, code, reCaptchaToken, recaptchaTokenType, devicePlatform) {
416
- const { api } = this.comoData;
417
- try {
418
- const { consent } = await api.logInVerify(code, type, identifier, reCaptchaToken, recaptchaTokenType, devicePlatform);
419
- this.comoData.consent = consent;
420
- } catch (error) {
421
- if (error.response && error.response.data) {
422
- const { code: errCode, message, retryAfter } = error.response.data;
423
- // The wrong-code case keeps reporting the message rather than the code,
424
- // since callers match on that string.
425
- const verifyError = (message && message === 'Invalid verification Code')
426
- ? new Error(message)
427
- : new Error(errCode || message);
428
- if (typeof retryAfter === 'number') { verifyError.retryAfter = retryAfter; }
429
- throw verifyError;
430
- }
431
- throw error;
432
- }
433
-
434
- return this.getCredentials();
435
- }
436
-
437
- /**
438
- * Reload and sets the internal membership state.
439
- * To get the reloaded membership make sure to call getMembership();
440
- * @param onlyAssetKeys - include assets list full data or only the asset keys
441
- * @returns {Promise<void>}
442
- */
443
- async reloadMembership(onlyAssetKeys = false) {
444
- const {
445
- env_params: env, locationId, api,
446
- } = this.comoData;
447
- const membership = await api.getUserAtLocation(env.zapp_root, locationId, onlyAssetKeys);
448
- this.comoData.membership = membership;
449
- }
450
-
451
- /**
452
- * Send an Open app request to update server.
453
- */
454
- async openApp(data) {
455
- const {
456
- api, locationId, env_params: env,
457
- } = this.comoData;
458
-
459
- return api.openApp(env.zapp_root, locationId, data);
460
- }
461
-
462
- /**
463
- * Update membership status (permissions).
464
- * @param {boolean} pushEnable
465
- * @param {boolean} locationEnable
466
- */
467
- async clientUpdateMembership(pushEnable, locationEnable) {
468
- const {
469
- api, locationId, token, env_params: env,
470
- } = this.comoData;
471
- try {
472
- return api.clientUpdateMembership(env.services_root, locationId, pushEnable, locationEnable);
473
- } catch (e) {
474
- console.log(`clientUpdateMembership failed, token:${token}, locationId:${locationId}, error: ${e}`);
475
- }
476
- }
477
-
478
- /**
479
- * Downloads the main resource by its id and sets the resource in the main resource's map.
480
- * @param {string} resourceId Main resource id
481
- */
482
-
483
- async downloadMainResource(resourceId) {
484
- try {
485
- const resource = this.comoData.mainResourcesMap[resourceId];
486
- if (!resource) {
487
- const err = `resource ${resourceId} not found!`;
488
- throw new Error(err);
489
- }
490
-
491
- const { env_params: env, api } = this.comoData;
492
- const responseJson = await api.getLoyaltyResource(
493
- env.services_root_cdn,
494
- resource.id,
495
- ('Namespace' in resource) ? resource.Namespace : `location_${this.comoData.locationId}`,
496
- resource.Version,
497
- this.comoData.locationId,
498
- );
499
-
500
- this.comoData.mainResources[resourceId] = responseJson;
501
- } catch (e) {
502
- console.log(`downloadMainResource failed, resourceId:${resourceId}, locationId:${this.comoData.locationId}, this.comoData.mainResourcesMap: ${this.comoData.mainResourcesMap}, error: ${e}`);
503
- throw new Error(e);
504
- }
505
- }
506
-
507
-
508
- /**
509
- * Reload and sets the internal location state.
510
- * To get the reloaded location state make sure to call getLocationState();
511
- */
512
- async reloadLocationState() {
513
- const { api } = this.comoData;
514
- const state = await api.getLocationState(this.comoData.env_params.zapp_root, this.comoData.locationId);
515
- this.comoData.locationState = state;
516
- const mainResources = state.MainResources.Resource;
517
-
518
- this.comoData.mainResourcesMap = mainResources.reduce((total, obj) => {
519
- total[obj.id] = obj; // eslint-disable-line no-param-reassign
520
- return total;
521
- }, {});
522
- }
523
-
524
- /**
525
- * Requests an app client id by the user's location id.
526
- */
527
- async getAppClientID() {
528
- const {
529
- env_params: env, locationId, api,
530
- } = this.comoData;
531
- await this.refreshTokenIfNeeded();
532
- const responseJson = await api.getShortUserId(env.zapp_root, locationId);
533
- return responseJson.ID;
534
- }
535
-
536
- /**
537
- * Requests a generated payment code from the loyalty server
538
- */
539
- async getPaymentCode() {
540
- const {
541
- env_params: env, locationId, api,
542
- } = this.comoData;
543
- const responseJson = await api.getPaymentCode(env.zapp_root, locationId);
544
- return responseJson.VerificationCode;
545
- }
546
-
547
- /**
548
- * Logout the user identified by its accessToken
549
- */
550
- async logout() {
551
- const { api } = this.comoData;
552
- try {
553
- const response = await api.logOut();
554
- return response;
555
- } catch (error) {
556
- if (error.response && error.response.data) {
557
- const { code: errCode, message } = error.response.data;
558
- throw new Error(errCode || message);
559
- }
560
- throw error;
561
- }
562
- }
563
-
564
- /**
565
- *
566
- * @param {string} assetKey asset's id
567
- */
568
- async redeemAsset(assetKey) {
569
- const {
570
- env_params: env, locationId, api,
571
- } = this.comoData;
572
- await this.refreshTokenIfNeeded();
573
- const responseJson = await api.redeemAsset(env.zapp_root, locationId, assetKey);
574
- return responseJson;
575
- }
576
-
577
- /**
578
- *
579
- * @param {string} itemId item's id
580
- */
581
- async purchaseAsset(itemId) {
582
- const {
583
- env_params: env, locationId, api,
584
- } = this.comoData;
585
- const responseJson = await api.purchaseAsset(env.zapp_root, locationId, itemId);
586
- return responseJson;
587
- }
588
-
589
- async getUserPointShopDataAPI2() {
590
- const {
591
- env_params: env, locationId, api,
592
- } = this.comoData;
593
- const responseJson = await api.getUserPointShopDataAPI2(env.zapp_root, locationId);
594
- return responseJson;
595
- }
596
-
597
-
598
- async purchaseAssetAPI2(assetID) {
599
- const {
600
- env_params: env, locationId, api,
601
- } = this.comoData;
602
- const responseJson = await api.purchaseAssetAPI2(env.zapp_root, locationId, assetID);
603
- return responseJson;
604
- }
605
-
606
- /**
607
- * Reload and sets the internal assets (expired and valid) state.
608
- * To get the reloaded assets make sure to call como.getAssets();
609
- */
610
- async reloadAssets() {
611
- const {
612
- env_params: env, locationId, api,
613
- } = this.comoData;
614
- const responseJson = await api.memberAssets(env.services_root, locationId);
615
- this.comoData.assets = responseJson;
616
- }
617
-
618
- /**
619
- * Merge the default app text with the location specific app texts
620
- * Both DefaultAppTexts and AppTexts are a MainResource that needs to be downloaded before merge
621
- */
622
- mergeTexts() {
623
- if (this.comoData.mainResources.AppTexts && this.comoData.mainResources.DefaultAppTexts) {
624
- this.comoData.app_texts = this.comoData.mainResources.DefaultAppTexts;
625
- Object.keys(this.comoData.mainResources.AppTexts).forEach(key => {
626
- this.comoData.app_texts[key] = this.comoData.mainResources.AppTexts[key];
627
- });
628
- }
629
- }
630
-
631
- /**
632
- *
633
- * @param {string} key app text key
634
- */
635
- getTextForKey(key) { return this.comoData.app_texts[key]; }
636
-
637
- /**
638
- * Downloads the main resources:
639
- * - LocationData
640
- * - Menu
641
- * - Updates
642
- * - TCAlts
643
- * - AppTexts
644
- * - DefaultAppTexts
645
- */
646
- async downloadMainResources() {
647
- const resources = [
648
- 'LocationData',
649
- 'Menu',
650
- 'Updates',
651
- 'TCAlts',
652
- 'AppTexts',
653
- 'DefaultAppTexts',
654
- ];
655
- const downloadMainResource = this.downloadMainResource.bind(this);
656
- const downloads = resources.map(downloadMainResource);
657
- await Promise.all(downloads);
658
- this.mergeTexts();
659
- }
660
-
661
- /**
662
- *
663
- * @param {string} type form type
664
- */
665
- loadForm(type) {
666
- const { api, locationId } = this.comoData;
667
-
668
- return api.getForm(type, locationId);
669
- }
670
-
671
- /**
672
- *
673
- * @param {string} type configuration type
674
- */
675
- getConfigration(type) {
676
- const { api, locationId } = this.comoData;
677
- const locationState = this.getLocationState();
678
- let version = null;
679
- if (locationState) {
680
- version = locationState.PublishVersion;
681
- }
682
-
683
- return api.getConfiguration(type, locationId, version);
684
- }
685
-
686
- /**
687
- *
688
- * @param {string} type resource type
689
- */
690
- getResource(type) {
691
- const { api, locationId } = this.comoData;
692
- return api.getResource(type, locationId);
693
- }
694
-
695
- /**
696
- *
697
- * Get all legacy resources (Zapp)
698
- */
699
- getLegacyResources() {
700
- const { api, locationId } = this.comoData;
701
- return api.getZappResource(locationId);
702
- }
703
-
704
- /**
705
- * Generates a new referral code for friend-referral
706
- */
707
- generateReferralCode() {
708
- const {
709
- api, locationId, env_params: env,
710
- } = this.comoData;
711
-
712
- return api.generateReferralCode(env.services_root, locationId);
713
- }
714
-
715
- /**
716
- * Check that referral code is valid
717
- */
718
- verifyReferralCode(code) {
719
- const {
720
- api, locationId, env_params: env,
721
- } = this.comoData;
722
-
723
- return api.verifyReferralCode(env.services_root, locationId, code);
724
- }
725
-
726
- /**
727
- * Returns current accessToken and refreshToken
728
- * Caution: make sure to pass refresh callback to init to get the latest credentials
729
- */
730
- getCredentials() {
731
- const {
732
- accessToken, refreshToken, expiresIn, consent, locationId,
733
- } = this.comoData;
734
- return {
735
- accessToken, refreshToken, expiresIn, consent, locationId,
736
- };
737
- }
738
-
739
- /**
740
- * Returns the current accessToken
741
- * Caution: make sure to pass refresh callback to como.init to get the latest credentials
742
- */
743
- getToken() { return this.comoData.token; }
744
-
745
- /**
746
- * Returns the como.js initialized installation id
747
- */
748
- getInstallationId() { return this.comoData.installationId; }
749
-
750
- /**
751
- * Return the user membership object
752
- * Make sure to call reloadMembership() to reload the membership object.
753
- */
754
- getMembership() { return this.comoData.membership; }
755
-
756
- /**
757
- * Return the user assets object
758
- * Make sure to call reloadAssets() to reload the assets object.
759
- */
760
- getAssets() { return this.comoData.assets; }
761
-
762
- /**
763
- * Return service recaptch config
764
- */
765
- async getRecaptchaConfig() {
766
- await this.refreshTokenIfNeeded();
767
- return this.comoData.recaptchaConfig;
768
- }
769
-
770
- /**
771
- * Returns the location specific registration web url
772
- */
773
- async getRegistrationUrl(overrides) {
774
- await this.refreshTokenIfNeeded();
775
- const {
776
- token, installationId, locationId, env_params: env,
777
- } = this.comoData;
778
-
779
- return urlsUtils.appendQuery(
780
- `${env.app_modules_root}/register?token=${token}&locationid=${locationId}`,
781
- {
782
- ...this.getCredentials(),
783
- installationId,
784
- disableSuccessScreen: 'true',
785
- ...overrides,
786
- },
787
- );
788
- }
789
-
790
- /**
791
- * Returns the location specific profile web url
792
- */
793
- async getProfileUrl(overrides) {
794
- await this.refreshTokenIfNeeded();
795
- const {
796
- token, installationId, locationId, env_params: env,
797
- } = this.comoData;
798
-
799
- return urlsUtils.appendQuery(
800
- `${env.app_modules_root}/profile?token=${token}&locationid=${locationId}`,
801
- {
802
- ...this.getCredentials(),
803
- installationId,
804
- disableSuccessScreen: 'true',
805
- ...overrides,
806
- },
807
- );
808
- }
809
-
810
- /**
811
- * Returns the location specific login web url
812
- */
813
- async getLoginUrl() {
814
- await this.refreshTokenIfNeeded();
815
- const { token, locationId, env_params: env } = this.comoData;
816
- return `${env.app_modules_root}/login?token=${token}&locationid=${locationId}`;
817
- }
818
-
819
- /**
820
- * Returns the location data Portability url
821
- */
822
- async getDataPortabilityUrl(url, overrides) {
823
- await this.refreshTokenIfNeeded();
824
- const {
825
- installationId,
826
- } = this.comoData;
827
-
828
- return urlsUtils.appendQuery(
829
- `${url}`,
830
- {
831
- installationId,
832
- ...overrides,
833
- },
834
- );
835
- }
836
-
837
- /**
838
- * Returns app-modules legacy root url
839
- */
840
- async getAppModulesLegacyBaseUrl() {
841
- await this.refreshTokenIfNeeded();
842
- const { env_params: env } = this.comoData;
843
- return `${env.app_modules_legacy_root}`;
844
- }
845
-
846
- /**
847
- * Returns the location specific friend referral web url
848
- */
849
- getFriendReferralInviteLink(referral) {
850
- const { env_params: env, locationId } = this.comoData;
851
- const cpBaseUrl = env.cp_base_url.replace('{location_id}', locationId);
852
- return `${cpBaseUrl}/auth/signin?onboardingflow=register&ReferralCode=${referral}`;
853
- }
854
-
855
- /**
856
- * Return the location state
857
- * Make sure to call reloadLocationState() to reload the location state object.
858
- */
859
- getLocationState() { return this.comoData.locationState; }
860
-
861
- /**
862
- * Returns the location point shop items
863
- */
864
- getPointShopItems() { return this.comoData.mainResources.menu.gifts_shop_item; }
865
-
866
- /**
867
- *
868
- * @param {string} resourceName resource name
869
- */
870
- getMainResource(resourceName) { return this.comoData.mainResources[resourceName]; }
871
-
872
- /**
873
- *
874
- * @param {string} resourceId resource id
875
- * @param {string} namespace resource namespace
876
- * @param {string|number} version resource version
877
- */
878
- getResourceUrl(resourceId, namespace, version) {
879
- const { api, env_params: env, locationId } = this.comoData;
880
- return api.getResourceUrl(env.services_root_cdn, resourceId, namespace, version, locationId);
881
- }
882
-
883
- getPurchaseReportUrl() {
884
- const { env_params: env } = this.comoData;
885
- return `${env.purchase_connect_base_url}/Purchase/Report`;
886
- }
887
-
888
- getCdnUrl() {
889
- return this.comoData.env_params.services_root_cdn;
890
- }
891
-
892
- /**
893
- * @param {string} identifier fcm token created by firebase
894
- * @param {boolean} isFirebaseProjectMigrated is migrated to new firebase project
895
- */
896
- sendPushChannel(identifier, isFirebaseProjectMigrated = false) {
897
- const {
898
- api, locationId, env_params: env,
899
- } = this.comoData;
900
- return api.sendPushChannel(env.services_root, locationId, identifier, isFirebaseProjectMigrated);
901
- }
902
-
903
- async getRegionConfig() {
904
- const {
905
- api, locationId, env_params: env,
906
- } = this.comoData;
907
- return api.getClientBusinessBackend(env.zapp_root, locationId);
908
- }
909
-
910
- /**
911
- * @param {string} code coupon code entered by user on App
912
- */
913
- sendCouponCode(code) {
914
- const {
915
- api, locationId, env_params: env,
916
- } = this.comoData;
917
- return api.sendCouponCode(env.zapp_root, locationId, code);
918
- }
919
-
920
- async addPaymentMethod(cardToken) {
921
- const {
922
- api, locationId, token, env_params: env,
923
- } = this.comoData;
924
- return api.addPaymentMethod(env.services_root, locationId, token, cardToken);
925
- }
926
-
927
- async knowYourData(email) {
928
- const {
929
- api, locationId, env_params: env,
930
- } = this.comoData;
931
- return api.knowYourData(env.services_root, locationId, email);
932
- }
933
-
934
- async consentWithdraw(consentData) {
935
- const {
936
- api, locationId, env_params: env,
937
- } = this.comoData;
938
- return api.consentWithdraw(env.services_root, locationId, consentData);
939
- }
940
-
941
- async getPaymentMethods() {
942
- const {
943
- env_params: env, locationId, api,
944
- } = this.comoData;
945
- const responseJson = await api.getPaymentMethods(env.services_root, locationId);
946
- return responseJson;
947
- }
948
-
949
- /**
950
- * @param {Integer} amount to charge
951
- * @param {String} creditCardToken to charge from
952
- * @param {String} itemName for submit purchase
953
- * @param {String} itemNumber for submit purchase
954
- * @param {String} membershipKey for user identification
955
- */
956
- async payInApp(amount, creditCardToken, itemName, itemNumber, membershipKey) {
957
- const {
958
- env_params: env, token, locationId, api,
959
- } = this.comoData;
960
- const responseJson = await api.payInApp(env.services_root, locationId, token, amount, creditCardToken, itemName, itemNumber, membershipKey);
961
- return responseJson;
962
- }
963
-
964
- /**
965
- * @param {string} creditCardToken which card to delete
966
- */
967
- async deletePayment(creditCardToken) {
968
- const {
969
- env_params: env, token, locationId, api,
970
- } = this.comoData;
971
- const responseJson = await api.deletePayment(env.services_root, locationId, token, creditCardToken);
972
- return responseJson;
973
- }
974
- /**
975
- * @param {string} tag for Pop-up Message Trigger (Optional param)
976
- */
977
- async getMemberMessages(tag, limit, offset, fetchExpiredMessages = false) {
978
- const {
979
- api, locationId, env_params: env,
980
- } = this.comoData;
981
- await this.refreshTokenIfNeeded();
982
- return api.getMemberMessages(env.services_root, locationId, tag, limit, offset, fetchExpiredMessages);
983
- }
984
-
985
- /**
986
- * @param {string} keysList keys of the messages to mark as read
987
- */
988
- markAsReadMemberMessages(keysList) {
989
- const {
990
- api, locationId, env_params: env,
991
- } = this.comoData;
992
- return api.markAsReadMemberMessages(env.services_root, locationId, keysList);
993
- }
994
-
995
- /**
996
- * @param {String} receiver to share with
997
- * @param {String} sender name
998
- * @param {Integer} amount to share
999
- * @param {String} type of wallet
1000
- */
1001
- async budgetTransfer(receiver, sender, amount, wallet) {
1002
- const {
1003
- api, locationId, env_params: env,
1004
- } = this.comoData;
1005
- return api.budgetTransfer(env.services_root, locationId, receiver, sender, amount, wallet);
1006
- }
1007
-
1008
- /**
1009
- * @param {string} claimId key of the credit claim to read the data for
1010
- */
1011
- getCreditClaimData(claimId) {
1012
- const {
1013
- api, env_params: env,
1014
- } = this.comoData;
1015
- return api.getCreditClaimData(env.services_root, claimId);
1016
- }
1017
-
1018
-
1019
- /**
1020
- * @param {String} claimCode to use for budget transfer claim
1021
- */
1022
- async budgetTransferClaim(claimCode) {
1023
- const {
1024
- api, locationId, env_params: env,
1025
- } = this.comoData;
1026
- return api.budgetTransferClaim(env.services_root, locationId, claimCode);
1027
- }
1028
-
1029
- /**
1030
- * API call for claim generic action. To specify your trigger button, you need to associate it with a particular item, asset or tag.
1031
- * @param {string} assetKey - asset to claim
1032
- * @param {string} itemId - item id to claim
1033
- * @param {string} tag - claim all with tag
1034
- */
1035
- claim(assetKey, itemId, tag) {
1036
- const {
1037
- env_params: env, locationId, api,
1038
- } = this.comoData;
1039
- return api.claim(env.zapp_root, locationId, assetKey, itemId, tag);
1040
- }
1041
-
1042
- /**
1043
- * Log user action
1044
- * @param {string} action
1045
- * @param {string} logData - log information
1046
- */
1047
- async logUserAction(action, logData) {
1048
- const {
1049
- env_params: env, locationId, api,
1050
- } = this.comoData;
1051
- return api.logUserAction(env.zapp_root, locationId, action, logData);
1052
- }
1053
-
1054
- /**
1055
- * Member purchase history
1056
- * @param {string} limit - how manay items to return (if exists) - default value is 25
1057
- * @param {string} offset - default value is 0(next offset would be 25)
1058
- */
1059
- async getPurchaseHistory(limit, offset) {
1060
- const {
1061
- locationId, api, membership,
1062
- } = this.comoData;
1063
- return api.getPurchaseHistory(locationId, membership.Key, limit, offset);
1064
- }
1065
-
1066
- /**
1067
- * Get app texts for multi languages - only for apps that has project set in translation service
1068
- */
1069
- getAppTextsV2() {
1070
- const { api, locationId } = this.comoData;
1071
- return api.getAllTranslations(locationId);
1072
- }
1073
-
1074
- /**
1075
- * Generate a temporary token for the location
1076
- * @param {number} timeToLive time to live in seconds
1077
- * @returns {string} temporary token
1078
- */
1079
- async generateTemporaryToken(timeToLive = 60) {
1080
- const { api, locationId, env_params: env } = this.comoData;
1081
- return api.generateTemporaryToken(env.services_root, locationId, timeToLive);
1082
- }
1083
- }
1084
-
1085
- module.exports = Como;