phenoml 6.1.0 → 6.3.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.
Files changed (71) hide show
  1. package/dist/cjs/BaseClient.d.ts +2 -0
  2. package/dist/cjs/Client.js +3 -3
  3. package/dist/cjs/api/resources/agent/client/Client.js +8 -0
  4. package/dist/cjs/api/resources/agent/resources/prompts/client/Client.js +7 -0
  5. package/dist/cjs/api/resources/cohort/client/Client.js +1 -0
  6. package/dist/cjs/api/resources/construe/client/Client.js +10 -0
  7. package/dist/cjs/api/resources/fhir/client/Client.js +6 -0
  8. package/dist/cjs/api/resources/fhirProvider/client/Client.js +7 -0
  9. package/dist/cjs/api/resources/lang2Fhir/client/Client.js +5 -0
  10. package/dist/cjs/api/resources/summary/client/Client.js +6 -0
  11. package/dist/cjs/api/resources/tools/client/Client.js +4 -0
  12. package/dist/cjs/api/resources/tools/resources/mcpServer/client/Client.js +4 -0
  13. package/dist/cjs/api/resources/tools/resources/mcpServer/resources/tools/client/Client.js +4 -0
  14. package/dist/cjs/api/resources/workflows/client/Client.js +6 -0
  15. package/dist/cjs/core/exports.d.ts +1 -0
  16. package/dist/cjs/core/exports.js +17 -0
  17. package/dist/cjs/core/fetcher/Fetcher.d.ts +2 -0
  18. package/dist/cjs/core/fetcher/Fetcher.js +192 -1
  19. package/dist/cjs/core/fetcher/makeRequest.js +0 -2
  20. package/dist/cjs/core/fetcher/requestWithRetries.js +0 -9
  21. package/dist/cjs/core/fetcher/signals.d.ts +0 -6
  22. package/dist/cjs/core/fetcher/signals.js +0 -12
  23. package/dist/cjs/core/index.d.ts +1 -0
  24. package/dist/cjs/core/index.js +2 -1
  25. package/dist/cjs/core/logging/exports.d.ts +18 -0
  26. package/dist/cjs/core/logging/exports.js +45 -0
  27. package/dist/cjs/core/logging/index.d.ts +1 -0
  28. package/dist/cjs/core/logging/index.js +17 -0
  29. package/dist/cjs/core/logging/logger.d.ts +126 -0
  30. package/dist/cjs/core/logging/logger.js +144 -0
  31. package/dist/cjs/core/url/join.js +0 -1
  32. package/dist/cjs/exports.d.ts +1 -0
  33. package/dist/cjs/exports.js +17 -0
  34. package/dist/cjs/version.d.ts +1 -1
  35. package/dist/cjs/version.js +1 -1
  36. package/dist/esm/BaseClient.d.mts +2 -0
  37. package/dist/esm/Client.mjs +3 -3
  38. package/dist/esm/api/resources/agent/client/Client.mjs +8 -0
  39. package/dist/esm/api/resources/agent/resources/prompts/client/Client.mjs +7 -0
  40. package/dist/esm/api/resources/cohort/client/Client.mjs +1 -0
  41. package/dist/esm/api/resources/construe/client/Client.mjs +10 -0
  42. package/dist/esm/api/resources/fhir/client/Client.mjs +6 -0
  43. package/dist/esm/api/resources/fhirProvider/client/Client.mjs +7 -0
  44. package/dist/esm/api/resources/lang2Fhir/client/Client.mjs +5 -0
  45. package/dist/esm/api/resources/summary/client/Client.mjs +6 -0
  46. package/dist/esm/api/resources/tools/client/Client.mjs +4 -0
  47. package/dist/esm/api/resources/tools/resources/mcpServer/client/Client.mjs +4 -0
  48. package/dist/esm/api/resources/tools/resources/mcpServer/resources/tools/client/Client.mjs +4 -0
  49. package/dist/esm/api/resources/workflows/client/Client.mjs +6 -0
  50. package/dist/esm/core/exports.d.mts +1 -0
  51. package/dist/esm/core/exports.mjs +1 -0
  52. package/dist/esm/core/fetcher/Fetcher.d.mts +2 -0
  53. package/dist/esm/core/fetcher/Fetcher.mjs +192 -1
  54. package/dist/esm/core/fetcher/makeRequest.mjs +0 -2
  55. package/dist/esm/core/fetcher/requestWithRetries.mjs +0 -9
  56. package/dist/esm/core/fetcher/signals.d.mts +0 -6
  57. package/dist/esm/core/fetcher/signals.mjs +0 -12
  58. package/dist/esm/core/index.d.mts +1 -0
  59. package/dist/esm/core/index.mjs +1 -0
  60. package/dist/esm/core/logging/exports.d.mts +18 -0
  61. package/dist/esm/core/logging/exports.mjs +9 -0
  62. package/dist/esm/core/logging/index.d.mts +1 -0
  63. package/dist/esm/core/logging/index.mjs +1 -0
  64. package/dist/esm/core/logging/logger.d.mts +126 -0
  65. package/dist/esm/core/logging/logger.mjs +138 -0
  66. package/dist/esm/core/url/join.mjs +0 -1
  67. package/dist/esm/exports.d.mts +1 -0
  68. package/dist/esm/exports.mjs +1 -0
  69. package/dist/esm/version.d.mts +1 -1
  70. package/dist/esm/version.mjs +1 -1
  71. package/package.json +2 -1
@@ -58,6 +58,7 @@ export class McpServer {
58
58
  maxRetries: (_h = requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.maxRetries) !== null && _h !== void 0 ? _h : (_j = this._options) === null || _j === void 0 ? void 0 : _j.maxRetries,
59
59
  abortSignal: requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.abortSignal,
60
60
  fetchFn: (_k = this._options) === null || _k === void 0 ? void 0 : _k.fetch,
61
+ logging: this._options.logging,
61
62
  });
62
63
  if (_response.ok) {
63
64
  return { data: _response.body, rawResponse: _response.rawResponse };
@@ -125,6 +126,7 @@ export class McpServer {
125
126
  maxRetries: (_h = requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.maxRetries) !== null && _h !== void 0 ? _h : (_j = this._options) === null || _j === void 0 ? void 0 : _j.maxRetries,
126
127
  abortSignal: requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.abortSignal,
127
128
  fetchFn: (_k = this._options) === null || _k === void 0 ? void 0 : _k.fetch,
129
+ logging: this._options.logging,
128
130
  });
129
131
  if (_response.ok) {
130
132
  return { data: _response.body, rawResponse: _response.rawResponse };
@@ -191,6 +193,7 @@ export class McpServer {
191
193
  maxRetries: (_h = requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.maxRetries) !== null && _h !== void 0 ? _h : (_j = this._options) === null || _j === void 0 ? void 0 : _j.maxRetries,
192
194
  abortSignal: requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.abortSignal,
193
195
  fetchFn: (_k = this._options) === null || _k === void 0 ? void 0 : _k.fetch,
196
+ logging: this._options.logging,
194
197
  });
195
198
  if (_response.ok) {
196
199
  return { data: _response.body, rawResponse: _response.rawResponse };
@@ -257,6 +260,7 @@ export class McpServer {
257
260
  maxRetries: (_h = requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.maxRetries) !== null && _h !== void 0 ? _h : (_j = this._options) === null || _j === void 0 ? void 0 : _j.maxRetries,
258
261
  abortSignal: requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.abortSignal,
259
262
  fetchFn: (_k = this._options) === null || _k === void 0 ? void 0 : _k.fetch,
263
+ logging: this._options.logging,
260
264
  });
261
265
  if (_response.ok) {
262
266
  return { data: _response.body, rawResponse: _response.rawResponse };
@@ -46,6 +46,7 @@ export class Tools {
46
46
  maxRetries: (_h = requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.maxRetries) !== null && _h !== void 0 ? _h : (_j = this._options) === null || _j === void 0 ? void 0 : _j.maxRetries,
47
47
  abortSignal: requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.abortSignal,
48
48
  fetchFn: (_k = this._options) === null || _k === void 0 ? void 0 : _k.fetch,
49
+ logging: this._options.logging,
49
50
  });
50
51
  if (_response.ok) {
51
52
  return { data: _response.body, rawResponse: _response.rawResponse };
@@ -112,6 +113,7 @@ export class Tools {
112
113
  maxRetries: (_h = requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.maxRetries) !== null && _h !== void 0 ? _h : (_j = this._options) === null || _j === void 0 ? void 0 : _j.maxRetries,
113
114
  abortSignal: requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.abortSignal,
114
115
  fetchFn: (_k = this._options) === null || _k === void 0 ? void 0 : _k.fetch,
116
+ logging: this._options.logging,
115
117
  });
116
118
  if (_response.ok) {
117
119
  return { data: _response.body, rawResponse: _response.rawResponse };
@@ -178,6 +180,7 @@ export class Tools {
178
180
  maxRetries: (_h = requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.maxRetries) !== null && _h !== void 0 ? _h : (_j = this._options) === null || _j === void 0 ? void 0 : _j.maxRetries,
179
181
  abortSignal: requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.abortSignal,
180
182
  fetchFn: (_k = this._options) === null || _k === void 0 ? void 0 : _k.fetch,
183
+ logging: this._options.logging,
181
184
  });
182
185
  if (_response.ok) {
183
186
  return { data: _response.body, rawResponse: _response.rawResponse };
@@ -253,6 +256,7 @@ export class Tools {
253
256
  maxRetries: (_h = requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.maxRetries) !== null && _h !== void 0 ? _h : (_j = this._options) === null || _j === void 0 ? void 0 : _j.maxRetries,
254
257
  abortSignal: requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.abortSignal,
255
258
  fetchFn: (_k = this._options) === null || _k === void 0 ? void 0 : _k.fetch,
259
+ logging: this._options.logging,
256
260
  });
257
261
  if (_response.ok) {
258
262
  return {
@@ -64,6 +64,7 @@ export class Workflows {
64
64
  maxRetries: (_h = requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.maxRetries) !== null && _h !== void 0 ? _h : (_j = this._options) === null || _j === void 0 ? void 0 : _j.maxRetries,
65
65
  abortSignal: requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.abortSignal,
66
66
  fetchFn: (_k = this._options) === null || _k === void 0 ? void 0 : _k.fetch,
67
+ logging: this._options.logging,
67
68
  });
68
69
  if (_response.ok) {
69
70
  return {
@@ -152,6 +153,7 @@ export class Workflows {
152
153
  maxRetries: (_h = requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.maxRetries) !== null && _h !== void 0 ? _h : (_j = this._options) === null || _j === void 0 ? void 0 : _j.maxRetries,
153
154
  abortSignal: requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.abortSignal,
154
155
  fetchFn: (_k = this._options) === null || _k === void 0 ? void 0 : _k.fetch,
156
+ logging: this._options.logging,
155
157
  });
156
158
  if (_response.ok) {
157
159
  return {
@@ -232,6 +234,7 @@ export class Workflows {
232
234
  maxRetries: (_h = requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.maxRetries) !== null && _h !== void 0 ? _h : (_j = this._options) === null || _j === void 0 ? void 0 : _j.maxRetries,
233
235
  abortSignal: requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.abortSignal,
234
236
  fetchFn: (_k = this._options) === null || _k === void 0 ? void 0 : _k.fetch,
237
+ logging: this._options.logging,
235
238
  });
236
239
  if (_response.ok) {
237
240
  return {
@@ -324,6 +327,7 @@ export class Workflows {
324
327
  maxRetries: (_h = requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.maxRetries) !== null && _h !== void 0 ? _h : (_j = this._options) === null || _j === void 0 ? void 0 : _j.maxRetries,
325
328
  abortSignal: requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.abortSignal,
326
329
  fetchFn: (_k = this._options) === null || _k === void 0 ? void 0 : _k.fetch,
330
+ logging: this._options.logging,
327
331
  });
328
332
  if (_response.ok) {
329
333
  return {
@@ -398,6 +402,7 @@ export class Workflows {
398
402
  maxRetries: (_h = requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.maxRetries) !== null && _h !== void 0 ? _h : (_j = this._options) === null || _j === void 0 ? void 0 : _j.maxRetries,
399
403
  abortSignal: requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.abortSignal,
400
404
  fetchFn: (_k = this._options) === null || _k === void 0 ? void 0 : _k.fetch,
405
+ logging: this._options.logging,
401
406
  });
402
407
  if (_response.ok) {
403
408
  return {
@@ -482,6 +487,7 @@ export class Workflows {
482
487
  maxRetries: (_h = requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.maxRetries) !== null && _h !== void 0 ? _h : (_j = this._options) === null || _j === void 0 ? void 0 : _j.maxRetries,
483
488
  abortSignal: requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.abortSignal,
484
489
  fetchFn: (_k = this._options) === null || _k === void 0 ? void 0 : _k.fetch,
490
+ logging: this._options.logging,
485
491
  });
486
492
  if (_response.ok) {
487
493
  return {
@@ -0,0 +1 @@
1
+ export * from "./logging/exports.mjs";
@@ -0,0 +1 @@
1
+ export * from "./logging/exports.mjs";
@@ -1,3 +1,4 @@
1
+ import { type LogConfig, type Logger } from "../logging/logger.mjs";
1
2
  import type { APIResponse } from "./APIResponse.mjs";
2
3
  import type { EndpointMetadata } from "./EndpointMetadata.mjs";
3
4
  import { EndpointSupplier } from "./EndpointSupplier.mjs";
@@ -19,6 +20,7 @@ export declare namespace Fetcher {
19
20
  duplex?: "half";
20
21
  endpointMetadata?: EndpointMetadata;
21
22
  fetchFn?: typeof fetch;
23
+ logging?: LogConfig | Logger;
22
24
  }
23
25
  type Error = FailedStatusCodeError | NonJsonError | TimeoutError | UnknownError;
24
26
  interface FailedStatusCodeError {
@@ -8,6 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { toJson } from "../json.mjs";
11
+ import { createLogger } from "../logging/logger.mjs";
11
12
  import { createRequestUrl } from "./createRequestUrl.mjs";
12
13
  import { EndpointSupplier } from "./EndpointSupplier.mjs";
13
14
  import { getErrorResponseBody } from "./getErrorResponseBody.mjs";
@@ -17,6 +18,135 @@ import { getResponseBody } from "./getResponseBody.mjs";
17
18
  import { makeRequest } from "./makeRequest.mjs";
18
19
  import { abortRawResponse, toRawResponse, unknownRawResponse } from "./RawResponse.mjs";
19
20
  import { requestWithRetries } from "./requestWithRetries.mjs";
21
+ const SENSITIVE_HEADERS = new Set([
22
+ "authorization",
23
+ "www-authenticate",
24
+ "x-api-key",
25
+ "api-key",
26
+ "apikey",
27
+ "x-api-token",
28
+ "x-auth-token",
29
+ "auth-token",
30
+ "cookie",
31
+ "set-cookie",
32
+ "proxy-authorization",
33
+ "proxy-authenticate",
34
+ "x-csrf-token",
35
+ "x-xsrf-token",
36
+ "x-session-token",
37
+ "x-access-token",
38
+ ]);
39
+ function redactHeaders(headers) {
40
+ const filtered = {};
41
+ for (const [key, value] of Object.entries(headers)) {
42
+ if (SENSITIVE_HEADERS.has(key.toLowerCase())) {
43
+ filtered[key] = "[REDACTED]";
44
+ }
45
+ else {
46
+ filtered[key] = value;
47
+ }
48
+ }
49
+ return filtered;
50
+ }
51
+ const SENSITIVE_QUERY_PARAMS = new Set([
52
+ "api_key",
53
+ "api-key",
54
+ "apikey",
55
+ "token",
56
+ "access_token",
57
+ "access-token",
58
+ "auth_token",
59
+ "auth-token",
60
+ "password",
61
+ "passwd",
62
+ "secret",
63
+ "api_secret",
64
+ "api-secret",
65
+ "apisecret",
66
+ "key",
67
+ "session",
68
+ "session_id",
69
+ "session-id",
70
+ ]);
71
+ function redactQueryParameters(queryParameters) {
72
+ if (queryParameters == null) {
73
+ return queryParameters;
74
+ }
75
+ const redacted = {};
76
+ for (const [key, value] of Object.entries(queryParameters)) {
77
+ if (SENSITIVE_QUERY_PARAMS.has(key.toLowerCase())) {
78
+ redacted[key] = "[REDACTED]";
79
+ }
80
+ else {
81
+ redacted[key] = value;
82
+ }
83
+ }
84
+ return redacted;
85
+ }
86
+ function redactUrl(url) {
87
+ const protocolIndex = url.indexOf("://");
88
+ if (protocolIndex === -1)
89
+ return url;
90
+ const afterProtocol = protocolIndex + 3;
91
+ // Find the first delimiter that marks the end of the authority section
92
+ const pathStart = url.indexOf("/", afterProtocol);
93
+ let queryStart = url.indexOf("?", afterProtocol);
94
+ let fragmentStart = url.indexOf("#", afterProtocol);
95
+ const firstDelimiter = Math.min(pathStart === -1 ? url.length : pathStart, queryStart === -1 ? url.length : queryStart, fragmentStart === -1 ? url.length : fragmentStart);
96
+ // Find the LAST @ before the delimiter (handles multiple @ in credentials)
97
+ let atIndex = -1;
98
+ for (let i = afterProtocol; i < firstDelimiter; i++) {
99
+ if (url[i] === "@") {
100
+ atIndex = i;
101
+ }
102
+ }
103
+ if (atIndex !== -1) {
104
+ url = `${url.slice(0, afterProtocol)}[REDACTED]@${url.slice(atIndex + 1)}`;
105
+ }
106
+ // Recalculate queryStart since url might have changed
107
+ queryStart = url.indexOf("?");
108
+ if (queryStart === -1)
109
+ return url;
110
+ fragmentStart = url.indexOf("#", queryStart);
111
+ const queryEnd = fragmentStart !== -1 ? fragmentStart : url.length;
112
+ const queryString = url.slice(queryStart + 1, queryEnd);
113
+ if (queryString.length === 0)
114
+ return url;
115
+ // FAST PATH: Quick check if any sensitive keywords present
116
+ // Using indexOf is faster than regex for simple substring matching
117
+ const lower = queryString.toLowerCase();
118
+ const hasSensitive = lower.includes("token") ||
119
+ lower.includes("key") ||
120
+ lower.includes("password") ||
121
+ lower.includes("passwd") ||
122
+ lower.includes("secret") ||
123
+ lower.includes("session") ||
124
+ lower.includes("auth");
125
+ if (!hasSensitive) {
126
+ return url;
127
+ }
128
+ // SLOW PATH: Parse and redact
129
+ const redactedParams = [];
130
+ const params = queryString.split("&");
131
+ for (const param of params) {
132
+ const equalIndex = param.indexOf("=");
133
+ if (equalIndex === -1) {
134
+ redactedParams.push(param);
135
+ continue;
136
+ }
137
+ const key = param.slice(0, equalIndex);
138
+ let shouldRedact = SENSITIVE_QUERY_PARAMS.has(key.toLowerCase());
139
+ if (!shouldRedact && key.includes("%")) {
140
+ try {
141
+ const decodedKey = decodeURIComponent(key);
142
+ shouldRedact = SENSITIVE_QUERY_PARAMS.has(decodedKey.toLowerCase());
143
+ }
144
+ catch (_a) { }
145
+ }
146
+ redactedParams.push(shouldRedact ? `${key}=[REDACTED]` : param);
147
+ }
148
+ return url.slice(0, queryStart + 1) + redactedParams.join("&") + url.slice(queryEnd);
149
+ }
20
150
  function getHeaders(args) {
21
151
  return __awaiter(this, void 0, void 0, function* () {
22
152
  var _a;
@@ -50,11 +180,32 @@ export function fetcherImpl(args) {
50
180
  type: (_a = args.requestType) !== null && _a !== void 0 ? _a : "other",
51
181
  });
52
182
  const fetchFn = (_b = args.fetchFn) !== null && _b !== void 0 ? _b : (yield getFetchFn());
183
+ const headers = yield getHeaders(args);
184
+ const logger = createLogger(args.logging);
185
+ if (logger.isDebug()) {
186
+ const metadata = {
187
+ method: args.method,
188
+ url: redactUrl(url),
189
+ headers: redactHeaders(headers),
190
+ queryParameters: redactQueryParameters(args.queryParameters),
191
+ hasBody: requestBody != null,
192
+ };
193
+ logger.debug("Making HTTP request", metadata);
194
+ }
53
195
  try {
54
196
  const response = yield requestWithRetries(() => __awaiter(this, void 0, void 0, function* () {
55
- return makeRequest(fetchFn, url, args.method, yield getHeaders(args), requestBody, args.timeoutMs, args.abortSignal, args.withCredentials, args.duplex);
197
+ return makeRequest(fetchFn, url, args.method, headers, requestBody, args.timeoutMs, args.abortSignal, args.withCredentials, args.duplex);
56
198
  }), args.maxRetries);
57
199
  if (response.status >= 200 && response.status < 400) {
200
+ if (logger.isDebug()) {
201
+ const metadata = {
202
+ method: args.method,
203
+ url: redactUrl(url),
204
+ statusCode: response.status,
205
+ responseHeaders: redactHeaders(Object.fromEntries(response.headers.entries())),
206
+ };
207
+ logger.debug("HTTP request succeeded", metadata);
208
+ }
58
209
  return {
59
210
  ok: true,
60
211
  body: (yield getResponseBody(response, args.responseType)),
@@ -63,6 +214,15 @@ export function fetcherImpl(args) {
63
214
  };
64
215
  }
65
216
  else {
217
+ if (logger.isError()) {
218
+ const metadata = {
219
+ method: args.method,
220
+ url: redactUrl(url),
221
+ statusCode: response.status,
222
+ responseHeaders: redactHeaders(Object.fromEntries(response.headers.entries())),
223
+ };
224
+ logger.error("HTTP request failed with error status", metadata);
225
+ }
66
226
  return {
67
227
  ok: false,
68
228
  error: {
@@ -76,6 +236,13 @@ export function fetcherImpl(args) {
76
236
  }
77
237
  catch (error) {
78
238
  if ((_c = args.abortSignal) === null || _c === void 0 ? void 0 : _c.aborted) {
239
+ if (logger.isError()) {
240
+ const metadata = {
241
+ method: args.method,
242
+ url: redactUrl(url),
243
+ };
244
+ logger.error("HTTP request was aborted", metadata);
245
+ }
79
246
  return {
80
247
  ok: false,
81
248
  error: {
@@ -86,6 +253,14 @@ export function fetcherImpl(args) {
86
253
  };
87
254
  }
88
255
  else if (error instanceof Error && error.name === "AbortError") {
256
+ if (logger.isError()) {
257
+ const metadata = {
258
+ method: args.method,
259
+ url: redactUrl(url),
260
+ timeoutMs: args.timeoutMs,
261
+ };
262
+ logger.error("HTTP request timed out", metadata);
263
+ }
89
264
  return {
90
265
  ok: false,
91
266
  error: {
@@ -95,6 +270,14 @@ export function fetcherImpl(args) {
95
270
  };
96
271
  }
97
272
  else if (error instanceof Error) {
273
+ if (logger.isError()) {
274
+ const metadata = {
275
+ method: args.method,
276
+ url: redactUrl(url),
277
+ errorMessage: error.message,
278
+ };
279
+ logger.error("HTTP request failed with error", metadata);
280
+ }
98
281
  return {
99
282
  ok: false,
100
283
  error: {
@@ -104,6 +287,14 @@ export function fetcherImpl(args) {
104
287
  rawResponse: unknownRawResponse,
105
288
  };
106
289
  }
290
+ if (logger.isError()) {
291
+ const metadata = {
292
+ method: args.method,
293
+ url: redactUrl(url),
294
+ error: toJson(error),
295
+ };
296
+ logger.error("HTTP request failed with unknown error", metadata);
297
+ }
107
298
  return {
108
299
  ok: false,
109
300
  error: {
@@ -10,14 +10,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { anySignal, getTimeoutSignal } from "./signals.mjs";
11
11
  export const makeRequest = (fetchFn, url, method, headers, requestBody, timeoutMs, abortSignal, withCredentials, duplex) => __awaiter(void 0, void 0, void 0, function* () {
12
12
  const signals = [];
13
- // Add timeout signal
14
13
  let timeoutAbortId;
15
14
  if (timeoutMs != null) {
16
15
  const { signal, abortId } = getTimeoutSignal(timeoutMs);
17
16
  timeoutAbortId = abortId;
18
17
  signals.push(signal);
19
18
  }
20
- // Add arbitrary signal
21
19
  if (abortSignal != null) {
22
20
  signals.push(abortSignal);
23
21
  }
@@ -12,25 +12,20 @@ const MAX_RETRY_DELAY = 60000; // in milliseconds
12
12
  const DEFAULT_MAX_RETRIES = 2;
13
13
  const JITTER_FACTOR = 0.2; // 20% random jitter
14
14
  function addPositiveJitter(delay) {
15
- // Generate a random value between 0 and +JITTER_FACTOR
16
15
  const jitterMultiplier = 1 + Math.random() * JITTER_FACTOR;
17
16
  return delay * jitterMultiplier;
18
17
  }
19
18
  function addSymmetricJitter(delay) {
20
- // Generate a random value in a JITTER_FACTOR-sized percentage range around delay
21
19
  const jitterMultiplier = 1 + (Math.random() - 0.5) * JITTER_FACTOR;
22
20
  return delay * jitterMultiplier;
23
21
  }
24
22
  function getRetryDelayFromHeaders(response, retryAttempt) {
25
- // Check for Retry-After header first (RFC 7231), with no jitter
26
23
  const retryAfter = response.headers.get("Retry-After");
27
24
  if (retryAfter) {
28
- // Parse as number of seconds...
29
25
  const retryAfterSeconds = parseInt(retryAfter, 10);
30
26
  if (!Number.isNaN(retryAfterSeconds) && retryAfterSeconds > 0) {
31
27
  return Math.min(retryAfterSeconds * 1000, MAX_RETRY_DELAY);
32
28
  }
33
- // ...or as an HTTP date; both are valid
34
29
  const retryAfterDate = new Date(retryAfter);
35
30
  if (!Number.isNaN(retryAfterDate.getTime())) {
36
31
  const delay = retryAfterDate.getTime() - Date.now();
@@ -39,19 +34,16 @@ function getRetryDelayFromHeaders(response, retryAttempt) {
39
34
  }
40
35
  }
41
36
  }
42
- // Then check for industry-standard X-RateLimit-Reset header, with positive jitter
43
37
  const rateLimitReset = response.headers.get("X-RateLimit-Reset");
44
38
  if (rateLimitReset) {
45
39
  const resetTime = parseInt(rateLimitReset, 10);
46
40
  if (!Number.isNaN(resetTime)) {
47
- // Assume Unix timestamp in epoch seconds
48
41
  const delay = resetTime * 1000 - Date.now();
49
42
  if (delay > 0) {
50
43
  return addPositiveJitter(Math.min(delay, MAX_RETRY_DELAY));
51
44
  }
52
45
  }
53
46
  }
54
- // Fall back to exponential backoff, with symmetric jitter
55
47
  return addSymmetricJitter(Math.min(INITIAL_RETRY_DELAY * Math.pow(2, retryAttempt), MAX_RETRY_DELAY));
56
48
  }
57
49
  export function requestWithRetries(requestFn_1) {
@@ -59,7 +51,6 @@ export function requestWithRetries(requestFn_1) {
59
51
  let response = yield requestFn();
60
52
  for (let i = 0; i < maxRetries; ++i) {
61
53
  if ([408, 429].includes(response.status) || response.status >= 500) {
62
- // Get delay with appropriate jitter applied
63
54
  const delay = getRetryDelayFromHeaders(response, i);
64
55
  yield new Promise((resolve) => setTimeout(resolve, delay));
65
56
  response = yield requestFn();
@@ -2,10 +2,4 @@ export declare function getTimeoutSignal(timeoutMs: number): {
2
2
  signal: AbortSignal;
3
3
  abortId: NodeJS.Timeout;
4
4
  };
5
- /**
6
- * Returns an abort signal that is getting aborted when
7
- * at least one of the specified abort signals is aborted.
8
- *
9
- * Requires at least node.js 18.
10
- */
11
5
  export declare function anySignal(...args: AbortSignal[] | [AbortSignal[]]): AbortSignal;
@@ -4,26 +4,14 @@ export function getTimeoutSignal(timeoutMs) {
4
4
  const abortId = setTimeout(() => controller.abort(TIMEOUT), timeoutMs);
5
5
  return { signal: controller.signal, abortId };
6
6
  }
7
- /**
8
- * Returns an abort signal that is getting aborted when
9
- * at least one of the specified abort signals is aborted.
10
- *
11
- * Requires at least node.js 18.
12
- */
13
7
  export function anySignal(...args) {
14
- // Allowing signals to be passed either as array
15
- // of signals or as multiple arguments.
16
8
  const signals = (args.length === 1 && Array.isArray(args[0]) ? args[0] : args);
17
9
  const controller = new AbortController();
18
10
  for (const signal of signals) {
19
11
  if (signal.aborted) {
20
- // Exiting early if one of the signals
21
- // is already aborted.
22
12
  controller.abort(signal === null || signal === void 0 ? void 0 : signal.reason);
23
13
  break;
24
14
  }
25
- // Listening for signals and removing the listeners
26
- // when at least one symbol is aborted.
27
15
  signal.addEventListener("abort", () => controller.abort(signal === null || signal === void 0 ? void 0 : signal.reason), {
28
16
  signal: controller.signal,
29
17
  });
@@ -1,5 +1,6 @@
1
1
  export * from "./auth/index.mjs";
2
2
  export * from "./base64.mjs";
3
3
  export * from "./fetcher/index.mjs";
4
+ export * as logging from "./logging/index.mjs";
4
5
  export * from "./runtime/index.mjs";
5
6
  export * as url from "./url/index.mjs";
@@ -1,5 +1,6 @@
1
1
  export * from "./auth/index.mjs";
2
2
  export * from "./base64.mjs";
3
3
  export * from "./fetcher/index.mjs";
4
+ export * as logging from "./logging/index.mjs";
4
5
  export * from "./runtime/index.mjs";
5
6
  export * as url from "./url/index.mjs";
@@ -0,0 +1,18 @@
1
+ import * as logger from "./logger.mjs";
2
+ export declare namespace logging {
3
+ /**
4
+ * Configuration for logger instances.
5
+ */
6
+ type LogConfig = logger.LogConfig;
7
+ type LogLevel = logger.LogLevel;
8
+ const LogLevel: typeof logger.LogLevel;
9
+ type ILogger = logger.ILogger;
10
+ /**
11
+ * Console logger implementation that outputs to the console.
12
+ */
13
+ type ConsoleLogger = logger.ConsoleLogger;
14
+ /**
15
+ * Console logger implementation that outputs to the console.
16
+ */
17
+ const ConsoleLogger: typeof logger.ConsoleLogger;
18
+ }
@@ -0,0 +1,9 @@
1
+ import * as logger from "./logger.mjs";
2
+ export var logging;
3
+ (function (logging) {
4
+ logging.LogLevel = logger.LogLevel;
5
+ /**
6
+ * Console logger implementation that outputs to the console.
7
+ */
8
+ logging.ConsoleLogger = logger.ConsoleLogger;
9
+ })(logging || (logging = {}));
@@ -0,0 +1 @@
1
+ export * from "./logger.mjs";
@@ -0,0 +1 @@
1
+ export * from "./logger.mjs";
@@ -0,0 +1,126 @@
1
+ export declare const LogLevel: {
2
+ readonly Debug: "debug";
3
+ readonly Info: "info";
4
+ readonly Warn: "warn";
5
+ readonly Error: "error";
6
+ };
7
+ export type LogLevel = (typeof LogLevel)[keyof typeof LogLevel];
8
+ export interface ILogger {
9
+ /**
10
+ * Logs a debug message.
11
+ * @param message - The message to log
12
+ * @param args - Additional arguments to log
13
+ */
14
+ debug(message: string, ...args: unknown[]): void;
15
+ /**
16
+ * Logs an info message.
17
+ * @param message - The message to log
18
+ * @param args - Additional arguments to log
19
+ */
20
+ info(message: string, ...args: unknown[]): void;
21
+ /**
22
+ * Logs a warning message.
23
+ * @param message - The message to log
24
+ * @param args - Additional arguments to log
25
+ */
26
+ warn(message: string, ...args: unknown[]): void;
27
+ /**
28
+ * Logs an error message.
29
+ * @param message - The message to log
30
+ * @param args - Additional arguments to log
31
+ */
32
+ error(message: string, ...args: unknown[]): void;
33
+ }
34
+ /**
35
+ * Configuration for logger initialization.
36
+ */
37
+ export interface LogConfig {
38
+ /**
39
+ * Minimum log level to output.
40
+ * @default LogLevel.Info
41
+ */
42
+ level?: LogLevel;
43
+ /**
44
+ * Logger implementation to use.
45
+ * @default new ConsoleLogger()
46
+ */
47
+ logger?: ILogger;
48
+ /**
49
+ * Whether logging should be silenced.
50
+ * @default true
51
+ */
52
+ silent?: boolean;
53
+ }
54
+ /**
55
+ * Default console-based logger implementation.
56
+ */
57
+ export declare class ConsoleLogger implements ILogger {
58
+ debug(message: string, ...args: unknown[]): void;
59
+ info(message: string, ...args: unknown[]): void;
60
+ warn(message: string, ...args: unknown[]): void;
61
+ error(message: string, ...args: unknown[]): void;
62
+ }
63
+ /**
64
+ * Logger class that provides level-based logging functionality.
65
+ */
66
+ export declare class Logger {
67
+ private readonly level;
68
+ private readonly logger;
69
+ private readonly silent;
70
+ /**
71
+ * Creates a new logger instance.
72
+ * @param config - Logger configuration
73
+ */
74
+ constructor(config: Required<LogConfig>);
75
+ /**
76
+ * Checks if a log level should be output based on configuration.
77
+ * @param level - The log level to check
78
+ * @returns True if the level should be logged
79
+ */
80
+ shouldLog(level: LogLevel): boolean;
81
+ /**
82
+ * Checks if debug logging is enabled.
83
+ * @returns True if debug logs should be output
84
+ */
85
+ isDebug(): boolean;
86
+ /**
87
+ * Logs a debug message if debug logging is enabled.
88
+ * @param message - The message to log
89
+ * @param args - Additional arguments to log
90
+ */
91
+ debug(message: string, ...args: unknown[]): void;
92
+ /**
93
+ * Checks if info logging is enabled.
94
+ * @returns True if info logs should be output
95
+ */
96
+ isInfo(): boolean;
97
+ /**
98
+ * Logs an info message if info logging is enabled.
99
+ * @param message - The message to log
100
+ * @param args - Additional arguments to log
101
+ */
102
+ info(message: string, ...args: unknown[]): void;
103
+ /**
104
+ * Checks if warning logging is enabled.
105
+ * @returns True if warning logs should be output
106
+ */
107
+ isWarn(): boolean;
108
+ /**
109
+ * Logs a warning message if warning logging is enabled.
110
+ * @param message - The message to log
111
+ * @param args - Additional arguments to log
112
+ */
113
+ warn(message: string, ...args: unknown[]): void;
114
+ /**
115
+ * Checks if error logging is enabled.
116
+ * @returns True if error logs should be output
117
+ */
118
+ isError(): boolean;
119
+ /**
120
+ * Logs an error message if error logging is enabled.
121
+ * @param message - The message to log
122
+ * @param args - Additional arguments to log
123
+ */
124
+ error(message: string, ...args: unknown[]): void;
125
+ }
126
+ export declare function createLogger(config?: LogConfig | Logger): Logger;