@emilgroup/changelog-sdk 1.3.1-beta.14 → 1.3.1-beta.16
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 +2 -2
- package/api/changelog-configurations-api.ts +20 -10
- package/api/changelog-events-api.ts +12 -6
- package/api/health-checks-api.ts +4 -2
- package/base.ts +164 -52
- package/common.ts +3 -2
- package/configuration.ts +11 -2
- package/dist/api/changelog-configurations-api.d.ts +5 -5
- package/dist/api/changelog-configurations-api.js +32 -19
- package/dist/api/changelog-events-api.d.ts +3 -3
- package/dist/api/changelog-events-api.js +15 -10
- package/dist/api/health-checks-api.d.ts +1 -1
- package/dist/api/health-checks-api.js +7 -4
- package/dist/base.d.ts +24 -1
- package/dist/base.js +169 -70
- package/dist/common.d.ts +1 -1
- package/dist/common.js +1 -0
- package/dist/configuration.d.ts +10 -2
- package/dist/configuration.js +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -17,11 +17,11 @@ Although this package can be used in both TypeScript and JavaScript, it is inten
|
|
|
17
17
|
Navigate to the folder of your consuming project and run one of the following commands:
|
|
18
18
|
|
|
19
19
|
```
|
|
20
|
-
npm install @emilgroup/changelog-sdk@1.3.1-beta.
|
|
20
|
+
npm install @emilgroup/changelog-sdk@1.3.1-beta.16 --save
|
|
21
21
|
```
|
|
22
22
|
or
|
|
23
23
|
```
|
|
24
|
-
yarn add @emilgroup/changelog-sdk@1.3.1-beta.
|
|
24
|
+
yarn add @emilgroup/changelog-sdk@1.3.1-beta.16
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
And then you can import ``.
|
|
@@ -63,8 +63,10 @@ export const ChangelogConfigurationsApiAxiosParamCreator = function (configurati
|
|
|
63
63
|
// http bearer authentication required
|
|
64
64
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
67
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
68
|
+
if (authorizationValue) {
|
|
69
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
|
|
@@ -111,8 +113,10 @@ export const ChangelogConfigurationsApiAxiosParamCreator = function (configurati
|
|
|
111
113
|
// http bearer authentication required
|
|
112
114
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
|
113
115
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
117
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
118
|
+
if (authorizationValue) {
|
|
119
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
116
120
|
}
|
|
117
121
|
|
|
118
122
|
|
|
@@ -156,8 +160,10 @@ export const ChangelogConfigurationsApiAxiosParamCreator = function (configurati
|
|
|
156
160
|
// http bearer authentication required
|
|
157
161
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
|
158
162
|
|
|
159
|
-
|
|
160
|
-
|
|
163
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
164
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
165
|
+
if (authorizationValue) {
|
|
166
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
161
167
|
}
|
|
162
168
|
|
|
163
169
|
|
|
@@ -232,8 +238,10 @@ export const ChangelogConfigurationsApiAxiosParamCreator = function (configurati
|
|
|
232
238
|
localVarQueryParameter['filters'] = filters;
|
|
233
239
|
}
|
|
234
240
|
|
|
235
|
-
|
|
236
|
-
|
|
241
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
242
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
243
|
+
if (authorizationValue) {
|
|
244
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
237
245
|
}
|
|
238
246
|
|
|
239
247
|
|
|
@@ -280,8 +288,10 @@ export const ChangelogConfigurationsApiAxiosParamCreator = function (configurati
|
|
|
280
288
|
// http bearer authentication required
|
|
281
289
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
|
282
290
|
|
|
283
|
-
|
|
284
|
-
|
|
291
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
292
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
293
|
+
if (authorizationValue) {
|
|
294
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
285
295
|
}
|
|
286
296
|
|
|
287
297
|
|
|
@@ -62,8 +62,10 @@ export const ChangelogEventsApiAxiosParamCreator = function (configuration?: Con
|
|
|
62
62
|
// http bearer authentication required
|
|
63
63
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
66
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
67
|
+
if (authorizationValue) {
|
|
68
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
|
|
@@ -138,8 +140,10 @@ export const ChangelogEventsApiAxiosParamCreator = function (configuration?: Con
|
|
|
138
140
|
localVarQueryParameter['filters'] = filters;
|
|
139
141
|
}
|
|
140
142
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
144
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
145
|
+
if (authorizationValue) {
|
|
146
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
143
147
|
}
|
|
144
148
|
|
|
145
149
|
|
|
@@ -218,8 +222,10 @@ export const ChangelogEventsApiAxiosParamCreator = function (configuration?: Con
|
|
|
218
222
|
localVarQueryParameter['filters'] = filters;
|
|
219
223
|
}
|
|
220
224
|
|
|
221
|
-
|
|
222
|
-
|
|
225
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
226
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
227
|
+
if (authorizationValue) {
|
|
228
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
223
229
|
}
|
|
224
230
|
|
|
225
231
|
|
package/api/health-checks-api.ts
CHANGED
|
@@ -56,8 +56,10 @@ export const HealthChecksApiAxiosParamCreator = function (configuration?: Config
|
|
|
56
56
|
// http bearer authentication required
|
|
57
57
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
60
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
61
|
+
if (authorizationValue) {
|
|
62
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
|
package/base.ts
CHANGED
|
@@ -32,9 +32,20 @@ export const COLLECTION_FORMATS = {
|
|
|
32
32
|
pipes: "|",
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
+
export interface SessionClass {
|
|
36
|
+
sub: string;
|
|
37
|
+
username?: string;
|
|
38
|
+
email?: string;
|
|
39
|
+
tenantSlug?: string;
|
|
40
|
+
permissions?: string;
|
|
41
|
+
expiresAt?: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
35
44
|
export interface LoginClass {
|
|
36
45
|
accessToken: string;
|
|
37
46
|
permissions: string;
|
|
47
|
+
authMode?: string;
|
|
48
|
+
session?: SessionClass;
|
|
38
49
|
}
|
|
39
50
|
|
|
40
51
|
export interface SwitchWorkspaceRequest {
|
|
@@ -45,6 +56,8 @@ export interface SwitchWorkspaceRequest {
|
|
|
45
56
|
export interface SwitchWorkspaceResponseClass {
|
|
46
57
|
accessToken: string;
|
|
47
58
|
permissions: string;
|
|
59
|
+
authMode?: string;
|
|
60
|
+
session?: SessionClass;
|
|
48
61
|
}
|
|
49
62
|
|
|
50
63
|
export enum Environment {
|
|
@@ -77,10 +90,19 @@ interface TokenData {
|
|
|
77
90
|
accessToken?: string;
|
|
78
91
|
username?: string;
|
|
79
92
|
permissions?: string;
|
|
93
|
+
// 'both' or 'session' when authservice keeps the tokens in a server session.
|
|
94
|
+
authMode?: string;
|
|
95
|
+
sub?: string;
|
|
80
96
|
}
|
|
81
97
|
|
|
82
98
|
const NETWORK_ERROR_MESSAGE = "Network Error";
|
|
83
99
|
const TOKEN_DATA = 'APP_TOKEN';
|
|
100
|
+
// Sent only to authservice, to ask for a server session.
|
|
101
|
+
const AUTH_MODE_HEADER = 'X-Emil-Auth-Mode';
|
|
102
|
+
// Names the account on every call; one browser session can hold several.
|
|
103
|
+
const ACCOUNT_HEADER = 'X-Emil-Account';
|
|
104
|
+
const SESSION_MODES = ['both', 'session'];
|
|
105
|
+
const RESEND_SAFE_METHODS = ['get', 'head', 'options'];
|
|
84
106
|
|
|
85
107
|
/**
|
|
86
108
|
*
|
|
@@ -103,7 +125,11 @@ export class BaseAPI {
|
|
|
103
125
|
this.basePath = configuration.basePath || this.basePath;
|
|
104
126
|
|
|
105
127
|
if (configuration.cookieAuth) {
|
|
106
|
-
this.
|
|
128
|
+
this.configuration.username = this.configuration.username || this.tokenData.username;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (this.usesSession()) {
|
|
132
|
+
this.useSessionAuth();
|
|
107
133
|
} else {
|
|
108
134
|
// Use config token if provided, otherwise use tokenData token
|
|
109
135
|
const configToken = this.configuration.accessToken;
|
|
@@ -123,10 +149,105 @@ export class BaseAPI {
|
|
|
123
149
|
this.attachInterceptor(axios);
|
|
124
150
|
}
|
|
125
151
|
|
|
126
|
-
//
|
|
127
|
-
private
|
|
128
|
-
|
|
129
|
-
|
|
152
|
+
// The app's own account wins over APP_TOKEN, which holds whichever tab wrote last.
|
|
153
|
+
private sessionAccount(): string | undefined {
|
|
154
|
+
return this.configuration.account || this.tokenData.sub;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Apps may pass the address as the second argument only; authservice is on the same host.
|
|
158
|
+
private authBasePath(): string {
|
|
159
|
+
return this.configuration.basePath || this.basePath;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private usesSession(): boolean {
|
|
163
|
+
return !!this.configuration.cookieAuth && SESSION_MODES.indexOf(this.tokenData.authMode) !== -1 && !!this.sessionAccount();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private useSessionAuth() {
|
|
167
|
+
const { headers, ...baseOptions } = this.configuration.baseOptions || {};
|
|
168
|
+
this.configuration.accessToken = '';
|
|
169
|
+
this.configuration.baseOptions = {
|
|
170
|
+
...baseOptions,
|
|
171
|
+
withCredentials: true,
|
|
172
|
+
headers: { ...headers, [ACCOUNT_HEADER]: this.sessionAccount() },
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private useHeaderAuth(accessToken: string) {
|
|
177
|
+
this.configuration.accessToken = accessToken ? `Bearer ${accessToken}` : '';
|
|
178
|
+
this.tokenData.accessToken = accessToken;
|
|
179
|
+
delete this.tokenData.authMode;
|
|
180
|
+
delete this.tokenData.sub;
|
|
181
|
+
if (this.configuration.cookieAuth) {
|
|
182
|
+
const { withCredentials, headers, ...baseOptions } = this.configuration.baseOptions || {};
|
|
183
|
+
const { [ACCOUNT_HEADER]: account, ...otherHeaders } = headers || {};
|
|
184
|
+
this.configuration.baseOptions = { ...baseOptions, headers: otherHeaders };
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
private applyTokenReply({ accessToken, authMode, session }: LoginClass) {
|
|
189
|
+
if (this.configuration.cookieAuth && SESSION_MODES.indexOf(authMode) !== -1 && session?.sub) {
|
|
190
|
+
this.tokenData.authMode = authMode;
|
|
191
|
+
this.tokenData.sub = session.sub;
|
|
192
|
+
if (this.configuration.account) {
|
|
193
|
+
// A workspace switch moves the app to another account.
|
|
194
|
+
this.configuration.account = session.sub;
|
|
195
|
+
}
|
|
196
|
+
// Both keeps the token for apps not moved yet; session mode keeps no token at all.
|
|
197
|
+
if (authMode === 'both' && accessToken) {
|
|
198
|
+
this.tokenData.accessToken = accessToken;
|
|
199
|
+
} else {
|
|
200
|
+
delete this.tokenData.accessToken;
|
|
201
|
+
}
|
|
202
|
+
this.useSessionAuth();
|
|
203
|
+
} else {
|
|
204
|
+
this.useHeaderAuth(accessToken);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
private sessionHeaders(): Record<string, string> {
|
|
209
|
+
if (!this.configuration.cookieAuth) {
|
|
210
|
+
return {};
|
|
211
|
+
}
|
|
212
|
+
return {
|
|
213
|
+
[AUTH_MODE_HEADER]: 'session',
|
|
214
|
+
...(this.usesSession() && { [ACCOUNT_HEADER]: this.sessionAccount() }),
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
private withCurrentAuth(config: AxiosRequestConfig): AxiosRequestConfig {
|
|
219
|
+
delete config.headers['Authorization'];
|
|
220
|
+
delete config.headers[ACCOUNT_HEADER];
|
|
221
|
+
if (this.usesSession()) {
|
|
222
|
+
config.headers[ACCOUNT_HEADER] = this.sessionAccount();
|
|
223
|
+
config.withCredentials = true;
|
|
224
|
+
} else if (this.configuration.accessToken) {
|
|
225
|
+
config.headers['Authorization'] = this.configuration.accessToken;
|
|
226
|
+
}
|
|
227
|
+
return config;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Both keeps the token, so a session call the browser could not complete can be sent again with it.
|
|
231
|
+
private canRetryWithToken(config: AxiosRequestConfig): boolean {
|
|
232
|
+
return !!config.withCredentials && !!config.headers?.[ACCOUNT_HEADER]
|
|
233
|
+
&& !!this.tokenData.accessToken && this.tokenData.authMode !== 'session';
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// A network error can come after the server ran the call, so only a call that is safe to repeat is sent again.
|
|
237
|
+
private canResend(config: AxiosRequestConfig): boolean {
|
|
238
|
+
return RESEND_SAFE_METHODS.indexOf((config.method || 'get').toLowerCase()) !== -1
|
|
239
|
+
|| Object.keys(config.headers || {}).some((name) => name.toLowerCase() === 'idempotency-key');
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
private switchToToken() {
|
|
243
|
+
this.useHeaderAuth(this.tokenData.accessToken);
|
|
244
|
+
this.storeTokenData(this.tokenData);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
private retryWithToken(axios: AxiosInstance, config: AxiosRequestConfig) {
|
|
248
|
+
this.switchToToken();
|
|
249
|
+
config.withCredentials = false;
|
|
250
|
+
return axios(this.withCurrentAuth(config));
|
|
130
251
|
}
|
|
131
252
|
|
|
132
253
|
selectEnvironment(env: Environment) {
|
|
@@ -148,8 +269,8 @@ export class BaseAPI {
|
|
|
148
269
|
async authorize(username: string, password: string, targetWorkspace?: string): Promise<void> {
|
|
149
270
|
const options: AxiosRequestConfig = {
|
|
150
271
|
method: 'POST',
|
|
151
|
-
url: `${this.
|
|
152
|
-
headers: { 'Content-Type': 'application/json' },
|
|
272
|
+
url: `${this.authBasePath()}/authservice/v1/login`,
|
|
273
|
+
headers: { 'Content-Type': 'application/json', ...(this.configuration.cookieAuth && { [AUTH_MODE_HEADER]: 'session' }) },
|
|
153
274
|
data: {
|
|
154
275
|
username,
|
|
155
276
|
password,
|
|
@@ -159,15 +280,10 @@ export class BaseAPI {
|
|
|
159
280
|
|
|
160
281
|
const response = await globalAxios.request<LoginClass>(options);
|
|
161
282
|
|
|
162
|
-
const { data: { accessToken, permissions } } = response;
|
|
163
|
-
|
|
164
283
|
this.configuration.username = username;
|
|
165
284
|
this.tokenData.username = username;
|
|
166
|
-
this.tokenData.permissions = permissions;
|
|
167
|
-
|
|
168
|
-
this.configuration.accessToken = `Bearer ${accessToken}`;
|
|
169
|
-
this.tokenData.accessToken = accessToken;
|
|
170
|
-
}
|
|
285
|
+
this.tokenData.permissions = response.data.permissions;
|
|
286
|
+
this.applyTokenReply(response.data);
|
|
171
287
|
|
|
172
288
|
// Switch workspace if provided
|
|
173
289
|
if (targetWorkspace) {
|
|
@@ -187,10 +303,11 @@ export class BaseAPI {
|
|
|
187
303
|
async switchWorkspace(targetWorkspace: string): Promise<void> {
|
|
188
304
|
const options: AxiosRequestConfig = {
|
|
189
305
|
method: 'POST',
|
|
190
|
-
url: `${this.
|
|
306
|
+
url: `${this.authBasePath()}/authservice/v1/workspaces/switch`,
|
|
191
307
|
headers: {
|
|
192
308
|
'Content-Type': 'application/json',
|
|
193
|
-
...
|
|
309
|
+
...this.sessionHeaders(),
|
|
310
|
+
...(!this.usesSession() && !!this.configuration.accessToken && { 'Authorization': this.configuration.accessToken as string }),
|
|
194
311
|
},
|
|
195
312
|
data: {
|
|
196
313
|
username: this.configuration.username,
|
|
@@ -201,13 +318,8 @@ export class BaseAPI {
|
|
|
201
318
|
|
|
202
319
|
const response = await globalAxios.request<SwitchWorkspaceResponseClass>(options);
|
|
203
320
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
this.tokenData.permissions = permissions;
|
|
207
|
-
if (!this.configuration.cookieAuth) {
|
|
208
|
-
this.configuration.accessToken = `Bearer ${accessToken}`;
|
|
209
|
-
this.tokenData.accessToken = accessToken;
|
|
210
|
-
}
|
|
321
|
+
this.tokenData.permissions = response.data.permissions;
|
|
322
|
+
this.applyTokenReply(response.data);
|
|
211
323
|
|
|
212
324
|
this.storeTokenData({
|
|
213
325
|
...this.tokenData
|
|
@@ -233,9 +345,10 @@ export class BaseAPI {
|
|
|
233
345
|
|
|
234
346
|
const options: AxiosRequestConfig = {
|
|
235
347
|
method: 'POST',
|
|
236
|
-
url: `${this.
|
|
348
|
+
url: `${this.authBasePath()}/authservice/v1/refresh-token`,
|
|
237
349
|
headers: {
|
|
238
350
|
'Content-Type': 'application/json',
|
|
351
|
+
...this.sessionHeaders(),
|
|
239
352
|
},
|
|
240
353
|
data: { username: username },
|
|
241
354
|
withCredentials: true,
|
|
@@ -247,11 +360,6 @@ export class BaseAPI {
|
|
|
247
360
|
|
|
248
361
|
private storeTokenData(tokenData?: TokenData) {
|
|
249
362
|
if (typeof window !== 'undefined') {
|
|
250
|
-
if (tokenData && this.configuration?.cookieAuth) {
|
|
251
|
-
// Cookie mode saves who is logged in, never the token; a token saved by apps not yet migrated stays.
|
|
252
|
-
const { username, permissions } = tokenData;
|
|
253
|
-
tokenData = { ...(defaultStorage().get<TokenData>(TOKEN_DATA) || {}), username, permissions };
|
|
254
|
-
}
|
|
255
363
|
defaultStorage().set<TokenData>(TOKEN_DATA, tokenData);
|
|
256
364
|
}
|
|
257
365
|
}
|
|
@@ -281,22 +389,22 @@ export class BaseAPI {
|
|
|
281
389
|
&& !originalConfig._retry) {
|
|
282
390
|
originalConfig._retry = true;
|
|
283
391
|
try {
|
|
284
|
-
const
|
|
285
|
-
this.tokenData.permissions = permissions;
|
|
286
|
-
|
|
287
|
-
|
|
392
|
+
const reply = await this.refreshTokenInternal();
|
|
393
|
+
this.tokenData.permissions = reply.permissions;
|
|
394
|
+
this.applyTokenReply(reply);
|
|
395
|
+
this.storeTokenData(this.tokenData);
|
|
288
396
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
const accessToken = `Bearer ${tokenString}`;
|
|
292
|
-
originalConfig.headers['Authorization'] = accessToken;
|
|
293
|
-
this.configuration.accessToken = accessToken;
|
|
294
|
-
this.tokenData.accessToken = tokenString;
|
|
397
|
+
if (!this.usesSession()) {
|
|
398
|
+
return axios(this.withCurrentAuth(originalConfig));
|
|
295
399
|
}
|
|
296
400
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
401
|
+
// Both mode: if the browser does not send the session cookie (another site), use the token.
|
|
402
|
+
return axios(this.withCurrentAuth(originalConfig)).catch((retryError) => {
|
|
403
|
+
if (retryError?.response?.status !== 401 || !this.tokenData.accessToken) {
|
|
404
|
+
return Promise.reject(retryError);
|
|
405
|
+
}
|
|
406
|
+
return this.retryWithToken(axios, originalConfig);
|
|
407
|
+
});
|
|
300
408
|
} catch (_error) {
|
|
301
409
|
if (_error.response && _error.response.data) {
|
|
302
410
|
return Promise.reject(_error.response.data);
|
|
@@ -304,26 +412,30 @@ export class BaseAPI {
|
|
|
304
412
|
return Promise.reject(_error);
|
|
305
413
|
}
|
|
306
414
|
}
|
|
415
|
+
} else if (err.message === NETWORK_ERROR_MESSAGE && this.canRetryWithToken(originalConfig)) {
|
|
416
|
+
// Both mode: the browser blocked the session call or hid its reply; later calls use the token.
|
|
417
|
+
if (!this.canResend(originalConfig)) {
|
|
418
|
+
this.switchToToken();
|
|
419
|
+
return Promise.reject(err);
|
|
420
|
+
}
|
|
421
|
+
return this.retryWithToken(axios, originalConfig);
|
|
307
422
|
} else if (err.message === NETWORK_ERROR_MESSAGE
|
|
308
|
-
&& originalConfig.headers.hasOwnProperty('Authorization')
|
|
423
|
+
&& (originalConfig.headers.hasOwnProperty('Authorization')
|
|
424
|
+
|| (this.configuration.cookieAuth && originalConfig.withCredentials && this.canResend(originalConfig)))
|
|
309
425
|
&& _retry_count < 4
|
|
310
426
|
) {
|
|
311
427
|
_retry_count++;
|
|
312
428
|
try {
|
|
313
|
-
|
|
314
|
-
const
|
|
315
|
-
this.tokenData.permissions = permissions;
|
|
429
|
+
// In session mode an unreadable 401 (no CORS headers on the error reply) also lands here.
|
|
430
|
+
const reply = await this.refreshTokenInternal();
|
|
431
|
+
this.tokenData.permissions = reply.permissions;
|
|
316
432
|
|
|
317
433
|
_retry = true;
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
this.configuration.accessToken = accessToken;
|
|
321
|
-
this.tokenData.accessToken = tokenString;
|
|
322
|
-
|
|
434
|
+
this.applyTokenReply(reply);
|
|
323
435
|
this.storeTokenData(this.tokenData);
|
|
324
436
|
|
|
325
437
|
return axios.request({
|
|
326
|
-
...originalConfig,
|
|
438
|
+
...this.withCurrentAuth(originalConfig),
|
|
327
439
|
});
|
|
328
440
|
} catch (_error) {
|
|
329
441
|
if (_error.response && _error.response.data) {
|
package/common.ts
CHANGED
|
@@ -130,9 +130,10 @@ export const toPathString = function (url: URL) {
|
|
|
130
130
|
* @export
|
|
131
131
|
*/
|
|
132
132
|
export const createRequestFunction = function (axiosArgs: RequestArgs, globalAxios: AxiosInstance, BASE_PATH: string, configuration?: Configuration) {
|
|
133
|
-
|
|
133
|
+
// Typed by hand: since axios 1.20, request() returns an internal axios type that SDK declarations cannot name.
|
|
134
|
+
return <T = unknown, R = AxiosResponse<T>>(axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH): Promise<R> => {
|
|
134
135
|
const axiosRequestArgs = {...axiosArgs.options, url: (configuration?.basePath || basePath) + axiosArgs.url};
|
|
135
|
-
return axios.request<T, R>(axiosRequestArgs)
|
|
136
|
+
return axios.request<T, R>(axiosRequestArgs) as Promise<R>;
|
|
136
137
|
};
|
|
137
138
|
}
|
|
138
139
|
|
package/configuration.ts
CHANGED
|
@@ -22,6 +22,7 @@ export interface ConfigurationParameters {
|
|
|
22
22
|
baseOptions?: any;
|
|
23
23
|
formDataCtor?: new () => any;
|
|
24
24
|
cookieAuth?: boolean;
|
|
25
|
+
account?: string;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
export class Configuration {
|
|
@@ -76,13 +77,20 @@ export class Configuration {
|
|
|
76
77
|
formDataCtor?: new () => any;
|
|
77
78
|
|
|
78
79
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
80
|
+
* Use a server session when authservice makes one; otherwise the token, as without this option.
|
|
81
|
+
* Set `account` too, so each SDK object keeps its own account.
|
|
81
82
|
*
|
|
82
83
|
* @type {boolean}
|
|
83
84
|
* @memberof Configuration
|
|
84
85
|
*/
|
|
85
86
|
cookieAuth?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* The session account (Cognito sub) this app shows, so the SDK never takes another tab's account.
|
|
89
|
+
*
|
|
90
|
+
* @type {string}
|
|
91
|
+
* @memberof Configuration
|
|
92
|
+
*/
|
|
93
|
+
account?: string;
|
|
86
94
|
|
|
87
95
|
constructor(param: ConfigurationParameters = {}) {
|
|
88
96
|
this.apiKey = param.apiKey;
|
|
@@ -93,6 +101,7 @@ export class Configuration {
|
|
|
93
101
|
this.baseOptions = param.baseOptions;
|
|
94
102
|
this.formDataCtor = param.formDataCtor;
|
|
95
103
|
this.cookieAuth = param.cookieAuth;
|
|
104
|
+
this.account = param.account;
|
|
96
105
|
}
|
|
97
106
|
|
|
98
107
|
/**
|
|
@@ -342,7 +342,7 @@ export declare class ChangelogConfigurationsApi extends BaseAPI {
|
|
|
342
342
|
* @throws {RequiredError}
|
|
343
343
|
* @memberof ChangelogConfigurationsApi
|
|
344
344
|
*/
|
|
345
|
-
createChangelogConfiguration(requestParameters: ChangelogConfigurationsApiCreateChangelogConfigurationRequest, options?: AxiosRequestConfig): Promise<import("axios").AxiosResponse<GetChangelogConfigurationResponseClass, any, {}>>;
|
|
345
|
+
createChangelogConfiguration(requestParameters: ChangelogConfigurationsApiCreateChangelogConfigurationRequest, options?: AxiosRequestConfig): Promise<import("axios").AxiosResponse<GetChangelogConfigurationResponseClass, any, {}, any>>;
|
|
346
346
|
/**
|
|
347
347
|
* Deletes a changelog configuration by its code **Required Permissions** \"changelog-management.changelog-configurations.delete\"
|
|
348
348
|
* @summary Delete the changelog configuration
|
|
@@ -351,7 +351,7 @@ export declare class ChangelogConfigurationsApi extends BaseAPI {
|
|
|
351
351
|
* @throws {RequiredError}
|
|
352
352
|
* @memberof ChangelogConfigurationsApi
|
|
353
353
|
*/
|
|
354
|
-
deleteChangelogConfiguration(requestParameters: ChangelogConfigurationsApiDeleteChangelogConfigurationRequest, options?: AxiosRequestConfig): Promise<import("axios").AxiosResponse<void, any, {}>>;
|
|
354
|
+
deleteChangelogConfiguration(requestParameters: ChangelogConfigurationsApiDeleteChangelogConfigurationRequest, options?: AxiosRequestConfig): Promise<import("axios").AxiosResponse<void, any, {}, any>>;
|
|
355
355
|
/**
|
|
356
356
|
* Retrieves a changelog configuration by its code **Required Permissions** \"changelog-management.changelog-configurations.view\"
|
|
357
357
|
* @summary Retrieve the changelog configuration
|
|
@@ -360,7 +360,7 @@ export declare class ChangelogConfigurationsApi extends BaseAPI {
|
|
|
360
360
|
* @throws {RequiredError}
|
|
361
361
|
* @memberof ChangelogConfigurationsApi
|
|
362
362
|
*/
|
|
363
|
-
getChangelogConfiguration(requestParameters: ChangelogConfigurationsApiGetChangelogConfigurationRequest, options?: AxiosRequestConfig): Promise<import("axios").AxiosResponse<GetChangelogConfigurationResponseClass, any, {}>>;
|
|
363
|
+
getChangelogConfiguration(requestParameters: ChangelogConfigurationsApiGetChangelogConfigurationRequest, options?: AxiosRequestConfig): Promise<import("axios").AxiosResponse<GetChangelogConfigurationResponseClass, any, {}, any>>;
|
|
364
364
|
/**
|
|
365
365
|
* Returns a list of changelog configurations you have previously created. The changelog configurations are returned in sorted order, with the oldest one appearing first. For more information about pagination, read the Pagination documentation. **Required Permissions** \"changelog-management.changelog-configurations.view\"
|
|
366
366
|
* @summary List changelog configurations
|
|
@@ -369,7 +369,7 @@ export declare class ChangelogConfigurationsApi extends BaseAPI {
|
|
|
369
369
|
* @throws {RequiredError}
|
|
370
370
|
* @memberof ChangelogConfigurationsApi
|
|
371
371
|
*/
|
|
372
|
-
listChangelogConfigurations(requestParameters?: ChangelogConfigurationsApiListChangelogConfigurationsRequest, options?: AxiosRequestConfig): Promise<import("axios").AxiosResponse<ListChangelogConfigurationsResponseClass, any, {}>>;
|
|
372
|
+
listChangelogConfigurations(requestParameters?: ChangelogConfigurationsApiListChangelogConfigurationsRequest, options?: AxiosRequestConfig): Promise<import("axios").AxiosResponse<ListChangelogConfigurationsResponseClass, any, {}, any>>;
|
|
373
373
|
/**
|
|
374
374
|
* Updates an existing changelog configuration **Required Permissions** \"changelog-management.changelog-configurations.update\"
|
|
375
375
|
* @summary Update the changelog configuration
|
|
@@ -378,5 +378,5 @@ export declare class ChangelogConfigurationsApi extends BaseAPI {
|
|
|
378
378
|
* @throws {RequiredError}
|
|
379
379
|
* @memberof ChangelogConfigurationsApi
|
|
380
380
|
*/
|
|
381
|
-
updateChangelogConfiguration(requestParameters: ChangelogConfigurationsApiUpdateChangelogConfigurationRequest, options?: AxiosRequestConfig): Promise<import("axios").AxiosResponse<GetChangelogConfigurationResponseClass, any, {}>>;
|
|
381
|
+
updateChangelogConfiguration(requestParameters: ChangelogConfigurationsApiUpdateChangelogConfigurationRequest, options?: AxiosRequestConfig): Promise<import("axios").AxiosResponse<GetChangelogConfigurationResponseClass, any, {}, any>>;
|
|
382
382
|
}
|