@accelbyte/sdk 3.0.7 → 4.0.0
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.
- package/README.md +572 -2
- package/dist/cjs/node/index.cjs +900 -832
- package/dist/cjs/node/index.cjs.map +1 -1
- package/dist/es/browser/index.browser.js +838 -792
- package/dist/es/browser/index.browser.js.map +1 -1
- package/dist/es/node/index.node.js +843 -793
- package/dist/es/node/index.node.js.map +1 -1
- package/dist/index.d.ts +312 -237
- package/package.json +40 -12
|
@@ -1,827 +1,873 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
import * as uuid from 'uuid';
|
|
5
|
-
import { z } from 'zod';
|
|
1
|
+
// src/polyfills/browser.ts
|
|
2
|
+
import { Buffer as Buffer2 } from "buffer";
|
|
3
|
+
window.Buffer = Buffer2;
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
SdkDevice.generateUUID = () => {
|
|
27
|
-
const deviceIdInUUID = uuid.v4().split('-').join('');
|
|
28
|
-
localStorage.setItem(SdkDevice.ID_KEY, deviceIdInUUID);
|
|
29
|
-
return deviceIdInUUID;
|
|
30
|
-
};
|
|
31
|
-
SdkDevice.getDeviceId = () => {
|
|
32
|
-
return localStorage.getItem(_a.ID_KEY) || _a.generateUUID();
|
|
33
|
-
};
|
|
34
|
-
/*
|
|
35
|
-
Bellow function is copied from npm 'is-mobile'
|
|
36
|
-
*/
|
|
37
|
-
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;
|
|
38
|
-
const tabletRE = /android|ipad|playbook|silk/i;
|
|
39
|
-
const isMobile = (opts) => {
|
|
40
|
-
if (!opts)
|
|
41
|
-
opts = {};
|
|
42
|
-
let ua = opts.ua;
|
|
43
|
-
if (!ua && typeof navigator !== 'undefined')
|
|
44
|
-
ua = navigator.userAgent;
|
|
45
|
-
if (ua && ua.headers && typeof ua.headers['user-agent'] === 'string') {
|
|
46
|
-
ua = ua.headers['user-agent'];
|
|
47
|
-
}
|
|
48
|
-
if (typeof ua !== 'string')
|
|
49
|
-
return false;
|
|
50
|
-
let result = mobileRE.test(ua) || (!!opts.tablet && tabletRE.test(ua));
|
|
51
|
-
if (!result &&
|
|
52
|
-
opts.tablet &&
|
|
53
|
-
opts.featureDetect &&
|
|
54
|
-
navigator &&
|
|
55
|
-
navigator.maxTouchPoints > 1 &&
|
|
56
|
-
ua.indexOf('Macintosh') !== -1 &&
|
|
57
|
-
ua.indexOf('Safari') !== -1) {
|
|
58
|
-
result = true;
|
|
59
|
-
}
|
|
60
|
-
return result;
|
|
5
|
+
// src/utils/ApiUtils.ts
|
|
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;
|
|
61
24
|
};
|
|
62
25
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
});
|
|
104
|
-
loggerInterceptor(axiosInstance);
|
|
105
|
-
return axiosInstance;
|
|
106
|
-
}
|
|
107
|
-
static withBearerToken(accessToken, config) {
|
|
108
|
-
return Network.create(config || {}, {
|
|
109
|
-
headers: { Authorization: `Bearer ${accessToken}` }
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
Network.setDeviceTokenCookie = () => {
|
|
114
|
-
const deviceId = SdkDevice.getDeviceId();
|
|
115
|
-
document.cookie = `device_token=${deviceId}; path=/;`;
|
|
116
|
-
};
|
|
117
|
-
Network.removeDeviceTokenCookie = () => {
|
|
118
|
-
document.cookie = `device_token=; expires=${new Date(0).toUTCString()}`;
|
|
119
|
-
};
|
|
120
|
-
Network.getFormUrlEncodedData = (data) => {
|
|
121
|
-
const formPayload = new URLSearchParams();
|
|
122
|
-
const formKeys = Object.keys(data);
|
|
123
|
-
formKeys.forEach(key => {
|
|
124
|
-
if (data[key])
|
|
125
|
-
formPayload.append(key, data[key]);
|
|
126
|
-
});
|
|
127
|
-
return formPayload;
|
|
26
|
+
// src/utils/Network.ts
|
|
27
|
+
import axios2 from "axios";
|
|
28
|
+
import qs from "query-string";
|
|
29
|
+
|
|
30
|
+
// src/utils/SdkDevice.ts
|
|
31
|
+
import * as uuid from "uuid";
|
|
32
|
+
var _SdkDevice = class _SdkDevice {
|
|
33
|
+
};
|
|
34
|
+
_SdkDevice.ID_KEY = "deviceId";
|
|
35
|
+
_SdkDevice.TYPE = {
|
|
36
|
+
MOBILE: "mobile",
|
|
37
|
+
DESKTOP: "desktop"
|
|
38
|
+
};
|
|
39
|
+
_SdkDevice.getType = () => {
|
|
40
|
+
return isMobile() ? _SdkDevice.TYPE.MOBILE : _SdkDevice.TYPE.DESKTOP;
|
|
41
|
+
};
|
|
42
|
+
_SdkDevice.generateUUID = () => {
|
|
43
|
+
const deviceIdInUUID = uuid.v4().split("-").join("");
|
|
44
|
+
localStorage.setItem(_SdkDevice.ID_KEY, deviceIdInUUID);
|
|
45
|
+
return deviceIdInUUID;
|
|
46
|
+
};
|
|
47
|
+
_SdkDevice.getDeviceId = () => {
|
|
48
|
+
return localStorage.getItem(_SdkDevice.ID_KEY) || _SdkDevice.generateUUID();
|
|
49
|
+
};
|
|
50
|
+
var SdkDevice = _SdkDevice;
|
|
51
|
+
var 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;
|
|
52
|
+
var tabletRE = /android|ipad|playbook|silk/i;
|
|
53
|
+
var isMobile = (opts) => {
|
|
54
|
+
if (!opts) opts = {};
|
|
55
|
+
let ua = opts.ua;
|
|
56
|
+
if (!ua && typeof navigator !== "undefined") ua = navigator.userAgent;
|
|
57
|
+
if (ua && ua.headers && typeof ua.headers["user-agent"] === "string") {
|
|
58
|
+
ua = ua.headers["user-agent"];
|
|
59
|
+
}
|
|
60
|
+
if (typeof ua !== "string") return false;
|
|
61
|
+
let result = mobileRE.test(ua) || !!opts.tablet && tabletRE.test(ua);
|
|
62
|
+
if (!result && opts.tablet && opts.featureDetect && navigator && navigator.maxTouchPoints > 1 && ua.indexOf("Macintosh") !== -1 && ua.indexOf("Safari") !== -1) {
|
|
63
|
+
result = true;
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
128
66
|
};
|
|
129
67
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
onError(error);
|
|
153
|
-
}
|
|
154
|
-
throw error;
|
|
155
|
-
});
|
|
68
|
+
// src/utils/Network.ts
|
|
69
|
+
var _Network = class _Network {
|
|
70
|
+
static create(...configs) {
|
|
71
|
+
const axiosInstance = axios2.create(
|
|
72
|
+
Object.assign(
|
|
73
|
+
{
|
|
74
|
+
paramsSerializer: qs.stringify
|
|
75
|
+
},
|
|
76
|
+
...configs
|
|
77
|
+
)
|
|
78
|
+
);
|
|
79
|
+
return axiosInstance;
|
|
80
|
+
}
|
|
81
|
+
static withBearerToken(accessToken, config) {
|
|
82
|
+
return _Network.create(config || {}, {
|
|
83
|
+
headers: { Authorization: `Bearer ${accessToken}` }
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
_Network.setDeviceTokenCookie = () => {
|
|
88
|
+
const deviceId = SdkDevice.getDeviceId();
|
|
89
|
+
document.cookie = `device_token=${deviceId}; path=/;`;
|
|
156
90
|
};
|
|
91
|
+
_Network.removeDeviceTokenCookie = () => {
|
|
92
|
+
document.cookie = `device_token=; expires=${(/* @__PURE__ */ new Date(0)).toUTCString()}`;
|
|
93
|
+
};
|
|
94
|
+
_Network.getFormUrlEncodedData = (data) => {
|
|
95
|
+
const formPayload = new URLSearchParams();
|
|
96
|
+
const formKeys = Object.keys(data);
|
|
97
|
+
formKeys.forEach((key) => {
|
|
98
|
+
if (data[key]) formPayload.append(key, data[key]);
|
|
99
|
+
});
|
|
100
|
+
return formPayload;
|
|
101
|
+
};
|
|
102
|
+
var Network = _Network;
|
|
157
103
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
104
|
+
// src/AccelByteSDK.ts
|
|
105
|
+
var AccelByte = {
|
|
106
|
+
SDK: (param) => {
|
|
107
|
+
return new AccelByteSDK(param);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
var AccelByteSDK = class _AccelByteSDK {
|
|
111
|
+
constructor({ coreConfig, axiosConfig }) {
|
|
112
|
+
this.coreConfig = {
|
|
113
|
+
...coreConfig,
|
|
114
|
+
useSchemaValidation: coreConfig.useSchemaValidation ?? true
|
|
115
|
+
};
|
|
116
|
+
this.axiosConfig = {
|
|
117
|
+
/**
|
|
118
|
+
* when user create a variable to store intercepters and passed into sdk
|
|
119
|
+
* the sdk will use the variable as reference value,
|
|
120
|
+
* so when new interceptor added, reference value will also has the new interceptor,
|
|
121
|
+
* to avoid this we create shallow copy for the interceptors
|
|
122
|
+
*/
|
|
123
|
+
interceptors: axiosConfig?.interceptors ? [...axiosConfig.interceptors] : void 0,
|
|
124
|
+
request: {
|
|
125
|
+
timeout: 6e4,
|
|
126
|
+
withCredentials: true,
|
|
127
|
+
...axiosConfig?.request,
|
|
128
|
+
headers: {
|
|
129
|
+
"Content-Type": "application/json",
|
|
130
|
+
...axiosConfig?.request?.headers
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
this.axiosInstance = this.createAxiosInstance();
|
|
135
|
+
this.token = {};
|
|
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
|
+
*/
|
|
155
|
+
assembly() {
|
|
156
|
+
return {
|
|
157
|
+
axiosInstance: this.axiosInstance,
|
|
158
|
+
coreConfig: this.coreConfig,
|
|
159
|
+
axiosConfig: this.axiosConfig
|
|
160
|
+
};
|
|
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
|
+
*/
|
|
168
|
+
clone(opts) {
|
|
169
|
+
const newConfigs = {
|
|
170
|
+
coreConfig: { ...this.coreConfig },
|
|
171
|
+
axiosConfig: { ...this.axiosConfig }
|
|
172
|
+
};
|
|
173
|
+
if (opts?.interceptors === false) {
|
|
174
|
+
delete newConfigs.axiosConfig.interceptors;
|
|
175
|
+
}
|
|
176
|
+
const newSdkInstance = new _AccelByteSDK(newConfigs);
|
|
177
|
+
newSdkInstance.setToken(this.token);
|
|
178
|
+
return newSdkInstance;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Adds interceptors to the current Axios configuration.
|
|
182
|
+
*/
|
|
183
|
+
addInterceptors(interceptors) {
|
|
184
|
+
if (!this.axiosConfig.interceptors) {
|
|
185
|
+
this.axiosConfig.interceptors = [];
|
|
186
|
+
}
|
|
187
|
+
this.axiosConfig.interceptors.push(...interceptors);
|
|
188
|
+
return this;
|
|
189
|
+
}
|
|
190
|
+
removeInterceptors(filterCallback) {
|
|
191
|
+
if (!this.axiosConfig?.interceptors) return this;
|
|
192
|
+
if (!filterCallback) {
|
|
193
|
+
this.axiosConfig.interceptors = void 0;
|
|
194
|
+
this.axiosInstance.interceptors.request.clear();
|
|
195
|
+
this.axiosInstance.interceptors.response.clear();
|
|
196
|
+
return this;
|
|
197
|
+
}
|
|
198
|
+
this.axiosConfig.interceptors = this.axiosConfig.interceptors.filter(filterCallback);
|
|
199
|
+
this.axiosInstance = this.createAxiosInstance();
|
|
200
|
+
return this;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Updates the SDK's core and Axios configurations.
|
|
204
|
+
* Merges the provided configurations with the current ones.
|
|
205
|
+
*/
|
|
206
|
+
setConfig({ coreConfig, axiosConfig }) {
|
|
207
|
+
this.coreConfig = {
|
|
208
|
+
...this.coreConfig,
|
|
209
|
+
...coreConfig
|
|
210
|
+
};
|
|
211
|
+
this.axiosConfig = {
|
|
212
|
+
...this.axiosConfig,
|
|
213
|
+
...axiosConfig?.interceptors,
|
|
214
|
+
request: ApiUtils.mergeAxiosConfigs(this.axiosConfig.request, axiosConfig?.request)
|
|
215
|
+
};
|
|
216
|
+
this.axiosInstance = this.createAxiosInstance();
|
|
217
|
+
return this;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Set accessToken and refreshToken and updates the Axios request headers to use Bearer authentication.
|
|
221
|
+
*/
|
|
222
|
+
setToken(token) {
|
|
223
|
+
this.token = {
|
|
224
|
+
...this.token,
|
|
225
|
+
...token
|
|
226
|
+
};
|
|
227
|
+
const configOverride = { headers: { Authorization: this.token.accessToken ? `Bearer ${this.token.accessToken}` : "" } };
|
|
228
|
+
this.axiosConfig = {
|
|
229
|
+
...this.axiosConfig,
|
|
230
|
+
request: ApiUtils.mergeAxiosConfigs(this.axiosInstance.defaults, configOverride)
|
|
231
|
+
};
|
|
232
|
+
this.axiosInstance = this.createAxiosInstance();
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Removes the currently set token.
|
|
236
|
+
*/
|
|
237
|
+
removeToken() {
|
|
238
|
+
this.token = {};
|
|
239
|
+
const configOverride = { headers: { Authorization: void 0 } };
|
|
240
|
+
this.axiosConfig = {
|
|
241
|
+
...this.axiosConfig,
|
|
242
|
+
request: ApiUtils.mergeAxiosConfigs(this.axiosInstance.defaults, configOverride)
|
|
243
|
+
};
|
|
244
|
+
this.axiosInstance = this.createAxiosInstance();
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Retrieves the current token configuration.
|
|
248
|
+
*/
|
|
249
|
+
getToken() {
|
|
250
|
+
return this.token;
|
|
251
|
+
}
|
|
167
252
|
};
|
|
168
253
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
254
|
+
// src/constants/IamErrorCode.ts
|
|
255
|
+
var IamErrorCode = /* @__PURE__ */ ((IamErrorCode2) => {
|
|
256
|
+
IamErrorCode2[IamErrorCode2["InternalServerError"] = 2e4] = "InternalServerError";
|
|
257
|
+
IamErrorCode2[IamErrorCode2["UnauthorizedAccess"] = 20001] = "UnauthorizedAccess";
|
|
258
|
+
IamErrorCode2[IamErrorCode2["ValidationError"] = 20002] = "ValidationError";
|
|
259
|
+
IamErrorCode2[IamErrorCode2["ForbiddenAccess"] = 20003] = "ForbiddenAccess";
|
|
260
|
+
IamErrorCode2[IamErrorCode2["TooManyRequests"] = 20007] = "TooManyRequests";
|
|
261
|
+
IamErrorCode2[IamErrorCode2["UserNotFound"] = 20008] = "UserNotFound";
|
|
262
|
+
IamErrorCode2[IamErrorCode2["TokenIsExpired"] = 20011] = "TokenIsExpired";
|
|
263
|
+
IamErrorCode2[IamErrorCode2["InsufficientPermissions"] = 20013] = "InsufficientPermissions";
|
|
264
|
+
IamErrorCode2[IamErrorCode2["InvalidAudience"] = 20014] = "InvalidAudience";
|
|
265
|
+
IamErrorCode2[IamErrorCode2["InsufficientScope"] = 20015] = "InsufficientScope";
|
|
266
|
+
IamErrorCode2[IamErrorCode2["UnableToParseRequestBody"] = 20019] = "UnableToParseRequestBody";
|
|
267
|
+
IamErrorCode2[IamErrorCode2["InvalidPaginationParameters"] = 20021] = "InvalidPaginationParameters";
|
|
268
|
+
IamErrorCode2[IamErrorCode2["TokenIsNotUserToken"] = 20022] = "TokenIsNotUserToken";
|
|
269
|
+
IamErrorCode2[IamErrorCode2["InvalidRefererHeader"] = 20023] = "InvalidRefererHeader";
|
|
270
|
+
IamErrorCode2[IamErrorCode2["SubdomainMismatch"] = 20030] = "SubdomainMismatch";
|
|
271
|
+
return IamErrorCode2;
|
|
272
|
+
})(IamErrorCode || {});
|
|
273
|
+
|
|
274
|
+
// src/constants/LinkAccount.ts
|
|
275
|
+
var ERROR_LINK_ANOTHER_3RD_PARTY_ACCOUNT = 10200;
|
|
276
|
+
var ERROR_CODE_LINK_DELETION_ACCOUNT = 10135;
|
|
277
|
+
var ERROR_CODE_TOKEN_EXPIRED = 10196;
|
|
278
|
+
var ERROR_USER_BANNED = 10134;
|
|
279
|
+
|
|
280
|
+
// src/interceptors/AuthInterceptors.ts
|
|
281
|
+
import axios3 from "axios";
|
|
282
|
+
|
|
283
|
+
// src/utils/DesktopChecker.ts
|
|
284
|
+
var _DesktopChecker = class _DesktopChecker {
|
|
285
|
+
static isDesktopApp() {
|
|
286
|
+
return _DesktopChecker.desktopApp && !_DesktopChecker.isInIframe();
|
|
287
|
+
}
|
|
288
|
+
static isInIframe() {
|
|
289
|
+
try {
|
|
290
|
+
return window.self !== window.top;
|
|
291
|
+
} catch (error) {
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// borrowed from https://github.com/cheton/is-electron
|
|
296
|
+
static isElectron() {
|
|
297
|
+
if (typeof window !== "undefined" && typeof window.process === "object" && window.process.type === "renderer") {
|
|
298
|
+
return true;
|
|
299
|
+
}
|
|
300
|
+
if (typeof process !== "undefined" && typeof process.versions === "object" && !!process.versions.electron) {
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
if (typeof navigator === "object" && typeof navigator.userAgent === "string" && navigator.userAgent.indexOf("Electron") >= 0) {
|
|
304
|
+
return true;
|
|
305
|
+
}
|
|
306
|
+
return false;
|
|
307
|
+
}
|
|
203
308
|
};
|
|
309
|
+
_DesktopChecker.desktopApp = _DesktopChecker.isElectron();
|
|
310
|
+
var DesktopChecker = _DesktopChecker;
|
|
204
311
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
class CodeGenUtil {
|
|
211
|
-
/**
|
|
212
|
-
* Returns a hash code from a string
|
|
213
|
-
* @param {String} str The string to hash.
|
|
214
|
-
* @return {Number} A 32bit integer
|
|
215
|
-
* @see http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
|
|
216
|
-
*/
|
|
217
|
-
static hashCode(str) {
|
|
218
|
-
let hash = 0;
|
|
219
|
-
for (let i = 0, len = str.length; i < len; i++) {
|
|
220
|
-
const chr = str.charCodeAt(i);
|
|
221
|
-
hash = (hash << 5) - hash + chr;
|
|
222
|
-
hash |= 0; // Convert to 32bit integer
|
|
223
|
-
}
|
|
224
|
-
return hash;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
CodeGenUtil.getFormUrlEncodedData = (data) => {
|
|
228
|
-
const formPayload = new URLSearchParams();
|
|
229
|
-
const formKeys = Object.keys(data);
|
|
230
|
-
formKeys.forEach(key => {
|
|
231
|
-
if (typeof data[key] !== 'undefined')
|
|
232
|
-
formPayload.append(key, data[key]);
|
|
233
|
-
});
|
|
234
|
-
return formPayload;
|
|
312
|
+
// src/utils/BrowserHelper.ts
|
|
313
|
+
var BrowserHelper = class {
|
|
314
|
+
};
|
|
315
|
+
BrowserHelper.isOnBrowser = () => {
|
|
316
|
+
return typeof window !== "undefined" && window.document;
|
|
235
317
|
};
|
|
236
318
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
319
|
+
// src/utils/RefreshSession.ts
|
|
320
|
+
var _RefreshSession = class _RefreshSession {
|
|
321
|
+
};
|
|
322
|
+
// --
|
|
323
|
+
_RefreshSession.KEY = "RefreshSession.lock";
|
|
324
|
+
_RefreshSession.isLocked = () => {
|
|
325
|
+
if (!BrowserHelper.isOnBrowser()) return false;
|
|
326
|
+
const lockStatus = localStorage.getItem(_RefreshSession.KEY);
|
|
327
|
+
if (!lockStatus) {
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
const lockExpiry = Number(lockStatus);
|
|
331
|
+
if (isNaN(lockExpiry)) {
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
return lockExpiry > (/* @__PURE__ */ new Date()).getTime();
|
|
335
|
+
};
|
|
336
|
+
_RefreshSession.lock = (expiry) => {
|
|
337
|
+
if (!BrowserHelper.isOnBrowser()) return;
|
|
338
|
+
localStorage.setItem(_RefreshSession.KEY, `${(/* @__PURE__ */ new Date()).getTime() + expiry}`);
|
|
339
|
+
};
|
|
340
|
+
_RefreshSession.unlock = () => {
|
|
341
|
+
if (!BrowserHelper.isOnBrowser()) return;
|
|
342
|
+
localStorage.removeItem(_RefreshSession.KEY);
|
|
261
343
|
};
|
|
344
|
+
_RefreshSession.sleepAsync = (timeInMs) => new Promise((resolve) => setTimeout(resolve, timeInMs));
|
|
345
|
+
_RefreshSession.isBearerAuth = (config) => {
|
|
346
|
+
if (config?.headers?.Authorization?.toLowerCase().indexOf("bearer") > -1) {
|
|
347
|
+
return true;
|
|
348
|
+
}
|
|
349
|
+
return false;
|
|
350
|
+
};
|
|
351
|
+
var RefreshSession = _RefreshSession;
|
|
262
352
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
return useSchemaValidation ? Validate.responseType(() => networkCall(), Codec, modelName) : Validate.unsafeResponse(() => networkCall());
|
|
266
|
-
}
|
|
267
|
-
static responseType(networkCall, Codec, modelName) {
|
|
268
|
-
return wrapNetworkCallSafely(async () => {
|
|
269
|
-
const response = await networkCall();
|
|
270
|
-
const decodeResult = Codec.safeParse(response.data);
|
|
271
|
-
if (!decodeResult.success && response.status !== 204) {
|
|
272
|
-
throw new DecodeError({ error: decodeResult.error, response, modelName });
|
|
273
|
-
}
|
|
274
|
-
return response;
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
static unsafeResponse(networkCall) {
|
|
278
|
-
return wrapNetworkCallSafely(() => networkCall());
|
|
279
|
-
}
|
|
280
|
-
static safeParse(data, Codec) {
|
|
281
|
-
const result = Codec.safeParse(data);
|
|
282
|
-
if (result.success) {
|
|
283
|
-
return result.data;
|
|
284
|
-
}
|
|
285
|
-
return null;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
async function wrapNetworkCallSafely(networkCallFunction) {
|
|
289
|
-
try {
|
|
290
|
-
const response = await networkCallFunction();
|
|
291
|
-
// Cleanup so we avoid polluting the response
|
|
292
|
-
// @ts-ignore
|
|
293
|
-
delete response.headers; // perhaps this may be required?
|
|
294
|
-
// @ts-ignore
|
|
295
|
-
delete response.statusText;
|
|
296
|
-
// @ts-ignore
|
|
297
|
-
delete response.config; // axios specific
|
|
298
|
-
delete response.request;
|
|
299
|
-
return { response, error: null };
|
|
300
|
-
}
|
|
301
|
-
catch (error) {
|
|
302
|
-
return { response: null, error: error };
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
class DecodeError extends Error {
|
|
306
|
-
constructor({ error, response, modelName }) {
|
|
307
|
-
const msg = `response from url "${response.config.url}" doesn't match model "${modelName}"`;
|
|
308
|
-
super(msg);
|
|
309
|
-
Logger.error(msg, error);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
353
|
+
// ../sdk-iam/src/generated-definitions/TokenWithDeviceCookieResponseV3.ts
|
|
354
|
+
import { z as z4 } from "zod";
|
|
312
355
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
enabled: z.boolean(),
|
|
322
|
-
endDate: z.string(),
|
|
323
|
-
targetedNamespace: z.string()
|
|
356
|
+
// ../sdk-iam/src/generated-definitions/JwtBanV3.ts
|
|
357
|
+
import { z } from "zod";
|
|
358
|
+
var JwtBanV3 = z.object({
|
|
359
|
+
ban: z.string(),
|
|
360
|
+
disabledDate: z.string().nullish(),
|
|
361
|
+
enabled: z.boolean(),
|
|
362
|
+
endDate: z.string(),
|
|
363
|
+
targetedNamespace: z.string()
|
|
324
364
|
});
|
|
325
365
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
* and restrictions contact your company contract manager.
|
|
330
|
-
*/
|
|
331
|
-
const NamespaceRole = z.object({ namespace: z.string(), roleId: z.string() });
|
|
366
|
+
// ../sdk-iam/src/generated-definitions/NamespaceRole.ts
|
|
367
|
+
import { z as z2 } from "zod";
|
|
368
|
+
var NamespaceRole = z2.object({ namespace: z2.string(), roleId: z2.string() });
|
|
332
369
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
schedAction: z.number().int().nullish(),
|
|
342
|
-
schedCron: z.string().nullish(),
|
|
343
|
-
schedRange: z.array(z.string()).nullish()
|
|
370
|
+
// ../sdk-iam/src/generated-definitions/PermissionV3.ts
|
|
371
|
+
import { z as z3 } from "zod";
|
|
372
|
+
var PermissionV3 = z3.object({
|
|
373
|
+
action: z3.number().int(),
|
|
374
|
+
resource: z3.string(),
|
|
375
|
+
schedAction: z3.number().int().nullish(),
|
|
376
|
+
schedCron: z3.string().nullish(),
|
|
377
|
+
schedRange: z3.array(z3.string()).nullish()
|
|
344
378
|
});
|
|
345
379
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
token_type: z.string(),
|
|
371
|
-
unique_display_name: z.string().nullish(),
|
|
372
|
-
user_id: z.string().nullish(),
|
|
373
|
-
xuid: z.string().nullish()
|
|
380
|
+
// ../sdk-iam/src/generated-definitions/TokenWithDeviceCookieResponseV3.ts
|
|
381
|
+
var TokenWithDeviceCookieResponseV3 = z4.object({
|
|
382
|
+
access_token: z4.string(),
|
|
383
|
+
auth_trust_id: z4.string().nullish(),
|
|
384
|
+
bans: z4.array(JwtBanV3).nullish(),
|
|
385
|
+
display_name: z4.string().nullish(),
|
|
386
|
+
expires_in: z4.number().int(),
|
|
387
|
+
is_comply: z4.boolean().nullish(),
|
|
388
|
+
jflgs: z4.number().int().nullish(),
|
|
389
|
+
namespace: z4.string(),
|
|
390
|
+
namespace_roles: z4.array(NamespaceRole).nullish(),
|
|
391
|
+
permissions: z4.array(PermissionV3),
|
|
392
|
+
platform_id: z4.string().nullish(),
|
|
393
|
+
platform_user_id: z4.string().nullish(),
|
|
394
|
+
refresh_expires_in: z4.number().int().nullish(),
|
|
395
|
+
refresh_token: z4.string().nullish(),
|
|
396
|
+
roles: z4.array(z4.string()).nullish(),
|
|
397
|
+
scope: z4.string(),
|
|
398
|
+
simultaneous_platform_id: z4.string().nullish(),
|
|
399
|
+
simultaneous_platform_user_id: z4.string().nullish(),
|
|
400
|
+
token_type: z4.string(),
|
|
401
|
+
unique_display_name: z4.string().nullish(),
|
|
402
|
+
user_id: z4.string().nullish(),
|
|
403
|
+
xuid: z4.string().nullish()
|
|
374
404
|
});
|
|
375
405
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
406
|
+
// src/utils/CodeGenUtil.ts
|
|
407
|
+
var CodeGenUtil = class {
|
|
408
|
+
/**
|
|
409
|
+
* Returns a hash code from a string
|
|
410
|
+
* @param {String} str The string to hash.
|
|
411
|
+
* @return {Number} A 32bit integer
|
|
412
|
+
* @see http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
|
|
413
|
+
*/
|
|
414
|
+
static hashCode(str) {
|
|
415
|
+
let hash = 0;
|
|
416
|
+
for (let i = 0, len = str.length; i < len; i++) {
|
|
417
|
+
const chr = str.charCodeAt(i);
|
|
418
|
+
hash = (hash << 5) - hash + chr;
|
|
419
|
+
hash |= 0;
|
|
420
|
+
}
|
|
421
|
+
return hash;
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
CodeGenUtil.getFormUrlEncodedData = (data) => {
|
|
425
|
+
const formPayload = new URLSearchParams();
|
|
426
|
+
const formKeys = Object.keys(data);
|
|
427
|
+
formKeys.forEach((key) => {
|
|
428
|
+
if (typeof data[key] !== "undefined") formPayload.append(key, data[key]);
|
|
429
|
+
});
|
|
430
|
+
return formPayload;
|
|
431
|
+
};
|
|
397
432
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
+
// src/utils/Validate.ts
|
|
434
|
+
var Validate = class _Validate {
|
|
435
|
+
static validateOrReturnResponse(useSchemaValidation, networkCall, Codec, modelName) {
|
|
436
|
+
return useSchemaValidation ? _Validate.responseType(() => networkCall(), Codec, modelName) : _Validate.unsafeResponse(() => networkCall());
|
|
437
|
+
}
|
|
438
|
+
static responseType(networkCall, Codec, modelName) {
|
|
439
|
+
return wrapNetworkCallSafely(async () => {
|
|
440
|
+
const response = await networkCall();
|
|
441
|
+
const decodeResult = Codec.safeParse(response.data);
|
|
442
|
+
if (!decodeResult.success && response.status !== 204) {
|
|
443
|
+
throw new DecodeError({ error: decodeResult.error, response, modelName });
|
|
444
|
+
}
|
|
445
|
+
return response;
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
static unsafeResponse(networkCall) {
|
|
449
|
+
return wrapNetworkCallSafely(() => networkCall());
|
|
450
|
+
}
|
|
451
|
+
static safeParse(data, Codec) {
|
|
452
|
+
const result = Codec.safeParse(data);
|
|
453
|
+
if (result.success) {
|
|
454
|
+
return result.data;
|
|
455
|
+
}
|
|
456
|
+
return null;
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
async function wrapNetworkCallSafely(networkCallFunction) {
|
|
460
|
+
try {
|
|
461
|
+
const response = await networkCallFunction();
|
|
462
|
+
return { response, error: null };
|
|
463
|
+
} catch (error) {
|
|
464
|
+
return { response: null, error };
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
var DecodeError = class extends Error {
|
|
468
|
+
constructor({ error, response, modelName }) {
|
|
469
|
+
const msg = `response from url "${response.config.url}" doesn't match model "${modelName}"`;
|
|
470
|
+
super(msg);
|
|
471
|
+
console.error(msg, error);
|
|
472
|
+
}
|
|
473
|
+
};
|
|
433
474
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
const
|
|
442
|
-
|
|
443
|
-
(
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
})
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
};
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
//
|
|
469
|
-
if (RefreshSession.isLocked()) {
|
|
470
|
-
return Promise.resolve().then(async () => {
|
|
471
|
-
// This block is executed when other tab / request is refreshing
|
|
472
|
-
while (RefreshSession.isLocked()) {
|
|
473
|
-
await RefreshSession.sleepAsync(REFRESH_EXPIRY_CHECK_RATE);
|
|
474
|
-
}
|
|
475
|
-
return {};
|
|
476
|
-
});
|
|
477
|
-
}
|
|
478
|
-
RefreshSession.lock(REFRESH_EXPIRY);
|
|
479
|
-
let isLocallyRefreshingToken = true;
|
|
480
|
-
(async () => {
|
|
481
|
-
// eslint-disable-next-line no-unmodified-loop-condition
|
|
482
|
-
while (isLocallyRefreshingToken) {
|
|
483
|
-
RefreshSession.lock(REFRESH_EXPIRY);
|
|
484
|
-
await RefreshSession.sleepAsync(REFRESH_EXPIRY_UPDATE_RATE);
|
|
485
|
-
}
|
|
486
|
-
})();
|
|
487
|
-
return Promise.resolve()
|
|
488
|
-
.then(doRefreshSession({ axiosConfig, clientId, refreshToken }))
|
|
489
|
-
.finally(() => {
|
|
490
|
-
isLocallyRefreshingToken = false;
|
|
491
|
-
RefreshSession.unlock();
|
|
492
|
-
});
|
|
493
|
-
};
|
|
494
|
-
const doRefreshSession = ({ axiosConfig, clientId, refreshToken }) => async () => {
|
|
495
|
-
// we need this to check if app use “withCredentials: false” and don’t have refreshToken it should return false,
|
|
496
|
-
// because we track it as a logout user, if not do this even user logout on the desktop app (that use withCredentials: false)
|
|
497
|
-
// will automatically login with refreshSession
|
|
498
|
-
if (DesktopChecker.isDesktopApp() && !axiosConfig.withCredentials && !refreshToken) {
|
|
499
|
-
return false;
|
|
500
|
-
}
|
|
501
|
-
const result = await refreshSession({ axiosConfig, clientId, refreshToken });
|
|
502
|
-
if (result.error) {
|
|
503
|
-
return false;
|
|
504
|
-
}
|
|
505
|
-
return result.response.data;
|
|
506
|
-
};
|
|
507
|
-
const injectAuthInterceptors = (clientId, getSDKConfig, onSessionExpired, onGetUserSession, getRefreshToken) => {
|
|
508
|
-
// ===== request
|
|
509
|
-
injectRequestInterceptors(async (config) => {
|
|
510
|
-
// need to lock on the desktop as well to sleep other request before refresh session is done
|
|
511
|
-
const isRefreshTokenUrl = config.url === LoginUrls.GRANT_TOKEN;
|
|
512
|
-
// eslint-disable-next-line no-unmodified-loop-condition
|
|
513
|
-
while (RefreshSession.isLocked() && !isRefreshTokenUrl) {
|
|
514
|
-
await RefreshSession.sleepAsync(200);
|
|
515
|
-
}
|
|
516
|
-
return config;
|
|
517
|
-
}, (error) => {
|
|
518
|
-
return Promise.reject(error);
|
|
519
|
-
});
|
|
520
|
-
// ===== response
|
|
521
|
-
injectResponseInterceptors(response => {
|
|
522
|
-
const { config, status } = response;
|
|
523
|
-
if (config.url === LoginUrls.GRANT_TOKEN && status === 200 && onGetUserSession) {
|
|
524
|
-
const { access_token, refresh_token } = response.data;
|
|
525
|
-
if (access_token) {
|
|
526
|
-
onGetUserSession(access_token, refresh_token ?? '');
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
return response;
|
|
530
|
-
}, async (error) => {
|
|
531
|
-
const { config, response } = error;
|
|
532
|
-
if (axios.isCancel(error)) {
|
|
533
|
-
// expected case, exit
|
|
534
|
-
throw error;
|
|
535
|
-
}
|
|
536
|
-
if (!response) {
|
|
537
|
-
console.error(`injectResponseInterceptors net::ERR_INTERNET_DISCONNECTED ${config?.baseURL}${config?.url}. ${error.message}\n`);
|
|
538
|
-
}
|
|
539
|
-
if (response?.status === 401) {
|
|
540
|
-
const { url } = config || {};
|
|
541
|
-
const axiosConfig = getSDKConfig();
|
|
542
|
-
const refreshToken = getRefreshToken ? getRefreshToken() : undefined;
|
|
543
|
-
// expected business case, exit
|
|
544
|
-
// @ts-ignore
|
|
545
|
-
if (Object.values(LoginUrls).includes(url)) {
|
|
546
|
-
throw error;
|
|
547
|
-
}
|
|
548
|
-
// need to lock on the desktop as well to prevent multiple token request
|
|
549
|
-
return refreshWithLock({ axiosConfig, clientId, refreshToken }).then(tokenResponse => {
|
|
550
|
-
return uponRefreshComplete(error, tokenResponse, onSessionExpired, axiosConfig, config || {});
|
|
551
|
-
});
|
|
552
|
-
}
|
|
553
|
-
return Promise.reject(error);
|
|
554
|
-
});
|
|
555
|
-
};
|
|
556
|
-
const uponRefreshComplete = (error, tokenResponse, onSessionExpired, axiosConfig, errorConfig) => {
|
|
557
|
-
//
|
|
558
|
-
if (tokenResponse) {
|
|
559
|
-
const { access_token } = tokenResponse;
|
|
560
|
-
// desktop
|
|
561
|
-
if (!axiosConfig.withCredentials && access_token) {
|
|
562
|
-
return axios({
|
|
563
|
-
...errorConfig,
|
|
564
|
-
headers: {
|
|
565
|
-
...errorConfig.headers,
|
|
566
|
-
Authorization: `Bearer ${access_token}`
|
|
567
|
-
}
|
|
568
|
-
});
|
|
569
|
-
// web
|
|
570
|
-
}
|
|
571
|
-
else {
|
|
572
|
-
return axios(errorConfig);
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
if (onSessionExpired) {
|
|
576
|
-
onSessionExpired();
|
|
577
|
-
}
|
|
578
|
-
throw error;
|
|
475
|
+
// src/interceptors/AuthInterceptorDeps.ts
|
|
476
|
+
var OAuth20$ = class {
|
|
477
|
+
// @ts-ignore
|
|
478
|
+
constructor(axiosInstance) {
|
|
479
|
+
this.axiosInstance = axiosInstance;
|
|
480
|
+
}
|
|
481
|
+
postOauthToken(data) {
|
|
482
|
+
const params = {};
|
|
483
|
+
const url = "/iam/v3/oauth/token";
|
|
484
|
+
const resultPromise = this.axiosInstance.post(url, CodeGenUtil.getFormUrlEncodedData(data), {
|
|
485
|
+
...params,
|
|
486
|
+
headers: { ...params.headers, "content-type": "application/x-www-form-urlencoded" }
|
|
487
|
+
});
|
|
488
|
+
return Validate.responseType(() => resultPromise, TokenWithDeviceCookieResponseV3, "TokenWithDeviceCookieResponseV3");
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
var OAuth20V4$ = class {
|
|
492
|
+
// @ts-ignore
|
|
493
|
+
// prettier-ignore
|
|
494
|
+
constructor(axiosInstance) {
|
|
495
|
+
this.axiosInstance = axiosInstance;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* This endpoint supports grant type: 1. Grant Type == <code>authorization_code</code>: It generates the user token by given the authorization code which generated in "/iam/v3/authenticate" API response. It should also pass in the redirect_uri, which should be the same as generating the authorization code request. 2. Grant Type == <code>password</code>: The grant type to use for authenticating a user, whether it's by email / username and password combination or through platform. 3. Grant Type == <code>refresh_token</code>: Used to get a new access token for a valid refresh token. 4. Grant Type == <code>client_credentials</code>: It generates a token by checking the client credentials provided through Authorization header. 5. Grant Type == <code>urn:ietf:params:oauth:grant-type:extend_client_credentials</code>: It generates a token by checking the client credentials provided through Authorization header. It only allows publisher/studio namespace client. In generated token: 1. There wil be no roles, namespace_roles & permission. 2. The scope will be fixed as 'extend'. 3. There will have a new field 'extend_namespace', the value is from token request body. 6. Grant Type == <code>urn:ietf:params:oauth:grant-type:login_queue_ticket</code>: It generates a token by validating the login queue ticket against login queue service. ## Access Token Content Following is the access token’s content: - **namespace**. It is the namespace the token was generated from. - **display_name**. The display name of the sub. It is empty if the token is generated from the client credential - **roles**. The sub’s roles. It is empty if the token is generated from the client credential - **namespace_roles**. The sub’s roles scoped to namespace. Improvement from roles, which make the role scoped to specific namespace instead of global to publisher namespace - **permissions**. The sub or aud’ permissions - **bans**. The sub’s list of bans. It is used by the IAM client for validating the token. - **jflgs**. It stands for Justice Flags. It is a special flag used for storing additional status information regarding the sub. It is implemented as a bit mask. Following explains what each bit represents: - 1: Email Address Verified - 2: Phone Number Verified - 4: Anonymous - 8: Suspicious Login - **aud**. The aud is the targeted resource server. - **iat**. The time the token issues at. It is in Epoch time format - **exp**. The time the token expires. It is in Epoch time format - **client_id**. The UserID. The sub is omitted if the token is generated from client credential - **scope**. The scope of the access request, expressed as a list of space-delimited, case-sensitive strings ## Bans The JWT contains user's active bans with its expiry date. List of ban types can be obtained from /bans. ## Device Cookie Validation _**For grant type "password" only**_ Device Cookie is used to protect the user account from brute force login attack, <a target="_blank" href="https://owasp.org/www-community/Slow_Down_Online_Guessing_Attacks_with_Device_Cookies">more detail from OWASP<a>. This endpoint will read device cookie from request header **Auth-Trust-Id**. If device cookie not found, it will generate a new one and set it into response body **auth_trust_id** when successfully login. ## Track Login History This endpoint will track login history to detect suspicious login activity, please provide **Device-Id** (alphanumeric) in request header parameter otherwise it will set to "unknown". Align with General Data Protection Regulation in Europe, user login history will be kept within 28 days by default" ## 2FA remember device To remember device for 2FA, should provide cookie: device_token or header: Device-Token ## Response note If it is a user token request and user hasn't accepted required legal policy, the field <code>is_comply</code> will be false in response and responsed token will have no permission. action code: 10703
|
|
499
|
+
*/
|
|
500
|
+
postOauthToken_v4(data, queryParams) {
|
|
501
|
+
const params = { code_challenge_method: "plain", ...queryParams };
|
|
502
|
+
const url = "/iam/v4/oauth/token";
|
|
503
|
+
const resultPromise = this.axiosInstance.post(url, CodeGenUtil.getFormUrlEncodedData(data), {
|
|
504
|
+
...params,
|
|
505
|
+
headers: { ...params.headers, "content-type": "application/x-www-form-urlencoded" }
|
|
506
|
+
});
|
|
507
|
+
return Validate.responseType(() => resultPromise, TokenWithDeviceCookieResponseV3, "TokenWithDeviceCookieResponseV3");
|
|
508
|
+
}
|
|
579
509
|
};
|
|
580
510
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
*/
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
511
|
+
// src/interceptors/AuthInterceptors.ts
|
|
512
|
+
var REFRESH_EXPIRY = 1e3;
|
|
513
|
+
var REFRESH_EXPIRY_UPDATE_RATE = 500;
|
|
514
|
+
var REFRESH_EXPIRY_CHECK_RATE = 1e3;
|
|
515
|
+
var GrantTokenUrls = /* @__PURE__ */ ((GrantTokenUrls2) => {
|
|
516
|
+
GrantTokenUrls2["GRANT_TOKEN"] = "/iam/v3/oauth/token";
|
|
517
|
+
GrantTokenUrls2["GRANT_TOKEN_V4"] = "/iam/v4/oauth/token";
|
|
518
|
+
return GrantTokenUrls2;
|
|
519
|
+
})(GrantTokenUrls || {});
|
|
520
|
+
var LoginUrls = /* @__PURE__ */ ((LoginUrls2) => {
|
|
521
|
+
LoginUrls2["REVOKE"] = "/iam/v3/oauth/revoke";
|
|
522
|
+
return LoginUrls2;
|
|
523
|
+
})(LoginUrls || {});
|
|
524
|
+
var noOp = () => {
|
|
525
|
+
};
|
|
526
|
+
var RefreshToken = class {
|
|
527
|
+
constructor({ config, interceptors }) {
|
|
528
|
+
// Return Promise<true> if refresh in any tab is successful;
|
|
529
|
+
this.runWithLock = () => {
|
|
530
|
+
if (RefreshSession.isLocked()) {
|
|
531
|
+
return Promise.resolve().then(async () => {
|
|
532
|
+
while (RefreshSession.isLocked()) {
|
|
533
|
+
await RefreshSession.sleepAsync(REFRESH_EXPIRY_CHECK_RATE);
|
|
534
|
+
}
|
|
535
|
+
return {};
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
RefreshSession.lock(REFRESH_EXPIRY);
|
|
539
|
+
let isLocallyRefreshingToken = true;
|
|
540
|
+
(async () => {
|
|
541
|
+
while (isLocallyRefreshingToken) {
|
|
542
|
+
RefreshSession.lock(REFRESH_EXPIRY);
|
|
543
|
+
await RefreshSession.sleepAsync(REFRESH_EXPIRY_UPDATE_RATE);
|
|
544
|
+
}
|
|
545
|
+
})();
|
|
546
|
+
return Promise.resolve().then(() => this.run()).finally(() => {
|
|
547
|
+
isLocallyRefreshingToken = false;
|
|
548
|
+
RefreshSession.unlock();
|
|
549
|
+
});
|
|
550
|
+
};
|
|
551
|
+
this.run = async () => {
|
|
552
|
+
const { axiosConfig, refreshToken } = this.config;
|
|
553
|
+
if (DesktopChecker.isDesktopApp() && !axiosConfig.withCredentials && !refreshToken) {
|
|
554
|
+
return false;
|
|
555
|
+
}
|
|
556
|
+
const result = await this.refreshToken();
|
|
557
|
+
if (result.error) {
|
|
558
|
+
return false;
|
|
559
|
+
}
|
|
560
|
+
return result.response.data;
|
|
561
|
+
};
|
|
562
|
+
this.refreshToken = () => {
|
|
563
|
+
const { axiosConfig, refreshToken, clientId, tokenUrl } = this.config;
|
|
564
|
+
const config = {
|
|
565
|
+
...axiosConfig,
|
|
566
|
+
/**
|
|
567
|
+
* Ideally `withCredentials` should be `true` to make sure that
|
|
568
|
+
* cookies always included when refreshing token
|
|
569
|
+
* especially on cross-origin requests.
|
|
570
|
+
* But if `refreshToken` is provided (e.g. from Launcher),
|
|
571
|
+
* we can set it to false and send refresh_token via payload.
|
|
572
|
+
*/
|
|
573
|
+
withCredentials: !refreshToken,
|
|
574
|
+
headers: {
|
|
575
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
576
|
+
Authorization: `Basic ${Buffer.from(`${clientId}:`).toString("base64")}`
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
const axios4 = Network.create(config);
|
|
580
|
+
for (const interceptor of this.interceptors) {
|
|
581
|
+
if (interceptor.type === "request") {
|
|
582
|
+
axios4.interceptors.request.use(interceptor?.onRequest, interceptor.onError);
|
|
583
|
+
}
|
|
584
|
+
if (interceptor.type === "response") {
|
|
585
|
+
axios4.interceptors.response.use(interceptor?.onSuccess, interceptor.onError);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
const payload = {
|
|
589
|
+
refresh_token: refreshToken || void 0,
|
|
590
|
+
client_id: clientId,
|
|
591
|
+
grant_type: "refresh_token"
|
|
592
|
+
};
|
|
593
|
+
if (tokenUrl === "/iam/v4/oauth/token" /* GRANT_TOKEN_V4 */) {
|
|
594
|
+
return new OAuth20V4$(axios4).postOauthToken_v4(payload);
|
|
595
|
+
}
|
|
596
|
+
const oauth20 = new OAuth20$(axios4);
|
|
597
|
+
return oauth20.postOauthToken(payload);
|
|
598
|
+
};
|
|
599
|
+
this.config = config;
|
|
600
|
+
this.interceptors = interceptors || [];
|
|
601
|
+
}
|
|
597
602
|
};
|
|
603
|
+
var refreshComplete = (error, tokenResponse, onSessionExpired, axiosConfig, errorConfig) => {
|
|
604
|
+
if (tokenResponse) {
|
|
605
|
+
const { access_token } = tokenResponse;
|
|
606
|
+
if (!axiosConfig.withCredentials && access_token) {
|
|
607
|
+
return axios3({
|
|
608
|
+
...errorConfig,
|
|
609
|
+
headers: {
|
|
610
|
+
...errorConfig.headers,
|
|
611
|
+
Authorization: `Bearer ${access_token}`
|
|
612
|
+
}
|
|
613
|
+
});
|
|
614
|
+
} else {
|
|
615
|
+
return axios3(errorConfig);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
if (onSessionExpired) {
|
|
619
|
+
onSessionExpired();
|
|
620
|
+
}
|
|
621
|
+
throw error;
|
|
622
|
+
};
|
|
623
|
+
var createAuthInterceptor = ({
|
|
624
|
+
clientId,
|
|
625
|
+
onSessionExpired,
|
|
626
|
+
onGetUserSession,
|
|
627
|
+
expectedErrorUrls = Object.values({ ...LoginUrls, ...GrantTokenUrls }),
|
|
628
|
+
getRefreshToken,
|
|
629
|
+
tokenUrl = "/iam/v3/oauth/token" /* GRANT_TOKEN */
|
|
630
|
+
}) => {
|
|
631
|
+
return {
|
|
632
|
+
type: "response",
|
|
633
|
+
name: "session-expired",
|
|
634
|
+
onError: (e) => {
|
|
635
|
+
const error = e;
|
|
636
|
+
const { config, response } = error;
|
|
637
|
+
if (axios3.isCancel(error)) {
|
|
638
|
+
return Promise.reject(error);
|
|
639
|
+
}
|
|
640
|
+
if (!response) {
|
|
641
|
+
console.warn(`sdk:ERR_INTERNET_DISCONNECTED ${config?.baseURL}${config?.url}. ${error.message}
|
|
642
|
+
`);
|
|
643
|
+
}
|
|
644
|
+
if (response?.status === 401) {
|
|
645
|
+
const { url } = config || {};
|
|
646
|
+
const axiosConfig = config;
|
|
647
|
+
const refreshToken = getRefreshToken?.();
|
|
648
|
+
if (!url || url && expectedErrorUrls.includes(url)) {
|
|
649
|
+
return Promise.reject(error);
|
|
650
|
+
}
|
|
651
|
+
const refresh = new RefreshToken({
|
|
652
|
+
config: { axiosConfig, clientId, refreshToken, tokenUrl },
|
|
653
|
+
interceptors: [
|
|
654
|
+
createRefreshSessionInterceptor({ tokenUrl }),
|
|
655
|
+
createGetSessionInterceptor({ onGetUserSession: onGetUserSession || noOp, tokenUrl })
|
|
656
|
+
]
|
|
657
|
+
});
|
|
658
|
+
return refresh.runWithLock().then((tokenResponse) => {
|
|
659
|
+
return refreshComplete(error, tokenResponse, onSessionExpired, axiosConfig, config || {});
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
return Promise.reject(error);
|
|
663
|
+
}
|
|
664
|
+
};
|
|
665
|
+
};
|
|
666
|
+
var createRefreshSessionInterceptor = (options) => {
|
|
667
|
+
const { tokenUrl = "/iam/v3/oauth/token" /* GRANT_TOKEN */ } = options || {};
|
|
668
|
+
return {
|
|
669
|
+
type: "request",
|
|
670
|
+
name: "refresh-session",
|
|
671
|
+
onError: (error) => Promise.reject(error),
|
|
672
|
+
onRequest: async (config) => {
|
|
673
|
+
const isRefreshTokenUrl = config.url === tokenUrl;
|
|
674
|
+
while (RefreshSession.isLocked() && !isRefreshTokenUrl) {
|
|
675
|
+
await RefreshSession.sleepAsync(200);
|
|
676
|
+
}
|
|
677
|
+
return config;
|
|
678
|
+
}
|
|
679
|
+
};
|
|
680
|
+
};
|
|
681
|
+
var createGetSessionInterceptor = ({
|
|
682
|
+
tokenUrl = "/iam/v3/oauth/token" /* GRANT_TOKEN */,
|
|
683
|
+
onGetUserSession
|
|
684
|
+
}) => ({
|
|
685
|
+
type: "response",
|
|
686
|
+
name: "get-session",
|
|
687
|
+
onError: (error) => Promise.reject(error),
|
|
688
|
+
onSuccess: (response) => {
|
|
689
|
+
const { config, status } = response;
|
|
690
|
+
if (config.url === tokenUrl && status === 200) {
|
|
691
|
+
const { access_token, refresh_token } = response.data;
|
|
692
|
+
if (access_token) {
|
|
693
|
+
onGetUserSession(access_token, refresh_token ?? "");
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
return response;
|
|
697
|
+
}
|
|
698
|
+
});
|
|
598
699
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
'/config': 'justice-config-service'
|
|
633
|
-
};
|
|
634
|
-
const injectInternalNetworkInterceptors = () => {
|
|
635
|
-
injectRequestInterceptors(async (config) => {
|
|
636
|
-
const { url } = config;
|
|
637
|
-
if (url) {
|
|
638
|
-
// url example = "/iam/v1/..."
|
|
639
|
-
const firstPath = url.split('/')[1];
|
|
640
|
-
const internalServiceName = internalServiceMap[`/${firstPath}`];
|
|
641
|
-
if (internalServiceName) {
|
|
642
|
-
config.baseURL = `http://${internalServiceName}`;
|
|
643
|
-
// final url will be
|
|
644
|
-
// http://${service-name}/{url}
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
return config;
|
|
648
|
-
}, (error) => {
|
|
649
|
-
return Promise.reject(error);
|
|
650
|
-
});
|
|
700
|
+
// src/constants/paths.ts
|
|
701
|
+
var INTERNAL_SERVICES = {
|
|
702
|
+
"/achievement": "justice-achievement-service",
|
|
703
|
+
"/basic": "justice-basic-service",
|
|
704
|
+
"/buildinfo": "justice-buildinfo-service",
|
|
705
|
+
"/chat": "justice-chat-service",
|
|
706
|
+
"/cloudsave": "justice-cloudsave-service",
|
|
707
|
+
"/content-management": "justice-odin-content-management-service",
|
|
708
|
+
"/differ": "justice-differ",
|
|
709
|
+
"/dsmcontroller": "justice-dsm-controller-service",
|
|
710
|
+
"/event": "justice-event-log-service",
|
|
711
|
+
"/game-telemetry": "analytics-game-telemetry-api",
|
|
712
|
+
"/gdpr": "justice-gdpr-service",
|
|
713
|
+
"/group": "justice-group-service",
|
|
714
|
+
"/iam": "justice-iam-service",
|
|
715
|
+
"/leaderboard": "justice-leaderboard-service",
|
|
716
|
+
"/agreement": "justice-legal-service",
|
|
717
|
+
// sdk-legal
|
|
718
|
+
"/lobby": "justice-lobby-server",
|
|
719
|
+
"/match2": "justice-matchmaking-v2",
|
|
720
|
+
// sdk-matchmaking
|
|
721
|
+
"/matchmaking": "justice-matchmaking",
|
|
722
|
+
// sdk-matchmaking-v1
|
|
723
|
+
"/odin-config": "justice-odin-config-service",
|
|
724
|
+
"/platform": "justice-platform-service",
|
|
725
|
+
"/qosm": "justice-qos-manager-service",
|
|
726
|
+
"/reporting": "justice-reporting-service",
|
|
727
|
+
"/seasonpass": "justice-seasonpass-service",
|
|
728
|
+
"/session": "justice-session-service",
|
|
729
|
+
"/sessionbrowser": "justice-session-browser-service",
|
|
730
|
+
"/social": "justice-social-service",
|
|
731
|
+
"/ugc": "justice-ugc-service",
|
|
732
|
+
"/config": "justice-config-service"
|
|
651
733
|
};
|
|
652
734
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
...config,
|
|
678
|
-
headers: {
|
|
679
|
-
'Content-Type': 'application/json',
|
|
680
|
-
...config?.headers
|
|
681
|
-
}
|
|
682
|
-
};
|
|
683
|
-
// TODO: instead of having a "global" axios interceptors, we can create the instance here.
|
|
684
|
-
// ```
|
|
685
|
-
// this.axiosInstance = Network.create(...)
|
|
686
|
-
// this.axiosInstance.interceptors.use(...)
|
|
687
|
-
// ```
|
|
688
|
-
// After that, our SDK assembly will return this axiosInstance, which will be used by each of the service SDKs.
|
|
689
|
-
// ```
|
|
690
|
-
// const { axiosInstance, opts } = sdk.assembly()
|
|
691
|
-
// axiosInstance.defaults = {
|
|
692
|
-
// ...axiosInstance.defaults,
|
|
693
|
-
// ...args.config,
|
|
694
|
-
// headers: {
|
|
695
|
-
// ...axiosInstance.defaults.headers,
|
|
696
|
-
// ...args.config.headers
|
|
697
|
-
// }
|
|
698
|
-
// }
|
|
699
|
-
// ```
|
|
700
|
-
// This way, each of the SDK instance will have their own interceptors and will not "pollute"
|
|
701
|
-
// the global axios interceptors. It's easier to test in isolation as well, because with the global
|
|
702
|
-
// interceptors, we can't isolate test the SDK instance... or maybe we can, with `axios.interceptors.request.clear`,
|
|
703
|
-
// but they can't be done in parallel.
|
|
704
|
-
}
|
|
705
|
-
init() {
|
|
706
|
-
const { baseURL, clientId, customInterceptors, useInternalNetwork } = this.options;
|
|
707
|
-
if (customInterceptors) {
|
|
708
|
-
injectRequestInterceptors(customInterceptors.request, customInterceptors.error);
|
|
709
|
-
injectResponseInterceptors(customInterceptors.response, customInterceptors.error);
|
|
710
|
-
}
|
|
711
|
-
else {
|
|
712
|
-
// Default interceptors.
|
|
713
|
-
if (useInternalNetwork) {
|
|
714
|
-
injectInternalNetworkInterceptors();
|
|
715
|
-
}
|
|
716
|
-
injectAuthInterceptors(clientId, this.getConfig, this.events?.onSessionExpired, this.events?.onGetUserSession, this.getRefreshToken);
|
|
717
|
-
injectErrorInterceptors({
|
|
718
|
-
baseUrl: baseURL,
|
|
719
|
-
onError: this.events?.onError,
|
|
720
|
-
onUserEligibilityChange: this.events?.onUserEligibilityChange,
|
|
721
|
-
onTooManyRequest: this.events?.onTooManyRequest
|
|
722
|
-
});
|
|
723
|
-
}
|
|
724
|
-
// TODO reintegrate doVersionDiagnostics later on
|
|
725
|
-
// setTimeout(() => this.doVersionDiagnostics(), TIMEOUT_TO_DIAGNOSTICS)
|
|
726
|
-
return {
|
|
727
|
-
refreshTokens: (accessToken, refreshToken) => this.refreshTokensImpl(accessToken, refreshToken),
|
|
728
|
-
assembly: () => {
|
|
729
|
-
return {
|
|
730
|
-
config: this.config,
|
|
731
|
-
namespace: this.options.namespace,
|
|
732
|
-
clientId: this.options.clientId,
|
|
733
|
-
redirectURI: this.options.redirectURI,
|
|
734
|
-
baseURL: this.options.baseURL,
|
|
735
|
-
refreshToken: this.refreshToken,
|
|
736
|
-
useSchemaValidation: this.options.useSchemaValidation !== undefined ? this.options.useSchemaValidation : true
|
|
737
|
-
};
|
|
738
|
-
}
|
|
739
|
-
};
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
const sdkInit = ({ options, config, onEvents }) => {
|
|
743
|
-
const sdkFactory = new AccelbyteSDKImpl(options, config, onEvents);
|
|
744
|
-
return sdkFactory.init();
|
|
745
|
-
};
|
|
746
|
-
// ts-prune-ignore-next
|
|
747
|
-
const Accelbyte = { SDK: sdkInit };
|
|
735
|
+
// src/interceptors/CustomPathInterceptor.ts
|
|
736
|
+
var createCustomPathInterceptor = ({ basePath, isInternalNetwork }) => {
|
|
737
|
+
return {
|
|
738
|
+
type: "request",
|
|
739
|
+
name: "custom-base-path",
|
|
740
|
+
onRequest: async (config) => {
|
|
741
|
+
const { url } = config;
|
|
742
|
+
if (url) {
|
|
743
|
+
const firstPath = url.split("/")[1];
|
|
744
|
+
const servicePath = `/${firstPath}`;
|
|
745
|
+
const newBasePath = basePath?.[servicePath];
|
|
746
|
+
const internalPath = INTERNAL_SERVICES?.[servicePath];
|
|
747
|
+
if (isInternalNetwork && internalPath) {
|
|
748
|
+
config.baseURL = `http://${internalPath}`;
|
|
749
|
+
}
|
|
750
|
+
if (newBasePath) {
|
|
751
|
+
config.url = config.url?.replace(servicePath, newBasePath);
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
return config;
|
|
755
|
+
},
|
|
756
|
+
onError: (error) => Promise.reject(error)
|
|
757
|
+
};
|
|
758
|
+
};
|
|
748
759
|
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
760
|
+
// src/interceptors/ErrorInterceptor.ts
|
|
761
|
+
var ERROR_ELIGIBILITY_CODE = 13130;
|
|
762
|
+
var ErrorInterceptors = [
|
|
763
|
+
{
|
|
764
|
+
type: "response",
|
|
765
|
+
name: "user-eligibilitiy-change",
|
|
766
|
+
onError: (e) => {
|
|
767
|
+
const error = e;
|
|
768
|
+
if (error.response) {
|
|
769
|
+
const { response } = error;
|
|
770
|
+
if (response?.status === 403 && (response?.config).url.includes(process.env.BASE_URL) && response?.config.withCredentials) {
|
|
771
|
+
if (response.data.errorCode === ERROR_ELIGIBILITY_CODE) {
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
return Promise.reject(error);
|
|
776
|
+
}
|
|
777
|
+
},
|
|
778
|
+
{
|
|
779
|
+
type: "response",
|
|
780
|
+
name: "too-many-request",
|
|
781
|
+
onError: (e) => {
|
|
782
|
+
const error = e;
|
|
783
|
+
if (error.response) {
|
|
784
|
+
const { response } = error;
|
|
785
|
+
if (response?.status === 429) {
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
return Promise.reject(error);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
];
|
|
756
792
|
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
*/
|
|
762
|
-
const ERROR_LINK_ANOTHER_3RD_PARTY_ACCOUNT = 10200;
|
|
763
|
-
const ERROR_CODE_LINK_DELETION_ACCOUNT = 10135;
|
|
764
|
-
const ERROR_CODE_TOKEN_EXPIRED = 10196;
|
|
765
|
-
const ERROR_USER_BANNED = 10134;
|
|
793
|
+
// src/utils/Type.ts
|
|
794
|
+
function isType(schema, data) {
|
|
795
|
+
return schema.safeParse(data).success;
|
|
796
|
+
}
|
|
766
797
|
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
// Remove the query parameter
|
|
807
|
-
params.delete(param);
|
|
808
|
-
// Preserving other URL attributes
|
|
809
|
-
let newUrlString;
|
|
810
|
-
if (params.toString() === '')
|
|
811
|
-
newUrlString = `${url.origin}${pathname}${url.hash}`;
|
|
812
|
-
else
|
|
813
|
-
newUrlString = `${url.origin}${pathname}?${params.toString()}${url.hash}`;
|
|
814
|
-
return newUrlString;
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
UrlHelper.isCompleteURLString = (urlString) => {
|
|
818
|
-
try {
|
|
819
|
-
const url = new URL(urlString);
|
|
820
|
-
return url.hostname !== '';
|
|
821
|
-
}
|
|
822
|
-
catch (error) { }
|
|
823
|
-
return false;
|
|
798
|
+
// src/utils/UrlHelper.ts
|
|
799
|
+
var _UrlHelper = class _UrlHelper {
|
|
800
|
+
static trimSlashFromStringEnd(pathString) {
|
|
801
|
+
let newString = pathString;
|
|
802
|
+
while (newString[newString.length - 1] === "/") {
|
|
803
|
+
newString = newString.slice(0, -1);
|
|
804
|
+
}
|
|
805
|
+
return newString;
|
|
806
|
+
}
|
|
807
|
+
static trimSlashFromStringStart(pathString) {
|
|
808
|
+
let newString = pathString;
|
|
809
|
+
while (newString[0] === "/") {
|
|
810
|
+
newString = newString.slice(1);
|
|
811
|
+
}
|
|
812
|
+
return newString;
|
|
813
|
+
}
|
|
814
|
+
static trimSlashFromStringEdges(pathString) {
|
|
815
|
+
return _UrlHelper.trimSlashFromStringStart(this.trimSlashFromStringEnd(pathString));
|
|
816
|
+
}
|
|
817
|
+
static combinePaths(...paths) {
|
|
818
|
+
const completePath = paths.join("/");
|
|
819
|
+
return completePath.replace(/\/{2,}/g, "/");
|
|
820
|
+
}
|
|
821
|
+
static combineURLPaths(urlString, ...paths) {
|
|
822
|
+
const url = new URL(urlString);
|
|
823
|
+
const { origin } = url;
|
|
824
|
+
const pathname = _UrlHelper.trimSlashFromStringEdges(_UrlHelper.combinePaths(url.pathname, ...paths));
|
|
825
|
+
return new URL(pathname, origin).toString();
|
|
826
|
+
}
|
|
827
|
+
static removeQueryParam(fullUrlString, param) {
|
|
828
|
+
const url = new URL(fullUrlString);
|
|
829
|
+
const params = url.searchParams;
|
|
830
|
+
const pathname = this.trimSlashFromStringEnd(url.pathname);
|
|
831
|
+
params.delete(param);
|
|
832
|
+
let newUrlString;
|
|
833
|
+
if (params.toString() === "") newUrlString = `${url.origin}${pathname}${url.hash}`;
|
|
834
|
+
else newUrlString = `${url.origin}${pathname}?${params.toString()}${url.hash}`;
|
|
835
|
+
return newUrlString;
|
|
836
|
+
}
|
|
824
837
|
};
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
838
|
+
_UrlHelper.isCompleteURLString = (urlString) => {
|
|
839
|
+
try {
|
|
840
|
+
const url = new URL(urlString);
|
|
841
|
+
return url.hostname !== "";
|
|
842
|
+
} catch (error) {
|
|
843
|
+
}
|
|
844
|
+
return false;
|
|
845
|
+
};
|
|
846
|
+
var UrlHelper = _UrlHelper;
|
|
847
|
+
export {
|
|
848
|
+
AccelByte,
|
|
849
|
+
AccelByteSDK,
|
|
850
|
+
ApiUtils,
|
|
851
|
+
BrowserHelper,
|
|
852
|
+
CodeGenUtil,
|
|
853
|
+
DecodeError,
|
|
854
|
+
DesktopChecker,
|
|
855
|
+
ERROR_CODE_LINK_DELETION_ACCOUNT,
|
|
856
|
+
ERROR_CODE_TOKEN_EXPIRED,
|
|
857
|
+
ERROR_LINK_ANOTHER_3RD_PARTY_ACCOUNT,
|
|
858
|
+
ERROR_USER_BANNED,
|
|
859
|
+
ErrorInterceptors,
|
|
860
|
+
IamErrorCode,
|
|
861
|
+
Network,
|
|
862
|
+
RefreshSession,
|
|
863
|
+
RefreshToken,
|
|
864
|
+
SdkDevice,
|
|
865
|
+
UrlHelper,
|
|
866
|
+
Validate,
|
|
867
|
+
createAuthInterceptor,
|
|
868
|
+
createCustomPathInterceptor,
|
|
869
|
+
createGetSessionInterceptor,
|
|
870
|
+
createRefreshSessionInterceptor,
|
|
871
|
+
isType
|
|
872
|
+
};
|
|
873
|
+
//# sourceMappingURL=index.browser.js.map
|