veryfront 0.1.1119 → 0.1.1122

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 (125) hide show
  1. package/esm/deno.js +1 -1
  2. package/esm/src/agent/ag-ui/runtime-chat-stream-encoder.d.ts.map +1 -1
  3. package/esm/src/agent/ag-ui/runtime-chat-stream-encoder.js +41 -4
  4. package/esm/src/agent/hosted/chat-runtime-tool-assembly.d.ts.map +1 -1
  5. package/esm/src/agent/hosted/chat-runtime-tool-assembly.js +35 -5
  6. package/esm/src/agent/input/human-input.d.ts.map +1 -1
  7. package/esm/src/agent/input/human-input.js +2 -6
  8. package/esm/src/agent/react/use-chat/streaming/handler.js +21 -0
  9. package/esm/src/agent/react/use-chat/streaming/parts-builder.js +1 -0
  10. package/esm/src/agent/react/use-chat/streaming/types.d.ts +2 -0
  11. package/esm/src/agent/react/use-chat/streaming/types.d.ts.map +1 -1
  12. package/esm/src/agent/runtime/index.d.ts.map +1 -1
  13. package/esm/src/agent/runtime/index.js +1 -0
  14. package/esm/src/agent/service/detached-run-tracker.d.ts.map +1 -1
  15. package/esm/src/agent/service/detached-run-tracker.js +1 -5
  16. package/esm/src/agent/service/registration.d.ts.map +1 -1
  17. package/esm/src/agent/service/registration.js +2 -6
  18. package/esm/src/agent/streaming/chat-ui-message-stream.d.ts.map +1 -1
  19. package/esm/src/agent/streaming/chat-ui-message-stream.js +24 -0
  20. package/esm/src/build/bundler/code-splitter/manifest-builder.d.ts +4 -0
  21. package/esm/src/build/bundler/code-splitter/manifest-builder.d.ts.map +1 -1
  22. package/esm/src/build/bundler/code-splitter/manifest-builder.js +2 -5
  23. package/esm/src/build/production-build/local-release-assets.js +2 -2
  24. package/esm/src/chat/conversation.d.ts.map +1 -1
  25. package/esm/src/chat/conversation.js +1 -5
  26. package/esm/src/chat/protocol.d.ts +6 -0
  27. package/esm/src/chat/protocol.d.ts.map +1 -1
  28. package/esm/src/discovery/transpiler.d.ts.map +1 -1
  29. package/esm/src/discovery/transpiler.js +4 -8
  30. package/esm/src/errors/error-handlers.d.ts +31 -3
  31. package/esm/src/errors/error-handlers.d.ts.map +1 -1
  32. package/esm/src/errors/error-handlers.js +33 -12
  33. package/esm/src/errors/index.d.ts +1 -1
  34. package/esm/src/errors/index.d.ts.map +1 -1
  35. package/esm/src/eval/agent-service/durable-run-canaries/runner.d.ts.map +1 -1
  36. package/esm/src/eval/agent-service/durable-run-canaries/runner.js +1 -5
  37. package/esm/src/eval/agent-service/live-evals/api-client.d.ts.map +1 -1
  38. package/esm/src/eval/agent-service/live-evals/api-client.js +3 -4
  39. package/esm/src/eval/provenance.d.ts.map +1 -1
  40. package/esm/src/eval/provenance.js +3 -13
  41. package/esm/src/eval/report.d.ts.map +1 -1
  42. package/esm/src/eval/report.js +2 -8
  43. package/esm/src/html/styles-builder/plugin-loader.d.ts.map +1 -1
  44. package/esm/src/html/styles-builder/plugin-loader.js +2 -13
  45. package/esm/src/knowledge/index.d.ts.map +1 -1
  46. package/esm/src/knowledge/index.js +2 -5
  47. package/esm/src/metrics/index.d.ts.map +1 -1
  48. package/esm/src/metrics/index.js +2 -1
  49. package/esm/src/oauth/providers/base.d.ts.map +1 -1
  50. package/esm/src/oauth/providers/base.js +2 -6
  51. package/esm/src/platform/adapters/fs/github/github-api-client.d.ts +0 -1
  52. package/esm/src/platform/adapters/fs/github/github-api-client.d.ts.map +1 -1
  53. package/esm/src/platform/adapters/fs/github/github-api-client.js +36 -37
  54. package/esm/src/platform/adapters/fs/veryfront/retry.d.ts.map +1 -1
  55. package/esm/src/platform/adapters/fs/veryfront/retry.js +12 -14
  56. package/esm/src/platform/adapters/veryfront-api-client/retry-handler.d.ts.map +1 -1
  57. package/esm/src/platform/adapters/veryfront-api-client/retry-handler.js +82 -86
  58. package/esm/src/proxy/logger.d.ts +2 -1
  59. package/esm/src/proxy/logger.d.ts.map +1 -1
  60. package/esm/src/proxy/logger.js +1 -112
  61. package/esm/src/proxy/routing-invalidation-redis.d.ts.map +1 -1
  62. package/esm/src/proxy/routing-invalidation-redis.js +2 -5
  63. package/esm/src/proxy/server-resolver.d.ts.map +1 -1
  64. package/esm/src/proxy/server-resolver.js +2 -1
  65. package/esm/src/release-assets/build-executor.js +5 -5
  66. package/esm/src/release-assets/index.d.ts +0 -1
  67. package/esm/src/release-assets/index.d.ts.map +1 -1
  68. package/esm/src/release-assets/index.js +0 -1
  69. package/esm/src/rendering/orchestrator/module-loader/cache.d.ts +9 -0
  70. package/esm/src/rendering/orchestrator/module-loader/cache.d.ts.map +1 -1
  71. package/esm/src/rendering/orchestrator/module-loader/cache.js +2 -11
  72. package/esm/src/routing/api/module-loader/esbuild-plugin.d.ts.map +1 -1
  73. package/esm/src/routing/api/module-loader/esbuild-plugin.js +2 -5
  74. package/esm/src/sandbox/lazy-sandbox.js +4 -4
  75. package/esm/src/security/http/auth.d.ts.map +1 -1
  76. package/esm/src/security/http/auth.js +1 -24
  77. package/esm/src/server/handlers/studio/bridge-modules.handler.d.ts.map +1 -1
  78. package/esm/src/server/handlers/studio/bridge-modules.handler.js +2 -5
  79. package/esm/src/server/project-env/fetcher.js +2 -2
  80. package/esm/src/server/services/rsc/endpoints/rsc-bundles.generated.d.ts.map +1 -1
  81. package/esm/src/server/services/rsc/endpoints/rsc-bundles.generated.js +1 -1
  82. package/esm/src/server/services/rsc/orchestrators/stream-handler.js +1 -4
  83. package/esm/src/transforms/esm/transform-utils.d.ts.map +1 -1
  84. package/esm/src/transforms/esm/transform-utils.js +2 -1
  85. package/esm/src/transforms/mdx/compiler/import-rewriter.d.ts.map +1 -1
  86. package/esm/src/transforms/mdx/compiler/import-rewriter.js +2 -1
  87. package/esm/src/transforms/pipeline/stages/resolve-imports.d.ts.map +1 -1
  88. package/esm/src/transforms/pipeline/stages/resolve-imports.js +3 -1
  89. package/esm/src/utils/base64url.d.ts +4 -3
  90. package/esm/src/utils/base64url.d.ts.map +1 -1
  91. package/esm/src/utils/base64url.js +30 -3
  92. package/esm/src/utils/hash-utils.d.ts +4 -1
  93. package/esm/src/utils/hash-utils.d.ts.map +1 -1
  94. package/esm/src/utils/hash-utils.js +9 -3
  95. package/esm/src/utils/index.d.ts +3 -1
  96. package/esm/src/utils/index.d.ts.map +1 -1
  97. package/esm/src/utils/index.js +3 -1
  98. package/esm/src/utils/sleep.d.ts +3 -0
  99. package/esm/src/utils/sleep.d.ts.map +1 -0
  100. package/esm/src/utils/sleep.js +18 -0
  101. package/esm/src/utils/version-constant.d.ts +1 -1
  102. package/esm/src/utils/version-constant.js +1 -1
  103. package/esm/src/workflow/claude-code/workspace-sync.d.ts.map +1 -1
  104. package/esm/src/workflow/claude-code/workspace-sync.js +3 -13
  105. package/esm/src/workflow/executor/dag/composite-node-execution.d.ts.map +1 -1
  106. package/esm/src/workflow/executor/dag/composite-node-execution.js +3 -24
  107. package/esm/src/workflow/executor/dag/loop-node-strategy.js +1 -1
  108. package/esm/src/workflow/executor/dag/utils.d.ts +0 -1
  109. package/esm/src/workflow/executor/dag/utils.d.ts.map +1 -1
  110. package/esm/src/workflow/executor/dag/utils.js +0 -17
  111. package/esm/src/workflow/executor/retry-policy.d.ts +13 -0
  112. package/esm/src/workflow/executor/retry-policy.d.ts.map +1 -0
  113. package/esm/src/workflow/executor/retry-policy.js +44 -0
  114. package/esm/src/workflow/executor/step-executor.d.ts +1 -11
  115. package/esm/src/workflow/executor/step-executor.d.ts.map +1 -1
  116. package/esm/src/workflow/executor/step-executor.js +6 -57
  117. package/esm/src/workflow/executor/workflow-executor.d.ts.map +1 -1
  118. package/esm/src/workflow/executor/workflow-executor.js +2 -3
  119. package/esm/src/workflow/worker/workflow-worker.d.ts +0 -4
  120. package/esm/src/workflow/worker/workflow-worker.d.ts.map +1 -1
  121. package/esm/src/workflow/worker/workflow-worker.js +2 -9
  122. package/package.json +5 -5
  123. package/esm/src/release-assets/hash.d.ts +0 -14
  124. package/esm/src/release-assets/hash.d.ts.map +0 -1
  125. package/esm/src/release-assets/hash.js +0 -22
@@ -1,7 +1,7 @@
1
1
  import * as dntShim from "../../../_dnt.shims.js";
2
2
  import { getEnv } from "../../platform/compat/process.js";
3
3
  import { INVALID_ARGUMENT, TOKEN_STORAGE_ERROR } from "../../errors/index.js";
4
- import { logger as baseLogger } from "../../utils/index.js";
4
+ import { base64urlEncodeBytes, logger as baseLogger } from "../../utils/index.js";
5
5
  const logger = baseLogger.component("o-auth");
6
6
  /** Buffer before token expiry to trigger proactive refresh (5 minutes). */
7
7
  const TOKEN_REFRESH_BUFFER_MS = 300_000;
@@ -19,11 +19,7 @@ function generateCodeVerifier() {
19
19
  }
20
20
  async function generateCodeChallenge(verifier) {
21
21
  const data = new TextEncoder().encode(verifier);
22
- const hash = await dntShim.crypto.subtle.digest("SHA-256", data);
23
- return btoa(String.fromCharCode(...new Uint8Array(hash)))
24
- .replace(/\+/g, "-")
25
- .replace(/\//g, "_")
26
- .replace(/=+$/, "");
22
+ return base64urlEncodeBytes(new Uint8Array(await dntShim.crypto.subtle.digest("SHA-256", data)));
27
23
  }
28
24
  /** Implement oauth provider. */
29
25
  export class OAuthProvider {
@@ -22,7 +22,6 @@ export declare class GitHubApiClient {
22
22
  private isClientError;
23
23
  private isRateLimitError;
24
24
  private calculateRetryDelay;
25
- private sleep;
26
25
  }
27
26
  export {};
28
27
  //# sourceMappingURL=github-api-client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"github-api-client.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/github/github-api-client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAIL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACxB,MAAM,oBAAoB,CAAC;AAO5B,UAAU,aAAa;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,IAAI,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAID,qBAAa,eAAe;IAId,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4B;IACpD,OAAO,CAAC,aAAa,CAA8B;gBAEtB,MAAM,EAAE,oBAAoB;IAEzD,IAAI,MAAM,IAAI,MAAM,CAEnB;IAEK,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAmBlD,WAAW,CACf,IAAI,EAAE,MAAM,EACZ,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,iBAAiB,GAAG,iBAAiB,EAAE,CAAC;IAY7C,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IASvD,gBAAgB,IAAI,aAAa,GAAG,IAAI;YAI1B,OAAO;IA6CrB,OAAO,CAAC,mBAAmB;IAuB3B,OAAO,CAAC,cAAc;IAkDtB,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,mBAAmB;IAe3B,OAAO,CAAC,KAAK;CAGd"}
1
+ {"version":3,"file":"github-api-client.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/github/github-api-client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAIL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACxB,MAAM,oBAAoB,CAAC;AAO5B,UAAU,aAAa;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,IAAI,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAID,qBAAa,eAAe;IAId,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4B;IACpD,OAAO,CAAC,aAAa,CAA8B;gBAEtB,MAAM,EAAE,oBAAoB;IAEzD,IAAI,MAAM,IAAI,MAAM,CAEnB;IAEK,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAmBlD,WAAW,CACf,IAAI,EAAE,MAAM,EACZ,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,iBAAiB,GAAG,iBAAiB,EAAE,CAAC;IAY7C,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IASvD,gBAAgB,IAAI,aAAa,GAAG,IAAI;IAIxC,OAAO,CAAC,OAAO;IAiDf,OAAO,CAAC,mBAAmB;IAuB3B,OAAO,CAAC,cAAc;IAkDtB,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,mBAAmB;CAa5B"}
@@ -1,4 +1,4 @@
1
- import { createError, toError } from "../../../../errors/index.js";
1
+ import { createError, retryWithBackoff, toError } from "../../../../errors/index.js";
2
2
  import { logger } from "../../../../utils/index.js";
3
3
  import { getGitHubBlobResponseSchema, getGitHubContentsResponseSchema, getGitHubTreeResponseSchema, } from "./schemas/index.js";
4
4
  const LOG_PREFIX = "[GitHubApiClient]";
@@ -42,43 +42,46 @@ export class GitHubApiClient {
42
42
  getRateLimitInfo() {
43
43
  return this.rateLimitInfo;
44
44
  }
45
- async request(endpoint) {
45
+ request(endpoint) {
46
46
  const url = `${this.baseUrl}${endpoint}`;
47
- let lastError = null;
48
- for (let attempt = 1; attempt <= this.config.retry.maxRetries; attempt++) {
49
- try {
50
- const response = await fetch(url, {
51
- headers: {
52
- Authorization: `Bearer ${this.config.token}`,
53
- Accept: "application/vnd.github.v3+json",
54
- "User-Agent": "veryfront-server",
55
- "X-GitHub-Api-Version": "2022-11-28",
56
- },
57
- });
58
- this.updateRateLimitInfo(response);
59
- if (!response.ok) {
60
- const errorBody = await response.text();
61
- throw this.createAPIError(response.status, errorBody, endpoint);
62
- }
63
- return await response.json();
47
+ return retryWithBackoff(async () => {
48
+ const response = await fetch(url, {
49
+ headers: {
50
+ Authorization: `Bearer ${this.config.token}`,
51
+ Accept: "application/vnd.github.v3+json",
52
+ "User-Agent": "veryfront-server",
53
+ "X-GitHub-Api-Version": "2022-11-28",
54
+ },
55
+ });
56
+ this.updateRateLimitInfo(response);
57
+ if (!response.ok) {
58
+ const errorBody = await response.text();
59
+ throw this.createAPIError(response.status, errorBody, endpoint);
64
60
  }
65
- catch (error) {
66
- lastError = error instanceof Error ? error : new Error(String(error));
67
- if (this.isClientError(lastError) && !this.isRateLimitError(lastError)) {
68
- throw lastError;
69
- }
70
- if (attempt >= this.config.retry.maxRetries)
71
- break;
72
- const delay = this.calculateRetryDelay(attempt, lastError);
61
+ return response.json();
62
+ }, {
63
+ // This client's config.retry.maxRetries has always meant TOTAL attempts
64
+ // (the old loop ran `attempt = 1..maxRetries`), unlike the veryfront-api
65
+ // clients where maxRetries means retries after the first try.
66
+ maxAttempts: this.config.retry.maxRetries,
67
+ initialDelay: this.config.retry.initialDelay,
68
+ maxDelay: this.config.retry.maxDelay,
69
+ shouldRetry: (error) => {
70
+ const err = error instanceof Error ? error : new Error(String(error));
71
+ return !(this.isClientError(err) && !this.isRateLimitError(err));
72
+ },
73
+ computeDelay: (attempt, error) => {
74
+ const err = error instanceof Error ? error : new Error(String(error));
75
+ return this.calculateRetryDelay(attempt + 1, err);
76
+ },
77
+ onRetry: ({ error, attempt, delay }) => {
73
78
  logger.warn(`${LOG_PREFIX} Request failed, retrying`, {
74
- attempt,
79
+ attempt: attempt + 1,
75
80
  delay,
76
- error: lastError.message,
81
+ error: error.message,
77
82
  });
78
- await this.sleep(delay);
79
- }
80
- }
81
- throw lastError ?? new Error("Request failed after retries");
83
+ },
84
+ });
82
85
  }
83
86
  updateRateLimitInfo(response) {
84
87
  const limit = response.headers.get("X-RateLimit-Limit");
@@ -157,8 +160,4 @@ export class GitHubApiClient {
157
160
  const delay = Math.min(this.config.retry.initialDelay * Math.pow(2, attempt - 1), this.config.retry.maxDelay);
158
161
  return delay + Math.random() * RETRY_JITTER_MAX_MS;
159
162
  }
160
- // no cleanup needed: one-shot
161
- sleep(ms) {
162
- return new Promise((resolve) => setTimeout(resolve, ms));
163
- }
164
163
  }
@@ -1 +1 @@
1
- {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAgDH;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,EAC1C,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,CAAC,CAAC,CAeZ"}
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiDH;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,CAAC,CAAC,CAWZ"}
@@ -7,6 +7,7 @@
7
7
  * @module platform/adapters/fs/veryfront/retry
8
8
  */
9
9
  import { logger as baseLogger } from "../../../../utils/index.js";
10
+ import { retryWithBackoff } from "../../../../errors/error-handlers.js";
10
11
  const logger = baseLogger.component("fs-retry");
11
12
  /** Delay between retries in milliseconds */
12
13
  const RETRY_DELAY_MS = 500;
@@ -48,18 +49,15 @@ function isTransientError(error) {
48
49
  * Execute an async function with a single retry for transient errors.
49
50
  * Non-transient errors (4xx, validation) are thrown immediately.
50
51
  */
51
- export async function withRetryOnTransient(fn, context) {
52
- try {
53
- return await fn();
54
- }
55
- catch (error) {
56
- if (!isTransientError(error))
57
- throw error;
58
- logger.warn(`${context} — transient error, retrying once`, {
59
- error: error instanceof Error ? error.message : String(error),
60
- });
61
- // no cleanup needed: one-shot
62
- await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY_MS));
63
- return fn();
64
- }
52
+ export function withRetryOnTransient(fn, context) {
53
+ return retryWithBackoff(() => fn(), {
54
+ maxAttempts: 2,
55
+ computeDelay: () => RETRY_DELAY_MS,
56
+ shouldRetry: (error) => isTransientError(error),
57
+ onRetry: ({ error }) => {
58
+ logger.warn(`${context} — transient error, retrying once`, {
59
+ error: error.message,
60
+ });
61
+ },
62
+ });
65
63
  }
@@ -1 +1 @@
1
- {"version":3,"file":"retry-handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/platform/adapters/veryfront-api-client/retry-handler.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,oFAAoF;IACpF,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAKD,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,WAAW,EACxB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,OAAO,CAAC,CA+HlB"}
1
+ {"version":3,"file":"retry-handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/platform/adapters/veryfront-api-client/retry-handler.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,oFAAoF;IACpF,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAaD,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,WAAW,EACxB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,OAAO,CAAC,CA8GlB"}
@@ -1,4 +1,5 @@
1
1
  import { logger } from "../../../utils/index.js";
2
+ import { retryWithBackoff } from "../../../errors/error-handlers.js";
2
3
  import { injectContext, withSpan } from "../../../observability/tracing/otlp-setup.js";
3
4
  import { SpanNames } from "../../../observability/tracing/span-names.js";
4
5
  import { recordApiRequest, recordApiRetry, } from "../../../observability/simple-metrics/metrics-recorder.js";
@@ -7,6 +8,13 @@ const apiLog = logger.component("api");
7
8
  const veryfrontApiClientLog = logger.component("veryfront-api-client");
8
9
  /** Default timeout for API requests (30 seconds) */
9
10
  const DEFAULT_REQUEST_TIMEOUT_MS = 30_000;
11
+ function logTimedOut(url, timeoutMs, attempt) {
12
+ veryfrontApiClientLog.warn("Request timed out", {
13
+ url: url.replace(/token=[^&]+/, "token=***"),
14
+ timeoutMs,
15
+ attempt: attempt + 1,
16
+ });
17
+ }
10
18
  export async function requestWithRetry(url, apiToken, retryConfig, options = {}) {
11
19
  const urlObj = new URL(url);
12
20
  const urlPath = urlObj.pathname;
@@ -14,102 +22,90 @@ export async function requestWithRetry(url, apiToken, retryConfig, options = {})
14
22
  const timeoutMs = options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
15
23
  // Note: We only trace the individual fetch attempts (HTTP_CLIENT_FETCH),
16
24
  // not the outer retry wrapper, to reduce span nesting and trace size.
17
- let lastError = null;
18
- for (let attempt = 0; attempt <= maxRetries; attempt++) {
19
- const controller = new AbortController();
20
- const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
21
- try {
22
- const result = await withSpan(SpanNames.HTTP_CLIENT_FETCH, async () => {
23
- const startTime = performance.now();
24
- const headers = new Headers(options.headers);
25
- headers.set("Authorization", `Bearer ${apiToken}`);
26
- if (!headers.has("Content-Type")) {
27
- headers.set("Content-Type", "application/json");
28
- }
29
- injectContext(headers);
30
- const response = await fetch(url, {
31
- method: options.method ?? "GET",
32
- headers,
33
- body: options.body,
34
- signal: controller.signal,
35
- });
36
- const duration = performance.now() - startTime;
37
- recordApiRequest(response.status);
38
- apiLog.debug("Request completed", {
39
- path: urlPath,
40
- status: response.status,
41
- durationMs: Math.round(duration),
42
- });
43
- if (!response.ok) {
44
- const text = await response.text();
45
- // Optional probes (for example stylesheet candidates) may expect a 404.
46
- // Keep only explicit opt-ins below warn while preserving thrown error semantics.
47
- const isExpected404 = options.expected404 === true && response.status === 404;
48
- // 4xx = client errors (expected, e.g. 404 for missing deno.json) → warn
49
- // 5xx = server errors (unexpected) → error
50
- const logLevel = isExpected404 ? "debug" : response.status >= 500 ? "error" : "warn";
51
- veryfrontApiClientLog[logLevel]("Request failed", {
52
- url: url.replace(/token=[^&]+/, "token=***"),
53
- status: response.status,
54
- statusText: response.statusText,
55
- responseText: text.slice(0, 500),
56
- });
57
- throw API_CLIENT_ERROR.create({
58
- detail: `API request failed: ${response.status} ${response.statusText}`,
59
- status: response.status,
60
- context: { details: { url, responseText: text } },
61
- });
62
- }
63
- const data = options.returnText ? await response.text() : await response.json();
64
- return { data, status: response.status, duration };
65
- }, {
66
- "http.method": options.method ?? "GET",
67
- "http.url": url,
68
- "http.target": urlPath,
69
- "http.host": urlObj.host,
70
- "http.scheme": urlObj.protocol.replace(":", ""),
71
- "http.retry_attempt": attempt,
25
+ const result = await retryWithBackoff((signal, attempt) => {
26
+ return withSpan(SpanNames.HTTP_CLIENT_FETCH, async () => {
27
+ const startTime = performance.now();
28
+ const headers = new Headers(options.headers);
29
+ headers.set("Authorization", `Bearer ${apiToken}`);
30
+ if (!headers.has("Content-Type")) {
31
+ headers.set("Content-Type", "application/json");
32
+ }
33
+ injectContext(headers);
34
+ const response = await fetch(url, {
35
+ method: options.method ?? "GET",
36
+ headers,
37
+ body: options.body,
38
+ signal,
39
+ });
40
+ const duration = performance.now() - startTime;
41
+ recordApiRequest(response.status);
42
+ apiLog.debug("Request completed", {
43
+ path: urlPath,
44
+ status: response.status,
45
+ durationMs: Math.round(duration),
72
46
  });
73
- return result.data;
74
- }
75
- catch (error) {
76
- lastError = error instanceof Error ? error : new Error(String(error));
77
- const isTimeout = lastError.name === "AbortError";
78
- if (isTimeout) {
79
- veryfrontApiClientLog.warn("Request timed out", {
47
+ if (!response.ok) {
48
+ const text = await response.text();
49
+ // Optional probes (for example stylesheet candidates) may expect a 404.
50
+ // Keep only explicit opt-ins below warn while preserving thrown error semantics.
51
+ const isExpected404 = options.expected404 === true && response.status === 404;
52
+ // 4xx = client errors (expected, e.g. 404 for missing deno.json) → warn
53
+ // 5xx = server errors (unexpected) error
54
+ const logLevel = isExpected404 ? "debug" : response.status >= 500 ? "error" : "warn";
55
+ veryfrontApiClientLog[logLevel]("Request failed", {
80
56
  url: url.replace(/token=[^&]+/, "token=***"),
81
- timeoutMs,
82
- attempt: attempt + 1,
57
+ status: response.status,
58
+ statusText: response.statusText,
59
+ responseText: text.slice(0, 500),
60
+ });
61
+ throw API_CLIENT_ERROR.create({
62
+ detail: `API request failed: ${response.status} ${response.statusText}`,
63
+ status: response.status,
64
+ context: { details: { url, responseText: text } },
83
65
  });
84
66
  }
85
- if (error instanceof VeryfrontError && error.slug === "api-client-error") {
86
- const status = error.status;
87
- if (status && status >= 400 && status < 500 && status !== 429) {
88
- throw error;
89
- }
90
- }
91
- if (attempt >= maxRetries) {
92
- break;
93
- }
94
- const delay = Math.min(initialDelay * 2 ** attempt, maxDelay);
67
+ const data = options.returnText ? await response.text() : await response.json();
68
+ return { data, status: response.status, duration };
69
+ }, {
70
+ "http.method": options.method ?? "GET",
71
+ "http.url": url,
72
+ "http.target": urlPath,
73
+ "http.host": urlObj.host,
74
+ "http.scheme": urlObj.protocol.replace(":", ""),
75
+ "http.retry_attempt": attempt,
76
+ });
77
+ }, {
78
+ maxAttempts: maxRetries + 1,
79
+ initialDelay,
80
+ maxDelay,
81
+ timeoutMs,
82
+ shouldRetry: (error) => {
83
+ if (!(error instanceof VeryfrontError) || error.slug !== "api-client-error")
84
+ return true;
85
+ const status = error.status;
86
+ return !status || status < 400 || status >= 500 || status === 429;
87
+ },
88
+ onRetry: ({ error, attempt, delay, isTimeout }) => {
89
+ if (isTimeout)
90
+ logTimedOut(url, timeoutMs, attempt);
95
91
  recordApiRetry();
96
92
  veryfrontApiClientLog.warn("Request failed, retrying...", {
97
93
  attempt: attempt + 1,
98
94
  maxRetries,
99
95
  delay,
100
- error: lastError.message,
96
+ error: error.message,
101
97
  timeout: isTimeout,
102
98
  });
103
- // no cleanup needed: one-shot
104
- await new Promise((resolve) => setTimeout(resolve, delay));
105
- }
106
- finally {
107
- clearTimeout(timeoutId);
108
- }
109
- }
110
- throw API_CLIENT_ERROR.create({
111
- detail: `API request failed after ${maxRetries} retries: ${lastError?.message}`,
112
- cause: lastError ?? undefined,
113
- context: { details: { originalError: lastError } },
99
+ },
100
+ wrapFinalError: (lastError, lastAttempt) => {
101
+ if (lastError.name === "AbortError")
102
+ logTimedOut(url, timeoutMs, lastAttempt);
103
+ return API_CLIENT_ERROR.create({
104
+ detail: `API request failed after ${maxRetries} retries: ${lastError.message}`,
105
+ cause: lastError,
106
+ context: { details: { originalError: lastError } },
107
+ });
108
+ },
114
109
  });
110
+ return result.data;
115
111
  }
@@ -1,3 +1,4 @@
1
+ import { type LogLevelName } from "../utils/logger/core.js";
1
2
  /**
2
3
  * Request context for proxy logging.
3
4
  * Stored in AsyncLocalStorage to propagate through the call stack.
@@ -17,7 +18,7 @@ interface ProxyRequestContext {
17
18
  * All logs within the function will include the request context fields.
18
19
  */
19
20
  export declare function runWithProxyRequestContext<T>(context: ProxyRequestContext, fn: () => T): T;
20
- export type LogLevel = "debug" | "info" | "warn" | "error";
21
+ export type LogLevel = LogLevelName;
21
22
  declare class ProxyLogger {
22
23
  private format;
23
24
  private log;
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/src/proxy/logger.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,UAAU,mBAAmB;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAID;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,EAC1C,OAAO,EAAE,mBAAmB,EAC5B,EAAE,EAAE,MAAM,CAAC,GACV,CAAC,CAEH;AASD,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AA+N3D,cAAM,WAAW;IACf,OAAO,CAAC,MAAM,CAAkB;IAEhC,OAAO,CAAC,GAAG;IA0CX,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI;IAC7C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI;IAmB/E;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB;CAG1D;AAED,cAAM,gBAAgB;IAElB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,YAAY;gBADZ,MAAM,EAAE,WAAW,EACnB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAG/C,OAAO,CAAC,KAAK;IAIb,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI;IAC7C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI;IAwB/E,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB;CAG1D;AAED,eAAO,MAAM,WAAW,aAAoB,CAAC"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/src/proxy/logger.ts"],"names":[],"mappings":"AAKA,OAAO,EAQL,KAAK,YAAY,EAIlB,MAAM,yBAAyB,CAAC;AAEjC;;;GAGG;AACH,UAAU,mBAAmB;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAID;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,EAC1C,OAAO,EAAE,mBAAmB,EAC5B,EAAE,EAAE,MAAM,CAAC,GACV,CAAC,CAEH;AASD,MAAM,MAAM,QAAQ,GAAG,YAAY,CAAC;AA2FpC,cAAM,WAAW;IACf,OAAO,CAAC,MAAM,CAAkB;IAEhC,OAAO,CAAC,GAAG;IA0CX,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI;IAC7C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI;IAmB/E;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB;CAG1D;AAED,cAAM,gBAAgB;IAElB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,YAAY;gBADZ,MAAM,EAAE,WAAW,EACnB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAG/C,OAAO,CAAC,KAAK;IAIb,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI;IAC7C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI;IAwB/E,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB;CAG1D;AAED,eAAO,MAAM,WAAW,aAAoB,CAAC"}
@@ -3,6 +3,7 @@ import { getEnv } from "./env.js";
3
3
  import { getTraceContext } from "./tracing.js";
4
4
  import { AsyncLocalStorage } from "node:async_hooks";
5
5
  import { PROXY_RUNTIME_VERSION } from "./version.js";
6
+ import { ANSI, colorize, formatContextText, formatTimestamp, isRecord, LEVEL_COLORS, LEVEL_GLYPHS, padTag, serializeError, } from "../utils/logger/core.js";
6
7
  const requestContextStore = new AsyncLocalStorage();
7
8
  /**
8
9
  * Run a function with proxy request context.
@@ -31,118 +32,6 @@ const MIN_LOG_LEVEL = (() => {
31
32
  }
32
33
  return "info"; // Default: suppress debug logs
33
34
  })();
34
- // ============================================================================
35
- // INLINED FORMATTING UTILITIES (from src/utils/logger/core.ts)
36
- // These must be kept in sync with core.ts but cannot be imported due to
37
- // Docker build constraints (proxy is built independently).
38
- // ============================================================================
39
- const TAG_WIDTH = 10;
40
- const PREFIX_WIDTH = 23; // timestamp(8) + gap(2) + tag(10) + space(1) + glyph(1) + space(1)
41
- const LEVEL_GLYPHS = {
42
- debug: "·",
43
- info: "●",
44
- warn: "▲",
45
- error: "✖",
46
- };
47
- const ANSI = {
48
- reset: "\u001b[0m",
49
- dim: "\u001b[2m",
50
- gray: "\u001b[90m",
51
- red: "\u001b[31m",
52
- green: "\u001b[32m",
53
- yellow: "\u001b[33m",
54
- cyan: "\u001b[36m",
55
- };
56
- const LEVEL_COLORS = {
57
- debug: ANSI.gray,
58
- info: ANSI.green,
59
- warn: ANSI.yellow,
60
- error: ANSI.red,
61
- };
62
- function padTag(tag) {
63
- if (tag.length >= TAG_WIDTH)
64
- return tag.slice(0, TAG_WIDTH);
65
- return tag.padEnd(TAG_WIDTH, " ");
66
- }
67
- function formatTimestamp(date = new Date()) {
68
- const pad = (value) => String(value).padStart(2, "0");
69
- return `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
70
- }
71
- function colorize(text, color, enable) {
72
- if (!enable || !color)
73
- return text;
74
- return `${color}${text}${ANSI.reset}`;
75
- }
76
- function normalizeText(value) {
77
- return value.replace(/\s+/g, " ");
78
- }
79
- function truncateText(value, maxLength = 80) {
80
- if (value.length <= maxLength)
81
- return value;
82
- return `${value.slice(0, maxLength - 1)}…`;
83
- }
84
- function formatValue(value) {
85
- if (typeof value === "string") {
86
- const trimmed = normalizeText(value);
87
- return /\s/.test(trimmed) ? JSON.stringify(trimmed) : trimmed;
88
- }
89
- if (typeof value === "number" || typeof value === "boolean")
90
- return String(value);
91
- if (value === null)
92
- return "null";
93
- if (value === undefined)
94
- return "undefined";
95
- let text;
96
- try {
97
- text = JSON.stringify(value);
98
- }
99
- catch (_) {
100
- /* expected: non-serializable value */
101
- text = String(value);
102
- }
103
- if (text === undefined)
104
- return "undefined";
105
- return truncateText(normalizeText(text));
106
- }
107
- function formatErrorText(error) {
108
- if (error == null)
109
- return "";
110
- const message = [error.name, error.message].join(": ");
111
- return truncateText(normalizeText(message), 120);
112
- }
113
- function serializeError(error) {
114
- if (error == null)
115
- return undefined;
116
- if (error instanceof Error) {
117
- const serialized = {
118
- name: error.name,
119
- message: error.message,
120
- };
121
- if (error.stack)
122
- serialized.stack = error.stack;
123
- return serialized;
124
- }
125
- return { name: "UnknownError", message: String(error) };
126
- }
127
- function formatContextText(context, error, enableColor) {
128
- const entries = [];
129
- for (const [key, value] of Object.entries(context)) {
130
- entries.push(`${key}=${formatValue(value)}`);
131
- }
132
- const errorText = formatErrorText(error);
133
- if (errorText)
134
- entries.push(`err=${errorText}`);
135
- if (entries.length === 0)
136
- return "";
137
- const coloredText = colorize(entries.join(" "), ANSI.dim, enableColor);
138
- return `\n${" ".repeat(PREFIX_WIDTH)}${coloredText}`;
139
- }
140
- function isRecord(value) {
141
- return typeof value === "object" && value !== null && !Array.isArray(value);
142
- }
143
- // ============================================================================
144
- // END INLINED FORMATTING UTILITIES
145
- // ============================================================================
146
35
  function isTty() {
147
36
  try {
148
37
  if (typeof dntShim.Deno !== "undefined" && typeof dntShim.Deno.stdout?.isTerminal === "function") {
@@ -1 +1 @@
1
- {"version":3,"file":"routing-invalidation-redis.d.ts","sourceRoot":"","sources":["../../../src/src/proxy/routing-invalidation-redis.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,6BAA6B,EAC7B,iCAAiC,EAElC,MAAM,2BAA2B,CAAC;AAgBnC,KAAK,aAAa,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAGhE,MAAM,WAAW,8BAA8B;IAC7C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3D,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACrE,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,OAAO,IAAI,IAAI,CAAC;IAChB,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC;CAClE;AAED,UAAU,yBAAyB;IACjC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC9E;AAED,MAAM,WAAW,2BAA4B,SAAQ,iCAAiC;IACpF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,UAAU,uCAAuC;IAC/C,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,YAAY,CAAC,EAAE,CACb,QAAQ,EAAE,MAAM,KACb,8BAA8B,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAAC;IAC9E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC,YAAY,EAAE,CAAC,KAAK,EAAE,6BAA6B,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAmPD,wBAAsB,gCAAgC,CACpD,OAAO,EAAE,uCAAuC,GAC/C,OAAO,CAAC,2BAA2B,GAAG,IAAI,CAAC,CAgP7C"}
1
+ {"version":3,"file":"routing-invalidation-redis.d.ts","sourceRoot":"","sources":["../../../src/src/proxy/routing-invalidation-redis.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,6BAA6B,EAC7B,iCAAiC,EAElC,MAAM,2BAA2B,CAAC;AAgBnC,KAAK,aAAa,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAGhE,MAAM,WAAW,8BAA8B;IAC7C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3D,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACrE,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,OAAO,IAAI,IAAI,CAAC;IAChB,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC;CAClE;AAED,UAAU,yBAAyB;IACjC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC9E;AAED,MAAM,WAAW,2BAA4B,SAAQ,iCAAiC;IACpF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,UAAU,uCAAuC;IAC/C,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,YAAY,CAAC,EAAE,CACb,QAAQ,EAAE,MAAM,KACb,8BAA8B,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAAC;IAC9E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC,YAAY,EAAE,CAAC,KAAK,EAAE,6BAA6B,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAgPD,wBAAsB,gCAAgC,CACpD,OAAO,EAAE,uCAAuC,GAC/C,OAAO,CAAC,2BAA2B,GAAG,IAAI,CAAC,CAgP7C"}
@@ -1,6 +1,7 @@
1
1
  import * as dntShim from "../../_dnt.shims.js";
2
2
  import { getRedisModule } from "../platform/adapters/redis/modules.js";
3
3
  import { getEnv } from "../platform/compat/process.js";
4
+ import { base64urlEncodeBytes } from "../utils/index.js";
4
5
  const ROUTING_INVALIDATION_CHANNEL = "vf-proxy-routing-invalidations-v1";
5
6
  const ROUTING_INVALIDATION_ACK_PREFIX = `${ROUTING_INVALIDATION_CHANNEL}:ack:`;
6
7
  const DEFAULT_ACKNOWLEDGEMENT_TIMEOUT_MS = 1_500;
@@ -54,10 +55,6 @@ function signatureInput(domain, issuedAtMs, payload) {
54
55
  const encoded = new TextEncoder().encode(`${signatureDomainPrefix(domain)}\0${issuedAtMs}\0${payload}`);
55
56
  return encoded.buffer.slice(encoded.byteOffset, encoded.byteOffset + encoded.byteLength);
56
57
  }
57
- function base64UrlEncode(bytes) {
58
- const binary = Array.from(new Uint8Array(bytes), (byte) => String.fromCharCode(byte)).join("");
59
- return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/u, "");
60
- }
61
58
  function base64UrlDecode(value) {
62
59
  if (!/^[A-Za-z0-9_-]+$/u.test(value))
63
60
  return null;
@@ -73,7 +70,7 @@ async function createHmacKey(secret) {
73
70
  return dntShim.crypto.subtle.importKey("raw", new TextEncoder().encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign", "verify"]);
74
71
  }
75
72
  async function signPayload(key, domain, issuedAtMs, payload) {
76
- return base64UrlEncode(await dntShim.crypto.subtle.sign("HMAC", key, signatureInput(domain, issuedAtMs, payload)));
73
+ return base64urlEncodeBytes(new Uint8Array(await dntShim.crypto.subtle.sign("HMAC", key, signatureInput(domain, issuedAtMs, payload))));
77
74
  }
78
75
  async function verifyPayloadSignature(key, domain, issuedAtMs, payload, signature) {
79
76
  const signatureBytes = base64UrlDecode(signature);
@@ -1 +1 @@
1
- {"version":3,"file":"server-resolver.d.ts","sourceRoot":"","sources":["../../../src/src/proxy/server-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA0BH,qBAAa,cAAc;IAMvB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,UAAU;IARpB,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,OAAO,CAAsD;IACrE,OAAO,CAAC,YAAY,CAA+C;gBAGzD,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,UAAU,GAAE,MAAe;IAQrC;;OAEG;IACG,OAAO,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAwCxE,KAAK,IAAI,IAAI;IAQb;;;;OAIG;YACW,WAAW;IAmCzB,OAAO,CAAC,OAAO;CAMhB"}
1
+ {"version":3,"file":"server-resolver.d.ts","sourceRoot":"","sources":["../../../src/src/proxy/server-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA2BH,qBAAa,cAAc;IAMvB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,UAAU;IARpB,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,OAAO,CAAsD;IACrE,OAAO,CAAC,YAAY,CAA+C;gBAGzD,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,UAAU,GAAE,MAAe;IAQrC;;OAEG;IACG,OAAO,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAwCxE,KAAK,IAAI,IAAI;IAQb;;;;OAIG;YACW,WAAW;IAmCzB,OAAO,CAAC,OAAO;CAMhB"}
@@ -9,6 +9,7 @@
9
9
  */
10
10
  import { proxyLogger } from "./logger.js";
11
11
  import { unrefTimer } from "../platform/compat/process.js";
12
+ import { encodeBase64 } from "../utils/index.js";
12
13
  const logger = proxyLogger.child({ module: "server-resolver" });
13
14
  /** Thrown when the API call fails (network error, non-OK status, parse error). */
14
15
  class ServerResolverError extends Error {
@@ -91,7 +92,7 @@ export class ServerResolver {
91
92
  const url = `${this.apiInternalUrl}/internal/environment-server?environmentId=${encodeURIComponent(environmentId)}`;
92
93
  const headers = { Accept: "application/json" };
93
94
  if (this.apiUser && this.apiPass) {
94
- headers.Authorization = `Basic ${btoa(`${this.apiUser}:${this.apiPass}`)}`;
95
+ headers.Authorization = `Basic ${encodeBase64(`${this.apiUser}:${this.apiPass}`)}`;
95
96
  }
96
97
  let response;
97
98
  try {