@palbase/web 7.3.0 → 7.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/internal.js CHANGED
@@ -6,8 +6,8 @@ import {
6
6
  createBoundClient,
7
7
  getRuntime,
8
8
  onConfigured
9
- } from "./chunk-YBURINUN.js";
10
- import "./chunk-ACCJV6FV.js";
9
+ } from "./chunk-TQAQR3OP.js";
10
+ import "./chunk-HKZVA3I3.js";
11
11
  import "./chunk-CFDU23TB.js";
12
12
  import "./chunk-PZ5AY32C.js";
13
13
  export {
@@ -56,6 +56,54 @@ var PalbaseError = class extends Error {
56
56
  this.details = details;
57
57
  }
58
58
  };
59
+ var POW_CHALLENGE_ID_HEADER = "X-PoW-Challenge-ID";
60
+ var POW_NONCE_HEADER = "X-PoW-Nonce";
61
+ function asPowChallenge(details) {
62
+ if (typeof details !== "object" || details === null) return null;
63
+ const env = details;
64
+ if (env.error !== "pow_required") return null;
65
+ const c = env.challenge;
66
+ if (typeof c !== "object" || c === null) return null;
67
+ const { id, prefix, difficulty } = c;
68
+ if (typeof id !== "string" || typeof prefix !== "string") return null;
69
+ if (typeof difficulty !== "number" || !Number.isInteger(difficulty) || difficulty < 0) return null;
70
+ return { id, prefix, difficulty };
71
+ }
72
+ var encoder = new TextEncoder();
73
+ function leadingZeroBits(hash) {
74
+ let bits = 0;
75
+ for (const byte of hash) {
76
+ if (byte === 0) {
77
+ bits += 8;
78
+ continue;
79
+ }
80
+ return bits + Math.clz32(byte) - 24;
81
+ }
82
+ return bits;
83
+ }
84
+ var MAX_POW_DIFFICULTY = 24;
85
+ function powBudget(difficulty) {
86
+ return 8 * 2 ** difficulty;
87
+ }
88
+ async function solvePowChallenge(challenge, maxIterations = powBudget(challenge.difficulty)) {
89
+ if (challenge.difficulty > MAX_POW_DIFFICULTY) {
90
+ throw new Error(
91
+ `proof-of-work: refusing difficulty ${challenge.difficulty}; this client attempts at most ${MAX_POW_DIFFICULTY}, which is the highest a Palbase stack issues`
92
+ );
93
+ }
94
+ for (let nonce = 0; nonce < maxIterations; nonce++) {
95
+ const digest = await crypto.subtle.digest("SHA-256", encoder.encode(challenge.prefix + nonce));
96
+ if (leadingZeroBits(new Uint8Array(digest)) >= challenge.difficulty) {
97
+ return {
98
+ [POW_CHALLENGE_ID_HEADER]: challenge.id,
99
+ [POW_NONCE_HEADER]: String(nonce)
100
+ };
101
+ }
102
+ }
103
+ throw new Error(
104
+ `proof-of-work: no nonce found for difficulty ${challenge.difficulty} within ${maxIterations} attempts`
105
+ );
106
+ }
59
107
  function detectPlatform() {
60
108
  if (typeof Deno !== "undefined") {
61
109
  return "deno";
@@ -192,9 +240,9 @@ var HttpClient = class _HttpClient {
192
240
  }
193
241
  return headers;
194
242
  }
195
- async executeWithRetry(method, path, options, attempt) {
243
+ async executeWithRetry(method, path, options, attempt, earned) {
196
244
  const url = `${this.getBaseUrl()}${path}`;
197
- const headers = this.buildHeaders(options);
245
+ const headers = { ...this.buildHeaders(options), ...earned };
198
246
  for (const interceptor of this.interceptors) {
199
247
  await interceptor({ headers, method, path });
200
248
  }
@@ -213,7 +261,7 @@ var HttpClient = class _HttpClient {
213
261
  if (attempt < MAX_RETRIES - 1) {
214
262
  const backoff = INITIAL_BACKOFF_MS * 2 ** attempt;
215
263
  await this.delay(backoff);
216
- return this.executeWithRetry(method, path, options, attempt + 1);
264
+ return this.executeWithRetry(method, path, options, attempt + 1, earned);
217
265
  }
218
266
  throw new PalbaseError(
219
267
  "network_error",
@@ -227,7 +275,7 @@ var HttpClient = class _HttpClient {
227
275
  const parsed = retryAfter ? Number.parseInt(retryAfter, 10) : Number.NaN;
228
276
  const delayMs = Number.isNaN(parsed) ? INITIAL_BACKOFF_MS * 2 ** attempt : Math.min(parsed * 1e3, MAX_RETRY_DELAY_MS);
229
277
  await this.delay(delayMs);
230
- return this.executeWithRetry(method, path, options, attempt + 1);
278
+ return this.executeWithRetry(method, path, options, attempt + 1, earned);
231
279
  }
232
280
  }
233
281
  let data = null;
@@ -241,6 +289,18 @@ var HttpClient = class _HttpClient {
241
289
  errorBody = body;
242
290
  }
243
291
  }
292
+ if (response.status === 403 && !earned) {
293
+ const challenge = asPowChallenge(errorBody);
294
+ if (challenge) {
295
+ return this.executeWithRetry(
296
+ method,
297
+ path,
298
+ options,
299
+ attempt,
300
+ await solvePowChallenge(challenge)
301
+ );
302
+ }
303
+ }
244
304
  if (!response.ok) {
245
305
  return {
246
306
  data: null,
@@ -458,47 +518,6 @@ function redactUrl(rawUrl) {
458
518
  return path.split("/").map((seg2) => isSensitiveSegment(seg2) ? ":id" : seg2).join("/");
459
519
  }
460
520
 
461
- // src/pow.ts
462
- var POW_CHALLENGE_ID_HEADER = "X-PoW-Challenge-ID";
463
- var POW_NONCE_HEADER = "X-PoW-Nonce";
464
- function asPowChallenge(details) {
465
- if (typeof details !== "object" || details === null) return null;
466
- const env = details;
467
- if (env.error !== "pow_required") return null;
468
- const c = env.challenge;
469
- if (typeof c !== "object" || c === null) return null;
470
- const { id, prefix, difficulty } = c;
471
- if (typeof id !== "string" || typeof prefix !== "string") return null;
472
- if (typeof difficulty !== "number" || !Number.isInteger(difficulty) || difficulty < 0) return null;
473
- return { id, prefix, difficulty };
474
- }
475
- var encoder = new TextEncoder();
476
- function leadingZeroBits(hash) {
477
- let bits = 0;
478
- for (const byte of hash) {
479
- if (byte === 0) {
480
- bits += 8;
481
- continue;
482
- }
483
- return bits + Math.clz32(byte) - 24;
484
- }
485
- return bits;
486
- }
487
- async function solvePowChallenge(challenge, maxIterations = 1 << 24) {
488
- for (let nonce = 0; nonce < maxIterations; nonce++) {
489
- const digest = await crypto.subtle.digest("SHA-256", encoder.encode(challenge.prefix + nonce));
490
- if (leadingZeroBits(new Uint8Array(digest)) >= challenge.difficulty) {
491
- return {
492
- [POW_CHALLENGE_ID_HEADER]: challenge.id,
493
- [POW_NONCE_HEADER]: String(nonce)
494
- };
495
- }
496
- }
497
- throw new Error(
498
- `proof-of-work: no nonce found for difficulty ${challenge.difficulty} within ${maxIterations} attempts`
499
- );
500
- }
501
-
502
521
  // src/request.ts
503
522
  var MUTATING = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"]);
504
523
  var PERF_EXCLUDED_PREFIX = "/v1/analytics/";
@@ -9145,7 +9164,7 @@ function defaultSessionStorage(key) {
9145
9164
  }
9146
9165
 
9147
9166
  // src/version.ts
9148
- var VERSION = "7.3.0";
9167
+ var VERSION = "7.3.2";
9149
9168
 
9150
9169
  // src/runtime.ts
9151
9170
  function buildRuntime(config) {