@ferricstore/ferricstore 0.11.9 → 0.11.10

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.js CHANGED
@@ -1456,6 +1456,7 @@ var neverAutoBatchCommandPrefixes = /* @__PURE__ */ new Set([
1456
1456
  "BLPOP",
1457
1457
  "BRPOP",
1458
1458
  "BRPOPLPUSH",
1459
+ "BZMPOP",
1459
1460
  "BZPOPMAX",
1460
1461
  "BZPOPMIN",
1461
1462
  "CLIENT",
@@ -1567,6 +1568,9 @@ var connectionBlockingCommands = /* @__PURE__ */ new Set([
1567
1568
  "BLPOP",
1568
1569
  "BRPOP",
1569
1570
  "BRPOPLPUSH",
1571
+ "BZMPOP",
1572
+ "BZPOPMAX",
1573
+ "BZPOPMIN",
1570
1574
  "XREAD",
1571
1575
  "XREADGROUP"
1572
1576
  ]);
@@ -2435,8 +2439,10 @@ function serverBlockMetadata(args) {
2435
2439
  serverBlockMs = blockDurationMs(args[3], 1e3);
2436
2440
  } else if (command === "BLMOVE" && args.length >= 6) {
2437
2441
  serverBlockMs = blockDurationMs(args[args.length - 1], 1e3);
2438
- } else if (command === "BLMPOP" && args.length >= 2) {
2442
+ } else if ((command === "BLMPOP" || command === "BZMPOP") && args.length >= 2) {
2439
2443
  serverBlockMs = blockDurationMs(args[1], 1e3);
2444
+ } else if ((command === "BZPOPMAX" || command === "BZPOPMIN") && args.length >= 3) {
2445
+ serverBlockMs = blockDurationMs(args[args.length - 1], 1e3);
2440
2446
  } else if (command === "XREAD" || command === "XREADGROUP") {
2441
2447
  serverBlockMs = optionBlockDurationMs(args, ["BLOCK"], "STREAMS");
2442
2448
  } else if (command === "WAIT" && args.length === 3) {
@@ -7496,6 +7502,24 @@ async function executeIndividually(host, commands, laneId, options) {
7496
7502
  }, commands, options);
7497
7503
  }
7498
7504
 
7505
+ // src/server-response-timeout.ts
7506
+ function serverResponseTimeoutMs(requestTimeoutMs, serverBlockMs) {
7507
+ if (serverBlockMs == null) return requestTimeoutMs;
7508
+ if (serverBlockMs === 0) return void 0;
7509
+ return saturatingAdd(requestTimeoutMs, serverBlockMs);
7510
+ }
7511
+ function combinedServerBlockMs(values) {
7512
+ let total;
7513
+ for (const value of values) {
7514
+ if (value === 0) return 0;
7515
+ if (value != null) total = saturatingAdd(total ?? 0, value);
7516
+ }
7517
+ return total;
7518
+ }
7519
+ function saturatingAdd(left, right) {
7520
+ return Math.min(Number.MAX_SAFE_INTEGER, left + right);
7521
+ }
7522
+
7499
7523
  // src/native-pending-timeout.ts
7500
7524
  function timeoutNativePendingRequest(operations, requestId, timeoutMs) {
7501
7525
  const pending = operations.getPending(requestId);
@@ -7524,10 +7548,7 @@ function timeoutNativePendingRequest(operations, requestId, timeoutMs) {
7524
7548
  pending.reject(new RequestTimeoutError(timeoutMs, "possibly_sent"));
7525
7549
  }
7526
7550
  function nativeResponseTimeoutMs(command, requestTimeoutMs) {
7527
- const blockMs = command.serverBlockMs;
7528
- if (blockMs == null) return requestTimeoutMs;
7529
- if (blockMs === 0) return void 0;
7530
- return Math.min(Number.MAX_SAFE_INTEGER, requestTimeoutMs + blockMs);
7551
+ return serverResponseTimeoutMs(requestTimeoutMs, command.serverBlockMs);
7531
7552
  }
7532
7553
 
7533
7554
  // src/native-chunk-assembler.ts
@@ -8555,12 +8576,14 @@ var NativeAdapter = class _NativeAdapter {
8555
8576
  };
8556
8577
 
8557
8578
  // src/http-command-policy.ts
8579
+ import { Buffer as Buffer33 } from "buffer";
8558
8580
  var nativeOnlyCommands = /* @__PURE__ */ new Set([
8559
8581
  "AUTH",
8560
8582
  "BACKPRESSURE",
8561
8583
  "CLIENT",
8562
8584
  "CLIENT.INFO",
8563
8585
  "CLIENT.SETNAME",
8586
+ "COMMAND_EXEC",
8564
8587
  "EVENT",
8565
8588
  "GOAWAY",
8566
8589
  "HELLO",
@@ -8576,48 +8599,67 @@ var nativeOnlyCommands = /* @__PURE__ */ new Set([
8576
8599
  "WINDOW_UPDATE"
8577
8600
  ]);
8578
8601
  var sessionOnlyCommands = /* @__PURE__ */ new Set([
8602
+ "ASKING",
8579
8603
  "AUTH",
8580
- "BLMOVE",
8581
- "BLMPOP",
8582
- "BLPOP",
8583
- "BRPOP",
8584
8604
  "CLIENT",
8585
8605
  "DISCARD",
8586
8606
  "EXEC",
8587
8607
  "HELLO",
8608
+ "MONITOR",
8588
8609
  "MULTI",
8589
8610
  "PSUBSCRIBE",
8611
+ "PSYNC",
8590
8612
  "PUNSUBSCRIBE",
8591
8613
  "QUIT",
8614
+ "READONLY",
8615
+ "READWRITE",
8616
+ "REPLCONF",
8617
+ "RESET",
8618
+ "SANDBOX",
8592
8619
  "SELECT",
8620
+ "SSUBSCRIBE",
8593
8621
  "SUBSCRIBE",
8622
+ "SUNSUBSCRIBE",
8623
+ "SYNC",
8594
8624
  "UNSUBSCRIBE",
8595
8625
  "UNWATCH",
8596
- "WATCH",
8597
- "XREAD",
8598
- "XREADGROUP"
8626
+ "WATCH"
8599
8627
  ]);
8600
8628
  function httpCommandDisposition(name) {
8601
8629
  const normalized = name.toUpperCase();
8602
8630
  return nativeOnlyCommands.has(normalized) || sessionOnlyCommands.has(normalized) ? "native_only" : "supported";
8603
8631
  }
8604
8632
  function assertHTTPCommandSupported(name) {
8605
- if (typeof name !== "string" || name === "") throw new TypeError("HTTP command must have a name");
8606
- if (sessionOnlyCommands.has(name.toUpperCase())) {
8607
- throw new Error(`${name.toUpperCase()} requires a persistent native TCP session`);
8633
+ const normalized = normalizedCommandName(name);
8634
+ if (normalized == null || normalized === "") throw new TypeError("HTTP command must have a name");
8635
+ if (sessionOnlyCommands.has(normalized)) {
8636
+ throw new InvalidCommandError(`${normalized} requires a persistent native TCP session`);
8637
+ }
8638
+ if (nativeOnlyCommands.has(normalized)) {
8639
+ throw new InvalidCommandError(`${normalized} is a native TCP transport control command`);
8640
+ }
8641
+ }
8642
+ function normalizedCommandName(value) {
8643
+ if (typeof value === "string") return value.toUpperCase();
8644
+ if (Buffer33.isBuffer(value) || value instanceof Uint8Array) {
8645
+ return Buffer33.from(value).toString("utf8").toUpperCase();
8608
8646
  }
8647
+ return void 0;
8609
8648
  }
8610
8649
 
8611
8650
  // src/http-envelope.ts
8612
- import { Buffer as Buffer33 } from "buffer";
8651
+ import { Buffer as Buffer34 } from "buffer";
8613
8652
  var encoding = "ferricstore-json-v1";
8614
8653
  var bytesMarker = "$ferricstore_bytes";
8615
8654
  var mapMarker = "$ferricstore_map";
8616
8655
  var maxDepth = 64;
8617
- function encodeHTTPCommands(commands) {
8618
- return Buffer33.from(JSON.stringify({
8656
+ var bytesMarkerBaseBytes = Buffer34.byteLength(bytesMarker) + 7;
8657
+ var mapMarkerBaseBytes = Buffer34.byteLength(mapMarker) + 7;
8658
+ function encodeHTTPCommands(commands, maxBytes = Number.MAX_SAFE_INTEGER) {
8659
+ const budget = { remaining: maxBytes };
8660
+ return Buffer34.from(JSON.stringify({
8619
8661
  encoding,
8620
- commands: commands.map((command) => encodeValue(command, 0))
8662
+ commands: commands.map((command) => encodeValue(command, 0, budget))
8621
8663
  }));
8622
8664
  }
8623
8665
  function decodeHTTPEnvelope(source) {
@@ -8630,30 +8672,55 @@ function decodeHTTPEnvelope(source) {
8630
8672
  if (!isRecord(parsed)) throw new TypeError("HTTP command response must be an object");
8631
8673
  return decodePlainRecord(parsed, 0);
8632
8674
  }
8633
- function encodeValue(value, depth) {
8675
+ function encodeValue(value, depth, budget) {
8634
8676
  if (depth > maxDepth) throw new TypeError("HTTP command value exceeds maximum depth");
8635
- if (value == null || typeof value === "string" || typeof value === "boolean") return value;
8636
- if (Buffer33.isBuffer(value) || value instanceof Uint8Array) {
8637
- return { [bytesMarker]: Buffer33.from(value).toString("base64") };
8677
+ if (value == null) {
8678
+ consumeBudget(budget, 1);
8679
+ return value;
8680
+ }
8681
+ if (typeof value === "string") {
8682
+ consumeBudget(budget, Buffer34.byteLength(value) + 2);
8683
+ return value;
8684
+ }
8685
+ if (typeof value === "boolean") {
8686
+ consumeBudget(budget, 1);
8687
+ return value;
8688
+ }
8689
+ if (Buffer34.isBuffer(value) || value instanceof Uint8Array) {
8690
+ consumeBudget(budget, bytesMarkerBaseBytes + 4 * Math.ceil(value.byteLength / 3));
8691
+ return { [bytesMarker]: Buffer34.from(value).toString("base64") };
8638
8692
  }
8639
8693
  if (typeof value === "number") {
8640
8694
  if (!Number.isFinite(value)) throw new TypeError("HTTP command numbers must be finite");
8695
+ consumeBudget(budget, 1);
8641
8696
  return value;
8642
8697
  }
8643
8698
  if (typeof value === "bigint") {
8644
- return value >= BigInt(Number.MIN_SAFE_INTEGER) && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : value.toString();
8699
+ const encoded = value >= BigInt(Number.MIN_SAFE_INTEGER) && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : value.toString();
8700
+ consumeBudget(budget, typeof encoded === "number" ? 1 : Buffer34.byteLength(encoded) + 2);
8701
+ return encoded;
8702
+ }
8703
+ if (Array.isArray(value)) {
8704
+ consumeBudget(budget, 2 + Math.max(0, value.length - 1));
8705
+ return denseArray(value, depth + 1, (item, itemDepth) => encodeValue(item, itemDepth, budget));
8645
8706
  }
8646
- if (Array.isArray(value)) return denseArray(value, depth + 1, encodeValue);
8647
8707
  if (value instanceof Map) {
8648
- return { [mapMarker]: [...value.entries()].map(([key, item]) => [
8649
- encodeValue(key, depth + 1),
8650
- encodeValue(item, depth + 1)
8651
- ]) };
8708
+ consumeBudget(budget, mapMarkerBaseBytes + value.size);
8709
+ const pairs = [];
8710
+ for (const [key, item] of value.entries()) {
8711
+ pairs.push([
8712
+ encodeValue(key, depth + 1, budget),
8713
+ encodeValue(item, depth + 1, budget)
8714
+ ]);
8715
+ }
8716
+ return { [mapMarker]: pairs };
8652
8717
  }
8653
8718
  if (isRecord(value)) {
8654
- return { [mapMarker]: Object.entries(value).map(([key, item]) => [
8655
- encodeValue(key, depth + 1),
8656
- encodeValue(item, depth + 1)
8719
+ const keys = Object.keys(value);
8720
+ consumeBudget(budget, mapMarkerBaseBytes + keys.length);
8721
+ return { [mapMarker]: keys.map((key) => [
8722
+ encodeValue(key, depth + 1, budget),
8723
+ encodeValue(value[key], depth + 1, budget)
8657
8724
  ]) };
8658
8725
  }
8659
8726
  throw new TypeError(`unsupported HTTP command value: ${typeof value}`);
@@ -8679,15 +8746,28 @@ function decodeBase64(value) {
8679
8746
  if (value.length % 4 !== 0 || !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(value)) {
8680
8747
  throw new TypeError("invalid HTTP bytes marker");
8681
8748
  }
8682
- const decoded = Buffer33.from(value, "base64");
8749
+ const decoded = Buffer34.from(value, "base64");
8683
8750
  if (decoded.toString("base64") !== value) throw new TypeError("invalid HTTP bytes marker");
8684
8751
  return decoded;
8685
8752
  }
8686
8753
  function decodePlainRecord(value, depth) {
8687
8754
  const result = {};
8688
- for (const [key, item] of Object.entries(value)) result[key] = decodeValue2(item, depth);
8755
+ for (const [key, item] of Object.entries(value)) {
8756
+ Object.defineProperty(result, key, {
8757
+ configurable: true,
8758
+ enumerable: true,
8759
+ value: decodeValue2(item, depth),
8760
+ writable: true
8761
+ });
8762
+ }
8689
8763
  return result;
8690
8764
  }
8765
+ function consumeBudget(budget, amount) {
8766
+ if (amount > budget.remaining) {
8767
+ throw new HTTPTransportError("HTTP command request exceeds maxRequestBytes");
8768
+ }
8769
+ budget.remaining -= amount;
8770
+ }
8691
8771
  function denseArray(values, depth, transform) {
8692
8772
  const result = new Array(values.length);
8693
8773
  for (let index = 0; index < values.length; index += 1) {
@@ -8697,10 +8777,12 @@ function denseArray(values, depth, transform) {
8697
8777
  return result;
8698
8778
  }
8699
8779
  function isRecord(value) {
8700
- return typeof value === "object" && value != null && !Array.isArray(value) && !Buffer33.isBuffer(value);
8780
+ return typeof value === "object" && value != null && !Array.isArray(value) && !Buffer34.isBuffer(value);
8701
8781
  }
8702
8782
 
8703
8783
  // src/http-options.ts
8784
+ import { Buffer as Buffer35 } from "buffer";
8785
+ import { validateHeaderName, validateHeaderValue } from "http";
8704
8786
  function normalizeHTTPOptions(value, options) {
8705
8787
  const url = new URL(value);
8706
8788
  if (url.protocol !== "http:" && url.protocol !== "https:") {
@@ -8726,10 +8808,10 @@ function normalizeHTTPOptions(value, options) {
8726
8808
  });
8727
8809
  }
8728
8810
  function normalizedHeaders(source) {
8729
- const headers = {};
8811
+ const headers = /* @__PURE__ */ Object.create(null);
8730
8812
  for (const [rawName, value] of Object.entries(source)) {
8731
8813
  const name = rawName.toLowerCase();
8732
- if (name === "" || !safeHeader(name) || !safeHeader(value)) {
8814
+ if (typeof value !== "string" || !validHeader(name, value)) {
8733
8815
  throw new TypeError(`invalid HTTP header: ${rawName}`);
8734
8816
  }
8735
8817
  headers[name] = value;
@@ -8741,7 +8823,9 @@ function authorizationHeader(url, options, custom) {
8741
8823
  const count = Number(custom != null) + Number(options.bearerToken != null) + Number(basic);
8742
8824
  if (count > 1) throw new TypeError("HTTP credentials are mutually exclusive");
8743
8825
  if (options.bearerToken != null) {
8744
- if (!safeHeader(options.bearerToken)) throw new TypeError("invalid bearer token");
8826
+ if (options.bearerToken === "" || !validHeader("authorization", `Bearer ${options.bearerToken}`)) {
8827
+ throw new TypeError("invalid bearer token");
8828
+ }
8745
8829
  return `Bearer ${options.bearerToken}`;
8746
8830
  }
8747
8831
  if (!basic) return custom;
@@ -8751,7 +8835,7 @@ function authorizationHeader(url, options, custom) {
8751
8835
  if (username === "" || username.includes(":") || !safeHeader(username) || !safeHeader(options.password)) {
8752
8836
  throw new TypeError("invalid Basic authentication credentials");
8753
8837
  }
8754
- return `Basic ${Buffer.from(`${username}:${options.password}`).toString("base64")}`;
8838
+ return `Basic ${Buffer35.from(`${username}:${options.password}`).toString("base64")}`;
8755
8839
  }
8756
8840
  function positiveInteger(value, fallback, name) {
8757
8841
  const result = value ?? fallback;
@@ -8771,36 +8855,167 @@ function booleanOption(value, fallback, name) {
8771
8855
  function safeHeader(value) {
8772
8856
  return !value.includes("\r") && !value.includes("\n");
8773
8857
  }
8858
+ function validHeader(name, value) {
8859
+ try {
8860
+ validateHeaderName(name);
8861
+ validateHeaderValue(name, value);
8862
+ return true;
8863
+ } catch {
8864
+ return false;
8865
+ }
8866
+ }
8774
8867
 
8775
8868
  // src/http-transport.ts
8776
8869
  import http from "http";
8777
8870
  import http2 from "http2";
8778
8871
  import https from "https";
8779
- import { Buffer as Buffer34 } from "buffer";
8872
+ import { Buffer as Buffer36 } from "buffer";
8873
+
8874
+ // src/http2-slot-pool.ts
8875
+ var HTTP2SessionRetiredError = class extends Error {
8876
+ constructor(message, cause) {
8877
+ super(message, { cause });
8878
+ this.name = "HTTP2SessionRetiredError";
8879
+ }
8880
+ };
8881
+ var HTTP2SlotPool = class {
8882
+ active = 0;
8883
+ idleCallback;
8884
+ limit;
8885
+ retiredError;
8886
+ waiterHead;
8887
+ waiterTail;
8888
+ acquire(signal) {
8889
+ if (signal.aborted) return Promise.reject(signalAbortError(signal));
8890
+ if (this.retiredError != null) return Promise.reject(this.retiredError);
8891
+ if (this.limit != null && this.active < this.limit) {
8892
+ this.active += 1;
8893
+ return Promise.resolve(this.releaseOnce());
8894
+ }
8895
+ return new Promise((resolve, reject) => {
8896
+ const waiter = {
8897
+ abort: () => {
8898
+ if (waiter.settled) return;
8899
+ waiter.settled = true;
8900
+ this.removeWaiter(waiter);
8901
+ reject(signalAbortError(signal));
8902
+ },
8903
+ queued: true,
8904
+ reject,
8905
+ resolve,
8906
+ settled: false,
8907
+ signal
8908
+ };
8909
+ this.enqueueWaiter(waiter);
8910
+ signal.addEventListener("abort", waiter.abort, { once: true });
8911
+ });
8912
+ }
8913
+ updateLimit(limit) {
8914
+ if (this.retiredError != null) return;
8915
+ this.limit = limit;
8916
+ this.drain();
8917
+ }
8918
+ retire(error) {
8919
+ if (this.retiredError != null) return;
8920
+ this.retiredError = error;
8921
+ while (this.waiterHead != null) {
8922
+ const waiter = this.waiterHead;
8923
+ this.removeWaiter(waiter);
8924
+ if (waiter.settled) continue;
8925
+ waiter.settled = true;
8926
+ waiter.signal.removeEventListener("abort", waiter.abort);
8927
+ waiter.reject(error);
8928
+ }
8929
+ }
8930
+ whenIdle(callback) {
8931
+ if (this.active === 0) callback();
8932
+ else this.idleCallback = callback;
8933
+ }
8934
+ drain() {
8935
+ while (this.retiredError == null && this.limit != null && this.active < this.limit) {
8936
+ const waiter = this.waiterHead;
8937
+ if (waiter == null) return;
8938
+ this.removeWaiter(waiter);
8939
+ if (waiter.settled) continue;
8940
+ waiter.settled = true;
8941
+ waiter.signal.removeEventListener("abort", waiter.abort);
8942
+ this.active += 1;
8943
+ waiter.resolve(this.releaseOnce());
8944
+ }
8945
+ }
8946
+ enqueueWaiter(waiter) {
8947
+ waiter.previous = this.waiterTail;
8948
+ if (this.waiterTail == null) this.waiterHead = waiter;
8949
+ else this.waiterTail.next = waiter;
8950
+ this.waiterTail = waiter;
8951
+ }
8952
+ removeWaiter(waiter) {
8953
+ if (!waiter.queued) return;
8954
+ if (waiter.previous == null) this.waiterHead = waiter.next;
8955
+ else waiter.previous.next = waiter.next;
8956
+ if (waiter.next == null) this.waiterTail = waiter.previous;
8957
+ else waiter.next.previous = waiter.previous;
8958
+ waiter.next = void 0;
8959
+ waiter.previous = void 0;
8960
+ waiter.queued = false;
8961
+ }
8962
+ releaseOnce() {
8963
+ let released = false;
8964
+ return () => {
8965
+ if (released) return;
8966
+ released = true;
8967
+ this.active -= 1;
8968
+ this.drain();
8969
+ if (this.active === 0) {
8970
+ const callback = this.idleCallback;
8971
+ this.idleCallback = void 0;
8972
+ callback?.();
8973
+ }
8974
+ };
8975
+ }
8976
+ };
8977
+ function signalAbortError(signal) {
8978
+ return signal.reason instanceof Error ? signal.reason : new HTTPTransportError("HTTP request was aborted", { raw: signal.reason });
8979
+ }
8980
+
8981
+ // src/http-transport.ts
8780
8982
  var HTTPTransport = class {
8781
8983
  constructor(config) {
8782
8984
  this.config = config;
8783
- this.#httpAgent = new http.Agent({ keepAlive: true, maxSockets: config.maxConnections });
8985
+ this.#httpAgent = new http.Agent({
8986
+ keepAlive: true,
8987
+ maxFreeSockets: config.maxConnections,
8988
+ maxSockets: config.maxConnections,
8989
+ maxTotalSockets: config.maxConnections
8990
+ });
8784
8991
  this.#httpsAgent = new https.Agent({
8785
8992
  ...config.tlsOptions,
8786
8993
  keepAlive: true,
8787
- maxSockets: config.maxConnections
8994
+ maxFreeSockets: config.maxConnections,
8995
+ maxSockets: config.maxConnections,
8996
+ maxTotalSockets: config.maxConnections
8788
8997
  });
8789
8998
  }
8790
8999
  config;
8791
9000
  #httpAgent;
8792
9001
  #httpsAgent;
9002
+ #allSessions = /* @__PURE__ */ new Set();
8793
9003
  #sessions = /* @__PURE__ */ new Map();
9004
+ #sessionSlots = /* @__PURE__ */ new WeakMap();
9005
+ #requests = /* @__PURE__ */ new Set();
8794
9006
  #closed = false;
8795
- async post(body) {
9007
+ async post(body, timeoutMs) {
8796
9008
  if (this.#closed) throw new HTTPTransportError("HTTP transport is closed");
8797
9009
  const controller = new AbortController();
8798
- const timer = setTimeout(() => controller.abort(), this.config.timeoutMs);
9010
+ this.#requests.add(controller);
9011
+ const timer = timeoutMs == null ? void 0 : setLongTimeout(() => controller.abort(requestTimeoutReason), timeoutMs);
9012
+ timer?.unref();
8799
9013
  try {
8800
9014
  return await this.request(this.config.commandUrl, "POST", body, 0, controller.signal);
8801
9015
  } catch (error) {
8802
9016
  if (controller.signal.aborted) {
8803
- throw new RequestTimeoutError(this.config.timeoutMs, "possibly_sent", {
9017
+ if (controller.signal.reason instanceof HTTPTransportError) throw controller.signal.reason;
9018
+ throw new RequestTimeoutError(timeoutMs ?? this.config.timeoutMs, "possibly_sent", {
8804
9019
  cause: error,
8805
9020
  raw: { retryable: true, safe_to_retry: false }
8806
9021
  });
@@ -8812,15 +9027,19 @@ var HTTPTransport = class {
8812
9027
  safeToRetry: false
8813
9028
  });
8814
9029
  } finally {
8815
- clearTimeout(timer);
9030
+ timer?.cancel();
9031
+ this.#requests.delete(controller);
8816
9032
  }
8817
9033
  }
8818
9034
  async close() {
8819
9035
  if (this.#closed) return;
8820
9036
  this.#closed = true;
9037
+ const error = new HTTPTransportError("HTTP transport is closed");
9038
+ for (const controller of this.#requests) controller.abort(error);
8821
9039
  this.#httpAgent.destroy();
8822
9040
  this.#httpsAgent.destroy();
8823
- for (const session of this.#sessions.values()) session.destroy();
9041
+ for (const session of this.#allSessions) session.destroy();
9042
+ this.#allSessions.clear();
8824
9043
  this.#sessions.clear();
8825
9044
  }
8826
9045
  async request(url, method, body, redirects, signal) {
@@ -8868,7 +9087,6 @@ var HTTPTransport = class {
8868
9087
  );
8869
9088
  }
8870
9089
  async http2Request(url, method, body, signal) {
8871
- const session = this.session(url);
8872
9090
  const headers = {
8873
9091
  ...this.requestHeaders(body),
8874
9092
  ":authority": url.host,
@@ -8876,8 +9094,41 @@ var HTTPTransport = class {
8876
9094
  ":path": `${url.pathname}${url.search}`,
8877
9095
  ":scheme": url.protocol.slice(0, -1)
8878
9096
  };
9097
+ if (signal.aborted) throw signalAbortError(signal);
9098
+ for (let attempt = 0; attempt < 2; attempt += 1) {
9099
+ const session = this.session(url);
9100
+ let release;
9101
+ try {
9102
+ release = await this.slotPool(session).acquire(signal);
9103
+ } catch (error) {
9104
+ if (attempt === 0 && error instanceof HTTP2SessionRetiredError && !signal.aborted) continue;
9105
+ throw error;
9106
+ }
9107
+ try {
9108
+ let stream;
9109
+ try {
9110
+ stream = session.request(headers);
9111
+ } catch (error) {
9112
+ if (attempt === 0 && retryableSessionOpenError(error) && !signal.aborted) {
9113
+ this.retireSession(url.origin, session, true, error);
9114
+ continue;
9115
+ }
9116
+ throw error;
9117
+ }
9118
+ try {
9119
+ return await this.collectHttp2(stream, body, signal);
9120
+ } catch (error) {
9121
+ if (attempt === 0 && refusedStreamError(error) && !signal.aborted) continue;
9122
+ throw error;
9123
+ }
9124
+ } finally {
9125
+ release();
9126
+ }
9127
+ }
9128
+ throw new HTTPTransportError("HTTP/2 session could not accept the request");
9129
+ }
9130
+ async collectHttp2(stream, body, signal) {
8879
9131
  return await new Promise((resolve, reject) => {
8880
- const stream = session.request(headers);
8881
9132
  let responseHeaders = {};
8882
9133
  const abort = () => stream.close(http2.constants.NGHTTP2_CANCEL);
8883
9134
  signal.addEventListener("abort", abort, { once: true });
@@ -8887,19 +9138,60 @@ var HTTPTransport = class {
8887
9138
  const status = Number(responseHeaders[":status"] ?? 0);
8888
9139
  resolve({ body: response.body, headers: normalizeHeaders(responseHeaders), status });
8889
9140
  }, reject).finally(() => signal.removeEventListener("abort", abort));
8890
- stream.end(body);
9141
+ if (signal.aborted) abort();
9142
+ else stream.end(body);
8891
9143
  });
8892
9144
  }
8893
9145
  session(url) {
8894
9146
  const origin = url.origin;
8895
9147
  const current = this.#sessions.get(origin);
8896
9148
  if (current != null && !current.closed && !current.destroyed) return current;
8897
- const session = http2.connect(origin, this.config.tlsOptions);
8898
- session.on("error", () => void 0);
8899
- session.once("close", () => this.#sessions.delete(origin));
9149
+ const session = http2.connect(origin, {
9150
+ ...this.config.tlsOptions,
9151
+ settings: { enablePush: false }
9152
+ });
9153
+ const slots = new HTTP2SlotPool();
9154
+ this.#allSessions.add(session);
9155
+ this.#sessionSlots.set(session, slots);
9156
+ session.on("remoteSettings", (settings) => {
9157
+ const remoteLimit = settings.maxConcurrentStreams;
9158
+ const limit = typeof remoteLimit === "number" && Number.isFinite(remoteLimit) ? Math.max(0, Math.floor(remoteLimit)) : this.config.maxConnections;
9159
+ slots.updateLimit(Math.min(this.config.maxConnections, limit));
9160
+ });
9161
+ session.on("error", (error) => this.retireSession(origin, session, true, error));
9162
+ session.once("goaway", () => {
9163
+ this.retireSession(
9164
+ origin,
9165
+ session,
9166
+ "when_idle",
9167
+ new HTTP2SessionRetiredError("HTTP/2 session received GOAWAY")
9168
+ );
9169
+ });
9170
+ session.once("close", () => {
9171
+ if (session.destroyed) this.#allSessions.delete(session);
9172
+ this.retireSession(origin, session);
9173
+ });
8900
9174
  this.#sessions.set(origin, session);
8901
9175
  return session;
8902
9176
  }
9177
+ retireSession(origin, session, destroy = false, cause) {
9178
+ if (this.#sessions.get(origin) === session) this.#sessions.delete(origin);
9179
+ const slots = this.#sessionSlots.get(session);
9180
+ slots?.retire(
9181
+ cause instanceof HTTP2SessionRetiredError ? cause : new HTTP2SessionRetiredError("HTTP/2 session is unavailable", cause)
9182
+ );
9183
+ if (destroy === true && !session.destroyed) session.destroy();
9184
+ else if (destroy === "when_idle") {
9185
+ slots?.whenIdle(() => {
9186
+ if (!session.destroyed) session.destroy();
9187
+ });
9188
+ }
9189
+ }
9190
+ slotPool(session) {
9191
+ const slots = this.#sessionSlots.get(session);
9192
+ if (slots == null) throw new HTTP2SessionRetiredError("HTTP/2 session is unavailable");
9193
+ return slots;
9194
+ }
8903
9195
  requestHeaders(body) {
8904
9196
  const headers = { ...this.config.headers };
8905
9197
  delete headers["content-length"];
@@ -8911,11 +9203,21 @@ var HTTPTransport = class {
8911
9203
  };
8912
9204
  }
8913
9205
  };
9206
+ var requestTimeoutReason = /* @__PURE__ */ Symbol("ferricstore-http-request-timeout");
9207
+ function retryableSessionOpenError(error) {
9208
+ if (typeof error !== "object" || error == null || !("code" in error)) return false;
9209
+ const code = error.code;
9210
+ return code === "ERR_HTTP2_GOAWAY_SESSION" || code === "ERR_HTTP2_INVALID_SESSION";
9211
+ }
9212
+ function refusedStreamError(error) {
9213
+ if (!(error instanceof Error)) return false;
9214
+ return error.code === "ERR_HTTP2_STREAM_ERROR" && error.message.includes("NGHTTP2_REFUSED_STREAM");
9215
+ }
8914
9216
  async function collectBody(source, status, headers, maximum) {
8915
9217
  const chunks = [];
8916
9218
  let size = 0;
8917
9219
  for await (const chunk of source) {
8918
- const bytes2 = Buffer34.from(chunk);
9220
+ const bytes2 = Buffer36.from(chunk);
8919
9221
  size += bytes2.byteLength;
8920
9222
  if (size > maximum) {
8921
9223
  const destroy = source.destroy;
@@ -8924,10 +9226,10 @@ async function collectBody(source, status, headers, maximum) {
8924
9226
  }
8925
9227
  chunks.push(bytes2);
8926
9228
  }
8927
- return { body: Buffer34.concat(chunks, size), headers, status };
9229
+ return { body: Buffer36.concat(chunks, size), headers, status };
8928
9230
  }
8929
9231
  function normalizeHeaders(headers) {
8930
- const result = {};
9232
+ const result = /* @__PURE__ */ Object.create(null);
8931
9233
  for (const [name, raw] of Object.entries(headers)) {
8932
9234
  const value = headerValue(raw);
8933
9235
  if (value != null) result[name.toLowerCase()] = value;
@@ -8979,11 +9281,16 @@ var HTTPAdapter = class _HTTPAdapter {
8979
9281
  throw new HTTPTransportError("HTTP command batch exceeds maxBatchItems");
8980
9282
  }
8981
9283
  for (const command of commands) assertHTTPCommandSupported(command[0]);
8982
- const body = encodeHTTPCommands(commands.map((command) => httpCommand(command, this.#config.maxRequestBytes)));
9284
+ const prepared = commands.map((command) => prepareHTTPCommand(command, this.#config.maxRequestBytes));
9285
+ const body = encodeHTTPCommands(prepared.map((command) => command.encoded), this.#config.maxRequestBytes);
8983
9286
  if (body.byteLength > this.#config.maxRequestBytes) {
8984
9287
  throw new HTTPTransportError("HTTP command request exceeds maxRequestBytes");
8985
9288
  }
8986
- const response = await this.#transport.post(body);
9289
+ const serverBlockMs = combinedServerBlockMs(prepared.map((command) => command.serverBlockMs));
9290
+ const response = await this.#transport.post(
9291
+ body,
9292
+ serverResponseTimeoutMs(this.#config.timeoutMs, serverBlockMs)
9293
+ );
8987
9294
  let envelope = {};
8988
9295
  try {
8989
9296
  if (response.body.byteLength > 0) envelope = decodeHTTPEnvelope(response.body);
@@ -9007,12 +9314,17 @@ var HTTPAdapter = class _HTTPAdapter {
9007
9314
  var commandNamesByOpcode = new Map(
9008
9315
  Object.entries(COMMAND_OPCODES).map(([name, opcode]) => [opcode, name])
9009
9316
  );
9010
- function httpCommand(command, maxRequestBytes) {
9317
+ function prepareHTTPCommand(command, maxRequestBytes) {
9011
9318
  const protocol = buildProtocolCommand(command, maxRequestBytes, false);
9012
- if (protocol.opcode === OPCODES.commandExec) return command;
9319
+ if (protocol.opcode === OPCODES.commandExec) {
9320
+ return { encoded: command, serverBlockMs: protocol.serverBlockMs };
9321
+ }
9013
9322
  const name = commandNamesByOpcode.get(protocol.opcode);
9014
9323
  if (name == null) throw new HTTPTransportError(`HTTP command has unknown opcode ${protocol.opcode}`);
9015
- return { command: name, opcode: protocol.opcode, payload: protocol.payload ?? {} };
9324
+ return {
9325
+ encoded: { command: name, opcode: protocol.opcode, payload: protocol.payload ?? {} },
9326
+ serverBlockMs: protocol.serverBlockMs
9327
+ };
9016
9328
  }
9017
9329
  function validatedResult(value) {
9018
9330
  if (!isRecord2(value)) throw new HTTPTransportError("HTTP response has an invalid result item");
@@ -9032,7 +9344,7 @@ function commandError(value) {
9032
9344
  function topLevelError(status, envelope, retryAfter) {
9033
9345
  const details = isRecord2(envelope.error) ? envelope.error : {};
9034
9346
  const message = typeof details.message === "string" ? details.message : `HTTP command request failed with status ${status}`;
9035
- const retryAfterMs2 = retryAfter == null || !/^\d+$/u.test(retryAfter) ? void 0 : Number(retryAfter) * 1e3;
9347
+ const retryAfterMs2 = retryAfterMilliseconds(retryAfter);
9036
9348
  return new HTTPTransportError(message, {
9037
9349
  raw: details,
9038
9350
  retryable: status === 408 || status === 425 || status === 429 || status >= 500,
@@ -9041,6 +9353,18 @@ function topLevelError(status, envelope, retryAfter) {
9041
9353
  statusCode: status
9042
9354
  });
9043
9355
  }
9356
+ function retryAfterMilliseconds(value) {
9357
+ if (value == null) return void 0;
9358
+ if (/^\d+$/u.test(value)) {
9359
+ const seconds = Number.parseInt(value, 10);
9360
+ const milliseconds2 = seconds * 1e3;
9361
+ return Number.isSafeInteger(milliseconds2) ? milliseconds2 : void 0;
9362
+ }
9363
+ const deadline = Date.parse(value);
9364
+ if (!Number.isFinite(deadline)) return void 0;
9365
+ const milliseconds = Math.max(0, deadline - Date.now());
9366
+ return Number.isSafeInteger(milliseconds) ? milliseconds : void 0;
9367
+ }
9044
9368
  function isRecord2(value) {
9045
9369
  return typeof value === "object" && value != null && !Array.isArray(value);
9046
9370
  }
@@ -9056,7 +9380,7 @@ function executeCommandArgs(executor, args) {
9056
9380
  import "buffer";
9057
9381
 
9058
9382
  // src/command-retry-policy.ts
9059
- import { Buffer as Buffer35 } from "buffer";
9383
+ import { Buffer as Buffer37 } from "buffer";
9060
9384
  function isCasMutation(args) {
9061
9385
  const offset = commandName2(args[0]) === "COMMAND_EXEC" ? 1 : 0;
9062
9386
  const name = commandName2(args[offset]);
@@ -9070,8 +9394,8 @@ function isCasMutation(args) {
9070
9394
  }
9071
9395
  function commandName2(value) {
9072
9396
  if (typeof value === "string") return value.toUpperCase();
9073
- if (Buffer35.isBuffer(value) || value instanceof Uint8Array) {
9074
- return Buffer35.from(value).toString("utf8").toUpperCase();
9397
+ if (Buffer37.isBuffer(value) || value instanceof Uint8Array) {
9398
+ return Buffer37.from(value).toString("utf8").toUpperCase();
9075
9399
  }
9076
9400
  return void 0;
9077
9401
  }
@@ -9286,12 +9610,12 @@ function normalizeNonNegativeInteger2(value, fallback) {
9286
9610
  import "buffer";
9287
9611
 
9288
9612
  // src/topology-routing.ts
9289
- import { Buffer as Buffer38 } from "buffer";
9613
+ import { Buffer as Buffer40 } from "buffer";
9290
9614
 
9291
9615
  // src/flow-partition-route-cache.ts
9292
- import { Buffer as Buffer37 } from "buffer";
9616
+ import { Buffer as Buffer39 } from "buffer";
9293
9617
  import { createHash } from "crypto";
9294
- var AUTO_PREFIX = Buffer37.from("__flow_auto__:", "ascii");
9618
+ var AUTO_PREFIX = Buffer39.from("__flow_auto__:", "ascii");
9295
9619
  var MAX_CACHEABLE_PARTITION_BYTES = 4 * 1024;
9296
9620
  var MAX_CACHE_BYTES = 1 * 1024 * 1024;
9297
9621
  var MAX_CACHE_ENTRIES = 1024;
@@ -9301,10 +9625,10 @@ var cacheBytes = 0;
9301
9625
  var cacheHits = 0;
9302
9626
  var cacheMisses = 0;
9303
9627
  function flowLogicalPartitionRoutingKey(value) {
9304
- if (typeof value !== "string" && !Buffer37.isBuffer(value)) return void 0;
9628
+ if (typeof value !== "string" && !Buffer39.isBuffer(value)) return void 0;
9305
9629
  const autoBucket = flowAutoBucket(value);
9306
9630
  if (autoBucket != null) return `{fa:${autoBucket}}`;
9307
- const bytes2 = Buffer37.isBuffer(value) ? value : Buffer37.from(value);
9631
+ const bytes2 = Buffer39.isBuffer(value) ? value : Buffer39.from(value);
9308
9632
  if (bytes2.byteLength > MAX_CACHEABLE_PARTITION_BYTES) return hashRoute(bytes2);
9309
9633
  const cacheKey = bytes2.toString("base64");
9310
9634
  const cached = routeCache.get(cacheKey);
@@ -9378,7 +9702,7 @@ function routingKeyFromProtocolPayload(name, command) {
9378
9702
  "scope"
9379
9703
  ]) {
9380
9704
  const value = getField(command.payload, field3);
9381
- if (typeof value === "string" || Buffer38.isBuffer(value)) {
9705
+ if (typeof value === "string" || Buffer40.isBuffer(value)) {
9382
9706
  return value;
9383
9707
  }
9384
9708
  }
@@ -9426,7 +9750,7 @@ function flowRoutingData(name, args) {
9426
9750
  if (typeof partition === "string" && partition.toUpperCase() !== "AUTO" && partition.toUpperCase() !== "MIXED") {
9427
9751
  return flowRoutingResult(flowLogicalPartitionRoutingKey(partition));
9428
9752
  }
9429
- if (Buffer38.isBuffer(partition)) {
9753
+ if (Buffer40.isBuffer(partition)) {
9430
9754
  const text3 = partition.toString("utf8").toUpperCase();
9431
9755
  if (text3 !== "AUTO" && text3 !== "MIXED") {
9432
9756
  return flowRoutingResult(flowLogicalPartitionRoutingKey(partition));
@@ -9517,17 +9841,17 @@ function flowPartitionRoutingKeyFromCommand(command, claim) {
9517
9841
  return { handled: false };
9518
9842
  }
9519
9843
  function isRoutingKey(value) {
9520
- return typeof value === "string" || Buffer38.isBuffer(value);
9844
+ return typeof value === "string" || Buffer40.isBuffer(value);
9521
9845
  }
9522
9846
  function flowAutoIdRoutingKey(value) {
9523
- if (typeof value !== "string" && !Buffer38.isBuffer(value)) {
9847
+ if (typeof value !== "string" && !Buffer40.isBuffer(value)) {
9524
9848
  return void 0;
9525
9849
  }
9526
- const bucket = (Buffer38.isBuffer(value) ? crc32(value) : crc32Utf8(value)) & 255;
9850
+ const bucket = (Buffer40.isBuffer(value) ? crc32(value) : crc32Utf8(value)) & 255;
9527
9851
  return `{fa:${bucket}}`;
9528
9852
  }
9529
9853
  function flowClaimLogicalPartitionRoutingKey(value) {
9530
- if (typeof value !== "string" && !Buffer38.isBuffer(value)) return void 0;
9854
+ if (typeof value !== "string" && !Buffer40.isBuffer(value)) return void 0;
9531
9855
  const selector = commandPart(value);
9532
9856
  if (selector === "AUTO" || selector === "ANY") return void 0;
9533
9857
  if (selector === "GLOBAL") return "{f}";
@@ -9542,7 +9866,7 @@ function singleShardFlowClaimPartitionKey(values) {
9542
9866
  return keys.some((key) => key == null) ? void 0 : singleShardKey(keys);
9543
9867
  }
9544
9868
  function singleShardKey(keys) {
9545
- if (keys.length === 0 || keys.some((key) => typeof key !== "string" && !Buffer38.isBuffer(key))) {
9869
+ if (keys.length === 0 || keys.some((key) => typeof key !== "string" && !Buffer40.isBuffer(key))) {
9546
9870
  return void 0;
9547
9871
  }
9548
9872
  const usable = keys;
@@ -9575,7 +9899,7 @@ function routedKeyGroups(keys, routeKey) {
9575
9899
  const groups = /* @__PURE__ */ new Map();
9576
9900
  for (let index = 0; index < keys.length; index += 1) {
9577
9901
  const key = keys[index];
9578
- if (typeof key !== "string" && !Buffer38.isBuffer(key)) return void 0;
9902
+ if (typeof key !== "string" && !Buffer40.isBuffer(key)) return void 0;
9579
9903
  const route = routeKey(key);
9580
9904
  const groupKey = `${route.endpointKey}\0${route.laneId}`;
9581
9905
  const group = groups.get(groupKey);
@@ -10664,7 +10988,7 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
10664
10988
  };
10665
10989
 
10666
10990
  // src/response-map-preservation.ts
10667
- import { Buffer as Buffer40 } from "buffer";
10991
+ import { Buffer as Buffer42 } from "buffer";
10668
10992
  function toStringKeyMapPreservingValues(value) {
10669
10993
  if (value == null) return void 0;
10670
10994
  const result = {};
@@ -10674,7 +10998,7 @@ function toStringKeyMapPreservingValues(value) {
10674
10998
  }
10675
10999
  return result;
10676
11000
  }
10677
- if (typeof value === "object" && !Array.isArray(value) && !Buffer40.isBuffer(value) && !(value instanceof Uint8Array)) {
11001
+ if (typeof value === "object" && !Array.isArray(value) && !Buffer42.isBuffer(value) && !(value instanceof Uint8Array)) {
10678
11002
  for (const [key, item] of Object.entries(value)) {
10679
11003
  setOwnValue(result, text(key), normalizeMapStructurePreservingBytes(item));
10680
11004
  }
@@ -10683,7 +11007,7 @@ function toStringKeyMapPreservingValues(value) {
10683
11007
  return void 0;
10684
11008
  }
10685
11009
  function normalizeMapStructurePreservingBytes(value) {
10686
- if (Buffer40.isBuffer(value) || value instanceof Uint8Array) return value;
11010
+ if (Buffer42.isBuffer(value) || value instanceof Uint8Array) return value;
10687
11011
  if (value instanceof Map) {
10688
11012
  const result = {};
10689
11013
  for (const [key, item] of value.entries()) {
@@ -10705,7 +11029,7 @@ function normalizeMapStructurePreservingBytes(value) {
10705
11029
  }
10706
11030
 
10707
11031
  // src/native-kv-responses.ts
10708
- import { Buffer as Buffer41 } from "buffer";
11032
+ import { Buffer as Buffer43 } from "buffer";
10709
11033
  function rateLimitResultFromResp(value) {
10710
11034
  if (!Array.isArray(value) || value.length !== 4) {
10711
11035
  throw new TypeError("RATELIMIT.ADD returned an unexpected response");
@@ -10762,13 +11086,13 @@ function fetchOrComputeResultFromResp(value, codec) {
10762
11086
  }
10763
11087
  function decodePayload(codec, value) {
10764
11088
  if (value == null) return null;
10765
- if (Buffer41.isBuffer(value)) return codec.decode(value);
10766
- if (value instanceof Uint8Array) return codec.decode(Buffer41.from(value));
10767
- if (typeof value === "string") return codec.decode(Buffer41.from(value));
11089
+ if (Buffer43.isBuffer(value)) return codec.decode(value);
11090
+ if (value instanceof Uint8Array) return codec.decode(Buffer43.from(value));
11091
+ if (typeof value === "string") return codec.decode(Buffer43.from(value));
10768
11092
  return normalizeRefMeta(value);
10769
11093
  }
10770
11094
  function requiredResponseString(value, context) {
10771
- if (typeof value !== "string" && !Buffer41.isBuffer(value) && !(value instanceof Uint8Array)) {
11095
+ if (typeof value !== "string" && !Buffer43.isBuffer(value) && !(value instanceof Uint8Array)) {
10772
11096
  throw new TypeError(`${context} returned an unexpected response`);
10773
11097
  }
10774
11098
  const result = text(value);
@@ -10785,7 +11109,7 @@ function requiredNonNegativeInteger(value, context) {
10785
11109
  return result;
10786
11110
  }
10787
11111
  function responseBytes(value, context) {
10788
- if (typeof value !== "string" && !Buffer41.isBuffer(value) && !(value instanceof Uint8Array)) {
11112
+ if (typeof value !== "string" && !Buffer43.isBuffer(value) && !(value instanceof Uint8Array)) {
10789
11113
  throw new TypeError(`${context} returned an unexpected response`);
10790
11114
  }
10791
11115
  return bytes(value);
@@ -11468,7 +11792,7 @@ function groupAutoPartitionItems(items) {
11468
11792
  }
11469
11793
 
11470
11794
  // src/client-values.ts
11471
- import { Buffer as Buffer42 } from "buffer";
11795
+ import { Buffer as Buffer44 } from "buffer";
11472
11796
  async function valueMGetEntries(client, refs, options = {}) {
11473
11797
  const refCount = refs.length;
11474
11798
  if (refCount === 0) {
@@ -11503,12 +11827,12 @@ async function valueMGetEntries(client, refs, options = {}) {
11503
11827
  const item = response[index];
11504
11828
  if (item == null) {
11505
11829
  entries[index] = { found: false };
11506
- } else if (Buffer42.isBuffer(item)) {
11830
+ } else if (Buffer44.isBuffer(item)) {
11507
11831
  entries[index] = { found: true, value: client.codec.decode(item) };
11508
11832
  } else if (item instanceof Uint8Array) {
11509
- entries[index] = { found: true, value: client.codec.decode(Buffer42.from(item)) };
11833
+ entries[index] = { found: true, value: client.codec.decode(Buffer44.from(item)) };
11510
11834
  } else if (typeof item === "string") {
11511
- entries[index] = { found: true, value: client.codec.decode(Buffer42.from(item)) };
11835
+ entries[index] = { found: true, value: client.codec.decode(Buffer44.from(item)) };
11512
11836
  } else {
11513
11837
  entries[index] = { found: true, value: item };
11514
11838
  }
@@ -11520,7 +11844,7 @@ async function valueMGetEntries(client, refs, options = {}) {
11520
11844
  import "buffer";
11521
11845
 
11522
11846
  // src/auto-batch-ordering.ts
11523
- import { Buffer as Buffer43 } from "buffer";
11847
+ import { Buffer as Buffer45 } from "buffer";
11524
11848
  function autoBatchOrderingPlan(batch) {
11525
11849
  const accesses = /* @__PURE__ */ new Map();
11526
11850
  const fallbackDependencies = [];
@@ -11635,13 +11959,13 @@ function flowManyAutoBatchIds(command, name) {
11635
11959
  return fixedFlowItemIds(
11636
11960
  command,
11637
11961
  mixed ? 4 : 3,
11638
- (itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && isFencingToken(command[itemIndex + (mixed ? 2 : 1)]) && Buffer43.isBuffer(command[itemIndex + (mixed ? 3 : 2)])
11962
+ (itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && isFencingToken(command[itemIndex + (mixed ? 2 : 1)]) && Buffer45.isBuffer(command[itemIndex + (mixed ? 3 : 2)])
11639
11963
  );
11640
11964
  }
11641
11965
  return fixedFlowItemIds(
11642
11966
  command,
11643
11967
  mixed ? 4 : 3,
11644
- (itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && Buffer43.isBuffer(command[itemIndex + (mixed ? 2 : 1)]) && isFencingToken(command[itemIndex + (mixed ? 3 : 2)])
11968
+ (itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && Buffer45.isBuffer(command[itemIndex + (mixed ? 2 : 1)]) && isFencingToken(command[itemIndex + (mixed ? 3 : 2)])
11645
11969
  );
11646
11970
  }
11647
11971
  function createManyAutoBatchIds(command) {
@@ -11654,7 +11978,7 @@ function createManyAutoBatchIds(command) {
11654
11978
  const ids = fixedFlowItemIds(
11655
11979
  command,
11656
11980
  width,
11657
- (itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && Buffer43.isBuffer(command[itemIndex + width - 1]),
11981
+ (itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && Buffer45.isBuffer(command[itemIndex + width - 1]),
11658
11982
  markerIndex
11659
11983
  );
11660
11984
  if (ids != null) return ids;
@@ -11672,7 +11996,7 @@ function extendedCreateManyAutoBatchIds(command, markerIndex) {
11672
11996
  let cursor = markerIndex + 2;
11673
11997
  for (let itemIndex = 0; itemIndex < itemCount; itemIndex += 1) {
11674
11998
  const id = command[cursor];
11675
- if (!isAutoBatchResourceValue(id) || !isAutoBatchResourceValue(command[cursor + 1]) || !Buffer43.isBuffer(command[cursor + 2])) return void 0;
11999
+ if (!isAutoBatchResourceValue(id) || !isAutoBatchResourceValue(command[cursor + 1]) || !Buffer45.isBuffer(command[cursor + 2])) return void 0;
11676
12000
  ids.push(id);
11677
12001
  cursor += 3;
11678
12002
  const afterValues = skipExtendedNamedItems(command, cursor, true);
@@ -11691,7 +12015,7 @@ function skipExtendedNamedItems(command, countIndex, encodedValues) {
11691
12015
  for (let index = 0; index < count; index += 1) {
11692
12016
  const name = command[firstItem + index * 2];
11693
12017
  const value = command[firstItem + index * 2 + 1];
11694
- if (!isAutoBatchResourceValue(name) || (encodedValues ? !Buffer43.isBuffer(value) : !isAutoBatchResourceValue(value))) return void 0;
12018
+ if (!isAutoBatchResourceValue(name) || (encodedValues ? !Buffer45.isBuffer(value) : !isAutoBatchResourceValue(value))) return void 0;
11695
12019
  }
11696
12020
  return firstItem + count * 2;
11697
12021
  }
@@ -11706,7 +12030,7 @@ function runStepsManyAutoBatchIds(command) {
11706
12030
  ids.push(item);
11707
12031
  continue;
11708
12032
  }
11709
- if (typeof item !== "object" || item == null || Array.isArray(item) || Buffer43.isBuffer(item)) return void 0;
12033
+ if (typeof item !== "object" || item == null || Array.isArray(item) || Buffer45.isBuffer(item)) return void 0;
11710
12034
  const id = item.id;
11711
12035
  if (!isAutoBatchResourceValue(id)) return void 0;
11712
12036
  ids.push(id);
@@ -11747,7 +12071,7 @@ function flowValuePutOwner(command, start) {
11747
12071
  }
11748
12072
  var flowValuePutOptionTokens = /* @__PURE__ */ new Set(["NAME", "NOW", "OVERRIDE", "OWNER_FLOW_ID", "PARTITION", "TTL", "TTL_MS"]);
11749
12073
  function isAutoBatchResourceValue(value) {
11750
- return typeof value === "string" || Buffer43.isBuffer(value);
12074
+ return typeof value === "string" || Buffer45.isBuffer(value);
11751
12075
  }
11752
12076
  function isFencingToken(value) {
11753
12077
  return typeof value === "number" && Number.isSafeInteger(value) || typeof value === "bigint";
@@ -11756,7 +12080,7 @@ function nonNegativeItemCount(value) {
11756
12080
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
11757
12081
  }
11758
12082
  function autoBatchResourceKey(namespace, value) {
11759
- return `${namespace}:${Buffer43.from(value).toString("base64")}`;
12083
+ return `${namespace}:${Buffer45.from(value).toString("base64")}`;
11760
12084
  }
11761
12085
  function autoBatchCommandName(command) {
11762
12086
  return commandView(command).name ?? null;
@@ -12168,10 +12492,10 @@ function claimFailure(error) {
12168
12492
  import "buffer";
12169
12493
 
12170
12494
  // src/flow-query-builder.ts
12171
- import { Buffer as Buffer46 } from "buffer";
12495
+ import { Buffer as Buffer48 } from "buffer";
12172
12496
 
12173
12497
  // src/flow-query-metadata.ts
12174
- import { Buffer as Buffer45 } from "buffer";
12498
+ import { Buffer as Buffer47 } from "buffer";
12175
12499
  var MAX_FLOW_QUERY_METADATA_KEY_BYTES = 64;
12176
12500
  function normalizeStateMeta(value, state) {
12177
12501
  if (value == null) return {};
@@ -12196,7 +12520,7 @@ function normalizeStateMeta(value, state) {
12196
12520
  function metadataEntries(value, context) {
12197
12521
  const entries = objectEntries(value ?? {}, context).map(([rawName, item]) => {
12198
12522
  const name = rawName.trim();
12199
- const size = Buffer45.byteLength(name, "utf8");
12523
+ const size = Buffer47.byteLength(name, "utf8");
12200
12524
  if (size === 0 || size > MAX_FLOW_QUERY_METADATA_KEY_BYTES || name.startsWith("__")) {
12201
12525
  throw new TypeError(`${context} key is invalid or reserved`);
12202
12526
  }
@@ -12220,7 +12544,7 @@ function objectEntries(value, context) {
12220
12544
  return keys.map((key) => [key, value[key]]);
12221
12545
  }
12222
12546
  function isPlainRecord(value) {
12223
- if (typeof value !== "object" || value == null || Array.isArray(value) || Buffer45.isBuffer(value)) {
12547
+ if (typeof value !== "object" || value == null || Array.isArray(value) || Buffer47.isBuffer(value)) {
12224
12548
  return false;
12225
12549
  }
12226
12550
  const prototype = Object.getPrototypeOf(value);
@@ -12290,7 +12614,7 @@ var FlowCollectionQuery = class {
12290
12614
  const states = /* @__PURE__ */ new Set();
12291
12615
  for (const [rawState, metadata] of objectEntries(values, "stateMeta")) {
12292
12616
  const state = requiredText(rawState, "stateMeta state").trim();
12293
- const stateBytes = Buffer46.byteLength(state, "utf8");
12617
+ const stateBytes = Buffer48.byteLength(state, "utf8");
12294
12618
  if (stateBytes === 0 || stateBytes > MAX_FLOW_QUERY_STATE_BYTES) {
12295
12619
  throw new TypeError(
12296
12620
  `stateMeta state names must be 1..${MAX_FLOW_QUERY_STATE_BYTES} bytes`
@@ -12469,7 +12793,7 @@ function requiredPartition(value) {
12469
12793
  "FLOW.QUERY convenience methods require a partition key"
12470
12794
  );
12471
12795
  }
12472
- const size = Buffer46.byteLength(value, "utf8");
12796
+ const size = Buffer48.byteLength(value, "utf8");
12473
12797
  if (size === 0 || size > MAX_FLOW_QUERY_PARTITION_BYTES) {
12474
12798
  throw new TypeError(
12475
12799
  `FLOW.QUERY partition key must be 1..${MAX_FLOW_QUERY_PARTITION_BYTES} bytes`
@@ -12517,23 +12841,23 @@ function requiredText(value, context) {
12517
12841
  return value;
12518
12842
  }
12519
12843
  function queryParameter(value, context) {
12520
- if (typeof value === "string" || typeof value === "boolean" || typeof value === "bigint" || typeof value === "number" || Buffer46.isBuffer(value)) {
12844
+ if (typeof value === "string" || typeof value === "boolean" || typeof value === "bigint" || typeof value === "number" || Buffer48.isBuffer(value)) {
12521
12845
  return value;
12522
12846
  }
12523
12847
  throw new TypeError(`${context} must be a scalar FLOW.QUERY parameter`);
12524
12848
  }
12525
12849
 
12526
12850
  // src/flow-query-response.ts
12527
- import { Buffer as Buffer50 } from "buffer";
12851
+ import { Buffer as Buffer52 } from "buffer";
12528
12852
 
12529
12853
  // src/flow-query-diagnostic-response.ts
12530
- import { Buffer as Buffer48 } from "buffer";
12854
+ import { Buffer as Buffer50 } from "buffer";
12531
12855
 
12532
12856
  // src/flow-query-response-validation.ts
12533
- import { Buffer as Buffer47 } from "buffer";
12857
+ import { Buffer as Buffer49 } from "buffer";
12534
12858
  function requiredMap2(value, context) {
12535
12859
  if (value instanceof Map) return value;
12536
- if (typeof value !== "object" || value == null || Array.isArray(value) || Buffer47.isBuffer(value) || value instanceof Uint8Array) {
12860
+ if (typeof value !== "object" || value == null || Array.isArray(value) || Buffer49.isBuffer(value) || value instanceof Uint8Array) {
12537
12861
  throw decodeError(`${context} must be a map`, value);
12538
12862
  }
12539
12863
  return value;
@@ -12590,7 +12914,7 @@ function normalizeMetadataValue(value, context, budget, ancestors, depth) {
12590
12914
  if (!value.isWellFormed()) throw decodeError(`${context} contains invalid text`, value);
12591
12915
  return value;
12592
12916
  }
12593
- if (Buffer47.isBuffer(value) || value instanceof Uint8Array) {
12917
+ if (Buffer49.isBuffer(value) || value instanceof Uint8Array) {
12594
12918
  const decoded = strictText2(value);
12595
12919
  if (decoded == null) throw decodeError(`${context} contains invalid UTF-8`, value);
12596
12920
  return decoded;
@@ -12669,7 +12993,7 @@ function optionalText2(mapping2, name, context) {
12669
12993
  }
12670
12994
  function requiredBoundedText2(mapping2, name, context, maximumBytes) {
12671
12995
  const value = requiredText2(mapping2, name, context);
12672
- if (Buffer47.byteLength(value, "utf8") > maximumBytes) {
12996
+ if (Buffer49.byteLength(value, "utf8") > maximumBytes) {
12673
12997
  throw decodeError(
12674
12998
  `${context} ${name} exceeds ${maximumBytes} bytes`,
12675
12999
  mapping2
@@ -12682,7 +13006,7 @@ function boundedText(value, context, maximumBytes) {
12682
13006
  if (decoded == null || decoded.length === 0) {
12683
13007
  throw decodeError(`${context} must be non-empty text`, value);
12684
13008
  }
12685
- if (Buffer47.byteLength(decoded, "utf8") > maximumBytes) {
13009
+ if (Buffer49.byteLength(decoded, "utf8") > maximumBytes) {
12686
13010
  throw decodeError(`${context} exceeds ${maximumBytes} bytes`, value);
12687
13011
  }
12688
13012
  return decoded;
@@ -12736,10 +13060,10 @@ function positiveBoundedInteger(value, maximum, context) {
12736
13060
  function hasKey(mapping2, name) {
12737
13061
  if (!(mapping2 instanceof Map)) return Object.hasOwn(mapping2, name);
12738
13062
  if (mapping2.has(name)) return true;
12739
- const binaryName = Buffer47.from(name);
13063
+ const binaryName = Buffer49.from(name);
12740
13064
  for (const key of mapping2.keys()) {
12741
- if (Buffer47.isBuffer(key) && key.equals(binaryName)) return true;
12742
- if (key instanceof Uint8Array && Buffer47.from(key).equals(binaryName))
13065
+ if (Buffer49.isBuffer(key) && key.equals(binaryName)) return true;
13066
+ if (key instanceof Uint8Array && Buffer49.from(key).equals(binaryName))
12743
13067
  return true;
12744
13068
  }
12745
13069
  return false;
@@ -12750,7 +13074,7 @@ function decodeError(message, raw) {
12750
13074
  function strictText2(value) {
12751
13075
  if (typeof value === "string")
12752
13076
  return value.isWellFormed() ? value : void 0;
12753
- if (Buffer47.isBuffer(value) || value instanceof Uint8Array) {
13077
+ if (Buffer49.isBuffer(value) || value instanceof Uint8Array) {
12754
13078
  try {
12755
13079
  return new TextDecoder("utf-8", { fatal: true }).decode(value);
12756
13080
  } catch {
@@ -12830,7 +13154,7 @@ function tryDecodeFlowQueryError(value, cause) {
12830
13154
  }
12831
13155
  function optionalDiagnosticText(mapping2, name) {
12832
13156
  const value = optionalText2(mapping2, name, "FLOW.QUERY diagnostic");
12833
- if (value != null && Buffer48.byteLength(value, "utf8") > DIAGNOSTIC_TEXT_BYTES) {
13157
+ if (value != null && Buffer50.byteLength(value, "utf8") > DIAGNOSTIC_TEXT_BYTES) {
12834
13158
  throw decodeError(
12835
13159
  `FLOW.QUERY diagnostic ${name} exceeds ${DIAGNOSTIC_TEXT_BYTES} bytes`,
12836
13160
  mapping2
@@ -12865,7 +13189,7 @@ function validateDiagnosticContextValue(value, depth, budget) {
12865
13189
  }
12866
13190
  const text3 = diagnosticContextText(value);
12867
13191
  if (text3 != null) {
12868
- if (Buffer48.byteLength(text3, "utf8") <= DIAGNOSTIC_TEXT_BYTES) return;
13192
+ if (Buffer50.byteLength(text3, "utf8") <= DIAGNOSTIC_TEXT_BYTES) return;
12869
13193
  throw decodeError("FLOW.QUERY diagnostic context contains oversized text", value);
12870
13194
  }
12871
13195
  if (depth <= 0) {
@@ -12891,7 +13215,7 @@ function validateDiagnosticContextValue(value, depth, budget) {
12891
13215
  }
12892
13216
  for (const [rawKey, item] of entries) {
12893
13217
  const key = diagnosticContextText(rawKey);
12894
- if (key == null || key.length === 0 || Buffer48.byteLength(key, "utf8") > DIAGNOSTIC_CONTEXT_KEY_BYTES) {
13218
+ if (key == null || key.length === 0 || Buffer50.byteLength(key, "utf8") > DIAGNOSTIC_CONTEXT_KEY_BYTES) {
12895
13219
  throw decodeError("FLOW.QUERY diagnostic context contains an invalid key", value);
12896
13220
  }
12897
13221
  validateDiagnosticContextValue(item, depth - 1, budget);
@@ -12908,7 +13232,7 @@ function consumeDiagnosticContextNode(value, budget) {
12908
13232
  }
12909
13233
  function diagnosticContextText(value) {
12910
13234
  if (typeof value === "string") return value.isWellFormed() ? value : void 0;
12911
- if (!Buffer48.isBuffer(value) && !(value instanceof Uint8Array)) return void 0;
13235
+ if (!Buffer50.isBuffer(value) && !(value instanceof Uint8Array)) return void 0;
12912
13236
  try {
12913
13237
  return new TextDecoder("utf-8", { fatal: true }).decode(value);
12914
13238
  } catch {
@@ -12934,7 +13258,7 @@ function decodePosition(value) {
12934
13258
  }
12935
13259
 
12936
13260
  // src/flow-query-index-contract.ts
12937
- import { Buffer as Buffer49 } from "buffer";
13261
+ import { Buffer as Buffer51 } from "buffer";
12938
13262
  var FLOW_QUERY_BUILD_PHASES = ["pending", "snapshot", "backfill", "done"];
12939
13263
  var FLOW_QUERY_VALIDATION_PHASES = [
12940
13264
  "pending",
@@ -13180,10 +13504,10 @@ function fieldKind(name) {
13180
13504
  return void 0;
13181
13505
  }
13182
13506
  function validUnquoted(value) {
13183
- return !value.startsWith("__") && UNQUOTED_METADATA.test(value) && Buffer49.byteLength(value, "ascii") <= 64;
13507
+ return !value.startsWith("__") && UNQUOTED_METADATA.test(value) && Buffer51.byteLength(value, "ascii") <= 64;
13184
13508
  }
13185
13509
  function validMetadata(value, rejectReserved) {
13186
- return value.length > 0 && Buffer49.byteLength(value, "utf8") <= 64 && (!rejectReserved || !value.startsWith("__"));
13510
+ return value.length > 0 && Buffer51.byteLength(value, "utf8") <= 64 && (!rejectReserved || !value.startsWith("__"));
13187
13511
  }
13188
13512
  function externalSelector(root, ...segments) {
13189
13513
  return segments.every(validUnquoted) ? [root, ...segments].join(".") : root + segments.map((segment) => `['${segment.replaceAll("'", "''")}']`).join("");
@@ -14090,7 +14414,7 @@ function decodePage(value) {
14090
14414
  const mapping2 = requiredMap2(value, "FLOW.QUERY page");
14091
14415
  const hasMore = requiredBoolean(mapping2, "has_more", "FLOW.QUERY page");
14092
14416
  const cursor = optionalText2(mapping2, "cursor", "FLOW.QUERY page");
14093
- if (cursor != null && (!cursor.startsWith("fqc1_") || Buffer50.byteLength(cursor) < 16 || Buffer50.byteLength(cursor) > 4096)) {
14417
+ if (cursor != null && (!cursor.startsWith("fqc1_") || Buffer52.byteLength(cursor) < 16 || Buffer52.byteLength(cursor) > 4096)) {
14094
14418
  throw decodeError("FLOW.QUERY page cursor is invalid", value);
14095
14419
  }
14096
14420
  if (hasMore !== (cursor != null)) {
@@ -14103,9 +14427,9 @@ function decodePage(value) {
14103
14427
  import "buffer";
14104
14428
 
14105
14429
  // src/client-core-helpers.ts
14106
- import { Buffer as Buffer51 } from "buffer";
14430
+ import { Buffer as Buffer53 } from "buffer";
14107
14431
  function bgsaveResponse(response) {
14108
- if ((typeof response === "string" || Buffer51.isBuffer(response) || response instanceof Uint8Array) && text(response) === "Background saving started") {
14432
+ if ((typeof response === "string" || Buffer53.isBuffer(response) || response instanceof Uint8Array) && text(response) === "Background saving started") {
14109
14433
  return true;
14110
14434
  }
14111
14435
  return okResponse(response);
@@ -14119,7 +14443,7 @@ function fetchOrComputeCompletionToken(options) {
14119
14443
  "fetch-or-compute completion requires computeToken"
14120
14444
  );
14121
14445
  }
14122
- if (!Buffer51.isBuffer(options.computeToken)) {
14446
+ if (!Buffer53.isBuffer(options.computeToken)) {
14123
14447
  throw new TypeError("fetch-or-compute computeToken must be a Buffer");
14124
14448
  }
14125
14449
  return options.computeToken;
@@ -14486,14 +14810,14 @@ var FerricStoreAdministrationClient = class extends FerricStoreClientBase {
14486
14810
  };
14487
14811
 
14488
14812
  // src/store-utilities.ts
14489
- import { Buffer as Buffer54 } from "buffer";
14813
+ import { Buffer as Buffer56 } from "buffer";
14490
14814
  function encode(codec, value) {
14491
14815
  return codec.encode(value);
14492
14816
  }
14493
14817
  function decode(codec, value) {
14494
14818
  if (value == null) return null;
14495
- if (Buffer54.isBuffer(value)) return codec.decode(value);
14496
- if (value instanceof Uint8Array) return codec.decode(Buffer54.from(value));
14819
+ if (Buffer56.isBuffer(value)) return codec.decode(value);
14820
+ if (value instanceof Uint8Array) return codec.decode(Buffer56.from(value));
14497
14821
  return value;
14498
14822
  }
14499
14823
  function number(value) {
@@ -17349,7 +17673,7 @@ function throwIfClosed(signal) {
17349
17673
  }
17350
17674
 
17351
17675
  // src/flow-policy.ts
17352
- import { Buffer as Buffer56 } from "buffer";
17676
+ import { Buffer as Buffer58 } from "buffer";
17353
17677
  var MAX_FLOW_POLICY_GENERATION = Number.MAX_SAFE_INTEGER;
17354
17678
  function assertFlowPolicyGeneration(value) {
17355
17679
  if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
@@ -17439,7 +17763,7 @@ function requiredRecord(value, context) {
17439
17763
  }
17440
17764
  return result;
17441
17765
  }
17442
- if (typeof value === "object" && value != null && !Array.isArray(value) && !Buffer56.isBuffer(value) && !(value instanceof Uint8Array)) return value;
17766
+ if (typeof value === "object" && value != null && !Array.isArray(value) && !Buffer58.isBuffer(value) && !(value instanceof Uint8Array)) return value;
17443
17767
  throw new TypeError(`${context} returned an unexpected response`);
17444
17768
  }
17445
17769
  function optionalRecord(value, context) {
@@ -17460,8 +17784,8 @@ function stringArray(value, context) {
17460
17784
  }
17461
17785
  function requiredText4(value, context) {
17462
17786
  if (typeof value === "string") return value;
17463
- if (Buffer56.isBuffer(value) || value instanceof Uint8Array) {
17464
- return Buffer56.from(value).toString("utf8");
17787
+ if (Buffer58.isBuffer(value) || value instanceof Uint8Array) {
17788
+ return Buffer58.from(value).toString("utf8");
17465
17789
  }
17466
17790
  throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
17467
17791
  }
@@ -17717,7 +18041,7 @@ var FerricStoreFlowSupportClient = class extends FerricStoreFlowQueryClient {
17717
18041
  };
17718
18042
 
17719
18043
  // src/flow-many-snapshot.ts
17720
- import { Buffer as Buffer58 } from "buffer";
18044
+ import { Buffer as Buffer60 } from "buffer";
17721
18045
  var encodedOptionFields = ["error", "payload", "reason", "result"];
17722
18046
  function snapshotCreateItem(item, codec) {
17723
18047
  const snapshot = {
@@ -17757,7 +18081,7 @@ function snapshotFlowManyOptions(options, codec) {
17757
18081
  }
17758
18082
  function snapshotClaimedItem(item) {
17759
18083
  const wire = item[CLAIMED_ITEM_WIRE];
17760
- const leaseToken = Buffer58.from(wire?.leaseToken ?? item.leaseToken);
18084
+ const leaseToken = Buffer60.from(wire?.leaseToken ?? item.leaseToken);
17761
18085
  const snapshot = {
17762
18086
  ...item,
17763
18087
  fencingToken: wire?.fencingToken ?? item.fencingToken,
@@ -17774,15 +18098,15 @@ function snapshotClaimedItem(item) {
17774
18098
  function snapshotFencedItem(item) {
17775
18099
  return Object.freeze({
17776
18100
  ...item,
17777
- ...item.leaseToken == null ? {} : { leaseToken: Buffer58.from(item.leaseToken) }
18101
+ ...item.leaseToken == null ? {} : { leaseToken: Buffer60.from(item.leaseToken) }
17778
18102
  });
17779
18103
  }
17780
18104
  function snapshotClaimedItemWire(wire, leaseToken) {
17781
18105
  return Object.freeze({
17782
18106
  fencingToken: wire.fencingToken,
17783
- id: Buffer58.from(wire.id),
18107
+ id: Buffer60.from(wire.id),
17784
18108
  leaseToken,
17785
- partitionKey: wire.partitionKey == null ? wire.partitionKey : Buffer58.from(wire.partitionKey)
18109
+ partitionKey: wire.partitionKey == null ? wire.partitionKey : Buffer60.from(wire.partitionKey)
17786
18110
  });
17787
18111
  }
17788
18112
  function snapshotArray(values) {
@@ -17793,7 +18117,7 @@ function snapshotArray(values) {
17793
18117
  return Object.freeze(snapshot);
17794
18118
  }
17795
18119
  function snapshotStateMeta(stateMeta) {
17796
- return snapshotRecord(stateMeta, (value) => Buffer58.isBuffer(value) ? Buffer58.from(value) : value);
18120
+ return snapshotRecord(stateMeta, (value) => Buffer60.isBuffer(value) ? Buffer60.from(value) : value);
17797
18121
  }
17798
18122
  function snapshotCommandRecord(values) {
17799
18123
  const seen = /* @__PURE__ */ new WeakMap();
@@ -17811,7 +18135,7 @@ function snapshotRecord(values, capture) {
17811
18135
  }
17812
18136
  function snapshotCommandArgument(value, seen) {
17813
18137
  if (typeof value !== "object" || value == null) return value;
17814
- if (Buffer58.isBuffer(value) || value instanceof Uint8Array) return Buffer58.from(value);
18138
+ if (Buffer60.isBuffer(value) || value instanceof Uint8Array) return Buffer60.from(value);
17815
18139
  const objectValue = value;
17816
18140
  const existing = seen.get(objectValue);
17817
18141
  if (existing != null) return existing;
@@ -18807,7 +19131,7 @@ function nativeOptionsForBootstrap(options, signal) {
18807
19131
  }
18808
19132
 
18809
19133
  // src/flow-query-projection.ts
18810
- import { Buffer as Buffer59 } from "buffer";
19134
+ import { Buffer as Buffer61 } from "buffer";
18811
19135
  var MAX_PROJECTION_FIELDS = 32;
18812
19136
  var MAX_DYNAMIC_NAME_BYTES = 64;
18813
19137
  var FIELD_BRAND = /* @__PURE__ */ Symbol("FerricStoreFlowProjectionField");
@@ -18877,7 +19201,7 @@ function projectFlowQuery(query, shape, ...fields) {
18877
19201
  }
18878
19202
  const base = stripOptionalTerminator(query);
18879
19203
  const result = `${base} RETURN ${shape.toUpperCase()} (${selectors.join(", ")})`;
18880
- if (Buffer59.byteLength(result, "utf8") > FLOW_QUERY_MAX_BYTES) {
19204
+ if (Buffer61.byteLength(result, "utf8") > FLOW_QUERY_MAX_BYTES) {
18881
19205
  throw new TypeError(`FLOW.QUERY query exceeds ${FLOW_QUERY_MAX_BYTES} bytes`);
18882
19206
  }
18883
19207
  return result;
@@ -18937,7 +19261,7 @@ function quoteName(value, allowPrivate) {
18937
19261
  throw new TypeError("Flow query projection metadata name must be text");
18938
19262
  }
18939
19263
  validateUnicodeScalarText2(value);
18940
- const size = Buffer59.byteLength(value, "utf8");
19264
+ const size = Buffer61.byteLength(value, "utf8");
18941
19265
  if (size === 0 || size > MAX_DYNAMIC_NAME_BYTES || !allowPrivate && value.startsWith("__")) {
18942
19266
  throw new TypeError(
18943
19267
  `Flow query projection metadata names must be 1..${MAX_DYNAMIC_NAME_BYTES} UTF-8 bytes`
@@ -20943,7 +21267,7 @@ var WorkflowWorker = class {
20943
21267
  };
20944
21268
 
20945
21269
  // src/version.ts
20946
- var FERRICSTORE_SDK_VERSION = "0.11.9";
21270
+ var FERRICSTORE_SDK_VERSION = "0.11.10";
20947
21271
  var FERRICSTORE_MINIMUM_SERVER_VERSION = "0.11.4";
20948
21272
  var FERRICSTORE_NATIVE_PROTOCOL_VERSION = 1;
20949
21273
  export {