@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.
@@ -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":"AASA,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAGzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAEnE,qBAAa,uBAAuB;IAChC,OAAO,CAAC,YAAY,CAAoB;IAExC,OAAO,CAAC,YAAY,CAAc;gBAMtB,YAAY,EAAE,MAAM;IAMhC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAInD,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;CAGlE"}
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 { createOAuth2TokenService, createTokenClient,
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
- getOAuth2Token(credId) {
28
- return this.oauth2Client.getAccessToken({ credentialId: credId });
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;AASlE,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AAEjE;;;;;;;;;;;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;IAsBf,MAAM,CACR,QAAQ,EAAE,MAAM,EAChB,EAAE,GAAE,OAAO,KAAwB,GACpC,OAAO,CAAC,OAAO,KAAK,GAAG,SAAS,CAAC;IA4B9B,aAAa,CACf,YAAY,EAAE,MAAM,EACpB,EAAE,GAAE,OAAO,KAAwB,GACpC,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IA4CtC,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,aAAa;YAUP,aAAa;YAoDb,gBAAgB;YAmChB,kBAAkB;YAiClB,aAAa;CAkD9B"}
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
- const conn = await this.platformAPIClient.getStaticConnection(cnxId);
117
- if (!conn) {
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
- return fn(_input, init);
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
- switch (conn.credentials[0].authSchemeConfig.type) {
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.info('Template not found in config, could be a static connection', {
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) && c.name.toLowerCase() === connName.toLowerCase());
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 tokenResponse = await this.tokenClient.getToken(conn.credentials[0].credential.id);
186
- const token = tokenResponse.token?.accessToken;
187
- const asc = conn.credentials[0].authSchemeConfig.apiKey;
188
- if (!token) {
189
- throw new Error('Token not found');
190
- }
191
- if (!asc) {
192
- throw new Error('API Key configuration not found');
193
- }
194
- const _fn = (input, init) => {
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 tokenResponse = await this.tokenClient.getToken(conn.credentials[0].credential.id);
234
- const token = tokenResponse.token?.accessToken;
235
- if (!token) {
236
- throw new Error('Token not found');
237
- }
238
- const _fn = (input, init) => {
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 tokenResponse = await this.tokenClient.getToken(conn.credentials[0].credential.id);
264
- const token = tokenResponse.token?.accessToken;
265
- if (!token) {
266
- throw new Error('Token not found');
267
- }
268
- const _fn = (input, init) => {
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 tokenResponse = await this.tokenClient.getOAuth2Token(conn.credentials[0].credential.id);
293
- const token = tokenResponse.token?.accessToken;
294
- const tokenType = tokenResponse.token?.tokenType;
295
- if (!token) {
296
- throw new Error('Token not found');
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
- const _fn = (input, init) => {
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,6 +1,6 @@
1
1
  {
2
2
  "name": "@versori/run",
3
- "version": "v0.2.0-alpha.4",
3
+ "version": "v0.2.0-alpha.6",
4
4
  "description": "Versori Run",
5
5
  "homepage": "https://github.com/versori/versori-run#readme",
6
6
  "repository": {
@@ -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":"AASA,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAGzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAEnE,qBAAa,uBAAuB;IAChC,OAAO,CAAC,YAAY,CAAoB;IAExC,OAAO,CAAC,YAAY,CAAc;gBAMtB,YAAY,EAAE,MAAM;IAMhC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAInD,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;CAGlE"}
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
- getOAuth2Token(credId) {
29
- return this.oauth2Client.getAccessToken({ credentialId: credId });
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;AASlE,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AAEjE;;;;;;;;;;;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;IAsBf,MAAM,CACR,QAAQ,EAAE,MAAM,EAChB,EAAE,GAAE,OAAO,KAAwB,GACpC,OAAO,CAAC,OAAO,KAAK,GAAG,SAAS,CAAC;IA4B9B,aAAa,CACf,YAAY,EAAE,MAAM,EACpB,EAAE,GAAE,OAAO,KAAwB,GACpC,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IA4CtC,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,aAAa;YAUP,aAAa;YAoDb,gBAAgB;YAmChB,kBAAkB;YAiClB,aAAa;CAkD9B"}
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
- const conn = await this.platformAPIClient.getStaticConnection(cnxId);
120
- if (!conn) {
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
- return fn(_input, init);
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
- switch (conn.credentials[0].authSchemeConfig.type) {
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.info('Template not found in config, could be a static connection', {
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) && c.name.toLowerCase() === connName.toLowerCase());
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 tokenResponse = await this.tokenClient.getToken(conn.credentials[0].credential.id);
189
- const token = tokenResponse.token?.accessToken;
190
- const asc = conn.credentials[0].authSchemeConfig.apiKey;
191
- if (!token) {
192
- throw new Error('Token not found');
193
- }
194
- if (!asc) {
195
- throw new Error('API Key configuration not found');
196
- }
197
- const _fn = (input, init) => {
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 tokenResponse = await this.tokenClient.getToken(conn.credentials[0].credential.id);
237
- const token = tokenResponse.token?.accessToken;
238
- if (!token) {
239
- throw new Error('Token not found');
240
- }
241
- const _fn = (input, init) => {
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 tokenResponse = await this.tokenClient.getToken(conn.credentials[0].credential.id);
267
- const token = tokenResponse.token?.accessToken;
268
- if (!token) {
269
- throw new Error('Token not found');
270
- }
271
- const _fn = (input, init) => {
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 tokenResponse = await this.tokenClient.getOAuth2Token(conn.credentials[0].credential.id);
296
- const token = tokenResponse.token?.accessToken;
297
- const tokenType = tokenResponse.token?.tokenType;
298
- if (!token) {
299
- throw new Error('Token not found');
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
- const _fn = (input, init) => {
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
  }