@versori/run 0.2.0-alpha.4 → 0.2.0-alpha.6
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/esm/src/dsl/http/versori/credentials/client.d.ts +1 -4
- package/esm/src/dsl/http/versori/credentials/client.d.ts.map +1 -1
- package/esm/src/dsl/http/versori/credentials/client.js +3 -16
- package/esm/src/dsl/http/versori/roundtripper.d.ts +0 -1
- package/esm/src/dsl/http/versori/roundtripper.d.ts.map +1 -1
- package/esm/src/dsl/http/versori/roundtripper.js +83 -60
- package/package.json +1 -1
- package/script/src/dsl/http/versori/credentials/client.d.ts +1 -4
- package/script/src/dsl/http/versori/credentials/client.d.ts.map +1 -1
- package/script/src/dsl/http/versori/credentials/client.js +2 -15
- package/script/src/dsl/http/versori/roundtripper.d.ts +0 -1
- package/script/src/dsl/http/versori/roundtripper.d.ts.map +1 -1
- package/script/src/dsl/http/versori/roundtripper.js +83 -60
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import { GetAccessTokenResponse } from './oauth2/v1/token_service_pb.js';
|
|
2
1
|
import { GetTokenResponse } from './tokens/v1/token_service_pb.js';
|
|
3
2
|
export declare class VersoriCredentialClient {
|
|
4
|
-
private oauth2Client;
|
|
5
3
|
private TokenService;
|
|
6
4
|
constructor(credsBaseUrl: string);
|
|
7
|
-
getToken(credId: string): Promise<GetTokenResponse>;
|
|
8
|
-
getOAuth2Token(credId: string): Promise<GetAccessTokenResponse>;
|
|
5
|
+
getToken(credId: string, forceRefresh?: boolean): Promise<GetTokenResponse>;
|
|
9
6
|
}
|
|
10
7
|
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../../../src/src/dsl/http/versori/credentials/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../../../src/src/dsl/http/versori/credentials/client.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAGnE,qBAAa,uBAAuB;IAEhC,OAAO,CAAC,YAAY,CAAc;gBAEtB,YAAY,EAAE,MAAM;IAIhC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,GAAE,OAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAGrF"}
|
|
@@ -1,30 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createTokenClient,
|
|
2
2
|
// createCredentialService,
|
|
3
3
|
} from './credentials.js';
|
|
4
4
|
export class VersoriCredentialClient {
|
|
5
|
-
// private CredentialService: CredentialService;
|
|
6
|
-
// need to add custom function service
|
|
7
5
|
constructor(credsBaseUrl) {
|
|
8
|
-
Object.defineProperty(this, "oauth2Client", {
|
|
9
|
-
enumerable: true,
|
|
10
|
-
configurable: true,
|
|
11
|
-
writable: true,
|
|
12
|
-
value: void 0
|
|
13
|
-
});
|
|
14
6
|
Object.defineProperty(this, "TokenService", {
|
|
15
7
|
enumerable: true,
|
|
16
8
|
configurable: true,
|
|
17
9
|
writable: true,
|
|
18
10
|
value: void 0
|
|
19
11
|
});
|
|
20
|
-
this.oauth2Client = createOAuth2TokenService(credsBaseUrl);
|
|
21
12
|
this.TokenService = createTokenClient(credsBaseUrl);
|
|
22
|
-
// this.CredentialService = createCredentialService(credsBaseUrl);
|
|
23
|
-
}
|
|
24
|
-
getToken(credId) {
|
|
25
|
-
return this.TokenService.getToken({ credentialId: credId });
|
|
26
13
|
}
|
|
27
|
-
|
|
28
|
-
return this.
|
|
14
|
+
getToken(credId, forceRefresh = false) {
|
|
15
|
+
return this.TokenService.getToken({ credentialId: credId, forceRefresh });
|
|
29
16
|
}
|
|
30
17
|
}
|
|
@@ -2,7 +2,6 @@ import { DynamicFetcher, RoundTripperFactory } from '../types.js';
|
|
|
2
2
|
import { VersoriCredentialClient } from './credentials/mod.js';
|
|
3
3
|
import { PlatformAPIClient } from './platformapi.js';
|
|
4
4
|
import { Logger } from '../../../observability/logging/Logger.js';
|
|
5
|
-
export type RunningEnvironment = 'local' | 'versori' | 'staging';
|
|
6
5
|
/**
|
|
7
6
|
* VersoriRoundTripper is an implementation of the RoundTripperFactory interface for Versori connections.
|
|
8
7
|
* This is the intended implementation for when projects/services are hosted on Versori infrastructure.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roundtripper.d.ts","sourceRoot":"","sources":["../../../../../src/src/dsl/http/versori/roundtripper.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,cAAc,EACd,mBAAmB,EAEtB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,0CAA0C,CAAC;
|
|
1
|
+
{"version":3,"file":"roundtripper.d.ts","sourceRoot":"","sources":["../../../../../src/src/dsl/http/versori/roundtripper.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,cAAc,EACd,mBAAmB,EAEtB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,0CAA0C,CAAC;AAUlE;;;;;;;;;;;GAWG;AACH,qBAAa,0BAA2B,YAAW,mBAAmB;IAClE,OAAO,CAAC,WAAW,CAA0B;IAE7C,OAAO,CAAC,iBAAiB,CAAoB;IAE7C,OAAO,CAAC,UAAU,CAAmB;IAErC,OAAO,CAAC,GAAG,CAAS;IAEpB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAK7B;gBAGE,WAAW,EAAE,uBAAuB,EACpC,iBAAiB,EAAE,iBAAiB,EACpC,MAAM,EAAE,MAAM;IAQlB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,0BAA0B;IA0B3D,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,aAAa;IAwBf,MAAM,CACR,QAAQ,EAAE,MAAM,EAChB,EAAE,GAAE,OAAO,KAAwB,GACpC,OAAO,CAAC,OAAO,KAAK,GAAG,SAAS,CAAC;IAqC9B,aAAa,CACf,YAAY,EAAE,MAAM,EACpB,EAAE,GAAE,OAAO,KAAwB,GACpC,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IA+CtC,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,aAAa;YAYP,aAAa;YAyDb,gBAAgB;YAqChB,kBAAkB;YAmClB,aAAa;CAuE9B"}
|
|
@@ -99,6 +99,7 @@ export class VersoriRoundTripperFactory {
|
|
|
99
99
|
const connBaseURL = conn.baseUrl;
|
|
100
100
|
// if the connection has no baseUrl set, but the pathname is a valid URL, return it as is
|
|
101
101
|
if (!connBaseURL && isValidURL(pathname)) {
|
|
102
|
+
this.log.debug('Using given URL as is', { url: pathname });
|
|
102
103
|
return pathname;
|
|
103
104
|
}
|
|
104
105
|
const connBaseURLObj = new URL(connBaseURL);
|
|
@@ -108,36 +109,45 @@ export class VersoriRoundTripperFactory {
|
|
|
108
109
|
_pathname = pathnameObj.pathname;
|
|
109
110
|
}
|
|
110
111
|
const newURL = new URL(_pathname, connBaseURLObj.origin);
|
|
112
|
+
this.log.debug('Using baseURL from connection', { url: newURL.toString() });
|
|
111
113
|
return newURL.toString();
|
|
112
114
|
}
|
|
113
|
-
// TODO: Currently if the connection is edited, then the fetcher will not be updated.
|
|
114
115
|
async create(connName, fn = globalThis.fetch) {
|
|
115
116
|
const cnxId = this.getConnectionID(connName);
|
|
116
|
-
|
|
117
|
-
|
|
117
|
+
if (!cnxId) {
|
|
118
|
+
this.log.debug('Connection not found in config, could be a dynamic connection', {
|
|
119
|
+
connectionName: connName,
|
|
120
|
+
});
|
|
118
121
|
return undefined;
|
|
119
122
|
}
|
|
120
|
-
const _fn = (input, init) => {
|
|
123
|
+
const _fn = async (input, init) => {
|
|
124
|
+
const conn = await this.platformAPIClient.getStaticConnection(cnxId);
|
|
125
|
+
if (!conn) {
|
|
126
|
+
this.log.error('Connection not found for user, using default fetch', {
|
|
127
|
+
connectionName: connName,
|
|
128
|
+
});
|
|
129
|
+
return globalThis.fetch(input, init);
|
|
130
|
+
}
|
|
121
131
|
const _input = this.changeRequestInit(input, conn);
|
|
122
|
-
|
|
132
|
+
switch (conn.credentials[0].authSchemeConfig.type) {
|
|
133
|
+
case 'api-key':
|
|
134
|
+
return (await this.apiKeyFetcher(conn, _fn))(_input, init);
|
|
135
|
+
case 'basic-auth':
|
|
136
|
+
return (await this.basicAuthFetcher(conn, _fn))(_input, init);
|
|
137
|
+
case 'jwt-bearer':
|
|
138
|
+
return (await this.bearerTokenFetcher(conn, _fn))(_input, init);
|
|
139
|
+
case 'oauth2':
|
|
140
|
+
return (await this.oauth2Fetcher(conn, _fn))(_input, init);
|
|
141
|
+
default:
|
|
142
|
+
return fn(_input, init);
|
|
143
|
+
}
|
|
123
144
|
};
|
|
124
|
-
|
|
125
|
-
case 'api-key':
|
|
126
|
-
return this.apiKeyFetcher(conn, _fn);
|
|
127
|
-
case 'basic-auth':
|
|
128
|
-
return this.basicAuthFetcher(conn, _fn);
|
|
129
|
-
case 'jwt-bearer':
|
|
130
|
-
return this.bearerTokenFetcher(conn, _fn);
|
|
131
|
-
case 'oauth2':
|
|
132
|
-
return this.oauth2Fetcher(conn, _fn);
|
|
133
|
-
default:
|
|
134
|
-
return fn;
|
|
135
|
-
}
|
|
145
|
+
return _fn;
|
|
136
146
|
}
|
|
137
147
|
async createDynamic(templateName, fn = globalThis.fetch) {
|
|
138
148
|
const template = this.getTemplateID(templateName);
|
|
139
149
|
if (!template) {
|
|
140
|
-
this.log.
|
|
150
|
+
this.log.debug('Template not found in config, could be a static connection', {
|
|
141
151
|
templateName: templateName,
|
|
142
152
|
});
|
|
143
153
|
return undefined;
|
|
@@ -168,7 +178,8 @@ export class VersoriRoundTripperFactory {
|
|
|
168
178
|
return _fn;
|
|
169
179
|
}
|
|
170
180
|
getConnectionID(connName) {
|
|
171
|
-
const conn = this.versoriCfg.mappings.find((c) => (c.dynamic === undefined || c.dynamic === false) &&
|
|
181
|
+
const conn = this.versoriCfg.mappings.find((c) => (c.dynamic === undefined || c.dynamic === false) &&
|
|
182
|
+
c.name.toLowerCase() === connName.toLowerCase());
|
|
172
183
|
if (!conn || !conn.connId) {
|
|
173
184
|
return '';
|
|
174
185
|
}
|
|
@@ -182,16 +193,16 @@ export class VersoriRoundTripperFactory {
|
|
|
182
193
|
return template.templateId;
|
|
183
194
|
}
|
|
184
195
|
async apiKeyFetcher(conn, fn) {
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
196
|
+
const _fn = async (input, init) => {
|
|
197
|
+
const tokenResponse = await this.tokenClient.getToken(conn.credentials[0].credential.id);
|
|
198
|
+
const token = tokenResponse.token?.accessToken;
|
|
199
|
+
const asc = conn.credentials[0].authSchemeConfig.apiKey;
|
|
200
|
+
if (!token) {
|
|
201
|
+
throw new Error('Token not found');
|
|
202
|
+
}
|
|
203
|
+
if (!asc) {
|
|
204
|
+
throw new Error('API Key configuration not found');
|
|
205
|
+
}
|
|
195
206
|
if (!init) {
|
|
196
207
|
init = {};
|
|
197
208
|
}
|
|
@@ -230,12 +241,12 @@ export class VersoriRoundTripperFactory {
|
|
|
230
241
|
return _fn;
|
|
231
242
|
}
|
|
232
243
|
async basicAuthFetcher(conn, fn) {
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
244
|
+
const _fn = async (input, init) => {
|
|
245
|
+
const tokenResponse = await this.tokenClient.getToken(conn.credentials[0].credential.id);
|
|
246
|
+
const token = tokenResponse.token?.accessToken;
|
|
247
|
+
if (!token) {
|
|
248
|
+
throw new Error('Token not found');
|
|
249
|
+
}
|
|
239
250
|
if (!init) {
|
|
240
251
|
init = {};
|
|
241
252
|
}
|
|
@@ -260,12 +271,12 @@ export class VersoriRoundTripperFactory {
|
|
|
260
271
|
}
|
|
261
272
|
// TODO: need to make the prefix and header name configurable from authschemeconfig
|
|
262
273
|
async bearerTokenFetcher(conn, fn) {
|
|
263
|
-
const
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
274
|
+
const _fn = async (input, init) => {
|
|
275
|
+
const tokenResponse = await this.tokenClient.getToken(conn.credentials[0].credential.id);
|
|
276
|
+
const token = tokenResponse.token?.accessToken;
|
|
277
|
+
if (!token) {
|
|
278
|
+
throw new Error('Token not found');
|
|
279
|
+
}
|
|
269
280
|
if (!init) {
|
|
270
281
|
init = {};
|
|
271
282
|
}
|
|
@@ -289,26 +300,26 @@ export class VersoriRoundTripperFactory {
|
|
|
289
300
|
return _fn;
|
|
290
301
|
}
|
|
291
302
|
async oauth2Fetcher(conn, fn) {
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const _tokenType = () => {
|
|
299
|
-
const _tt = tokenType?.toLowerCase();
|
|
300
|
-
switch (_tt) {
|
|
301
|
-
case 'bearer':
|
|
302
|
-
return 'Bearer';
|
|
303
|
-
case 'mac':
|
|
304
|
-
return 'MAC';
|
|
305
|
-
case 'basic':
|
|
306
|
-
return 'Basic';
|
|
307
|
-
default:
|
|
308
|
-
return 'Bearer';
|
|
303
|
+
const refreshFn = async (input, init, forceRefresh = false) => {
|
|
304
|
+
const tokenResponse = await this.tokenClient.getToken(conn.credentials[0].credential.id, forceRefresh);
|
|
305
|
+
const token = tokenResponse.token?.accessToken;
|
|
306
|
+
const tokenType = tokenResponse.token?.tokenType;
|
|
307
|
+
if (!token) {
|
|
308
|
+
throw new Error('Token not found');
|
|
309
309
|
}
|
|
310
|
-
|
|
311
|
-
|
|
310
|
+
const _tokenType = () => {
|
|
311
|
+
const _tt = tokenType?.toLowerCase();
|
|
312
|
+
switch (_tt) {
|
|
313
|
+
case 'bearer':
|
|
314
|
+
return 'Bearer';
|
|
315
|
+
case 'mac':
|
|
316
|
+
return 'MAC';
|
|
317
|
+
case 'basic':
|
|
318
|
+
return 'Basic';
|
|
319
|
+
default:
|
|
320
|
+
return 'Bearer';
|
|
321
|
+
}
|
|
322
|
+
};
|
|
312
323
|
if (!init) {
|
|
313
324
|
init = {};
|
|
314
325
|
}
|
|
@@ -329,6 +340,18 @@ export class VersoriRoundTripperFactory {
|
|
|
329
340
|
}
|
|
330
341
|
return fn(input, init);
|
|
331
342
|
};
|
|
343
|
+
const _fn = async (input, init) => {
|
|
344
|
+
const resp = await refreshFn(input, init, false);
|
|
345
|
+
if (resp.status === 401) {
|
|
346
|
+
this.log.debug('Received 401 Unauthorized response, attempting refresh', {
|
|
347
|
+
url: input,
|
|
348
|
+
status: resp.status,
|
|
349
|
+
});
|
|
350
|
+
// TODO: attempt refresh until precondition failed??
|
|
351
|
+
return refreshFn(input, init, true);
|
|
352
|
+
}
|
|
353
|
+
return Promise.resolve(resp);
|
|
354
|
+
};
|
|
332
355
|
return _fn;
|
|
333
356
|
}
|
|
334
357
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import { GetAccessTokenResponse } from './oauth2/v1/token_service_pb.js';
|
|
2
1
|
import { GetTokenResponse } from './tokens/v1/token_service_pb.js';
|
|
3
2
|
export declare class VersoriCredentialClient {
|
|
4
|
-
private oauth2Client;
|
|
5
3
|
private TokenService;
|
|
6
4
|
constructor(credsBaseUrl: string);
|
|
7
|
-
getToken(credId: string): Promise<GetTokenResponse>;
|
|
8
|
-
getOAuth2Token(credId: string): Promise<GetAccessTokenResponse>;
|
|
5
|
+
getToken(credId: string, forceRefresh?: boolean): Promise<GetTokenResponse>;
|
|
9
6
|
}
|
|
10
7
|
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../../../src/src/dsl/http/versori/credentials/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../../../src/src/dsl/http/versori/credentials/client.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAGnE,qBAAa,uBAAuB;IAEhC,OAAO,CAAC,YAAY,CAAc;gBAEtB,YAAY,EAAE,MAAM;IAIhC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,GAAE,OAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAGrF"}
|
|
@@ -3,30 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.VersoriCredentialClient = void 0;
|
|
4
4
|
const credentials_js_1 = require("./credentials.js");
|
|
5
5
|
class VersoriCredentialClient {
|
|
6
|
-
// private CredentialService: CredentialService;
|
|
7
|
-
// need to add custom function service
|
|
8
6
|
constructor(credsBaseUrl) {
|
|
9
|
-
Object.defineProperty(this, "oauth2Client", {
|
|
10
|
-
enumerable: true,
|
|
11
|
-
configurable: true,
|
|
12
|
-
writable: true,
|
|
13
|
-
value: void 0
|
|
14
|
-
});
|
|
15
7
|
Object.defineProperty(this, "TokenService", {
|
|
16
8
|
enumerable: true,
|
|
17
9
|
configurable: true,
|
|
18
10
|
writable: true,
|
|
19
11
|
value: void 0
|
|
20
12
|
});
|
|
21
|
-
this.oauth2Client = (0, credentials_js_1.createOAuth2TokenService)(credsBaseUrl);
|
|
22
13
|
this.TokenService = (0, credentials_js_1.createTokenClient)(credsBaseUrl);
|
|
23
|
-
// this.CredentialService = createCredentialService(credsBaseUrl);
|
|
24
|
-
}
|
|
25
|
-
getToken(credId) {
|
|
26
|
-
return this.TokenService.getToken({ credentialId: credId });
|
|
27
14
|
}
|
|
28
|
-
|
|
29
|
-
return this.
|
|
15
|
+
getToken(credId, forceRefresh = false) {
|
|
16
|
+
return this.TokenService.getToken({ credentialId: credId, forceRefresh });
|
|
30
17
|
}
|
|
31
18
|
}
|
|
32
19
|
exports.VersoriCredentialClient = VersoriCredentialClient;
|
|
@@ -2,7 +2,6 @@ import { DynamicFetcher, RoundTripperFactory } from '../types.js';
|
|
|
2
2
|
import { VersoriCredentialClient } from './credentials/mod.js';
|
|
3
3
|
import { PlatformAPIClient } from './platformapi.js';
|
|
4
4
|
import { Logger } from '../../../observability/logging/Logger.js';
|
|
5
|
-
export type RunningEnvironment = 'local' | 'versori' | 'staging';
|
|
6
5
|
/**
|
|
7
6
|
* VersoriRoundTripper is an implementation of the RoundTripperFactory interface for Versori connections.
|
|
8
7
|
* This is the intended implementation for when projects/services are hosted on Versori infrastructure.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roundtripper.d.ts","sourceRoot":"","sources":["../../../../../src/src/dsl/http/versori/roundtripper.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,cAAc,EACd,mBAAmB,EAEtB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,0CAA0C,CAAC;
|
|
1
|
+
{"version":3,"file":"roundtripper.d.ts","sourceRoot":"","sources":["../../../../../src/src/dsl/http/versori/roundtripper.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,cAAc,EACd,mBAAmB,EAEtB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,0CAA0C,CAAC;AAUlE;;;;;;;;;;;GAWG;AACH,qBAAa,0BAA2B,YAAW,mBAAmB;IAClE,OAAO,CAAC,WAAW,CAA0B;IAE7C,OAAO,CAAC,iBAAiB,CAAoB;IAE7C,OAAO,CAAC,UAAU,CAAmB;IAErC,OAAO,CAAC,GAAG,CAAS;IAEpB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAK7B;gBAGE,WAAW,EAAE,uBAAuB,EACpC,iBAAiB,EAAE,iBAAiB,EACpC,MAAM,EAAE,MAAM;IAQlB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,0BAA0B;IA0B3D,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,aAAa;IAwBf,MAAM,CACR,QAAQ,EAAE,MAAM,EAChB,EAAE,GAAE,OAAO,KAAwB,GACpC,OAAO,CAAC,OAAO,KAAK,GAAG,SAAS,CAAC;IAqC9B,aAAa,CACf,YAAY,EAAE,MAAM,EACpB,EAAE,GAAE,OAAO,KAAwB,GACpC,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IA+CtC,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,aAAa;YAYP,aAAa;YAyDb,gBAAgB;YAqChB,kBAAkB;YAmClB,aAAa;CAuE9B"}
|
|
@@ -102,6 +102,7 @@ class VersoriRoundTripperFactory {
|
|
|
102
102
|
const connBaseURL = conn.baseUrl;
|
|
103
103
|
// if the connection has no baseUrl set, but the pathname is a valid URL, return it as is
|
|
104
104
|
if (!connBaseURL && isValidURL(pathname)) {
|
|
105
|
+
this.log.debug('Using given URL as is', { url: pathname });
|
|
105
106
|
return pathname;
|
|
106
107
|
}
|
|
107
108
|
const connBaseURLObj = new URL(connBaseURL);
|
|
@@ -111,36 +112,45 @@ class VersoriRoundTripperFactory {
|
|
|
111
112
|
_pathname = pathnameObj.pathname;
|
|
112
113
|
}
|
|
113
114
|
const newURL = new URL(_pathname, connBaseURLObj.origin);
|
|
115
|
+
this.log.debug('Using baseURL from connection', { url: newURL.toString() });
|
|
114
116
|
return newURL.toString();
|
|
115
117
|
}
|
|
116
|
-
// TODO: Currently if the connection is edited, then the fetcher will not be updated.
|
|
117
118
|
async create(connName, fn = globalThis.fetch) {
|
|
118
119
|
const cnxId = this.getConnectionID(connName);
|
|
119
|
-
|
|
120
|
-
|
|
120
|
+
if (!cnxId) {
|
|
121
|
+
this.log.debug('Connection not found in config, could be a dynamic connection', {
|
|
122
|
+
connectionName: connName,
|
|
123
|
+
});
|
|
121
124
|
return undefined;
|
|
122
125
|
}
|
|
123
|
-
const _fn = (input, init) => {
|
|
126
|
+
const _fn = async (input, init) => {
|
|
127
|
+
const conn = await this.platformAPIClient.getStaticConnection(cnxId);
|
|
128
|
+
if (!conn) {
|
|
129
|
+
this.log.error('Connection not found for user, using default fetch', {
|
|
130
|
+
connectionName: connName,
|
|
131
|
+
});
|
|
132
|
+
return globalThis.fetch(input, init);
|
|
133
|
+
}
|
|
124
134
|
const _input = this.changeRequestInit(input, conn);
|
|
125
|
-
|
|
135
|
+
switch (conn.credentials[0].authSchemeConfig.type) {
|
|
136
|
+
case 'api-key':
|
|
137
|
+
return (await this.apiKeyFetcher(conn, _fn))(_input, init);
|
|
138
|
+
case 'basic-auth':
|
|
139
|
+
return (await this.basicAuthFetcher(conn, _fn))(_input, init);
|
|
140
|
+
case 'jwt-bearer':
|
|
141
|
+
return (await this.bearerTokenFetcher(conn, _fn))(_input, init);
|
|
142
|
+
case 'oauth2':
|
|
143
|
+
return (await this.oauth2Fetcher(conn, _fn))(_input, init);
|
|
144
|
+
default:
|
|
145
|
+
return fn(_input, init);
|
|
146
|
+
}
|
|
126
147
|
};
|
|
127
|
-
|
|
128
|
-
case 'api-key':
|
|
129
|
-
return this.apiKeyFetcher(conn, _fn);
|
|
130
|
-
case 'basic-auth':
|
|
131
|
-
return this.basicAuthFetcher(conn, _fn);
|
|
132
|
-
case 'jwt-bearer':
|
|
133
|
-
return this.bearerTokenFetcher(conn, _fn);
|
|
134
|
-
case 'oauth2':
|
|
135
|
-
return this.oauth2Fetcher(conn, _fn);
|
|
136
|
-
default:
|
|
137
|
-
return fn;
|
|
138
|
-
}
|
|
148
|
+
return _fn;
|
|
139
149
|
}
|
|
140
150
|
async createDynamic(templateName, fn = globalThis.fetch) {
|
|
141
151
|
const template = this.getTemplateID(templateName);
|
|
142
152
|
if (!template) {
|
|
143
|
-
this.log.
|
|
153
|
+
this.log.debug('Template not found in config, could be a static connection', {
|
|
144
154
|
templateName: templateName,
|
|
145
155
|
});
|
|
146
156
|
return undefined;
|
|
@@ -171,7 +181,8 @@ class VersoriRoundTripperFactory {
|
|
|
171
181
|
return _fn;
|
|
172
182
|
}
|
|
173
183
|
getConnectionID(connName) {
|
|
174
|
-
const conn = this.versoriCfg.mappings.find((c) => (c.dynamic === undefined || c.dynamic === false) &&
|
|
184
|
+
const conn = this.versoriCfg.mappings.find((c) => (c.dynamic === undefined || c.dynamic === false) &&
|
|
185
|
+
c.name.toLowerCase() === connName.toLowerCase());
|
|
175
186
|
if (!conn || !conn.connId) {
|
|
176
187
|
return '';
|
|
177
188
|
}
|
|
@@ -185,16 +196,16 @@ class VersoriRoundTripperFactory {
|
|
|
185
196
|
return template.templateId;
|
|
186
197
|
}
|
|
187
198
|
async apiKeyFetcher(conn, fn) {
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
199
|
+
const _fn = async (input, init) => {
|
|
200
|
+
const tokenResponse = await this.tokenClient.getToken(conn.credentials[0].credential.id);
|
|
201
|
+
const token = tokenResponse.token?.accessToken;
|
|
202
|
+
const asc = conn.credentials[0].authSchemeConfig.apiKey;
|
|
203
|
+
if (!token) {
|
|
204
|
+
throw new Error('Token not found');
|
|
205
|
+
}
|
|
206
|
+
if (!asc) {
|
|
207
|
+
throw new Error('API Key configuration not found');
|
|
208
|
+
}
|
|
198
209
|
if (!init) {
|
|
199
210
|
init = {};
|
|
200
211
|
}
|
|
@@ -233,12 +244,12 @@ class VersoriRoundTripperFactory {
|
|
|
233
244
|
return _fn;
|
|
234
245
|
}
|
|
235
246
|
async basicAuthFetcher(conn, fn) {
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
247
|
+
const _fn = async (input, init) => {
|
|
248
|
+
const tokenResponse = await this.tokenClient.getToken(conn.credentials[0].credential.id);
|
|
249
|
+
const token = tokenResponse.token?.accessToken;
|
|
250
|
+
if (!token) {
|
|
251
|
+
throw new Error('Token not found');
|
|
252
|
+
}
|
|
242
253
|
if (!init) {
|
|
243
254
|
init = {};
|
|
244
255
|
}
|
|
@@ -263,12 +274,12 @@ class VersoriRoundTripperFactory {
|
|
|
263
274
|
}
|
|
264
275
|
// TODO: need to make the prefix and header name configurable from authschemeconfig
|
|
265
276
|
async bearerTokenFetcher(conn, fn) {
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
277
|
+
const _fn = async (input, init) => {
|
|
278
|
+
const tokenResponse = await this.tokenClient.getToken(conn.credentials[0].credential.id);
|
|
279
|
+
const token = tokenResponse.token?.accessToken;
|
|
280
|
+
if (!token) {
|
|
281
|
+
throw new Error('Token not found');
|
|
282
|
+
}
|
|
272
283
|
if (!init) {
|
|
273
284
|
init = {};
|
|
274
285
|
}
|
|
@@ -292,26 +303,26 @@ class VersoriRoundTripperFactory {
|
|
|
292
303
|
return _fn;
|
|
293
304
|
}
|
|
294
305
|
async oauth2Fetcher(conn, fn) {
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
const _tokenType = () => {
|
|
302
|
-
const _tt = tokenType?.toLowerCase();
|
|
303
|
-
switch (_tt) {
|
|
304
|
-
case 'bearer':
|
|
305
|
-
return 'Bearer';
|
|
306
|
-
case 'mac':
|
|
307
|
-
return 'MAC';
|
|
308
|
-
case 'basic':
|
|
309
|
-
return 'Basic';
|
|
310
|
-
default:
|
|
311
|
-
return 'Bearer';
|
|
306
|
+
const refreshFn = async (input, init, forceRefresh = false) => {
|
|
307
|
+
const tokenResponse = await this.tokenClient.getToken(conn.credentials[0].credential.id, forceRefresh);
|
|
308
|
+
const token = tokenResponse.token?.accessToken;
|
|
309
|
+
const tokenType = tokenResponse.token?.tokenType;
|
|
310
|
+
if (!token) {
|
|
311
|
+
throw new Error('Token not found');
|
|
312
312
|
}
|
|
313
|
-
|
|
314
|
-
|
|
313
|
+
const _tokenType = () => {
|
|
314
|
+
const _tt = tokenType?.toLowerCase();
|
|
315
|
+
switch (_tt) {
|
|
316
|
+
case 'bearer':
|
|
317
|
+
return 'Bearer';
|
|
318
|
+
case 'mac':
|
|
319
|
+
return 'MAC';
|
|
320
|
+
case 'basic':
|
|
321
|
+
return 'Basic';
|
|
322
|
+
default:
|
|
323
|
+
return 'Bearer';
|
|
324
|
+
}
|
|
325
|
+
};
|
|
315
326
|
if (!init) {
|
|
316
327
|
init = {};
|
|
317
328
|
}
|
|
@@ -332,6 +343,18 @@ class VersoriRoundTripperFactory {
|
|
|
332
343
|
}
|
|
333
344
|
return fn(input, init);
|
|
334
345
|
};
|
|
346
|
+
const _fn = async (input, init) => {
|
|
347
|
+
const resp = await refreshFn(input, init, false);
|
|
348
|
+
if (resp.status === 401) {
|
|
349
|
+
this.log.debug('Received 401 Unauthorized response, attempting refresh', {
|
|
350
|
+
url: input,
|
|
351
|
+
status: resp.status,
|
|
352
|
+
});
|
|
353
|
+
// TODO: attempt refresh until precondition failed??
|
|
354
|
+
return refreshFn(input, init, true);
|
|
355
|
+
}
|
|
356
|
+
return Promise.resolve(resp);
|
|
357
|
+
};
|
|
335
358
|
return _fn;
|
|
336
359
|
}
|
|
337
360
|
}
|