@accelbyte/sdk 1.1.3 → 1.2.2

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 (39) hide show
  1. package/dist/cjs/node/index.node.js +834 -0
  2. package/dist/cjs/node/index.node.js.map +1 -0
  3. package/dist/es/browser/index.browser.js +515 -18602
  4. package/dist/es/browser/index.browser.js.map +1 -1
  5. package/dist/es/node/index.node.js +515 -18603
  6. package/dist/es/node/index.node.js.map +1 -1
  7. package/dist/index.d.ts +257 -73569
  8. package/package.json +3 -3
  9. package/dist/cjs/node/index.cjs +0 -19820
  10. package/dist/cjs/node/index.cjs.map +0 -1
  11. package/examples/next/README.md +0 -13
  12. package/examples/next/package.json +0 -24
  13. package/examples/next/pages/_app.tsx +0 -12
  14. package/examples/next/pages/_document.tsx +0 -19
  15. package/examples/next/pages/api/hello.ts +0 -10
  16. package/examples/next/pages/index.tsx +0 -109
  17. package/examples/next/public/favicon.ico +0 -0
  18. package/examples/next/public/next.svg +0 -1
  19. package/examples/next/public/thirteen.svg +0 -1
  20. package/examples/next/public/vercel.svg +0 -1
  21. package/examples/next/styles/Home.module.css +0 -274
  22. package/examples/next/styles/globals.css +0 -112
  23. package/examples/next/yarn.lock +0 -360
  24. package/examples/node/index.js +0 -58
  25. package/examples/node/index.mjs +0 -56
  26. package/examples/node/package.json +0 -15
  27. package/examples/node/yarn.lock +0 -592
  28. package/examples/vite/README.md +0 -13
  29. package/examples/vite/index.html +0 -13
  30. package/examples/vite/package.json +0 -26
  31. package/examples/vite/public/vite.svg +0 -1
  32. package/examples/vite/src/App.css +0 -43
  33. package/examples/vite/src/App.tsx +0 -64
  34. package/examples/vite/src/Sdk.ts +0 -38
  35. package/examples/vite/src/assets/react.svg +0 -1
  36. package/examples/vite/src/index.css +0 -75
  37. package/examples/vite/src/main.tsx +0 -15
  38. package/examples/vite/src/vite-env.d.ts +0 -1
  39. package/examples/vite/yarn.lock +0 -890
@@ -0,0 +1,834 @@
1
+ 'use strict';
2
+
3
+ var crypto = require('crypto');
4
+ var axios = require('axios');
5
+ var qs = require('query-string');
6
+ var uuid = require('uuid');
7
+ var zod = require('zod');
8
+ var isEqual = require('lodash/isEqual.js');
9
+
10
+ function _interopNamespaceDefault(e) {
11
+ var n = Object.create(null);
12
+ if (e) {
13
+ Object.keys(e).forEach(function (k) {
14
+ if (k !== 'default') {
15
+ var d = Object.getOwnPropertyDescriptor(e, k);
16
+ Object.defineProperty(n, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: function () { return e[k]; }
19
+ });
20
+ }
21
+ });
22
+ }
23
+ n.default = e;
24
+ return Object.freeze(n);
25
+ }
26
+
27
+ var uuid__namespace = /*#__PURE__*/_interopNamespaceDefault(uuid);
28
+
29
+ /*
30
+ * Copyright (c) 2018-2023 AccelByte Inc. All Rights Reserved
31
+ * This is licensed software from AccelByte Inc, for limitations
32
+ * and restrictions contact your company contract manager.
33
+ */
34
+ global.crypto = crypto.webcrypto;
35
+
36
+ var _a$1;
37
+ class SdkDevice {
38
+ }
39
+ _a$1 = SdkDevice;
40
+ SdkDevice.ID_KEY = 'deviceId';
41
+ SdkDevice.TYPE = {
42
+ MOBILE: 'mobile',
43
+ DESKTOP: 'desktop'
44
+ };
45
+ SdkDevice.getType = () => {
46
+ return isMobile() ? SdkDevice.TYPE.MOBILE : SdkDevice.TYPE.DESKTOP;
47
+ };
48
+ SdkDevice.generateUUID = () => {
49
+ const deviceIdInUUID = uuid__namespace.v4().split('-').join('');
50
+ localStorage.setItem(SdkDevice.ID_KEY, deviceIdInUUID);
51
+ return deviceIdInUUID;
52
+ };
53
+ SdkDevice.getDeviceId = () => {
54
+ return localStorage.getItem(_a$1.ID_KEY) || _a$1.generateUUID();
55
+ };
56
+ /*
57
+ Bellow function is copied from npm 'is-mobile'
58
+ */
59
+ const mobileRE = /(android|bb\d+|meego).+mobile|armv7l|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series[46]0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i;
60
+ const tabletRE = /android|ipad|playbook|silk/i;
61
+ const isMobile = (opts) => {
62
+ if (!opts)
63
+ opts = {};
64
+ let ua = opts.ua;
65
+ if (!ua && typeof navigator !== 'undefined')
66
+ ua = navigator.userAgent;
67
+ if (ua && ua.headers && typeof ua.headers['user-agent'] === 'string') {
68
+ ua = ua.headers['user-agent'];
69
+ }
70
+ if (typeof ua !== 'string')
71
+ return false;
72
+ let result = mobileRE.test(ua) || (!!opts.tablet && tabletRE.test(ua));
73
+ if (!result &&
74
+ opts.tablet &&
75
+ opts.featureDetect &&
76
+ navigator &&
77
+ navigator.maxTouchPoints > 1 &&
78
+ ua.indexOf('Macintosh') !== -1 &&
79
+ ua.indexOf('Safari') !== -1) {
80
+ result = true;
81
+ }
82
+ return result;
83
+ };
84
+
85
+ /*
86
+ * Copyright (c) 2022-2023 AccelByte Inc. All Rights Reserved
87
+ * This is licensed software from AccelByte Inc, for limitations
88
+ * and restrictions contact your company contract manager.
89
+ */
90
+ const requestInterceptors = new Map();
91
+ const responseInterceptors = new Map();
92
+ const injectRequestInterceptors = (requestInterceptor, errorInterceptor) => {
93
+ const pair = { interceptor: requestInterceptor, errorInterceptor };
94
+ const ejectId = axios.interceptors.request.use(requestInterceptor, errorInterceptor);
95
+ requestInterceptors.set(ejectId, pair);
96
+ return ejectId;
97
+ };
98
+ const injectResponseInterceptors = (responseInterceptor, errorInterceptor) => {
99
+ const pair = { interceptor: responseInterceptor, errorInterceptor };
100
+ const ejectId = axios.interceptors.response.use(responseInterceptor, errorInterceptor);
101
+ responseInterceptors.set(ejectId, pair);
102
+ return ejectId;
103
+ };
104
+ const loggerInterceptor = (axiosInstance) => {
105
+ axiosInstance.interceptors.request.use(config => {
106
+ // Logger.info(config.method?.toUpperCase(), `${config.url}`)
107
+ return config;
108
+ }, error => {
109
+ return Promise.reject(error);
110
+ });
111
+ };
112
+ class Network {
113
+ //
114
+ static create(...configs) {
115
+ const axiosInstance = axios.create(Object.assign({
116
+ paramsSerializer: qs.stringify
117
+ }, ...configs));
118
+ Array.from(requestInterceptors).forEach(([_key, interceptorPair]) => {
119
+ const { interceptor, errorInterceptor } = interceptorPair;
120
+ axiosInstance.interceptors.request.use(interceptor, errorInterceptor);
121
+ });
122
+ Array.from(responseInterceptors).forEach(([_key, interceptorPair]) => {
123
+ const { interceptor, errorInterceptor } = interceptorPair;
124
+ axiosInstance.interceptors.response.use(interceptor, errorInterceptor);
125
+ });
126
+ loggerInterceptor(axiosInstance);
127
+ return axiosInstance;
128
+ }
129
+ static withBearerToken(accessToken, config) {
130
+ return Network.create(config || {}, {
131
+ headers: { Authorization: `Bearer ${accessToken}` }
132
+ });
133
+ }
134
+ }
135
+ Network.setDeviceTokenCookie = () => {
136
+ const deviceId = SdkDevice.getDeviceId();
137
+ document.cookie = `device_token=${deviceId}; path=/;`;
138
+ };
139
+ Network.removeDeviceTokenCookie = () => {
140
+ document.cookie = `device_token=; expires=${new Date(0).toUTCString()}`;
141
+ };
142
+ Network.getFormUrlEncodedData = (data) => {
143
+ const formPayload = new URLSearchParams();
144
+ const formKeys = Object.keys(data);
145
+ formKeys.forEach(key => {
146
+ if (data[key])
147
+ formPayload.append(key, data[key]);
148
+ });
149
+ return formPayload;
150
+ };
151
+
152
+ const ERROR_ELIGIBILITY_CODE = 13130;
153
+ const injectErrorInterceptors = (baseUrl, onUserEligibilityChange, onError) => {
154
+ injectResponseInterceptors(response => {
155
+ return response;
156
+ }, (error) => {
157
+ if (error.response) {
158
+ const { response } = error;
159
+ if (response?.status === 403 && response?.config.url.includes(baseUrl) && response?.config.withCredentials) {
160
+ if (response.data.errorCode === ERROR_ELIGIBILITY_CODE && onUserEligibilityChange) {
161
+ onUserEligibilityChange();
162
+ }
163
+ }
164
+ }
165
+ if (onError) {
166
+ onError(error);
167
+ }
168
+ throw error;
169
+ });
170
+ };
171
+
172
+ /*
173
+ * Copyright (c) 2022 AccelByte Inc. All Rights Reserved
174
+ * This is licensed software from AccelByte Inc, for limitations
175
+ * and restrictions contact your company contract manager.
176
+ */
177
+ class BrowserHelper {
178
+ }
179
+ BrowserHelper.isOnBrowser = () => {
180
+ return typeof window !== 'undefined' && window.document;
181
+ };
182
+
183
+ class RefreshSession {
184
+ }
185
+ // --
186
+ RefreshSession.KEY = 'RefreshSession.lock';
187
+ RefreshSession.isLocked = () => {
188
+ if (!BrowserHelper.isOnBrowser())
189
+ return false;
190
+ const lockStatus = localStorage.getItem(RefreshSession.KEY);
191
+ if (!lockStatus) {
192
+ return false;
193
+ }
194
+ const lockExpiry = Number(lockStatus);
195
+ if (isNaN(lockExpiry)) {
196
+ return false;
197
+ }
198
+ return lockExpiry > new Date().getTime();
199
+ };
200
+ RefreshSession.lock = (expiry) => {
201
+ if (!BrowserHelper.isOnBrowser())
202
+ return;
203
+ localStorage.setItem(RefreshSession.KEY, `${new Date().getTime() + expiry}`);
204
+ };
205
+ RefreshSession.unlock = () => {
206
+ if (!BrowserHelper.isOnBrowser())
207
+ return;
208
+ localStorage.removeItem(RefreshSession.KEY);
209
+ };
210
+ RefreshSession.sleepAsync = (timeInMs) => new Promise(resolve => setTimeout(resolve, timeInMs));
211
+ RefreshSession.isBearerAuth = (config) => {
212
+ // @ts-ignore
213
+ if (config?.headers?.Authorization?.toLowerCase().indexOf('bearer') > -1) {
214
+ return true;
215
+ }
216
+ return false;
217
+ };
218
+
219
+ /*
220
+ * Copyright (c) 2022 AccelByte Inc. All Rights Reserved
221
+ * This is licensed software from AccelByte Inc, for limitations
222
+ * and restrictions contact your company contract manager.
223
+ */
224
+ class CodeGenUtil {
225
+ /**
226
+ * Returns a hash code from a string
227
+ * @param {String} str The string to hash.
228
+ * @return {Number} A 32bit integer
229
+ * @see http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
230
+ */
231
+ static hashCode(str) {
232
+ let hash = 0;
233
+ for (let i = 0, len = str.length; i < len; i++) {
234
+ const chr = str.charCodeAt(i);
235
+ hash = (hash << 5) - hash + chr;
236
+ hash |= 0; // Convert to 32bit integer
237
+ }
238
+ return hash;
239
+ }
240
+ }
241
+ CodeGenUtil.getFormUrlEncodedData = (data) => {
242
+ const formPayload = new URLSearchParams();
243
+ const formKeys = Object.keys(data);
244
+ formKeys.forEach(key => {
245
+ if (typeof data[key] !== 'undefined')
246
+ formPayload.append(key, data[key]);
247
+ });
248
+ return formPayload;
249
+ };
250
+
251
+ /*
252
+ * Copyright (c) 2022 AccelByte Inc. All Rights Reserved
253
+ * This is licensed software from AccelByte Inc, for limitations
254
+ * and restrictions contact your company contract manager.
255
+ */
256
+ // TODO replace with Winston
257
+ class Logger {
258
+ static info(message, object = '') {
259
+ _log('info:', message, object);
260
+ }
261
+ static warn(message, object = '') {
262
+ _log('warn:', message, object);
263
+ }
264
+ static error(message, object = '') {
265
+ _log('error:', message, object);
266
+ }
267
+ }
268
+ const _log = (type, message = '', object = '') => {
269
+ if (type === 'error:') {
270
+ console.error('\x1b[31m%s\x1b[0m', type, message, object);
271
+ }
272
+ else {
273
+ console.log('\x1b[34m%s\x1b[0m', type, message, object); // blue
274
+ }
275
+ };
276
+
277
+ class Validate {
278
+ //
279
+ static responseType(networkCall, Codec, modelName) {
280
+ return wrapNetworkCallSafely(async () => {
281
+ const response = await networkCall();
282
+ const decodeResult = Codec.safeParse(response.data);
283
+ if (!decodeResult.success) {
284
+ throw new DecodeError({ error: decodeResult.error, response, modelName });
285
+ }
286
+ return response;
287
+ });
288
+ }
289
+ static safeParse(data, Codec) {
290
+ const result = Codec.safeParse(data);
291
+ if (result.success) {
292
+ return result.data;
293
+ }
294
+ return null;
295
+ }
296
+ }
297
+ async function wrapNetworkCallSafely(networkCallFunction) {
298
+ try {
299
+ const response = await networkCallFunction();
300
+ // Cleanup so we avoid polluting the response
301
+ // @ts-ignore
302
+ delete response.headers; // perhaps this may be required?
303
+ // @ts-ignore
304
+ delete response.statusText;
305
+ // @ts-ignore
306
+ delete response.config; // axios specific
307
+ delete response.request;
308
+ return { response, error: null };
309
+ }
310
+ catch (error) {
311
+ return { response: null, error: error };
312
+ }
313
+ }
314
+ class DecodeError extends Error {
315
+ constructor({ error, response, modelName }) {
316
+ const msg = `response from url "${response.config.url}" doesn't match model "${modelName}"`;
317
+ super(msg);
318
+ Logger.error(msg, error);
319
+ }
320
+ }
321
+
322
+ /*
323
+ * Copyright (c) 2022-2023 AccelByte Inc. All Rights Reserved
324
+ * This is licensed software from AccelByte Inc, for limitations
325
+ * and restrictions contact your company contract manager.
326
+ */
327
+ const NamespaceRole = zod.z.object({ namespace: zod.z.string(), roleId: zod.z.string() });
328
+ const PermissionV3 = zod.z.object({
329
+ action: zod.z.number().int(),
330
+ resource: zod.z.string(),
331
+ schedAction: zod.z.number().int().nullish(),
332
+ schedCron: zod.z.string().nullish(),
333
+ schedRange: zod.z.array(zod.z.string()).nullish()
334
+ });
335
+ const JwtBanV3 = zod.z.object({
336
+ ban: zod.z.string(),
337
+ disabledDate: zod.z.string().nullish(),
338
+ enabled: zod.z.boolean(),
339
+ endDate: zod.z.string(),
340
+ targetedNamespace: zod.z.string()
341
+ });
342
+ const TokenWithDeviceCookieResponseV3 = zod.z.object({
343
+ access_token: zod.z.string(),
344
+ auth_trust_id: zod.z.string().nullish(),
345
+ bans: zod.z.array(JwtBanV3).nullish(),
346
+ display_name: zod.z.string().nullish(),
347
+ expires_in: zod.z.number().int(),
348
+ is_comply: zod.z.boolean().nullish(),
349
+ jflgs: zod.z.number().int().nullish(),
350
+ namespace: zod.z.string(),
351
+ namespace_roles: zod.z.array(NamespaceRole).nullish(),
352
+ permissions: zod.z.array(PermissionV3),
353
+ platform_id: zod.z.string().nullish(),
354
+ platform_user_id: zod.z.string().nullish(),
355
+ refresh_expires_in: zod.z.number().int().nullish(),
356
+ refresh_token: zod.z.string().nullish(),
357
+ roles: zod.z.array(zod.z.string()).nullish(),
358
+ scope: zod.z.string(),
359
+ token_type: zod.z.string(),
360
+ user_id: zod.z.string().nullish(),
361
+ xuid: zod.z.string().nullish()
362
+ });
363
+ /*
364
+ * Copyright (c) 2022-2023 AccelByte Inc. All Rights Reserved
365
+ * This is licensed software from AccelByte Inc, for limitations
366
+ * and restrictions contact your company contract manager.
367
+ */
368
+ class OAuth20$ {
369
+ // @ts-ignore
370
+ constructor(axiosInstance, namespace, cache = false) {
371
+ this.axiosInstance = axiosInstance;
372
+ this.namespace = namespace;
373
+ this.cache = cache;
374
+ }
375
+ postOauthToken(data) {
376
+ const params = {};
377
+ const url = '/iam/v3/oauth/token';
378
+ const resultPromise = this.axiosInstance.post(url, CodeGenUtil.getFormUrlEncodedData(data), {
379
+ ...params,
380
+ headers: { ...params.headers, 'content-type': 'application/x-www-form-urlencoded' }
381
+ });
382
+ return Validate.responseType(() => resultPromise, TokenWithDeviceCookieResponseV3, 'TokenWithDeviceCookieResponseV3');
383
+ }
384
+ }
385
+
386
+ /*
387
+ * Copyright (c) 2022 AccelByte Inc. All Rights Reserved
388
+ * This is licensed software from AccelByte Inc, for limitations
389
+ * and restrictions contact your company contract manager.
390
+ */
391
+ class DesktopChecker {
392
+ static isDesktopApp() {
393
+ return DesktopChecker.desktopApp && !DesktopChecker.isInIframe();
394
+ }
395
+ static isInIframe() {
396
+ try {
397
+ return window.self !== window.top;
398
+ }
399
+ catch (error) {
400
+ return true;
401
+ }
402
+ }
403
+ // borrowed from https://github.com/cheton/is-electron
404
+ static isElectron() {
405
+ // @ts-ignore Renderer process
406
+ if (typeof window !== 'undefined' && typeof window.process === 'object' && window.process.type === 'renderer') {
407
+ return true;
408
+ }
409
+ // Main process
410
+ if (typeof process !== 'undefined' && typeof process.versions === 'object' && !!process.versions.electron) {
411
+ return true;
412
+ }
413
+ // Detect the user agent when the `nodeIntegration` option is set to false
414
+ if (typeof navigator === 'object' && typeof navigator.userAgent === 'string' && navigator.userAgent.indexOf('Electron') >= 0) {
415
+ return true;
416
+ }
417
+ return false;
418
+ }
419
+ }
420
+ DesktopChecker.desktopApp = DesktopChecker.isElectron();
421
+
422
+ /*
423
+ * Copyright (c) 2022-2023 AccelByte Inc. All Rights Reserved
424
+ * This is licensed software from AccelByte Inc, for limitations
425
+ * and restrictions contact your company contract manager.
426
+ */
427
+ const REFRESH_EXPIRY = 1000;
428
+ const REFRESH_EXPIRY_UPDATE_RATE = 500;
429
+ const REFRESH_EXPIRY_CHECK_RATE = 1000;
430
+ var LoginUrls;
431
+ (function (LoginUrls) {
432
+ LoginUrls["REFRESH_SESSION"] = "/iam/v3/oauth/token";
433
+ LoginUrls["LOGOUT"] = "/iam/v3/logout";
434
+ LoginUrls["REVOKE"] = "/iam/v3/oauth/revoke";
435
+ })(LoginUrls || (LoginUrls = {}));
436
+ /* eslint camelcase: 0 */
437
+ const refreshSession = ({ axiosConfig, refreshToken, clientId }) => {
438
+ const config = {
439
+ ...axiosConfig,
440
+ withCredentials: false,
441
+ headers: {
442
+ 'Content-Type': 'application/x-www-form-urlencoded',
443
+ Authorization: `Basic ${Buffer.from(`${clientId}:`).toString('base64')}`
444
+ }
445
+ };
446
+ const axios = Network.create(config);
447
+ const payload = {
448
+ refresh_token: refreshToken || undefined,
449
+ client_id: clientId,
450
+ grant_type: 'refresh_token'
451
+ };
452
+ const oauth20 = new OAuth20$(axios, 'NAMESPACE-NOT-REQUIRED', false);
453
+ return oauth20.postOauthToken(payload);
454
+ };
455
+ // Return Promise<true> if refresh in any tab is successful;
456
+ const refreshWithLock = ({ axiosConfig, refreshToken, clientId }) => {
457
+ //
458
+ if (RefreshSession.isLocked()) {
459
+ return Promise.resolve().then(async () => {
460
+ // This block is executed when other tab / request is refreshing
461
+ while (RefreshSession.isLocked()) {
462
+ await RefreshSession.sleepAsync(REFRESH_EXPIRY_CHECK_RATE);
463
+ }
464
+ return {};
465
+ });
466
+ }
467
+ RefreshSession.lock(REFRESH_EXPIRY);
468
+ let isLocallyRefreshingToken = true;
469
+ (async () => {
470
+ // eslint-disable-next-line no-unmodified-loop-condition
471
+ while (isLocallyRefreshingToken) {
472
+ RefreshSession.lock(REFRESH_EXPIRY);
473
+ await RefreshSession.sleepAsync(REFRESH_EXPIRY_UPDATE_RATE);
474
+ }
475
+ })();
476
+ return Promise.resolve()
477
+ .then(doRefreshSession({ axiosConfig, clientId, refreshToken }))
478
+ .finally(() => {
479
+ isLocallyRefreshingToken = false;
480
+ RefreshSession.unlock();
481
+ });
482
+ };
483
+ const doRefreshSession = ({ axiosConfig, clientId, refreshToken }) => async () => {
484
+ // we need this to check if app use “withCredentials: false” and don’t have refreshToken it should return false,
485
+ // because we track it as a logout user, if not do this even user logout on the desktop app (that use withCredentials: false)
486
+ // will automatically login with refreshSession
487
+ if (DesktopChecker.isDesktopApp() && !axiosConfig.withCredentials && !refreshToken) {
488
+ return false;
489
+ }
490
+ const result = await refreshSession({ axiosConfig, clientId, refreshToken });
491
+ if (result.error) {
492
+ return false;
493
+ }
494
+ return result.response.data;
495
+ };
496
+ const injectAuthInterceptors = (clientId, getSDKConfig, onSessionExpired, onGetUserSession, getRefreshToken) => {
497
+ // ===== request
498
+ injectRequestInterceptors(async (config) => {
499
+ // need to lock on the desktop as well to sleep other request before refresh session is done
500
+ const isRefreshTokenUrl = config.url === LoginUrls.REFRESH_SESSION;
501
+ // eslint-disable-next-line no-unmodified-loop-condition
502
+ while (RefreshSession.isLocked() && !isRefreshTokenUrl) {
503
+ await RefreshSession.sleepAsync(200);
504
+ }
505
+ return config;
506
+ }, (error) => {
507
+ return Promise.reject(error);
508
+ });
509
+ // ===== response
510
+ injectResponseInterceptors(response => {
511
+ return response;
512
+ }, async (error) => {
513
+ if (axios.isCancel(error)) {
514
+ // expected case, exit
515
+ throw error;
516
+ }
517
+ else {
518
+ const { config, response } = error;
519
+ if (!response) {
520
+ console.error('injectResponseInterceptors net::ERR_INTERNET_DISCONNECTED');
521
+ }
522
+ if (response?.status === 401) {
523
+ const { url } = config;
524
+ const axiosConfig = getSDKConfig();
525
+ const refreshToken = getRefreshToken ? getRefreshToken() : undefined;
526
+ // expected business case, exit
527
+ // @ts-ignore
528
+ if (Object.values(LoginUrls).includes(url)) {
529
+ throw error;
530
+ }
531
+ // need to lock on the desktop as well to prevent multiple token request
532
+ return refreshWithLock({ axiosConfig, clientId, refreshToken }).then(tokenResponse => {
533
+ return uponRefreshComplete(error, tokenResponse, onGetUserSession, onSessionExpired, axiosConfig, config);
534
+ });
535
+ }
536
+ }
537
+ return Promise.reject(error);
538
+ });
539
+ };
540
+ const uponRefreshComplete = (error, tokenResponse, onGetUserSession, onSessionExpired, axiosConfig, errorConfig) => {
541
+ //
542
+ if (tokenResponse) {
543
+ const { access_token, refresh_token } = tokenResponse;
544
+ if (onGetUserSession && access_token && refresh_token) {
545
+ onGetUserSession(access_token, refresh_token);
546
+ }
547
+ // desktop
548
+ if (!axiosConfig.withCredentials && access_token) {
549
+ return axios({
550
+ ...errorConfig,
551
+ headers: {
552
+ ...errorConfig.headers,
553
+ Authorization: `Bearer ${access_token}`
554
+ }
555
+ });
556
+ // web
557
+ }
558
+ else {
559
+ return axios(errorConfig);
560
+ }
561
+ }
562
+ if (onSessionExpired) {
563
+ console.log('session expired auth');
564
+ onSessionExpired();
565
+ }
566
+ throw error;
567
+ };
568
+
569
+ /*
570
+ * Copyright (c) 2022-2023 AccelByte Inc. All Rights Reserved
571
+ * This is licensed software from AccelByte Inc, for limitations
572
+ * and restrictions contact your company contract manager.
573
+ */
574
+ class ApiUtils {
575
+ }
576
+ ApiUtils.mergedConfigs = (config, overrides) => {
577
+ return {
578
+ ...config,
579
+ ...overrides?.config,
580
+ headers: {
581
+ ...config.headers,
582
+ ...overrides?.config?.headers
583
+ }
584
+ };
585
+ };
586
+
587
+ /*
588
+ * Copyright (c) 2022-2023 AccelByte Inc. All Rights Reserved
589
+ * This is licensed software from AccelByte Inc, for limitations
590
+ * and restrictions contact your company contract manager.
591
+ */
592
+ class AccelbyteSDKImpl {
593
+ constructor(options, config, events) {
594
+ this.getRefreshToken = () => this.refreshToken;
595
+ this.getConfig = () => this.config;
596
+ this.refreshTokensImpl = (accessToken, refreshToken) => {
597
+ if (refreshToken) {
598
+ this.refreshToken = refreshToken;
599
+ }
600
+ const configOverride = { headers: { Authorization: accessToken ? `Bearer ${accessToken}` : '' } };
601
+ this.config = ApiUtils.mergedConfigs(this.config, { config: configOverride });
602
+ };
603
+ this.options = {
604
+ cache: false,
605
+ ...options
606
+ };
607
+ this.events = events;
608
+ this.config = {
609
+ timeout: 60000,
610
+ baseURL: options.baseURL,
611
+ withCredentials: true,
612
+ ...config,
613
+ headers: {
614
+ 'Content-Type': 'application/json',
615
+ ...config?.headers
616
+ }
617
+ };
618
+ }
619
+ init() {
620
+ const { baseURL, clientId } = this.options;
621
+ injectAuthInterceptors(clientId, this.getConfig, this.events?.onSessionExpired, this.events?.onGetUserSession, this.getRefreshToken);
622
+ injectErrorInterceptors(baseURL, this.events?.onUserEligibilityChange, this.events?.onError);
623
+ // TODO reintegrate doVersionDiagnostics later on
624
+ // setTimeout(() => this.doVersionDiagnostics(), TIMEOUT_TO_DIAGNOSTICS)
625
+ return {
626
+ refreshTokens: (accessToken, refreshToken) => this.refreshTokensImpl(accessToken, refreshToken),
627
+ assembly: () => {
628
+ return {
629
+ config: this.config,
630
+ namespace: this.options.namespace,
631
+ clientId: this.options.clientId,
632
+ redirectURI: this.options.redirectURI,
633
+ baseURL: this.options.baseURL,
634
+ cache: this.options.cache !== undefined ? this.options.cache : false
635
+ };
636
+ }
637
+ };
638
+ }
639
+ }
640
+ const sdkInit = ({ options, config, onEvents }) => {
641
+ const sdkFactory = new AccelbyteSDKImpl(options, config, onEvents);
642
+ return sdkFactory.init();
643
+ };
644
+ // ts-prune-ignore-next
645
+ const Accelbyte = { SDK: sdkInit };
646
+
647
+ /*
648
+ * Copyright (c) 2022 AccelByte Inc. All Rights Reserved
649
+ * This is licensed software from AccelByte Inc, for limitations
650
+ * and restrictions contact your company contract manager.
651
+ */
652
+ // ts-prune-ignore-next
653
+ const VALIDATION_ERROR_CODE = 20002;
654
+
655
+ /*
656
+ * Copyright (c) 2022-2023 AccelByte Inc. All Rights Reserved
657
+ * This is licensed software from AccelByte Inc, for limitations
658
+ * and restrictions contact your company contract manager.
659
+ */
660
+ const ERROR_LINK_ANOTHER_3RD_PARTY_ACCOUNT = 10200;
661
+ const ERROR_CODE_LINK_DELETION_ACCOUNT = 10135;
662
+ const ERROR_CODE_TOKEN_EXPIRED = 10196;
663
+ const ERROR_USER_BANNED = 10134;
664
+
665
+ /*
666
+ * Copyright (c) 2022 AccelByte Inc. All Rights Reserved
667
+ * This is licensed software from AccelByte Inc, for limitations
668
+ * and restrictions contact your company contract manager.
669
+ */
670
+ class UrlHelper {
671
+ static trimSlashFromStringEnd(pathString) {
672
+ let newString = pathString;
673
+ while (newString[newString.length - 1] === '/') {
674
+ newString = newString.slice(0, -1);
675
+ }
676
+ return newString;
677
+ }
678
+ static trimSlashFromStringStart(pathString) {
679
+ let newString = pathString;
680
+ while (newString[0] === '/') {
681
+ newString = newString.slice(1);
682
+ }
683
+ return newString;
684
+ }
685
+ static trimSlashFromStringEdges(pathString) {
686
+ return UrlHelper.trimSlashFromStringStart(this.trimSlashFromStringEnd(pathString));
687
+ }
688
+ static combinePaths(...paths) {
689
+ const completePath = paths.join('/');
690
+ // Replace 2 or more consecutive slashes with a single slash.
691
+ // This is also the behavior from Node's `path.join`.
692
+ return completePath.replace(/\/{2,}/g, '/');
693
+ }
694
+ static combineURLPaths(urlString, ...paths) {
695
+ const url = new URL(urlString);
696
+ const { origin } = url;
697
+ const pathname = UrlHelper.trimSlashFromStringEdges(UrlHelper.combinePaths(url.pathname, ...paths));
698
+ return new URL(pathname, origin).toString();
699
+ }
700
+ }
701
+ UrlHelper.isCompleteURLString = (urlString) => {
702
+ try {
703
+ const url = new URL(urlString);
704
+ return url.hostname !== '';
705
+ }
706
+ catch (error) { }
707
+ return false;
708
+ };
709
+
710
+ var _a;
711
+ class SdkCache {
712
+ static async withoutCache(apiCall) {
713
+ // Intercept the call and add onSync callback so that even though cache is false, the client cn still safely attach onSync
714
+ let apiResponse;
715
+ let apiError;
716
+ try {
717
+ apiResponse = await apiCall();
718
+ if (apiResponse.error)
719
+ throw apiResponse.error;
720
+ }
721
+ catch (e) {
722
+ apiError = e;
723
+ }
724
+ return new Promise((resolve, reject) => {
725
+ // const result = apiCall()
726
+ // resolve && resolve(result.then())
727
+ // reject && reject(result.catch())
728
+ const success = {
729
+ response: apiResponse?.response,
730
+ error: apiError,
731
+ onSync: _syncedData => {
732
+ // Add empty implementation so client onSync call does not fail with undefined 'onSync' function
733
+ }
734
+ };
735
+ resolve && resolve(success);
736
+ reject && reject(apiError || apiResponse.error);
737
+ });
738
+ }
739
+ static async withCache(key, apiCall) {
740
+ let syncObserver;
741
+ const cacheData = this.cacheStrategy.get(key);
742
+ if (!cacheData) {
743
+ const res = await apiCall();
744
+ const data = res.response?.data;
745
+ const error = res.error;
746
+ if (error) {
747
+ return {
748
+ response: res.response,
749
+ error,
750
+ onSync: func => (syncObserver = func)
751
+ };
752
+ }
753
+ const skipNon200FromCaching = res.response?.status !== 200;
754
+ if (skipNon200FromCaching) {
755
+ return {
756
+ response: res.response,
757
+ error: null,
758
+ onSync: func => (syncObserver = func)
759
+ };
760
+ }
761
+ if (data) {
762
+ this.cacheStrategy.set(key, data);
763
+ }
764
+ return {
765
+ response: { data, status: 200 },
766
+ error,
767
+ onSync: func => (syncObserver = func)
768
+ };
769
+ }
770
+ const onSyncCall = async () => {
771
+ const onSyncResponse = await apiCall();
772
+ if (onSyncResponse.error) {
773
+ const res = {
774
+ response: null,
775
+ error: onSyncResponse.error
776
+ };
777
+ syncObserver && syncObserver(res);
778
+ return res;
779
+ }
780
+ const newData = onSyncResponse.response?.data;
781
+ if (!isEqual(this.cacheStrategy.get(key), newData)) {
782
+ this.cacheStrategy.set(key, newData);
783
+ const res = {
784
+ response: { data: newData, status: 200 },
785
+ error: null
786
+ };
787
+ syncObserver && syncObserver(res);
788
+ return res;
789
+ }
790
+ const res = {
791
+ response: null,
792
+ error: null
793
+ };
794
+ return res;
795
+ };
796
+ Promise.resolve().then(onSyncCall);
797
+ return {
798
+ response: { data: cacheData, status: 200 },
799
+ error: null,
800
+ onSync: observer => (syncObserver = observer)
801
+ };
802
+ }
803
+ }
804
+ _a = SdkCache;
805
+ // this could be localStorage or indexeddb
806
+ SdkCache.cacheStrategy = new Map();
807
+ SdkCache.clearCache = () => {
808
+ _a.cacheStrategy.clear();
809
+ };
810
+
811
+ exports.Accelbyte = Accelbyte;
812
+ exports.ApiUtils = ApiUtils;
813
+ exports.BrowserHelper = BrowserHelper;
814
+ exports.CodeGenUtil = CodeGenUtil;
815
+ exports.DecodeError = DecodeError;
816
+ exports.DesktopChecker = DesktopChecker;
817
+ exports.ERROR_CODE_LINK_DELETION_ACCOUNT = ERROR_CODE_LINK_DELETION_ACCOUNT;
818
+ exports.ERROR_CODE_TOKEN_EXPIRED = ERROR_CODE_TOKEN_EXPIRED;
819
+ exports.ERROR_LINK_ANOTHER_3RD_PARTY_ACCOUNT = ERROR_LINK_ANOTHER_3RD_PARTY_ACCOUNT;
820
+ exports.ERROR_USER_BANNED = ERROR_USER_BANNED;
821
+ exports.Network = Network;
822
+ exports.RefreshSession = RefreshSession;
823
+ exports.SdkCache = SdkCache;
824
+ exports.SdkDevice = SdkDevice;
825
+ exports.UrlHelper = UrlHelper;
826
+ exports.VALIDATION_ERROR_CODE = VALIDATION_ERROR_CODE;
827
+ exports.Validate = Validate;
828
+ exports.doRefreshSession = doRefreshSession;
829
+ exports.injectAuthInterceptors = injectAuthInterceptors;
830
+ exports.injectErrorInterceptors = injectErrorInterceptors;
831
+ exports.injectRequestInterceptors = injectRequestInterceptors;
832
+ exports.injectResponseInterceptors = injectResponseInterceptors;
833
+ exports.refreshWithLock = refreshWithLock;
834
+ //# sourceMappingURL=index.node.js.map