@accelbyte/sdk 0.0.0-dev-20240906023252 → 0.0.0-dev-20240911051006

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.
@@ -2,8 +2,29 @@
2
2
  import { Buffer as Buffer2 } from "buffer";
3
3
  window.Buffer = Buffer2;
4
4
 
5
- // src/utils/Network.ts
5
+ // src/utils/ApiUtils.ts
6
6
  import axios from "axios";
7
+ var ApiUtils = class {
8
+ };
9
+ ApiUtils.mergeAxiosConfigs = (config, overrides) => {
10
+ return {
11
+ ...config,
12
+ ...overrides,
13
+ headers: {
14
+ ...config?.headers,
15
+ ...overrides?.headers
16
+ }
17
+ };
18
+ };
19
+ ApiUtils.is4xxError = (error) => {
20
+ if (axios.isAxiosError(error) && error.response) {
21
+ return error.response.status >= 400 && error.response.status <= 499;
22
+ }
23
+ return false;
24
+ };
25
+
26
+ // src/utils/Network.ts
27
+ import axios2 from "axios";
7
28
  import qs from "query-string";
8
29
 
9
30
  // src/utils/SdkDevice.ts
@@ -47,7 +68,7 @@ var isMobile = (opts) => {
47
68
  // src/utils/Network.ts
48
69
  var _Network = class _Network {
49
70
  static create(...configs) {
50
- const axiosInstance = axios.create(
71
+ const axiosInstance = axios2.create(
51
72
  Object.assign(
52
73
  {
53
74
  paramsSerializer: qs.stringify
@@ -110,9 +131,27 @@ var AccelByteSDK = class _AccelByteSDK {
110
131
  }
111
132
  }
112
133
  };
113
- this.axiosInstance = Network.create({ baseURL: coreConfig.baseURL, ...this.axiosConfig.request });
134
+ this.axiosInstance = this.createAxiosInstance();
114
135
  this.token = {};
115
136
  }
137
+ createAxiosInstance() {
138
+ const axiosInstance = Network.create({ baseURL: this.coreConfig.baseURL, ...this.axiosConfig.request });
139
+ const interceptors = this.axiosConfig.interceptors;
140
+ if (interceptors) {
141
+ for (const interceptor of interceptors) {
142
+ if (interceptor.type === "request") {
143
+ axiosInstance.interceptors.request.use(interceptor?.onRequest, interceptor.onError);
144
+ }
145
+ if (interceptor.type === "response") {
146
+ axiosInstance.interceptors.response.use(interceptor?.onSuccess, interceptor.onError);
147
+ }
148
+ }
149
+ }
150
+ return axiosInstance;
151
+ }
152
+ /**
153
+ * Assembles and returns the current Axios instance along with core and Axios configurations.
154
+ */
116
155
  assembly() {
117
156
  return {
118
157
  axiosInstance: this.axiosInstance,
@@ -120,6 +159,12 @@ var AccelByteSDK = class _AccelByteSDK {
120
159
  axiosConfig: this.axiosConfig
121
160
  };
122
161
  }
162
+ /**
163
+ * Creates a new instance of AccelByteSDK with a shallow copy of the current configurations.
164
+ * Optionally allows excluding interceptors.
165
+ * @param {boolean} [opts.interceptors] - Whether to include interceptors in the clone. Default is true.
166
+ * @returns {AccelByteSDK} A new instance of AccelByteSDK with the cloned configuration.
167
+ */
123
168
  clone(opts) {
124
169
  const newConfigs = {
125
170
  coreConfig: { ...this.coreConfig },
@@ -130,6 +175,9 @@ var AccelByteSDK = class _AccelByteSDK {
130
175
  }
131
176
  return new _AccelByteSDK(newConfigs);
132
177
  }
178
+ /**
179
+ * Adds interceptors to the current Axios configuration.
180
+ */
133
181
  addInterceptors(interceptors) {
134
182
  if (!this.axiosConfig.interceptors) {
135
183
  this.axiosConfig.interceptors = [];
@@ -141,11 +189,18 @@ var AccelByteSDK = class _AccelByteSDK {
141
189
  if (!this.axiosConfig?.interceptors) return this;
142
190
  if (!filterCallback) {
143
191
  this.axiosConfig.interceptors = void 0;
192
+ this.axiosInstance.interceptors.request.clear();
193
+ this.axiosInstance.interceptors.response.clear();
144
194
  return this;
145
195
  }
146
196
  this.axiosConfig.interceptors = this.axiosConfig.interceptors.filter(filterCallback);
197
+ this.axiosInstance = this.createAxiosInstance();
147
198
  return this;
148
199
  }
200
+ /**
201
+ * Updates the SDK's core and Axios configurations.
202
+ * Merges the provided configurations with the current ones.
203
+ */
149
204
  setConfig({ coreConfig, axiosConfig }) {
150
205
  this.coreConfig = {
151
206
  ...this.coreConfig,
@@ -153,19 +208,36 @@ var AccelByteSDK = class _AccelByteSDK {
153
208
  };
154
209
  this.axiosConfig = {
155
210
  ...this.axiosConfig,
156
- ...axiosConfig
211
+ ...axiosConfig?.interceptors,
212
+ request: ApiUtils.mergeAxiosConfigs(this.axiosConfig.request, axiosConfig?.request)
157
213
  };
214
+ this.axiosInstance = this.createAxiosInstance();
158
215
  return this;
159
216
  }
217
+ /**
218
+ * Set accessToken and refreshToken and updates the Axios request headers to use Bearer authentication.
219
+ */
160
220
  setToken(token) {
161
221
  this.token = {
162
222
  ...this.token,
163
223
  ...token
164
224
  };
225
+ const configOverride = { headers: { Authorization: this.token.accessToken ? `Bearer ${this.token.accessToken}` : "" } };
226
+ this.axiosConfig = {
227
+ ...this.axiosConfig,
228
+ request: ApiUtils.mergeAxiosConfigs(this.axiosInstance.defaults, configOverride)
229
+ };
230
+ this.axiosInstance = this.createAxiosInstance();
165
231
  }
232
+ /**
233
+ * Removes the currently set token.
234
+ */
166
235
  removeToken() {
167
236
  this.token = {};
168
237
  }
238
+ /**
239
+ * Retrieves the current token configuration.
240
+ */
169
241
  getToken() {
170
242
  return this.token;
171
243
  }
@@ -198,7 +270,7 @@ var ERROR_CODE_TOKEN_EXPIRED = 10196;
198
270
  var ERROR_USER_BANNED = 10134;
199
271
 
200
272
  // src/interceptors/AuthInterceptors.ts
201
- import axios2 from "axios";
273
+ import axios3 from "axios";
202
274
 
203
275
  // src/utils/DesktopChecker.ts
204
276
  var _DesktopChecker = class _DesktopChecker {
@@ -441,69 +513,83 @@ var LoginUrls = /* @__PURE__ */ ((LoginUrls2) => {
441
513
  LoginUrls2["REVOKE"] = "/iam/v3/oauth/revoke";
442
514
  return LoginUrls2;
443
515
  })(LoginUrls || {});
444
- var refreshSession = ({ axiosConfig, refreshToken, clientId, tokenUrl }) => {
445
- const config = {
446
- ...axiosConfig,
447
- withCredentials: false,
448
- headers: {
449
- "Content-Type": "application/x-www-form-urlencoded",
450
- Authorization: `Basic ${Buffer.from(`${clientId}:`).toString("base64")}`
451
- }
452
- };
453
- const axios4 = Network.create(config);
454
- const payload = {
455
- refresh_token: refreshToken || void 0,
456
- client_id: clientId,
457
- grant_type: "refresh_token"
458
- };
459
- if (tokenUrl === "/iam/v4/oauth/token" /* GRANT_TOKEN_V4 */) {
460
- return new OAuth20V4$(axios4).postOauthToken_v4(payload);
461
- }
462
- const oauth20 = new OAuth20$(axios4);
463
- return oauth20.postOauthToken(payload);
464
- };
465
- var refreshWithLock = ({
466
- axiosConfig,
467
- refreshToken,
468
- clientId,
469
- tokenUrl
470
- }) => {
471
- if (RefreshSession.isLocked()) {
472
- return Promise.resolve().then(async () => {
473
- while (RefreshSession.isLocked()) {
474
- await RefreshSession.sleepAsync(REFRESH_EXPIRY_CHECK_RATE);
516
+ var noOp = () => {
517
+ };
518
+ var RefreshToken = class {
519
+ constructor({ config, interceptors }) {
520
+ // Return Promise<true> if refresh in any tab is successful;
521
+ this.runWithLock = () => {
522
+ if (RefreshSession.isLocked()) {
523
+ return Promise.resolve().then(async () => {
524
+ while (RefreshSession.isLocked()) {
525
+ await RefreshSession.sleepAsync(REFRESH_EXPIRY_CHECK_RATE);
526
+ }
527
+ return {};
528
+ });
475
529
  }
476
- return {};
477
- });
478
- }
479
- RefreshSession.lock(REFRESH_EXPIRY);
480
- let isLocallyRefreshingToken = true;
481
- (async () => {
482
- while (isLocallyRefreshingToken) {
483
530
  RefreshSession.lock(REFRESH_EXPIRY);
484
- await RefreshSession.sleepAsync(REFRESH_EXPIRY_UPDATE_RATE);
485
- }
486
- })();
487
- return Promise.resolve().then(doRefreshSession({ axiosConfig, clientId, refreshToken, tokenUrl })).finally(() => {
488
- isLocallyRefreshingToken = false;
489
- RefreshSession.unlock();
490
- });
491
- };
492
- var doRefreshSession = ({ axiosConfig, clientId, refreshToken, tokenUrl }) => async () => {
493
- if (DesktopChecker.isDesktopApp() && !axiosConfig.withCredentials && !refreshToken) {
494
- return false;
495
- }
496
- const result = await refreshSession({ axiosConfig, clientId, refreshToken, tokenUrl });
497
- if (result.error) {
498
- return false;
531
+ let isLocallyRefreshingToken = true;
532
+ (async () => {
533
+ while (isLocallyRefreshingToken) {
534
+ RefreshSession.lock(REFRESH_EXPIRY);
535
+ await RefreshSession.sleepAsync(REFRESH_EXPIRY_UPDATE_RATE);
536
+ }
537
+ })();
538
+ return Promise.resolve().then(() => this.run()).finally(() => {
539
+ isLocallyRefreshingToken = false;
540
+ RefreshSession.unlock();
541
+ });
542
+ };
543
+ this.run = async () => {
544
+ const { axiosConfig, refreshToken } = this.config;
545
+ if (DesktopChecker.isDesktopApp() && !axiosConfig.withCredentials && !refreshToken) {
546
+ return false;
547
+ }
548
+ const result = await this.refreshToken();
549
+ if (result.error) {
550
+ return false;
551
+ }
552
+ return result.response.data;
553
+ };
554
+ this.refreshToken = () => {
555
+ const { axiosConfig, refreshToken, clientId, tokenUrl } = this.config;
556
+ const config = {
557
+ ...axiosConfig,
558
+ withCredentials: false,
559
+ headers: {
560
+ "Content-Type": "application/x-www-form-urlencoded",
561
+ Authorization: `Basic ${Buffer.from(`${clientId}:`).toString("base64")}`
562
+ }
563
+ };
564
+ const axios4 = Network.create(config);
565
+ for (const interceptor of this.interceptors) {
566
+ if (interceptor.type === "request") {
567
+ axios4.interceptors.request.use(interceptor?.onRequest, interceptor.onError);
568
+ }
569
+ if (interceptor.type === "response") {
570
+ axios4.interceptors.response.use(interceptor?.onSuccess, interceptor.onError);
571
+ }
572
+ }
573
+ const payload = {
574
+ refresh_token: refreshToken || void 0,
575
+ client_id: clientId,
576
+ grant_type: "refresh_token"
577
+ };
578
+ if (tokenUrl === "/iam/v4/oauth/token" /* GRANT_TOKEN_V4 */) {
579
+ return new OAuth20V4$(axios4).postOauthToken_v4(payload);
580
+ }
581
+ const oauth20 = new OAuth20$(axios4);
582
+ return oauth20.postOauthToken(payload);
583
+ };
584
+ this.config = config;
585
+ this.interceptors = interceptors || [];
499
586
  }
500
- return result.response.data;
501
587
  };
502
- var uponRefreshComplete = (error, tokenResponse, onSessionExpired, axiosConfig, errorConfig) => {
588
+ var refreshComplete = (error, tokenResponse, onSessionExpired, axiosConfig, errorConfig) => {
503
589
  if (tokenResponse) {
504
590
  const { access_token } = tokenResponse;
505
591
  if (!axiosConfig.withCredentials && access_token) {
506
- return axios2({
592
+ return axios3({
507
593
  ...errorConfig,
508
594
  headers: {
509
595
  ...errorConfig.headers,
@@ -511,7 +597,7 @@ var uponRefreshComplete = (error, tokenResponse, onSessionExpired, axiosConfig,
511
597
  }
512
598
  });
513
599
  } else {
514
- return axios2(errorConfig);
600
+ return axios3(errorConfig);
515
601
  }
516
602
  }
517
603
  if (onSessionExpired) {
@@ -519,6 +605,49 @@ var uponRefreshComplete = (error, tokenResponse, onSessionExpired, axiosConfig,
519
605
  }
520
606
  throw error;
521
607
  };
608
+ var createAuthInterceptor = ({
609
+ clientId,
610
+ onSessionExpired,
611
+ onGetUserSession,
612
+ expectedErrorUrls = Object.values({ ...LoginUrls, ...GrantTokenUrls }),
613
+ getRefreshToken,
614
+ tokenUrl = "/iam/v3/oauth/token" /* GRANT_TOKEN */
615
+ }) => {
616
+ return {
617
+ type: "response",
618
+ name: "session-expired",
619
+ onError: (e) => {
620
+ const error = e;
621
+ const { config, response } = error;
622
+ if (axios3.isCancel(error)) {
623
+ return Promise.reject(error);
624
+ }
625
+ if (!response) {
626
+ console.warn(`sdk:ERR_INTERNET_DISCONNECTED ${config?.baseURL}${config?.url}. ${error.message}
627
+ `);
628
+ }
629
+ if (response?.status === 401) {
630
+ const { url } = config || {};
631
+ const axiosConfig = config;
632
+ const refreshToken = getRefreshToken();
633
+ if (!url || url && expectedErrorUrls.includes(url)) {
634
+ return Promise.reject(error);
635
+ }
636
+ const refresh = new RefreshToken({
637
+ config: { axiosConfig, clientId, refreshToken, tokenUrl },
638
+ interceptors: [
639
+ createRefreshSessionInterceptor({ tokenUrl }),
640
+ createGetSessionInterceptor({ onGetUserSession: onGetUserSession || noOp, tokenUrl })
641
+ ]
642
+ });
643
+ return refresh.runWithLock().then((tokenResponse) => {
644
+ return refreshComplete(error, tokenResponse, onSessionExpired, axiosConfig, config || {});
645
+ });
646
+ }
647
+ return Promise.reject(error);
648
+ }
649
+ };
650
+ };
522
651
  var createRefreshSessionInterceptor = (options) => {
523
652
  const { tokenUrl = "/iam/v3/oauth/token" /* GRANT_TOKEN */ } = options || {};
524
653
  return {
@@ -552,41 +681,6 @@ var createGetSessionInterceptor = ({
552
681
  return response;
553
682
  }
554
683
  });
555
- var createSessionExpiredInterceptor = ({
556
- clientId,
557
- onSessionExpired,
558
- expectedErrorUrls = Object.values({ ...LoginUrls, ...GrantTokenUrls }),
559
- getRefreshToken,
560
- tokenUrl = "/iam/v3/oauth/token" /* GRANT_TOKEN */
561
- }) => {
562
- return {
563
- type: "response",
564
- name: "session-expired",
565
- onError: (e) => {
566
- const error = e;
567
- const { config, response } = error;
568
- if (axios2.isCancel(error)) {
569
- return Promise.reject(error);
570
- }
571
- if (!response) {
572
- console.warn(`sdk:ERR_INTERNET_DISCONNECTED ${config?.baseURL}${config?.url}. ${error.message}
573
- `);
574
- }
575
- if (response?.status === 401) {
576
- const { url } = config || {};
577
- const axiosConfig = config;
578
- const refreshToken = getRefreshToken();
579
- if (!url || url && expectedErrorUrls.includes(url)) {
580
- return Promise.reject(error);
581
- }
582
- return refreshWithLock({ axiosConfig, clientId, refreshToken, tokenUrl }).then((tokenResponse) => {
583
- return uponRefreshComplete(error, tokenResponse, onSessionExpired, axiosConfig, config || {});
584
- });
585
- }
586
- return Promise.reject(error);
587
- }
588
- };
589
- };
590
684
 
591
685
  // src/constants/paths.ts
592
686
  var INTERNAL_SERVICES = {
@@ -681,27 +775,6 @@ var ErrorInterceptors = [
681
775
  }
682
776
  ];
683
777
 
684
- // src/utils/ApiUtils.ts
685
- import axios3 from "axios";
686
- var ApiUtils = class {
687
- };
688
- ApiUtils.mergeAxiosConfigs = (config, overrides) => {
689
- return {
690
- ...config,
691
- ...overrides,
692
- headers: {
693
- ...config?.headers,
694
- ...overrides?.headers
695
- }
696
- };
697
- };
698
- ApiUtils.is4xxError = (error) => {
699
- if (axios3.isAxiosError(error) && error.response) {
700
- return error.response.status >= 400 && error.response.status <= 499;
701
- }
702
- return false;
703
- };
704
-
705
778
  // src/utils/Type.ts
706
779
  function isType(schema, data) {
707
780
  return schema.safeParse(data).success;
@@ -772,15 +845,14 @@ export {
772
845
  IamErrorCode,
773
846
  Network,
774
847
  RefreshSession,
848
+ RefreshToken,
775
849
  SdkDevice,
776
850
  UrlHelper,
777
851
  Validate,
852
+ createAuthInterceptor,
778
853
  createCustomPathInterceptor,
779
854
  createGetSessionInterceptor,
780
855
  createRefreshSessionInterceptor,
781
- createSessionExpiredInterceptor,
782
- doRefreshSession,
783
- isType,
784
- refreshWithLock
856
+ isType
785
857
  };
786
858
  //# sourceMappingURL=index.browser.js.map