@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/index.d.cts CHANGED
@@ -206,6 +206,6 @@ interface MlsGlue {
206
206
  */
207
207
  declare function initMls(): Promise<MlsGlue>;
208
208
 
209
- declare const VERSION = "7.3.0";
209
+ declare const VERSION = "7.3.2";
210
210
 
211
211
  export { VERSION, initMls };
package/dist/index.d.ts CHANGED
@@ -206,6 +206,6 @@ interface MlsGlue {
206
206
  */
207
207
  declare function initMls(): Promise<MlsGlue>;
208
208
 
209
- declare const VERSION = "7.3.0";
209
+ declare const VERSION = "7.3.2";
210
210
 
211
211
  export { VERSION, initMls };
package/dist/index.js CHANGED
@@ -11,11 +11,11 @@ import {
11
11
  localStorageSessionStorage,
12
12
  memorySessionStorage,
13
13
  pb
14
- } from "./chunk-YBURINUN.js";
14
+ } from "./chunk-TQAQR3OP.js";
15
15
  import {
16
16
  BackendError,
17
17
  isBackendError
18
- } from "./chunk-ACCJV6FV.js";
18
+ } from "./chunk-HKZVA3I3.js";
19
19
  import "./chunk-CFDU23TB.js";
20
20
  import "./chunk-PZ5AY32C.js";
21
21
  export {
package/dist/internal.cjs CHANGED
@@ -54,6 +54,54 @@ var PalbaseError = class extends Error {
54
54
  this.details = details;
55
55
  }
56
56
  };
57
+ var POW_CHALLENGE_ID_HEADER = "X-PoW-Challenge-ID";
58
+ var POW_NONCE_HEADER = "X-PoW-Nonce";
59
+ function asPowChallenge(details) {
60
+ if (typeof details !== "object" || details === null) return null;
61
+ const env = details;
62
+ if (env.error !== "pow_required") return null;
63
+ const c = env.challenge;
64
+ if (typeof c !== "object" || c === null) return null;
65
+ const { id, prefix, difficulty } = c;
66
+ if (typeof id !== "string" || typeof prefix !== "string") return null;
67
+ if (typeof difficulty !== "number" || !Number.isInteger(difficulty) || difficulty < 0) return null;
68
+ return { id, prefix, difficulty };
69
+ }
70
+ var encoder = new TextEncoder();
71
+ function leadingZeroBits(hash) {
72
+ let bits = 0;
73
+ for (const byte of hash) {
74
+ if (byte === 0) {
75
+ bits += 8;
76
+ continue;
77
+ }
78
+ return bits + Math.clz32(byte) - 24;
79
+ }
80
+ return bits;
81
+ }
82
+ var MAX_POW_DIFFICULTY = 24;
83
+ function powBudget(difficulty) {
84
+ return 8 * 2 ** difficulty;
85
+ }
86
+ async function solvePowChallenge(challenge, maxIterations = powBudget(challenge.difficulty)) {
87
+ if (challenge.difficulty > MAX_POW_DIFFICULTY) {
88
+ throw new Error(
89
+ `proof-of-work: refusing difficulty ${challenge.difficulty}; this client attempts at most ${MAX_POW_DIFFICULTY}, which is the highest a Palbase stack issues`
90
+ );
91
+ }
92
+ for (let nonce = 0; nonce < maxIterations; nonce++) {
93
+ const digest = await crypto.subtle.digest("SHA-256", encoder.encode(challenge.prefix + nonce));
94
+ if (leadingZeroBits(new Uint8Array(digest)) >= challenge.difficulty) {
95
+ return {
96
+ [POW_CHALLENGE_ID_HEADER]: challenge.id,
97
+ [POW_NONCE_HEADER]: String(nonce)
98
+ };
99
+ }
100
+ }
101
+ throw new Error(
102
+ `proof-of-work: no nonce found for difficulty ${challenge.difficulty} within ${maxIterations} attempts`
103
+ );
104
+ }
57
105
  function detectPlatform() {
58
106
  if (typeof Deno !== "undefined") {
59
107
  return "deno";
@@ -190,9 +238,9 @@ var HttpClient = class _HttpClient {
190
238
  }
191
239
  return headers;
192
240
  }
193
- async executeWithRetry(method, path, options, attempt) {
241
+ async executeWithRetry(method, path, options, attempt, earned) {
194
242
  const url = `${this.getBaseUrl()}${path}`;
195
- const headers = this.buildHeaders(options);
243
+ const headers = { ...this.buildHeaders(options), ...earned };
196
244
  for (const interceptor of this.interceptors) {
197
245
  await interceptor({ headers, method, path });
198
246
  }
@@ -211,7 +259,7 @@ var HttpClient = class _HttpClient {
211
259
  if (attempt < MAX_RETRIES - 1) {
212
260
  const backoff = INITIAL_BACKOFF_MS * 2 ** attempt;
213
261
  await this.delay(backoff);
214
- return this.executeWithRetry(method, path, options, attempt + 1);
262
+ return this.executeWithRetry(method, path, options, attempt + 1, earned);
215
263
  }
216
264
  throw new PalbaseError(
217
265
  "network_error",
@@ -225,7 +273,7 @@ var HttpClient = class _HttpClient {
225
273
  const parsed = retryAfter ? Number.parseInt(retryAfter, 10) : Number.NaN;
226
274
  const delayMs = Number.isNaN(parsed) ? INITIAL_BACKOFF_MS * 2 ** attempt : Math.min(parsed * 1e3, MAX_RETRY_DELAY_MS);
227
275
  await this.delay(delayMs);
228
- return this.executeWithRetry(method, path, options, attempt + 1);
276
+ return this.executeWithRetry(method, path, options, attempt + 1, earned);
229
277
  }
230
278
  }
231
279
  let data = null;
@@ -239,6 +287,18 @@ var HttpClient = class _HttpClient {
239
287
  errorBody = body;
240
288
  }
241
289
  }
290
+ if (response.status === 403 && !earned) {
291
+ const challenge = asPowChallenge(errorBody);
292
+ if (challenge) {
293
+ return this.executeWithRetry(
294
+ method,
295
+ path,
296
+ options,
297
+ attempt,
298
+ await solvePowChallenge(challenge)
299
+ );
300
+ }
301
+ }
242
302
  if (!response.ok) {
243
303
  return {
244
304
  data: null,
@@ -456,47 +516,6 @@ function redactUrl(rawUrl) {
456
516
  return path.split("/").map((seg2) => isSensitiveSegment(seg2) ? ":id" : seg2).join("/");
457
517
  }
458
518
 
459
- // src/pow.ts
460
- var POW_CHALLENGE_ID_HEADER = "X-PoW-Challenge-ID";
461
- var POW_NONCE_HEADER = "X-PoW-Nonce";
462
- function asPowChallenge(details) {
463
- if (typeof details !== "object" || details === null) return null;
464
- const env = details;
465
- if (env.error !== "pow_required") return null;
466
- const c = env.challenge;
467
- if (typeof c !== "object" || c === null) return null;
468
- const { id, prefix, difficulty } = c;
469
- if (typeof id !== "string" || typeof prefix !== "string") return null;
470
- if (typeof difficulty !== "number" || !Number.isInteger(difficulty) || difficulty < 0) return null;
471
- return { id, prefix, difficulty };
472
- }
473
- var encoder = new TextEncoder();
474
- function leadingZeroBits(hash) {
475
- let bits = 0;
476
- for (const byte of hash) {
477
- if (byte === 0) {
478
- bits += 8;
479
- continue;
480
- }
481
- return bits + Math.clz32(byte) - 24;
482
- }
483
- return bits;
484
- }
485
- async function solvePowChallenge(challenge, maxIterations = 1 << 24) {
486
- for (let nonce = 0; nonce < maxIterations; nonce++) {
487
- const digest = await crypto.subtle.digest("SHA-256", encoder.encode(challenge.prefix + nonce));
488
- if (leadingZeroBits(new Uint8Array(digest)) >= challenge.difficulty) {
489
- return {
490
- [POW_CHALLENGE_ID_HEADER]: challenge.id,
491
- [POW_NONCE_HEADER]: String(nonce)
492
- };
493
- }
494
- }
495
- throw new Error(
496
- `proof-of-work: no nonce found for difficulty ${challenge.difficulty} within ${maxIterations} attempts`
497
- );
498
- }
499
-
500
519
  // src/request.ts
501
520
  var MUTATING = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"]);
502
521
  var PERF_EXCLUDED_PREFIX = "/v1/analytics/";
@@ -9345,7 +9364,7 @@ function defaultSessionStorage(key) {
9345
9364
  }
9346
9365
 
9347
9366
  // src/version.ts
9348
- var VERSION = "7.3.0";
9367
+ var VERSION = "7.3.2";
9349
9368
 
9350
9369
  // src/runtime.ts
9351
9370
  function buildRuntime(config) {