@ferricstore/ferricstore 0.1.7 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/README.md +17 -5
  2. package/dist/index.cjs +869 -548
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +29 -30
  5. package/dist/index.d.ts +29 -30
  6. package/dist/index.js +856 -537
  7. package/dist/index.js.map +1 -1
  8. package/docs/api/assets/hierarchy.js +1 -1
  9. package/docs/api/assets/navigation.js +1 -1
  10. package/docs/api/assets/search.js +1 -1
  11. package/docs/api/classes/ClaimHydrationError.html +5 -2
  12. package/docs/api/classes/ConnectionClosedError.html +6 -3
  13. package/docs/api/classes/FerricStoreClient.html +4 -4
  14. package/docs/api/classes/FerricStoreError.html +6 -3
  15. package/docs/api/classes/FlowAlreadyExistsError.html +6 -3
  16. package/docs/api/classes/FlowBatchError.html +6 -3
  17. package/docs/api/classes/FlowNotFoundError.html +6 -3
  18. package/docs/api/classes/FlowWrongStateError.html +6 -3
  19. package/docs/api/classes/InvalidCommandError.html +6 -3
  20. package/docs/api/classes/KeyValueStore.html +2 -2
  21. package/docs/api/classes/LeaseRenewalError.html +1 -1
  22. package/docs/api/classes/LockHeldError.html +6 -3
  23. package/docs/api/classes/LockNotOwnedError.html +6 -3
  24. package/docs/api/classes/NativeAdapter.html +2 -2
  25. package/docs/api/classes/OverloadedError.html +6 -4
  26. package/docs/api/classes/QueueCompletionError.html +1 -1
  27. package/docs/api/classes/RequestTimeoutError.html +6 -3
  28. package/docs/api/classes/RerouteError.html +6 -3
  29. package/docs/api/classes/StaleLeaseError.html +6 -3
  30. package/docs/api/classes/TDigestStore.html +2 -2
  31. package/docs/api/classes/TopKStore.html +1 -1
  32. package/docs/api/classes/TopologyNativeAdapterPool.html +1 -1
  33. package/docs/api/classes/Workflow.html +1 -1
  34. package/docs/api/functions/classifyServerError.html +1 -1
  35. package/docs/api/functions/mapException.html +1 -1
  36. package/docs/api/hierarchy.html +1 -1
  37. package/docs/api/index.html +16 -6
  38. package/docs/api/interfaces/AdminListOptions.html +1 -1
  39. package/docs/api/interfaces/CancelOptions.html +2 -2
  40. package/docs/api/interfaces/ClaimDueOptions.html +3 -3
  41. package/docs/api/interfaces/CompleteJobsAndClaimJobsResult.html +6 -6
  42. package/docs/api/interfaces/CompleteManyOptions.html +2 -2
  43. package/docs/api/interfaces/CompleteOptions.html +2 -2
  44. package/docs/api/interfaces/CompleteOutcome.html +1 -1
  45. package/docs/api/interfaces/CreateManyOptions.html +1 -1
  46. package/docs/api/interfaces/EffectCompensateOptions.html +1 -1
  47. package/docs/api/interfaces/EffectConfirmOptions.html +1 -1
  48. package/docs/api/interfaces/EffectFailOptions.html +1 -1
  49. package/docs/api/interfaces/EffectStatusOptions.html +1 -1
  50. package/docs/api/interfaces/ExtendLeaseOptions.html +2 -2
  51. package/docs/api/interfaces/FailOptions.html +2 -2
  52. package/docs/api/interfaces/FailOutcome.html +1 -1
  53. package/docs/api/interfaces/FerricStoreClientFromUrlOptions.html +1 -1
  54. package/docs/api/interfaces/FerricStoreClientOptions.html +1 -1
  55. package/docs/api/interfaces/{FetchOrComputeLegacyResult.html → FetchOrComputeComputeResult.html} +2 -2
  56. package/docs/api/interfaces/FlowMaxActiveFailure.html +3 -0
  57. package/docs/api/interfaces/FlowPolicyOptions.html +3 -3
  58. package/docs/api/interfaces/FlowRecord.html +4 -2
  59. package/docs/api/interfaces/FlowStatePolicy.html +2 -2
  60. package/docs/api/interfaces/HistoryOptions.html +2 -2
  61. package/docs/api/interfaces/InvocationCreateOptions.html +2 -2
  62. package/docs/api/interfaces/LeaseMutationOptions.html +2 -2
  63. package/docs/api/interfaces/LimitListOptions.html +1 -1
  64. package/docs/api/interfaces/MutateOptions.html +2 -2
  65. package/docs/api/interfaces/NamedValueMutation.html +1 -1
  66. package/docs/api/interfaces/ProtocolCommand.html +2 -2
  67. package/docs/api/interfaces/ReadOptions.html +2 -2
  68. package/docs/api/interfaces/ReclaimOptions.html +2 -2
  69. package/docs/api/interfaces/RequestContext.html +2 -2
  70. package/docs/api/interfaces/RequestContextOptions.html +2 -2
  71. package/docs/api/interfaces/RetryOptions.html +2 -2
  72. package/docs/api/interfaces/RetryOutcome.html +1 -1
  73. package/docs/api/interfaces/RunStepsItem.html +2 -2
  74. package/docs/api/interfaces/RunStepsManyOptions.html +2 -2
  75. package/docs/api/interfaces/SearchOptions.html +2 -2
  76. package/docs/api/interfaces/StartAndClaimOptions.html +4 -2
  77. package/docs/api/interfaces/StepContinueOptions.html +3 -3
  78. package/docs/api/interfaces/TDigestCreateOptions.html +1 -1
  79. package/docs/api/interfaces/TDigestMergeOptions.html +1 -1
  80. package/docs/api/interfaces/TransitionOptions.html +2 -2
  81. package/docs/api/interfaces/TransitionOutcome.html +1 -1
  82. package/docs/api/modules.html +1 -1
  83. package/docs/api/types/FetchOrComputeFencedResult.html +1 -0
  84. package/docs/api/types/FetchOrComputeResult.html +1 -1
  85. package/docs/api/types/FlowStateMode.html +1 -1
  86. package/docs/api/types/FlowStatePolicyLike.html +1 -1
  87. package/docs/api/types/ManagementPairs.html +1 -1
  88. package/docs/api/types/RequestDisposition.html +1 -1
  89. package/docs/api/types/SearchStateMeta.html +1 -1
  90. package/docs/api/types/TopKReserveOptions.html +1 -1
  91. package/docs/api/variables/COMMAND_OPCODES.html +1 -1
  92. package/docs/api/variables/FERRICSTORE_MINIMUM_SERVER_VERSION.html +2 -0
  93. package/docs/api/variables/FERRICSTORE_NATIVE_PROTOCOL_VERSION.html +2 -0
  94. package/docs/api/variables/FERRICSTORE_SDK_VERSION.html +2 -0
  95. package/package.json +6 -1
  96. package/docs/api/interfaces/FetchOrComputeFencedResult.html +0 -9
  97. package/docs/api/types/FetchOrComputeComputeResult.html +0 -1
  98. package/docs/api/variables/COMPACT_RESPONSE_OPCODES.html +0 -2
package/dist/index.cjs CHANGED
@@ -33,11 +33,13 @@ __export(index_exports, {
33
33
  BitmapStore: () => BitmapStore,
34
34
  BloomFilterStore: () => BloomFilterStore,
35
35
  COMMAND_OPCODES: () => COMMAND_OPCODES,
36
- COMPACT_RESPONSE_OPCODES: () => COMPACT_RESPONSE_OPCODES,
37
36
  ClaimHydrationError: () => ClaimHydrationError,
38
37
  ConnectionClosedError: () => ConnectionClosedError,
39
38
  CountMinSketchStore: () => CountMinSketchStore,
40
39
  CuckooFilterStore: () => CuckooFilterStore,
40
+ FERRICSTORE_MINIMUM_SERVER_VERSION: () => FERRICSTORE_MINIMUM_SERVER_VERSION,
41
+ FERRICSTORE_NATIVE_PROTOCOL_VERSION: () => FERRICSTORE_NATIVE_PROTOCOL_VERSION,
42
+ FERRICSTORE_SDK_VERSION: () => FERRICSTORE_SDK_VERSION,
41
43
  FerricStoreClient: () => FerricStoreClient,
42
44
  FerricStoreError: () => FerricStoreError,
43
45
  FlowAlreadyExistsError: () => FlowAlreadyExistsError,
@@ -100,16 +102,22 @@ function assertSafeVariadicDispatch(argumentCount, arrayCapability) {
100
102
  // src/native-adapter.ts
101
103
  var import_node_net3 = require("net");
102
104
  var import_node_tls3 = require("tls");
103
- var import_node_buffer22 = require("buffer");
105
+ var import_node_buffer25 = require("buffer");
104
106
 
105
107
  // src/errors.ts
106
108
  var FerricStoreError = class extends Error {
107
109
  code = "ferricstore_error";
108
110
  raw;
111
+ retryable;
112
+ safeToRetry;
113
+ retryAfterMs;
109
114
  constructor(message, options = {}) {
110
115
  super(message, { cause: options.cause });
111
116
  this.name = new.target.name;
112
117
  this.raw = options.raw;
118
+ this.retryable = options.retryable ?? structuredBooleanField(options.raw, "retryable");
119
+ this.safeToRetry = options.safeToRetry ?? structuredBooleanField(options.raw, "safe_to_retry");
120
+ this.retryAfterMs = options.retryAfterMs ?? structuredIntegerField(options.raw, "retry_after_ms");
113
121
  }
114
122
  };
115
123
  var ConnectionClosedError = class extends FerricStoreError {
@@ -156,11 +164,14 @@ var InvalidCommandError = class extends FerricStoreError {
156
164
  };
157
165
  var OverloadedError = class extends FerricStoreError {
158
166
  code = "overloaded";
159
- retryAfterMs;
160
167
  reason;
161
168
  constructor(message, options = {}) {
162
- super(message, options);
163
- this.retryAfterMs = options.retryAfterMs;
169
+ const local = options.raw == null;
170
+ super(message, {
171
+ ...options,
172
+ retryable: options.retryable ?? (local ? true : void 0),
173
+ safeToRetry: options.safeToRetry ?? (local ? true : void 0)
174
+ });
164
175
  this.reason = options.reason;
165
176
  }
166
177
  };
@@ -178,15 +189,21 @@ function classifyServerError(message, raw, cause, status) {
178
189
  const lower = message.toLowerCase();
179
190
  const structuredCode = structuredStringField(raw, "code");
180
191
  const code = structuredCode?.toLowerCase();
192
+ const retry2 = {
193
+ retryable: structuredBooleanField(raw, "retryable"),
194
+ safeToRetry: structuredBooleanField(raw, "safe_to_retry"),
195
+ retryAfterMs: structuredIntegerField(raw, "retry_after_ms") ?? intField(lower, "retry_after_ms")
196
+ };
181
197
  if (isRerouteStatus(status) || code === "reroute") {
182
- return new RerouteError(message, { cause, raw });
198
+ return new RerouteError(message, { cause, raw, ...definedRetryMetadata(retry2) });
183
199
  }
184
200
  if (isBusyStatus(status) || isOverloadCode(structuredCode) || overloadMessage(lower)) {
185
201
  return new OverloadedError(message, {
186
202
  cause,
187
203
  raw,
204
+ ...definedRetryMetadata(retry2),
188
205
  reason: structuredStringField(raw, "reason") ?? structuredCode ?? stringField(lower, "reason"),
189
- retryAfterMs: structuredIntegerField(raw, "retry_after_ms") ?? intField(lower, "retry_after_ms")
206
+ retryAfterMs: retry2.retryAfterMs
190
207
  });
191
208
  }
192
209
  if (code === "flow_already_exists" || lower.includes("flow") && lower.includes("already exists")) {
@@ -210,7 +227,7 @@ function classifyServerError(message, raw, cause, status) {
210
227
  if (code === "invalid_command" || lower.includes("wrong number of arguments") || lower.includes("syntax error")) {
211
228
  return new InvalidCommandError(message, { cause, raw });
212
229
  }
213
- return new FerricStoreError(message, { cause, raw });
230
+ return new FerricStoreError(message, { cause, raw, ...definedRetryMetadata(retry2) });
214
231
  }
215
232
  function mapException(error) {
216
233
  if (error instanceof FerricStoreError) {
@@ -250,8 +267,23 @@ function structuredIntegerField(raw, name) {
250
267
  if (typeof value === "bigint") {
251
268
  return value >= 0n && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : void 0;
252
269
  }
253
- const text2 = binaryText(value);
254
- return text2 == null ? void 0 : nonNegativeSafeIntegerText(text2);
270
+ const text3 = binaryText(value);
271
+ return text3 == null ? void 0 : nonNegativeSafeIntegerText(text3);
272
+ }
273
+ function structuredBooleanField(raw, name) {
274
+ const value = structuredField(raw, name);
275
+ if (typeof value === "boolean") return value;
276
+ const text3 = binaryText(value)?.toLowerCase();
277
+ if (text3 === "true" || text3 === "1") return true;
278
+ if (text3 === "false" || text3 === "0") return false;
279
+ return void 0;
280
+ }
281
+ function definedRetryMetadata(metadata) {
282
+ return {
283
+ ...metadata.retryable == null ? {} : { retryable: metadata.retryable },
284
+ ...metadata.safeToRetry == null ? {} : { safeToRetry: metadata.safeToRetry },
285
+ ...metadata.retryAfterMs == null ? {} : { retryAfterMs: metadata.retryAfterMs }
286
+ };
255
287
  }
256
288
  function nonNegativeSafeIntegerText(value) {
257
289
  if (!/^[0-9]+$/u.test(value)) return void 0;
@@ -424,9 +456,6 @@ function mapDenseResponseArray(value, transform) {
424
456
  return result;
425
457
  }
426
458
 
427
- // src/auto-partition.ts
428
- var import_node_buffer2 = require("buffer");
429
-
430
459
  // src/crc32.ts
431
460
  var import_node_buffer = require("buffer");
432
461
  var table = new Uint32Array(256);
@@ -444,12 +473,49 @@ function crc32(buffer) {
444
473
  }
445
474
  return (value ^ 4294967295) >>> 0;
446
475
  }
476
+ function crc32Utf8(text3, start = 0, end = text3.length) {
477
+ let value = 4294967295;
478
+ for (let index = start; index < end; index += 1) {
479
+ const first = text3.charCodeAt(index);
480
+ let point = first;
481
+ if (first >= 55296 && first <= 56319) {
482
+ const second = index + 1 < end ? text3.charCodeAt(index + 1) : 0;
483
+ if (second >= 56320 && second <= 57343) {
484
+ point = 65536 + (first - 55296 << 10) + second - 56320;
485
+ index += 1;
486
+ } else {
487
+ point = 65533;
488
+ }
489
+ } else if (first >= 56320 && first <= 57343) {
490
+ point = 65533;
491
+ }
492
+ if (point < 128) {
493
+ value = updateCrc32(value, point);
494
+ } else if (point < 2048) {
495
+ value = updateCrc32(value, 192 | point >>> 6);
496
+ value = updateCrc32(value, 128 | point & 63);
497
+ } else if (point < 65536) {
498
+ value = updateCrc32(value, 224 | point >>> 12);
499
+ value = updateCrc32(value, 128 | point >>> 6 & 63);
500
+ value = updateCrc32(value, 128 | point & 63);
501
+ } else {
502
+ value = updateCrc32(value, 240 | point >>> 18);
503
+ value = updateCrc32(value, 128 | point >>> 12 & 63);
504
+ value = updateCrc32(value, 128 | point >>> 6 & 63);
505
+ value = updateCrc32(value, 128 | point & 63);
506
+ }
507
+ }
508
+ return (value ^ 4294967295) >>> 0;
509
+ }
510
+ function updateCrc32(value, byte) {
511
+ return value >>> 8 ^ (table[(value ^ byte) & 255] ?? 0);
512
+ }
447
513
 
448
514
  // src/auto-partition.ts
449
515
  var AUTO_PARTITION_PREFIX = "__flow_auto__:";
450
516
  var AUTO_PARTITION_BUCKETS = 256;
451
517
  function autoPartitionKeyForId(id) {
452
- return `${AUTO_PARTITION_PREFIX}${crc32(import_node_buffer2.Buffer.from(id)) % AUTO_PARTITION_BUCKETS}`;
518
+ return `${AUTO_PARTITION_PREFIX}${crc32Utf8(id) % AUTO_PARTITION_BUCKETS}`;
453
519
  }
454
520
 
455
521
  // src/flow-argument-helpers.ts
@@ -842,7 +908,7 @@ function coerceDiagnosticValue(value) {
842
908
  // src/native-connection.ts
843
909
  var import_node_net = __toESM(require("net"), 1);
844
910
  var import_node_tls = __toESM(require("tls"), 1);
845
- var import_node_buffer3 = require("buffer");
911
+ var import_node_buffer2 = require("buffer");
846
912
  function parseFerricUrl(value) {
847
913
  const url = new URL(value);
848
914
  if (url.protocol !== "ferric:" && url.protocol !== "ferrics:") {
@@ -968,7 +1034,7 @@ function nonNegativeSafeInteger(value) {
968
1034
  if (typeof value === "bigint") {
969
1035
  return value >= 0n && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : void 0;
970
1036
  }
971
- const source = import_node_buffer3.Buffer.isBuffer(value) || value instanceof Uint8Array ? import_node_buffer3.Buffer.from(value).toString("utf8") : value;
1037
+ const source = import_node_buffer2.Buffer.isBuffer(value) || value instanceof Uint8Array ? import_node_buffer2.Buffer.from(value).toString("utf8") : value;
972
1038
  if (typeof source !== "number" && (typeof source !== "string" || !/^\d+$/u.test(source))) {
973
1039
  return void 0;
974
1040
  }
@@ -1202,10 +1268,10 @@ var NativeHeartbeat = class {
1202
1268
  };
1203
1269
 
1204
1270
  // src/protocol.ts
1205
- var import_node_buffer18 = require("buffer");
1271
+ var import_node_buffer21 = require("buffer");
1206
1272
 
1207
1273
  // src/command-grammar.ts
1208
- var import_node_buffer4 = require("buffer");
1274
+ var import_node_buffer3 = require("buffer");
1209
1275
 
1210
1276
  // src/command-metadata-flow.ts
1211
1277
  var flowStateIdCommands = /* @__PURE__ */ new Set([
@@ -1652,8 +1718,8 @@ var secondKeySubcommands = /* @__PURE__ */ new Map([
1652
1718
  ]);
1653
1719
  function commandToken(value) {
1654
1720
  if (typeof value === "string") return value.toUpperCase();
1655
- if (import_node_buffer4.Buffer.isBuffer(value) || value instanceof Uint8Array) {
1656
- return import_node_buffer4.Buffer.from(value).toString("utf8").toUpperCase();
1721
+ if (import_node_buffer3.Buffer.isBuffer(value) || value instanceof Uint8Array) {
1722
+ return import_node_buffer3.Buffer.from(value).toString("utf8").toUpperCase();
1657
1723
  }
1658
1724
  return void 0;
1659
1725
  }
@@ -1756,7 +1822,7 @@ function safeIntegerArgument(value) {
1756
1822
  if (typeof value === "bigint") {
1757
1823
  return value >= BigInt(Number.MIN_SAFE_INTEGER) && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : void 0;
1758
1824
  }
1759
- const source = typeof value === "string" ? value : import_node_buffer4.Buffer.isBuffer(value) || value instanceof Uint8Array ? import_node_buffer4.Buffer.from(value).toString("utf8") : void 0;
1825
+ const source = typeof value === "string" ? value : import_node_buffer3.Buffer.isBuffer(value) || value instanceof Uint8Array ? import_node_buffer3.Buffer.from(value).toString("utf8") : void 0;
1760
1826
  if (source == null || !/^[+-]?\d+$/u.test(source)) return void 0;
1761
1827
  const parsed = BigInt(source);
1762
1828
  return parsed >= BigInt(Number.MIN_SAFE_INTEGER) && parsed <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(parsed) : void 0;
@@ -1809,10 +1875,10 @@ function hasOwnCommandArgument(args, index, end, section) {
1809
1875
  }
1810
1876
 
1811
1877
  // src/protocol-core.ts
1812
- var import_node_buffer8 = require("buffer");
1878
+ var import_node_buffer7 = require("buffer");
1813
1879
 
1814
1880
  // src/protocol-constants.ts
1815
- var import_node_buffer5 = require("buffer");
1881
+ var import_node_buffer4 = require("buffer");
1816
1882
 
1817
1883
  // src/native-protocol-manifest.json
1818
1884
  var native_protocol_manifest_default = {
@@ -2017,6 +2083,7 @@ var OPCODES = {
2017
2083
  flowFail: COMMAND_OPCODES["FLOW.FAIL"],
2018
2084
  flowValuePut: COMMAND_OPCODES["FLOW.VALUE.PUT"],
2019
2085
  flowValueMGet: COMMAND_OPCODES["FLOW.VALUE.MGET"],
2086
+ flowSignal: COMMAND_OPCODES["FLOW.SIGNAL"],
2020
2087
  flowCreateMany: COMMAND_OPCODES["FLOW.CREATE_MANY"],
2021
2088
  flowCompleteMany: COMMAND_OPCODES["FLOW.COMPLETE_MANY"],
2022
2089
  flowTransitionMany: COMMAND_OPCODES["FLOW.TRANSITION_MANY"],
@@ -2029,68 +2096,15 @@ var OPCODES = {
2029
2096
  flowRunStepsMany: COMMAND_OPCODES["FLOW.RUN_STEPS_MANY"],
2030
2097
  flowSearch: COMMAND_OPCODES["FLOW.SEARCH"]
2031
2098
  };
2032
- var COMPACT_RESPONSE_OPCODES = {
2033
- flow_claim_jobs_v1: [COMMAND_OPCODES["FLOW.CLAIM_DUE"]],
2034
- flow_record_list_v1: [
2035
- COMMAND_OPCODES["FLOW.LIST"],
2036
- COMMAND_OPCODES["FLOW.TERMINALS"],
2037
- COMMAND_OPCODES["FLOW.FAILURES"],
2038
- COMMAND_OPCODES["FLOW.BY_PARENT"],
2039
- COMMAND_OPCODES["FLOW.BY_ROOT"],
2040
- COMMAND_OPCODES["FLOW.BY_CORRELATION"],
2041
- COMMAND_OPCODES["FLOW.STUCK"]
2042
- ],
2043
- flow_record_v1: [COMMAND_OPCODES["FLOW.GET"]],
2044
- kv_get_v1: [COMMAND_OPCODES.GET],
2045
- kv_mget_v1: [COMMAND_OPCODES.MGET, COMMAND_OPCODES["FLOW.VALUE.MGET"]],
2046
- ok_list_v1: [
2047
- COMMAND_OPCODES.SET,
2048
- COMMAND_OPCODES.MSET,
2049
- COMMAND_OPCODES["FLOW.CREATE_MANY"],
2050
- COMMAND_OPCODES["FLOW.COMPLETE_MANY"],
2051
- COMMAND_OPCODES["FLOW.RETRY_MANY"],
2052
- COMMAND_OPCODES["FLOW.FAIL_MANY"],
2053
- COMMAND_OPCODES["FLOW.CANCEL_MANY"]
2054
- ],
2055
- pipeline_v1: [COMMAND_OPCODES.PIPELINE]
2056
- };
2057
- var COMPACT_KIND_FLOW_CLAIM_JOBS = 1 << 0;
2058
- var COMPACT_KIND_FLOW_RECORD = 1 << 1;
2059
- var COMPACT_KIND_FLOW_RECORD_LIST = 1 << 2;
2060
- var COMPACT_KIND_KV_GET = 1 << 3;
2061
- var COMPACT_KIND_KV_MGET = 1 << 4;
2062
- var COMPACT_KIND_OK_LIST = 1 << 5;
2063
- var COMPACT_KIND_PIPELINE = 1 << 6;
2064
- var compactResponseOpcodeKinds = new Uint8Array(
2065
- Math.max(...Object.values(COMPACT_RESPONSE_OPCODES).flat()) + 1
2066
- );
2067
- registerCompactResponseOpcodes(COMPACT_KIND_FLOW_CLAIM_JOBS, COMPACT_RESPONSE_OPCODES.flow_claim_jobs_v1);
2068
- registerCompactResponseOpcodes(COMPACT_KIND_FLOW_RECORD, COMPACT_RESPONSE_OPCODES.flow_record_v1);
2069
- registerCompactResponseOpcodes(COMPACT_KIND_FLOW_RECORD_LIST, COMPACT_RESPONSE_OPCODES.flow_record_list_v1);
2070
- registerCompactResponseOpcodes(COMPACT_KIND_KV_GET, COMPACT_RESPONSE_OPCODES.kv_get_v1);
2071
- registerCompactResponseOpcodes(COMPACT_KIND_KV_MGET, [
2072
- ...COMPACT_RESPONSE_OPCODES.kv_mget_v1,
2073
- COMMAND_OPCODES.PIPELINE
2074
- ]);
2075
- registerCompactResponseOpcodes(COMPACT_KIND_OK_LIST, [
2076
- ...COMPACT_RESPONSE_OPCODES.ok_list_v1,
2077
- COMMAND_OPCODES.PIPELINE
2078
- ]);
2079
- registerCompactResponseOpcodes(COMPACT_KIND_PIPELINE, COMPACT_RESPONSE_OPCODES.pipeline_v1);
2080
- function registerCompactResponseOpcodes(kind, opcodes) {
2081
- for (const opcode of opcodes) {
2082
- compactResponseOpcodeKinds[opcode] = (compactResponseOpcodeKinds[opcode] ?? 0) | kind;
2083
- }
2084
- }
2085
- function compactResponseOpcodeSupports(opcode, kind) {
2086
- return ((compactResponseOpcodeKinds[opcode] ?? 0) & kind) !== 0;
2087
- }
2088
2099
  var COMPACT_FLOW_CLAIM_JOBS = 128;
2089
2100
  var COMPACT_OK_LIST = 129;
2090
2101
  var COMPACT_KV_GET = 130;
2091
2102
  var COMPACT_KV_MGET = 131;
2092
2103
  var COMPACT_FLOW_RECORD = 132;
2093
2104
  var COMPACT_FLOW_RECORD_LIST = 133;
2105
+ var COMPACT_BINARY_LIST_LIST = 134;
2106
+ var COMPACT_BINARY_MAP_LIST = 135;
2107
+ var COMPACT_INTEGER_LIST = 136;
2094
2108
  var COMPACT_KV_MGET_FIXED = 137;
2095
2109
  var COMPACT_FLOW_CREATE_MANY_REQUEST = 144;
2096
2110
  var COMPACT_FLOW_CLAIM_DUE_REQUEST = 145;
@@ -2160,16 +2174,16 @@ var FLOW_RECORD_FIELD_KEYS = [
2160
2174
  ];
2161
2175
 
2162
2176
  // src/protocol-text.ts
2163
- var import_node_buffer6 = require("buffer");
2177
+ var import_node_buffer5 = require("buffer");
2164
2178
  function toBuffer(value) {
2165
- if (import_node_buffer6.Buffer.isBuffer(value)) return value;
2166
- if (value instanceof Uint8Array) return import_node_buffer6.Buffer.from(value);
2167
- if (typeof value === "string") return import_node_buffer6.Buffer.from(value);
2179
+ if (import_node_buffer5.Buffer.isBuffer(value)) return value;
2180
+ if (value instanceof Uint8Array) return import_node_buffer5.Buffer.from(value);
2181
+ if (typeof value === "string") return import_node_buffer5.Buffer.from(value);
2168
2182
  if (typeof value === "number" || typeof value === "bigint" || typeof value === "boolean") {
2169
- return import_node_buffer6.Buffer.from(String(value));
2183
+ return import_node_buffer5.Buffer.from(String(value));
2170
2184
  }
2171
- if (typeof value === "symbol") return import_node_buffer6.Buffer.from(value.description ?? value.toString());
2172
- if (value == null) return import_node_buffer6.Buffer.alloc(0);
2185
+ if (typeof value === "symbol") return import_node_buffer5.Buffer.from(value.description ?? value.toString());
2186
+ if (value == null) return import_node_buffer5.Buffer.alloc(0);
2173
2187
  throw new FerricStoreError(`unsupported binary command argument type: ${typeof value}`);
2174
2188
  }
2175
2189
  function asText(value) {
@@ -2177,14 +2191,14 @@ function asText(value) {
2177
2191
  }
2178
2192
  function optionalText(value) {
2179
2193
  if (value == null || value === "") return void 0;
2180
- if (typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" || import_node_buffer6.Buffer.isBuffer(value) || value instanceof Uint8Array) {
2194
+ if (typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" || import_node_buffer5.Buffer.isBuffer(value) || value instanceof Uint8Array) {
2181
2195
  return asText(value);
2182
2196
  }
2183
2197
  return void 0;
2184
2198
  }
2185
2199
  function commandTokenIs(value, expected) {
2186
2200
  if (typeof value === "string") return value.toUpperCase() === expected;
2187
- if (import_node_buffer6.Buffer.isBuffer(value) || value instanceof Uint8Array) {
2201
+ if (import_node_buffer5.Buffer.isBuffer(value) || value instanceof Uint8Array) {
2188
2202
  return asText(value).toUpperCase() === expected;
2189
2203
  }
2190
2204
  return false;
@@ -2198,7 +2212,7 @@ function commandNameIs(value, expected) {
2198
2212
  }
2199
2213
 
2200
2214
  // src/request-context.ts
2201
- var import_node_buffer7 = require("buffer");
2215
+ var import_node_buffer6 = require("buffer");
2202
2216
  var requestContextCommands = /* @__PURE__ */ new Set([
2203
2217
  "INVOCATION.CREATE",
2204
2218
  "INVOCATION.DEFINITION.GET",
@@ -2253,9 +2267,9 @@ function requestContextCommandToken(value) {
2253
2267
  const upper = value.toUpperCase();
2254
2268
  return isRequestContextCommand(upper) ? upper : void 0;
2255
2269
  }
2256
- if (import_node_buffer7.Buffer.isBuffer(value) || value instanceof Uint8Array) {
2270
+ if (import_node_buffer6.Buffer.isBuffer(value) || value instanceof Uint8Array) {
2257
2271
  if (value[0] !== 73 && value[0] !== 105) return void 0;
2258
- const command = import_node_buffer7.Buffer.from(value).toString("utf8").toUpperCase();
2272
+ const command = import_node_buffer6.Buffer.from(value).toString("utf8").toUpperCase();
2259
2273
  return isRequestContextCommand(command) ? command : void 0;
2260
2274
  }
2261
2275
  return void 0;
@@ -2286,12 +2300,12 @@ function requestContextText(context, fieldName) {
2286
2300
  return value;
2287
2301
  }
2288
2302
  function isPlainObject(value) {
2289
- return typeof value === "object" && value != null && !Array.isArray(value) && !import_node_buffer7.Buffer.isBuffer(value) && !(value instanceof Uint8Array);
2303
+ return typeof value === "object" && value != null && !Array.isArray(value) && !import_node_buffer6.Buffer.isBuffer(value) && !(value instanceof Uint8Array);
2290
2304
  }
2291
2305
  function commandToken2(value) {
2292
2306
  if (typeof value === "string") return value.toUpperCase();
2293
- if (import_node_buffer7.Buffer.isBuffer(value) || value instanceof Uint8Array) {
2294
- return import_node_buffer7.Buffer.from(value).toString("utf8").toUpperCase();
2307
+ if (import_node_buffer6.Buffer.isBuffer(value) || value instanceof Uint8Array) {
2308
+ return import_node_buffer6.Buffer.from(value).toString("utf8").toUpperCase();
2295
2309
  }
2296
2310
  return "";
2297
2311
  }
@@ -2381,17 +2395,17 @@ function requestFrameTooLarge(maxBytes) {
2381
2395
  );
2382
2396
  }
2383
2397
  function binaryValueByteLength(value) {
2384
- if (import_node_buffer8.Buffer.isBuffer(value) || value instanceof Uint8Array) return value.byteLength;
2385
- if (typeof value === "string") return import_node_buffer8.Buffer.byteLength(value);
2398
+ if (import_node_buffer7.Buffer.isBuffer(value) || value instanceof Uint8Array) return value.byteLength;
2399
+ if (typeof value === "string") return import_node_buffer7.Buffer.byteLength(value);
2386
2400
  if (typeof value === "number" || typeof value === "bigint" || typeof value === "boolean") {
2387
- return import_node_buffer8.Buffer.byteLength(String(value));
2401
+ return import_node_buffer7.Buffer.byteLength(String(value));
2388
2402
  }
2389
- if (typeof value === "symbol") return import_node_buffer8.Buffer.byteLength(value.description ?? value.toString());
2403
+ if (typeof value === "symbol") return import_node_buffer7.Buffer.byteLength(value.description ?? value.toString());
2390
2404
  if (value == null) return 0;
2391
2405
  return toBuffer(value).byteLength;
2392
2406
  }
2393
2407
  function writeCustomPayload(output, offset, value, knownByteLength) {
2394
- if (import_node_buffer8.Buffer.isBuffer(value)) {
2408
+ if (import_node_buffer7.Buffer.isBuffer(value)) {
2395
2409
  value.copy(output, offset);
2396
2410
  return;
2397
2411
  }
@@ -2400,17 +2414,17 @@ function writeCustomPayload(output, offset, value, knownByteLength) {
2400
2414
  return;
2401
2415
  }
2402
2416
  if (value == null) return;
2403
- let text2;
2417
+ let text3;
2404
2418
  if (typeof value === "string") {
2405
- text2 = value;
2419
+ text3 = value;
2406
2420
  } else if (typeof value === "number" || typeof value === "bigint" || typeof value === "boolean") {
2407
- text2 = String(value);
2421
+ text3 = String(value);
2408
2422
  } else if (typeof value === "symbol") {
2409
- text2 = value.description ?? value.toString();
2423
+ text3 = value.description ?? value.toString();
2410
2424
  } else {
2411
2425
  throw new FerricStoreError(`unsupported binary command argument type: ${typeof value}`);
2412
2426
  }
2413
- output.write(text2, offset, knownByteLength ?? import_node_buffer8.Buffer.byteLength(text2), "utf8");
2427
+ output.write(text3, offset, knownByteLength ?? import_node_buffer7.Buffer.byteLength(text3), "utf8");
2414
2428
  }
2415
2429
  function compactBinaryEncodedLength(value) {
2416
2430
  return 4 + compactBinaryByteLength(value);
@@ -2423,10 +2437,10 @@ function compactBinaryByteLength(value) {
2423
2437
  return byteLength;
2424
2438
  }
2425
2439
  function isCompactBinaryArgument(value) {
2426
- return typeof value === "string" || import_node_buffer8.Buffer.isBuffer(value) || value instanceof Uint8Array;
2440
+ return typeof value === "string" || import_node_buffer7.Buffer.isBuffer(value) || value instanceof Uint8Array;
2427
2441
  }
2428
2442
  function isCompactBinaryScalar(value) {
2429
- return value == null || typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" || typeof value === "symbol" || import_node_buffer8.Buffer.isBuffer(value) || value instanceof Uint8Array;
2443
+ return value == null || typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" || typeof value === "symbol" || import_node_buffer7.Buffer.isBuffer(value) || value instanceof Uint8Array;
2430
2444
  }
2431
2445
  function compactOptionalBinaryEncodedLength(value) {
2432
2446
  return value == null ? 4 : compactBinaryEncodedLength(value);
@@ -2509,13 +2523,13 @@ function i64Arg(value) {
2509
2523
  }
2510
2524
  function boolArg(value) {
2511
2525
  if (typeof value === "boolean") return value;
2512
- const text2 = asText(value).toUpperCase();
2513
- return text2 === "1" || text2 === "TRUE" || text2 === "YES" || text2 === "ON";
2526
+ const text3 = asText(value).toUpperCase();
2527
+ return text3 === "1" || text3 === "TRUE" || text3 === "YES" || text3 === "ON";
2514
2528
  }
2515
2529
  function isBoolToken(value) {
2516
2530
  if (typeof value === "boolean") return true;
2517
- const text2 = asText(value).toUpperCase();
2518
- return text2 === "1" || text2 === "0" || text2 === "TRUE" || text2 === "FALSE" || text2 === "YES" || text2 === "NO" || text2 === "ON" || text2 === "OFF";
2531
+ const text3 = asText(value).toUpperCase();
2532
+ return text3 === "1" || text3 === "0" || text3 === "TRUE" || text3 === "FALSE" || text3 === "YES" || text3 === "NO" || text3 === "ON" || text3 === "OFF";
2519
2533
  }
2520
2534
  function independentMode(value) {
2521
2535
  if (value === true) return 2;
@@ -2557,7 +2571,23 @@ function setOwnValue2(target, key, value) {
2557
2571
  }
2558
2572
 
2559
2573
  // src/protocol-flow-options.ts
2560
- var import_node_buffer9 = require("buffer");
2574
+ var import_node_buffer8 = require("buffer");
2575
+
2576
+ // src/protocol-flow-option-value.ts
2577
+ function setFlowOptionValue(payload, field2, value, repeat) {
2578
+ if (!repeat || !Object.hasOwn(payload, field2)) {
2579
+ setOwnValue2(payload, field2, value);
2580
+ return;
2581
+ }
2582
+ const previous = payload[field2];
2583
+ setOwnValue2(
2584
+ payload,
2585
+ field2,
2586
+ Array.isArray(previous) ? [...previous, value] : [previous, value]
2587
+ );
2588
+ }
2589
+
2590
+ // src/protocol-flow-options.ts
2561
2591
  var OPTION_FIELDS = {
2562
2592
  CONSISTENT_PROJECTION: "consistent_projection",
2563
2593
  COUNT: "count",
@@ -2632,7 +2662,7 @@ function normalizeFlowSearchStateMeta(payload) {
2632
2662
  payload.state_meta = { [asText(state)]: stateMeta };
2633
2663
  }
2634
2664
  function isPlainObject2(value) {
2635
- return typeof value === "object" && value != null && !Array.isArray(value) && !import_node_buffer9.Buffer.isBuffer(value) && !(value instanceof Uint8Array);
2665
+ return typeof value === "object" && value != null && !Array.isArray(value) && !import_node_buffer8.Buffer.isBuffer(value) && !(value instanceof Uint8Array);
2636
2666
  }
2637
2667
  function parseFlowOptions(args, start, end, config) {
2638
2668
  const payload = {};
@@ -2726,8 +2756,9 @@ function parseFlowOptions(args, start, end, config) {
2726
2756
  case "TRANSITION_TO":
2727
2757
  case "TO_EVENT":
2728
2758
  case "EXPECT_STATE": {
2729
- const field2 = token.toLowerCase();
2730
- if (!putScalar(payload, field2, args, index + 1, end)) return void 0;
2759
+ const field2 = token === "IDEMPOTENCY" ? "idempotency_key" : token.toLowerCase();
2760
+ if (!hasOwnCommandArgument(args, index + 1, end, "Flow options")) return void 0;
2761
+ setFlowOptionValue(payload, field2, args[index + 1], token === "IF_STATE");
2731
2762
  index += 2;
2732
2763
  break;
2733
2764
  }
@@ -3017,6 +3048,7 @@ var FLOW_ADMIN_FIELDS = {
3017
3048
  LEASE_MS: "lease_ms",
3018
3049
  LEASE_TOKEN: "lease_token",
3019
3050
  LIMIT: "limit",
3051
+ MAX_ACTIVE_MS: "max_active_ms",
3020
3052
  MAX_FIRES: "max_fires",
3021
3053
  MAXBYTES: "payload_max_bytes",
3022
3054
  NOW: "now_ms",
@@ -3026,7 +3058,6 @@ var FLOW_ADMIN_FIELDS = {
3026
3058
  OVERLAP_RETRY_MS: "overlap_retry_ms",
3027
3059
  OVERWRITE: "overwrite",
3028
3060
  PARENT_FLOW_ID: "parent_flow_id",
3029
- PARENT_ID: "parent_id",
3030
3061
  PARTITION: "partition_key",
3031
3062
  PAYLOAD: "payload",
3032
3063
  PAYLOAD_MAX_BYTES: "payload_max_bytes",
@@ -3041,7 +3072,6 @@ var FLOW_ADMIN_FIELDS = {
3041
3072
  REV: "rev",
3042
3073
  RETURN: "return",
3043
3074
  ROOT_FLOW_ID: "root_flow_id",
3044
- ROOT_ID: "root_id",
3045
3075
  SCOPE: "scope",
3046
3076
  SHARD_ID: "shard_id",
3047
3077
  START_AT_MS: "start_at_ms",
@@ -3178,7 +3208,7 @@ function flowAdminPayload(opcode, args, leadingFields = []) {
3178
3208
  }
3179
3209
 
3180
3210
  // src/protocol-flow-compact.ts
3181
- var import_node_buffer11 = require("buffer");
3211
+ var import_node_buffer10 = require("buffer");
3182
3212
 
3183
3213
  // src/protocol-flow-compact-common.ts
3184
3214
  function compactManyRequestTag(value, regularTag, okOnSuccessTag) {
@@ -3287,7 +3317,7 @@ function parseNamedCountMap(values, start) {
3287
3317
  }
3288
3318
 
3289
3319
  // src/protocol-flow-compact-transition.ts
3290
- var import_node_buffer10 = require("buffer");
3320
+ var import_node_buffer9 = require("buffer");
3291
3321
  function compactFlowTransitionManyPayload(partition, fromState, toState, rawItems, mixed, options, maxBodyBytes) {
3292
3322
  if ("payload" in options || "priority" in options || "state_meta" in options || "values" in options || "value_refs" in options || "drop_values" in options || "override_values" in options || "attributes_merge" in options || "attributes_delete" in options || typeof options.now_ms !== "number" || !Number.isSafeInteger(options.now_ms) || options.now_ms < 0) {
3293
3323
  return void 0;
@@ -3339,7 +3369,7 @@ function compactFlowTransitionManyPayload(partition, fromState, toState, rawItem
3339
3369
  total += 4 + idLength + 4 + itemPartitionLength + 8 + 4 + leaseLength;
3340
3370
  }
3341
3371
  assertCompactPayloadFits(total, maxBodyBytes);
3342
- const out = import_node_buffer10.Buffer.allocUnsafe(total);
3372
+ const out = import_node_buffer9.Buffer.allocUnsafe(total);
3343
3373
  let offset = 0;
3344
3374
  out.writeUInt8(tag, offset);
3345
3375
  offset += 1;
@@ -3397,7 +3427,7 @@ function compactFlowCreateManyPayload(partition, rawItems, mixed, auto, options,
3397
3427
  }
3398
3428
  assertCompactPayloadFits(total, maxBodyBytes);
3399
3429
  const tag = mixed ? COMPACT_FLOW_CREATE_MANY_MIXED_REQUEST : auto ? COMPACT_FLOW_CREATE_MANY_REQUEST : COMPACT_FLOW_CREATE_MANY_PARTITION_REQUEST;
3400
- const out = import_node_buffer11.Buffer.allocUnsafe(total);
3430
+ const out = import_node_buffer10.Buffer.allocUnsafe(total);
3401
3431
  let offset = 0;
3402
3432
  out.writeUInt8(tag, offset++);
3403
3433
  offset = writeBinary(out, offset, toBuffer(options.type));
@@ -3442,7 +3472,7 @@ function compactFlowClaimDuePayload(type, options, maxBodyBytes) {
3442
3472
  total += 1;
3443
3473
  }
3444
3474
  assertCompactPayloadFits(total, maxBodyBytes);
3445
- const out = import_node_buffer11.Buffer.allocUnsafe(total);
3475
+ const out = import_node_buffer10.Buffer.allocUnsafe(total);
3446
3476
  let offset = 0;
3447
3477
  out.writeUInt8(COMPACT_FLOW_CLAIM_DUE_REQUEST, offset++);
3448
3478
  offset = writeBinary(out, offset, toBuffer(type));
@@ -3496,7 +3526,7 @@ function compactFlowCompleteManyPayload(opcode, partition, rawItems, mixed, auto
3496
3526
  total += compactBinaryEncodedLength(rawItems[rawIndex]) + compactOptionalBinaryEncodedLength(mixed ? rawItems[rawIndex + 1] : null) + compactBinaryEncodedLength(rawItems[rawIndex + width - 2]) + 8;
3497
3527
  }
3498
3528
  assertCompactPayloadFits(total, maxBodyBytes);
3499
- const out = import_node_buffer11.Buffer.allocUnsafe(total);
3529
+ const out = import_node_buffer10.Buffer.allocUnsafe(total);
3500
3530
  let offset = 0;
3501
3531
  out.writeUInt8(
3502
3532
  returnMode === "OK_ON_SUCCESS" ? COMPACT_FLOW_COMPLETE_MANY_OK_REQUEST : COMPACT_FLOW_COMPLETE_MANY_REQUEST,
@@ -3543,7 +3573,7 @@ function compactFlowRetryManyPayload(partition, rawItems, mixed, auto, options,
3543
3573
  total += compactBinaryEncodedLength(rawItems[rawIndex]) + compactOptionalBinaryEncodedLength(mixed ? rawItems[rawIndex + 1] : null) + compactBinaryEncodedLength(rawItems[rawIndex + width - 2]) + 8;
3544
3574
  }
3545
3575
  assertCompactPayloadFits(total, maxBodyBytes);
3546
- const out = import_node_buffer11.Buffer.allocUnsafe(total);
3576
+ const out = import_node_buffer10.Buffer.allocUnsafe(total);
3547
3577
  let offset = 0;
3548
3578
  out.writeUInt8(
3549
3579
  returnMode === "OK_ON_SUCCESS" ? COMPACT_FLOW_RETRY_MANY_OK_REQUEST : COMPACT_FLOW_RETRY_MANY_REQUEST,
@@ -3631,7 +3661,7 @@ function compactFlowCancelManyPayload(args, maxBodyBytes) {
3631
3661
  total += 4 + idLength + 4 + itemPartitionLength + 8;
3632
3662
  }
3633
3663
  assertCompactPayloadFits(total, maxBodyBytes);
3634
- const out = import_node_buffer11.Buffer.allocUnsafe(total);
3664
+ const out = import_node_buffer10.Buffer.allocUnsafe(total);
3635
3665
  let offset = 0;
3636
3666
  out.writeUInt8(tag, offset);
3637
3667
  offset += 1;
@@ -3667,7 +3697,7 @@ function isOptionalSafeIntegerNumber(value) {
3667
3697
  }
3668
3698
 
3669
3699
  // src/protocol-flow-compact-single.ts
3670
- var import_node_buffer12 = require("buffer");
3700
+ var import_node_buffer11 = require("buffer");
3671
3701
  function compactFlowValueMGetPayload(refs, maxBytes, maxBodyBytes) {
3672
3702
  if (refs.length > 4294967295 || maxBytes != null && (typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 0)) return void 0;
3673
3703
  const minimum = 13 + refs.length * 4;
@@ -3684,7 +3714,7 @@ function compactFlowValueMGetPayload(refs, maxBytes, maxBodyBytes) {
3684
3714
  total += 4 + byteLength;
3685
3715
  }
3686
3716
  assertCompactPayloadFits(total, maxBodyBytes);
3687
- const out = import_node_buffer12.Buffer.allocUnsafe(total);
3717
+ const out = import_node_buffer11.Buffer.allocUnsafe(total);
3688
3718
  let offset = 0;
3689
3719
  out.writeUInt8(COMPACT_FLOW_VALUE_MGET_REQUEST, offset);
3690
3720
  offset += 1;
@@ -3727,7 +3757,7 @@ function compactFlowListPayload(args, maxBodyBytes) {
3727
3757
  const stateLength = state == null ? 0 : compactBinaryByteLength(state);
3728
3758
  const total = 1 + 4 + typeLength + 4 + stateLength + 8 + 1;
3729
3759
  assertCompactPayloadFits(total, maxBodyBytes);
3730
- const out = import_node_buffer12.Buffer.allocUnsafe(total);
3760
+ const out = import_node_buffer11.Buffer.allocUnsafe(total);
3731
3761
  let offset = 0;
3732
3762
  out.writeUInt8(COMPACT_FLOW_LIST_REQUEST, offset);
3733
3763
  offset += 1;
@@ -4170,6 +4200,7 @@ function flowSpawnChildrenPayload(args) {
4170
4200
  "FROM_STATE",
4171
4201
  "ON_CHILD_FAILED",
4172
4202
  "ON_PARENT_CLOSED",
4203
+ "MAX_ACTIVE_MS",
4173
4204
  "VALUE",
4174
4205
  "VALUE_REF"
4175
4206
  ])
@@ -4200,6 +4231,29 @@ function flowSearchPayload(args) {
4200
4231
  return { opcode: OPCODES.flowSearch, payload: { type: args[0], ...payload } };
4201
4232
  }
4202
4233
 
4234
+ // src/protocol-flow-signal.ts
4235
+ function flowSignalPayload(args) {
4236
+ if (args.length < 3) return void 0;
4237
+ const options = parseFlowOptions(args, 1, args.length, {
4238
+ allowed: /* @__PURE__ */ new Set([
4239
+ "SIGNAL",
4240
+ "PARTITION",
4241
+ "IDEMPOTENCY",
4242
+ "IF_STATE",
4243
+ "TRANSITION_TO",
4244
+ "RUN_AT",
4245
+ "NOW",
4246
+ "VALUE",
4247
+ "VALUE_REF",
4248
+ "DROP_VALUE",
4249
+ "OVERRIDE_VALUE"
4250
+ ]),
4251
+ required: /* @__PURE__ */ new Set(["SIGNAL"])
4252
+ });
4253
+ if (options == null) return void 0;
4254
+ return { opcode: OPCODES.flowSignal, payload: { id: args[0], ...options } };
4255
+ }
4256
+
4203
4257
  // src/protocol-connection-policy.ts
4204
4258
  function assertCommandDoesNotRequirePinnedConnection(args) {
4205
4259
  const outer = commandName(args[0]);
@@ -4247,7 +4301,7 @@ function commandRequiresOrderedPipelineExecution(args) {
4247
4301
  }
4248
4302
 
4249
4303
  // src/protocol-compact-request.ts
4250
- var import_node_buffer13 = require("buffer");
4304
+ var import_node_buffer12 = require("buffer");
4251
4305
  function compactMsetPayload(args, maxBodyBytes) {
4252
4306
  if (args.length % 2 !== 0) throw new FerricStoreError("MSET requires key/value pairs");
4253
4307
  const minimum = 6 + args.length * 4;
@@ -4266,7 +4320,7 @@ function compactMsetPayload(args, maxBodyBytes) {
4266
4320
  total += 4 + byteLength;
4267
4321
  }
4268
4322
  assertCompactPayloadFits(total, maxBodyBytes);
4269
- const out = import_node_buffer13.Buffer.allocUnsafe(total);
4323
+ const out = import_node_buffer12.Buffer.allocUnsafe(total);
4270
4324
  let offset = writeCompactPipelineHeader(out, 1, args.length / 2);
4271
4325
  for (let index = 0; index < args.length; index += 1) {
4272
4326
  offset = writeBinaryValue(out, offset, args[index], byteLengths[index] ?? 0);
@@ -4290,7 +4344,7 @@ function compactKeyPipelinePayload(opcode, args, mode, maxBodyBytes) {
4290
4344
  total += 4 + byteLength;
4291
4345
  }
4292
4346
  assertCompactPayloadFits(total, maxBodyBytes);
4293
- const out = import_node_buffer13.Buffer.allocUnsafe(total);
4347
+ const out = import_node_buffer12.Buffer.allocUnsafe(total);
4294
4348
  let offset = writeCompactPipelineHeader(out, mode, args.length);
4295
4349
  for (let index = 0; index < args.length; index += 1) {
4296
4350
  offset = writeBinaryValue(out, offset, args[index], byteLengths[index] ?? 0);
@@ -4300,7 +4354,7 @@ function compactKeyPipelinePayload(opcode, args, mode, maxBodyBytes) {
4300
4354
  function compactPipelinePayload(commands, maxBodyBytes) {
4301
4355
  if (commands.length === 0) {
4302
4356
  assertCompactPayloadFits(6, maxBodyBytes);
4303
- const out = import_node_buffer13.Buffer.allocUnsafe(6);
4357
+ const out = import_node_buffer12.Buffer.allocUnsafe(6);
4304
4358
  writeCompactPipelineHeader(out, 128 | 2, 0);
4305
4359
  return out;
4306
4360
  }
@@ -4342,7 +4396,7 @@ function compactSetPipelinePayload(commands, maxBodyBytes) {
4342
4396
  total += 8 + keyByteLength + valueByteLength;
4343
4397
  }
4344
4398
  assertCompactPayloadFits(total, maxBodyBytes);
4345
- const out = import_node_buffer13.Buffer.allocUnsafe(total);
4399
+ const out = import_node_buffer12.Buffer.allocUnsafe(total);
4346
4400
  let offset = writeCompactPipelineHeader(out, 128 | 1, commands.length);
4347
4401
  for (let index = 0; index < commands.length; index += 1) {
4348
4402
  offset = writeBinaryValue(out, offset, argumentValues[index * 2], argumentByteLengths[index * 2] ?? 0);
@@ -4377,7 +4431,7 @@ function compactGetPipelinePayload(commands, maxBodyBytes) {
4377
4431
  total += 4 + keyByteLength;
4378
4432
  }
4379
4433
  assertCompactPayloadFits(total, maxBodyBytes);
4380
- const out = import_node_buffer13.Buffer.allocUnsafe(total);
4434
+ const out = import_node_buffer12.Buffer.allocUnsafe(total);
4381
4435
  let offset = writeCompactPipelineHeader(out, 128 | 2, commands.length);
4382
4436
  for (let index = 0; index < commands.length; index += 1) {
4383
4437
  offset = writeBinaryValue(out, offset, keys[index], keyByteLengths[index] ?? 0);
@@ -4418,7 +4472,7 @@ function writeCompactPipelineHeader(out, mode, count) {
4418
4472
  }
4419
4473
 
4420
4474
  // src/protocol-kv.ts
4421
- var import_node_buffer14 = require("buffer");
4475
+ var import_node_buffer13 = require("buffer");
4422
4476
  function collectionProtocolCommand(command, args) {
4423
4477
  switch (command) {
4424
4478
  case "CAS":
@@ -4566,15 +4620,20 @@ function fetchOrComputeCommand(args) {
4566
4620
  };
4567
4621
  }
4568
4622
  function fetchOrComputeResultCommand(args) {
4569
- if (args.length !== 4 || !isBinaryCommandArgument(args[0]) || !isBinaryCommandArgument(args[1])) return void 0;
4623
+ if (args.length !== 4 || !isBinaryCommandArgument(args[0]) || !isBinaryCommandArgument(args[1])) {
4624
+ throw new FerricStoreError("FETCH_OR_COMPUTE_RESULT requires key, ownership token, value, and ttl_ms");
4625
+ }
4570
4626
  const ttlMs = positiveSafeInteger2(args[3]);
4571
- return ttlMs == null ? void 0 : {
4627
+ if (ttlMs == null) throw new FerricStoreError("FETCH_OR_COMPUTE_RESULT ttl_ms must be positive");
4628
+ return {
4572
4629
  opcode: COMMAND_OPCODES.FETCH_OR_COMPUTE_RESULT,
4573
4630
  payload: { key: args[0], token: args[1], ttl_ms: ttlMs, value: args[2] }
4574
4631
  };
4575
4632
  }
4576
4633
  function fetchOrComputeErrorCommand(args) {
4577
- if (args.length !== 3 || !isBinaryCommandArgument(args[0]) || !isBinaryCommandArgument(args[1]) || !isBinaryCommandArgument(args[2])) return void 0;
4634
+ if (args.length !== 3 || !isBinaryCommandArgument(args[0]) || !isBinaryCommandArgument(args[1]) || !isBinaryCommandArgument(args[2])) {
4635
+ throw new FerricStoreError("FETCH_OR_COMPUTE_ERROR requires key, ownership token, and message");
4636
+ }
4578
4637
  return {
4579
4638
  opcode: COMMAND_OPCODES.FETCH_OR_COMPUTE_ERROR,
4580
4639
  payload: { key: args[0], message: args[2], token: args[1] }
@@ -4660,17 +4719,17 @@ function parsedNumber(value) {
4660
4719
  }
4661
4720
  }
4662
4721
  function isBinaryCommandArgument(value) {
4663
- return typeof value === "string" || import_node_buffer14.Buffer.isBuffer(value);
4722
+ return typeof value === "string" || import_node_buffer13.Buffer.isBuffer(value);
4664
4723
  }
4665
4724
  function isDirectKvValueArgument(value) {
4666
4725
  return isBinaryCommandArgument(value) || typeof value === "object" && value != null;
4667
4726
  }
4668
4727
  function binaryToken(value) {
4669
- return typeof value === "string" ? value.toUpperCase() : import_node_buffer14.Buffer.isBuffer(value) ? value.toString("utf8").toUpperCase() : void 0;
4728
+ return typeof value === "string" ? value.toUpperCase() : import_node_buffer13.Buffer.isBuffer(value) ? value.toString("utf8").toUpperCase() : void 0;
4670
4729
  }
4671
4730
 
4672
4731
  // src/protocol-value.ts
4673
- var import_node_buffer15 = require("buffer");
4732
+ var import_node_buffer14 = require("buffer");
4674
4733
  function planValueWithLimit(value, maxBytes) {
4675
4734
  const budget = {
4676
4735
  maxBytes,
@@ -4725,7 +4784,7 @@ function planContainerValue(value, budget, ancestors, depth) {
4725
4784
  let byteLength = 5;
4726
4785
  let index = 0;
4727
4786
  for (const [key, item] of entries) {
4728
- const keyByteLength = import_node_buffer15.Buffer.byteLength(key);
4787
+ const keyByteLength = import_node_buffer14.Buffer.byteLength(key);
4729
4788
  consumeEncodeBytes(budget, 4 + keyByteLength);
4730
4789
  const valuePlan = planValueAt(item, budget, ancestors, depth + 1);
4731
4790
  entryPlans[index] = { key, keyByteLength, value: valuePlan };
@@ -4774,7 +4833,7 @@ function planScalarValue(value, budget) {
4774
4833
  consumeEncodeBytes(budget, 9);
4775
4834
  return { byteLength: 9, tag: 7, value };
4776
4835
  }
4777
- if (typeof value === "string" || import_node_buffer15.Buffer.isBuffer(value) || value instanceof Uint8Array) {
4836
+ if (typeof value === "string" || import_node_buffer14.Buffer.isBuffer(value) || value instanceof Uint8Array) {
4778
4837
  const valueByteLength = binaryValueByteLength(value);
4779
4838
  const byteLength = 5 + valueByteLength;
4780
4839
  consumeEncodeBytes(budget, byteLength);
@@ -4798,7 +4857,7 @@ function writeValuePlan(output, start, plan) {
4798
4857
  offset += 4;
4799
4858
  if (typeof plan.value === "string") {
4800
4859
  output.write(plan.value, offset, plan.valueByteLength, "utf8");
4801
- } else if (import_node_buffer15.Buffer.isBuffer(plan.value)) {
4860
+ } else if (import_node_buffer14.Buffer.isBuffer(plan.value)) {
4802
4861
  plan.value.copy(output, offset);
4803
4862
  } else {
4804
4863
  output.set(plan.value, offset);
@@ -4931,58 +4990,458 @@ function requireAvailable(data, offset, size) {
4931
4990
  }
4932
4991
  }
4933
4992
 
4993
+ // src/key-slot-validation.ts
4994
+ var import_node_buffer16 = require("buffer");
4995
+
4996
+ // src/topology-utilities.ts
4997
+ var import_node_buffer15 = require("buffer");
4998
+ function isPlainObject3(value) {
4999
+ return typeof value === "object" && value != null && !Array.isArray(value) && !import_node_buffer15.Buffer.isBuffer(value);
5000
+ }
5001
+ function getField(source, ...keys) {
5002
+ if (source instanceof Map) {
5003
+ for (const key of keys) {
5004
+ if (source.has(key)) return source.get(key);
5005
+ const bufferKey = import_node_buffer15.Buffer.from(key);
5006
+ for (const [itemKey, value] of source.entries()) {
5007
+ if (import_node_buffer15.Buffer.isBuffer(itemKey) && itemKey.equals(bufferKey)) return value;
5008
+ }
5009
+ }
5010
+ return void 0;
5011
+ }
5012
+ if (isPlainObject3(source)) {
5013
+ for (const key of keys) {
5014
+ if (Object.hasOwn(source, key)) return source[key];
5015
+ }
5016
+ }
5017
+ return void 0;
5018
+ }
5019
+ function textOrUndefined(value) {
5020
+ if (typeof value === "string") return value;
5021
+ if (import_node_buffer15.Buffer.isBuffer(value)) return value.toString("utf8");
5022
+ return void 0;
5023
+ }
5024
+ function numberOrUndefined(value) {
5025
+ return typeof value === "number" && Number.isSafeInteger(value) ? value : void 0;
5026
+ }
5027
+ function nativeEventName(event) {
5028
+ return textOrUndefined(getField(event.value, "event"))?.toUpperCase();
5029
+ }
5030
+ function endpointFromRange(item) {
5031
+ const endpointValue = getField(item, "endpoint");
5032
+ if (endpointValue != null && !isPlainObject3(endpointValue) && !(endpointValue instanceof Map)) {
5033
+ throw new FerricStoreError("invalid SHARDS endpoint", { raw: item });
5034
+ }
5035
+ const raw = endpointValue ?? item;
5036
+ const host = textOrUndefined(getField(raw, "host", "native_host"));
5037
+ const nativePort = numberOrUndefined(getField(raw, "native_port"));
5038
+ if (host == null || !validEndpointHost(host) || nativePort == null || nativePort <= 0 || nativePort > 65535) {
5039
+ throw new FerricStoreError("invalid SHARDS endpoint", { raw: item });
5040
+ }
5041
+ const nativeTlsPortValue = getField(raw, "native_tls_port");
5042
+ const nativeTlsPort = numberOrUndefined(nativeTlsPortValue);
5043
+ if (nativeTlsPortValue != null && (nativeTlsPort == null || nativeTlsPort <= 0 || nativeTlsPort > 65535)) {
5044
+ throw new FerricStoreError("invalid SHARDS endpoint", { raw: item });
5045
+ }
5046
+ return {
5047
+ host,
5048
+ nativePort,
5049
+ node: textOrUndefined(getField(raw, "node", "leader_node", "owner_node")) ?? host,
5050
+ ...nativeTlsPort == null ? {} : { nativeTlsPort }
5051
+ };
5052
+ }
5053
+ function validEndpointHost(host) {
5054
+ if (host.length === 0 || host.trim() !== host || /[\s\\/?#@]/u.test(host)) return false;
5055
+ const authorityHost = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
5056
+ try {
5057
+ const url = new URL(`ferric://${authorityHost}:6388`);
5058
+ return url.hostname !== "" && url.port === "6388" && url.username === "" && url.password === "";
5059
+ } catch {
5060
+ return false;
5061
+ }
5062
+ }
5063
+ function sameEndpoint(left, right) {
5064
+ return normalizedEndpointHost(left.host) === normalizedEndpointHost(right.host) && left.nativePort === right.nativePort && left.nativeTlsPort === right.nativeTlsPort && left.node === right.node;
5065
+ }
5066
+ function parseFerricUrl2(value) {
5067
+ const url = new URL(value);
5068
+ if (url.protocol !== "ferric:" && url.protocol !== "ferrics:") {
5069
+ throw new FerricStoreError(`unsupported FerricStore URL scheme: ${url.protocol}`);
5070
+ }
5071
+ return {
5072
+ host: normalizeFerricUrlHost(url.hostname),
5073
+ ...url.password === "" ? {} : { password: decodeURIComponent(url.password) },
5074
+ port: Number(url.port || (url.protocol === "ferrics:" ? 6389 : 6388)),
5075
+ tls: url.protocol === "ferrics:",
5076
+ ...url.username === "" ? {} : { username: decodeURIComponent(url.username) }
5077
+ };
5078
+ }
5079
+ function endpointKeyFor(endpoint) {
5080
+ return `${normalizedEndpointHost(endpoint.host)}:${endpoint.nativePort}`;
5081
+ }
5082
+ function connectionKeyForEndpoint(endpoint, useTls) {
5083
+ const port = useTls && endpoint.nativeTlsPort != null ? endpoint.nativeTlsPort : endpoint.nativePort;
5084
+ return `${useTls ? "ferrics" : "ferric"}://${normalizedEndpointHost(endpoint.host)}:${port}`;
5085
+ }
5086
+ function connectionKeyFromUrl(url) {
5087
+ const parsed = parseFerricUrl2(url);
5088
+ return `${parsed.tls ? "ferrics" : "ferric"}://${normalizedEndpointHost(parsed.host)}:${parsed.port}`;
5089
+ }
5090
+ function normalizedEndpointHost(host) {
5091
+ const lower = host.toLowerCase();
5092
+ return lower.startsWith("[") && lower.endsWith("]") ? lower.slice(1, -1) : lower;
5093
+ }
5094
+ function urlFromEndpoint(endpoint, useTls) {
5095
+ const port = useTls && endpoint.nativeTlsPort != null ? endpoint.nativeTlsPort : endpoint.nativePort;
5096
+ const host = endpoint.host.includes(":") && !endpoint.host.startsWith("[") ? `[${endpoint.host}]` : endpoint.host;
5097
+ return `${useTls ? "ferrics" : "ferric"}://${host}:${port}`;
5098
+ }
5099
+ async function mapSettledWithConcurrency(items, concurrency, operation) {
5100
+ const results = new Array(items.length);
5101
+ let nextIndex = 0;
5102
+ const worker = async () => {
5103
+ while (nextIndex < items.length) {
5104
+ const index = nextIndex++;
5105
+ const item = items[index];
5106
+ try {
5107
+ results[index] = { status: "fulfilled", value: await operation(item, index) };
5108
+ } catch (reason) {
5109
+ results[index] = { status: "rejected", reason };
5110
+ }
5111
+ }
5112
+ };
5113
+ await Promise.all(Array.from(
5114
+ { length: Math.min(concurrency, items.length) },
5115
+ async () => await worker()
5116
+ ));
5117
+ return results;
5118
+ }
5119
+ function throwFirstRejected(results) {
5120
+ for (const result of results) {
5121
+ if (result.status === "rejected") throw result.reason;
5122
+ }
5123
+ }
5124
+ var TaskConcurrencyLimiter = class {
5125
+ constructor(concurrency) {
5126
+ this.concurrency = concurrency;
5127
+ }
5128
+ concurrency;
5129
+ active = 0;
5130
+ head = 0;
5131
+ pending = [];
5132
+ async run(operation) {
5133
+ await this.acquire();
5134
+ try {
5135
+ return await operation();
5136
+ } finally {
5137
+ this.release();
5138
+ }
5139
+ }
5140
+ acquire() {
5141
+ if (this.active < this.concurrency) {
5142
+ this.active += 1;
5143
+ return Promise.resolve();
5144
+ }
5145
+ return new Promise((resolve) => this.pending.push(resolve));
5146
+ }
5147
+ release() {
5148
+ const next = this.pending[this.head];
5149
+ if (next == null) {
5150
+ this.active -= 1;
5151
+ return;
5152
+ }
5153
+ this.head += 1;
5154
+ next();
5155
+ if (this.head === this.pending.length) {
5156
+ this.pending.length = 0;
5157
+ this.head = 0;
5158
+ } else if (this.head >= 1024 && this.head * 2 >= this.pending.length) {
5159
+ this.pending.splice(0, this.head);
5160
+ this.head = 0;
5161
+ }
5162
+ }
5163
+ };
5164
+ function normalizedHostSet(hosts) {
5165
+ return new Set(
5166
+ hosts.filter((host) => host != null && host !== "").map((host) => normalizedEndpointHost(host))
5167
+ );
5168
+ }
5169
+ var OPEN_BRACE = "{".charCodeAt(0);
5170
+ var CLOSE_BRACE = "}".charCodeAt(0);
5171
+ function hashTagOrKey(key) {
5172
+ const start = key.indexOf(OPEN_BRACE);
5173
+ if (start < 0) return key;
5174
+ const end = key.indexOf(CLOSE_BRACE, start + 1);
5175
+ return end > start + 1 ? key.subarray(start + 1, end) : key;
5176
+ }
5177
+ var ROUTE_SLOT_MASK = 1023;
5178
+ function routingSlotForKey(key) {
5179
+ if (typeof key === "string") {
5180
+ const [start, end] = stringHashRange(key);
5181
+ return crc32Utf8(key, start, end) & ROUTE_SLOT_MASK;
5182
+ }
5183
+ const keyBytes = key;
5184
+ return crc32(hashTagOrKey(keyBytes)) & ROUTE_SLOT_MASK;
5185
+ }
5186
+ function stringHashRange(key) {
5187
+ const startBrace = key.indexOf("{");
5188
+ const endBrace = startBrace < 0 ? -1 : key.indexOf("}", startBrace + 1);
5189
+ return endBrace > startBrace + 1 ? [startBrace + 1, endBrace] : [0, key.length];
5190
+ }
5191
+
5192
+ // src/key-slot-validation.ts
5193
+ var validatedCommands = /* @__PURE__ */ new WeakSet();
5194
+ function assertAtomicKeyValueCommandSharesSlot(args) {
5195
+ const value = args[0];
5196
+ const command = (typeof value === "string" ? value : import_node_buffer16.Buffer.isBuffer(value) ? value.toString("utf8") : "").toUpperCase();
5197
+ if (command === "MSET" || command === "MSETNX") {
5198
+ assertKeyValueCommandSharesSlot(args, command);
5199
+ }
5200
+ }
5201
+ function assertKeyValueCommandSharesSlot(args, command) {
5202
+ if (validatedCommands.has(args) || args.length < 3 || args.length % 2 === 0) return;
5203
+ let expectedSlot;
5204
+ for (let index = 1; index < args.length; index += 2) {
5205
+ const key = args[index];
5206
+ if (typeof key !== "string" && !import_node_buffer16.Buffer.isBuffer(key)) return;
5207
+ const slot = routingSlotForKey(key);
5208
+ expectedSlot ??= slot;
5209
+ if (slot !== expectedSlot) {
5210
+ throw new TypeError(`${command} keys must share a slot`);
5211
+ }
5212
+ }
5213
+ validatedCommands.add(args);
5214
+ }
5215
+
4934
5216
  // src/protocol-response.ts
5217
+ var import_node_buffer20 = require("buffer");
5218
+
5219
+ // src/protocol-compact-response.ts
5220
+ var import_node_buffer19 = require("buffer");
5221
+
5222
+ // src/native-negotiation.ts
4935
5223
  var import_node_buffer17 = require("buffer");
5224
+ var EMPTY_COMPACT_RESPONSE_OPCODES = /* @__PURE__ */ new Map();
5225
+ function nativeNegotiation(value) {
5226
+ const capabilities = field(value, "capabilities") ?? value;
5227
+ const limits = field(capabilities, "limits");
5228
+ const responseCodecs = field(capabilities, "response_codecs");
5229
+ const maxResponseBytes = positiveSafeInteger3(field(limits, "max_response_bytes"));
5230
+ return {
5231
+ compactResponseOpcodes: parseCompactResponseOpcodes(
5232
+ field(responseCodecs, "compact_response_opcodes")
5233
+ ),
5234
+ ...maxResponseBytes == null ? {} : { maxResponseBytes }
5235
+ };
5236
+ }
5237
+ function compactResponseOpcodeSupports(capabilities, codec, opcode) {
5238
+ return capabilities?.get(codec)?.has(opcode) === true;
5239
+ }
5240
+ function parseCompactResponseOpcodes(value) {
5241
+ const entries = mapEntries(value);
5242
+ if (entries == null) return EMPTY_COMPACT_RESPONSE_OPCODES;
5243
+ const result = /* @__PURE__ */ new Map();
5244
+ for (const [rawName, rawOpcodes] of entries) {
5245
+ const name = text2(rawName);
5246
+ if (name == null || name.length === 0 || !Array.isArray(rawOpcodes)) continue;
5247
+ const opcodes = /* @__PURE__ */ new Set();
5248
+ let valid = true;
5249
+ for (let index = 0; index < rawOpcodes.length; index += 1) {
5250
+ if (!Object.hasOwn(rawOpcodes, index)) {
5251
+ valid = false;
5252
+ break;
5253
+ }
5254
+ const opcode = unsigned16(rawOpcodes[index]);
5255
+ if (opcode == null) {
5256
+ valid = false;
5257
+ break;
5258
+ }
5259
+ opcodes.add(opcode);
5260
+ }
5261
+ if (valid) result.set(name, opcodes);
5262
+ }
5263
+ return result;
5264
+ }
5265
+ function mapEntries(value) {
5266
+ if (value instanceof Map) return [...value.entries()];
5267
+ if (typeof value !== "object" || value == null || Array.isArray(value)) return void 0;
5268
+ return Object.entries(value);
5269
+ }
5270
+ function unsigned16(value) {
5271
+ const parsed = nonNegativeSafeInteger2(value);
5272
+ return parsed != null && parsed <= 65535 ? parsed : void 0;
5273
+ }
5274
+ function positiveSafeInteger3(value) {
5275
+ const parsed = nonNegativeSafeInteger2(value);
5276
+ return parsed != null && parsed > 0 ? parsed : void 0;
5277
+ }
5278
+ function nonNegativeSafeInteger2(value) {
5279
+ if (typeof value === "bigint") {
5280
+ return value >= 0n && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : void 0;
5281
+ }
5282
+ const source = text2(value) ?? value;
5283
+ if (typeof source !== "number" && (typeof source !== "string" || !/^\d+$/u.test(source))) {
5284
+ return void 0;
5285
+ }
5286
+ const parsed = Number(source);
5287
+ return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : void 0;
5288
+ }
5289
+ function text2(value) {
5290
+ if (typeof value === "string") return value;
5291
+ if (import_node_buffer17.Buffer.isBuffer(value) || value instanceof Uint8Array) {
5292
+ return import_node_buffer17.Buffer.from(value).toString("utf8");
5293
+ }
5294
+ return void 0;
5295
+ }
5296
+
5297
+ // src/protocol-compact-collections.ts
5298
+ var import_node_buffer18 = require("buffer");
5299
+ function decodeCompactIntegerList(data, budget) {
5300
+ requireAvailable(data, 0, 5);
5301
+ const count = data.readUInt32BE(1);
5302
+ requireCompactContainer(count, budget);
5303
+ if (data.byteLength !== 5 + count * 8) {
5304
+ throw new FerricStoreError("invalid compact integer list response");
5305
+ }
5306
+ const values = new Array(count);
5307
+ for (let index = 0, offset = 5; index < count; index += 1, offset += 8) {
5308
+ const value = data.readBigInt64BE(offset);
5309
+ values[index] = value <= MAX_SAFE_INTEGER_BIGINT && value >= MIN_SAFE_INTEGER_BIGINT ? Number(value) : value;
5310
+ }
5311
+ return values;
5312
+ }
5313
+ function decodeCompactBinaryListList(data, budget) {
5314
+ requireAvailable(data, 0, 5);
5315
+ const count = data.readUInt32BE(1);
5316
+ requireCompactContainer(count, budget);
5317
+ let offset = 5;
5318
+ const values = new Array(count);
5319
+ for (let index = 0; index < count; index += 1) {
5320
+ const read = readCompactBinaryList(data, offset, budget);
5321
+ values[index] = read.value;
5322
+ offset = read.offset;
5323
+ }
5324
+ if (offset !== data.byteLength) throw new FerricStoreError("trailing compact binary list-list bytes");
5325
+ return values;
5326
+ }
5327
+ function decodeCompactBinaryMapList(data, budget) {
5328
+ requireAvailable(data, 0, 5);
5329
+ const count = data.readUInt32BE(1);
5330
+ requireCompactContainer(count, budget);
5331
+ let offset = 5;
5332
+ const values = new Array(count);
5333
+ for (let index = 0; index < count; index += 1) {
5334
+ const read = readCompactBinaryMap(data, offset, budget);
5335
+ values[index] = read.value;
5336
+ offset = read.offset;
5337
+ }
5338
+ if (offset !== data.byteLength) throw new FerricStoreError("trailing compact binary map-list bytes");
5339
+ return values;
5340
+ }
5341
+ function readCompactBinaryList(data, offset, budget) {
5342
+ requireAvailable(data, offset, 4);
5343
+ const count = data.readUInt32BE(offset);
5344
+ requireCompactContainer(count, budget);
5345
+ offset += 4;
5346
+ const values = new Array(count);
5347
+ for (let index = 0; index < count; index += 1) {
5348
+ const read = readBinary(data, offset);
5349
+ values[index] = read.value;
5350
+ offset = read.offset;
5351
+ }
5352
+ return { value: values, offset };
5353
+ }
5354
+ function readCompactBinaryMap(data, offset, budget) {
5355
+ requireAvailable(data, offset, 4);
5356
+ const count = data.readUInt32BE(offset);
5357
+ requireCompactContainer(count, budget);
5358
+ offset += 4;
5359
+ const values = {};
5360
+ for (let index = 0; index < count; index += 1) {
5361
+ const key = readBinary(data, offset);
5362
+ const value = readBinary(data, key.offset);
5363
+ setOwnValue2(values, key.value.toString("utf8"), value.value);
5364
+ offset = value.offset;
5365
+ }
5366
+ return { value: values, offset };
5367
+ }
5368
+ function markCompactPipelineDecoded(values) {
5369
+ Object.defineProperty(values, COMPACT_PIPELINE_DECODED, { value: true });
5370
+ return values;
5371
+ }
5372
+ function requireCompactContainer(count, budget) {
5373
+ if (count > DEFAULT_MAX_VALUE_ITEMS) {
5374
+ throw new FerricStoreError("native compact response container exceeds max items");
5375
+ }
5376
+ consumeDecodeItems(count, budget);
5377
+ }
4936
5378
 
4937
5379
  // src/protocol-compact-response.ts
4938
- var import_node_buffer16 = require("buffer");
4939
5380
  function tryDecodeCompactResponse(opcode, body, hints) {
4940
5381
  if (body.byteLength === 0) return { found: false, value: void 0 };
4941
5382
  const budget = { remainingItems: DEFAULT_MAX_VALUE_ITEMS };
4942
5383
  const tag = body.readUInt8(0);
4943
- if (tag === COMPACT_OK_LIST && isOkListOpcode(opcode)) {
5384
+ const pipelineValues = opcode === OPCODES.pipeline && supports(hints, "pipeline_v1", opcode);
5385
+ if (tag === COMPACT_OK_LIST && (supports(hints, "ok_list_v1", opcode) || pipelineValues)) {
4944
5386
  const values = decodeCompactOkList(body, budget);
4945
- return { found: true, value: opcode === OPCODES.pipeline ? values : values.length === 1 ? "OK" : values };
5387
+ return {
5388
+ found: true,
5389
+ value: opcode === OPCODES.pipeline ? markCompactPipelineDecoded(values) : values.length === 1 ? "OK" : values
5390
+ };
4946
5391
  }
4947
- if (tag === COMPACT_KV_GET && compactResponseOpcodeSupports(opcode, COMPACT_KIND_KV_GET)) {
5392
+ if (tag === COMPACT_KV_GET && supports(hints, "kv_get_v1", opcode)) {
4948
5393
  return { found: true, value: decodeCompactKvGet(body) };
4949
5394
  }
4950
- if ((tag === COMPACT_KV_MGET || tag === COMPACT_KV_MGET_FIXED) && compactResponseOpcodeSupports(opcode, COMPACT_KIND_KV_MGET)) {
5395
+ if ((tag === COMPACT_KV_MGET || tag === COMPACT_KV_MGET_FIXED) && (supports(hints, "kv_mget_v1", opcode) || pipelineValues)) {
5396
+ const values = tag === COMPACT_KV_MGET ? decodeCompactMget(body, budget) : decodeCompactMgetFixed(body, budget);
4951
5397
  return {
4952
5398
  found: true,
4953
- value: tag === COMPACT_KV_MGET ? decodeCompactMget(body, budget) : decodeCompactMgetFixed(body, budget)
5399
+ value: opcode === OPCODES.pipeline ? markCompactPipelineDecoded(values) : values
4954
5400
  };
4955
5401
  }
4956
- if (tag === COMPACT_PIPELINE_RESPONSE && compactResponseOpcodeSupports(opcode, COMPACT_KIND_PIPELINE)) {
5402
+ if (tag === COMPACT_INTEGER_LIST && pipelineValues) {
5403
+ return { found: true, value: markCompactPipelineDecoded(decodeCompactIntegerList(body, budget)) };
5404
+ }
5405
+ if (tag === COMPACT_BINARY_LIST_LIST && pipelineValues) {
5406
+ return { found: true, value: markCompactPipelineDecoded(decodeCompactBinaryListList(body, budget)) };
5407
+ }
5408
+ if (tag === COMPACT_BINARY_MAP_LIST && pipelineValues) {
5409
+ return { found: true, value: markCompactPipelineDecoded(decodeCompactBinaryMapList(body, budget)) };
5410
+ }
5411
+ if (tag === COMPACT_PIPELINE_RESPONSE && pipelineValues) {
4957
5412
  return { found: true, value: decodeCompactPipeline(body, budget, hints.pipelineClaimModes) };
4958
5413
  }
4959
- if (tag === COMPACT_FLOW_CLAIM_JOBS && compactResponseOpcodeSupports(opcode, COMPACT_KIND_FLOW_CLAIM_JOBS)) {
4960
- return { found: true, value: decodeCompactClaimJobs(body, budget, hints.compactClaimMode) };
5414
+ if (tag === COMPACT_FLOW_CLAIM_JOBS && (supports(hints, "flow_claim_jobs_v1", opcode) || pipelineValues)) {
5415
+ const values = decodeCompactClaimJobs(body, budget, hints.compactClaimMode);
5416
+ return {
5417
+ found: true,
5418
+ value: opcode === OPCODES.pipeline ? markCompactPipelineDecoded(values) : values
5419
+ };
4961
5420
  }
4962
- if (tag === COMPACT_FLOW_RECORD && compactResponseOpcodeSupports(opcode, COMPACT_KIND_FLOW_RECORD)) {
5421
+ if (tag === COMPACT_FLOW_RECORD && supports(hints, "flow_record_v1", opcode)) {
4963
5422
  const read = readCompactFlowRecord(body, 0, budget);
4964
5423
  if (read.offset !== body.byteLength) throw new FerricStoreError("trailing compact Flow record bytes");
4965
5424
  return { found: true, value: read.value };
4966
5425
  }
4967
- if (tag === COMPACT_FLOW_RECORD_LIST && isFlowRecordListOpcode(opcode)) {
5426
+ if (tag === COMPACT_FLOW_RECORD_LIST && (supports(hints, "flow_record_list_v1", opcode) || pipelineValues)) {
4968
5427
  const read = readCompactFlowRecordList(body, 0, budget);
4969
5428
  if (read.offset !== body.byteLength) throw new FerricStoreError("trailing compact Flow record list bytes");
4970
- return { found: true, value: read.value };
5429
+ return {
5430
+ found: true,
5431
+ value: opcode === OPCODES.pipeline ? markCompactPipelineDecoded(read.value) : read.value
5432
+ };
4971
5433
  }
4972
5434
  return { found: false, value: void 0 };
4973
5435
  }
4974
- function isOkListOpcode(opcode) {
4975
- return compactResponseOpcodeSupports(opcode, COMPACT_KIND_OK_LIST);
4976
- }
4977
- function isFlowRecordListOpcode(opcode) {
4978
- return compactResponseOpcodeSupports(opcode, COMPACT_KIND_FLOW_RECORD_LIST);
5436
+ function supports(hints, codec, opcode) {
5437
+ return compactResponseOpcodeSupports(hints.compactResponseOpcodes, codec, opcode);
4979
5438
  }
4980
5439
  function decodeCompactOkList(data, budget) {
4981
5440
  requireAvailable(data, 0, 5);
4982
5441
  const count = data.readUInt32BE(1);
4983
- requireCompactContainer(count, budget);
5442
+ requireCompactContainer2(count, budget);
4984
5443
  if (data.byteLength !== 5) throw new FerricStoreError("invalid compact OK list response");
4985
- return Array.from({ length: count }, () => import_node_buffer16.Buffer.from("OK"));
5444
+ return Array.from({ length: count }, () => import_node_buffer19.Buffer.from("OK"));
4986
5445
  }
4987
5446
  function decodeCompactKvGet(data) {
4988
5447
  requireAvailable(data, 0, 2);
@@ -4999,7 +5458,7 @@ function decodeCompactKvGet(data) {
4999
5458
  function decodeCompactMget(data, budget) {
5000
5459
  requireAvailable(data, 0, 5);
5001
5460
  const count = data.readUInt32BE(1);
5002
- requireCompactContainer(count, budget);
5461
+ requireCompactContainer2(count, budget);
5003
5462
  let offset = 5;
5004
5463
  const values = [];
5005
5464
  for (let index = 0; index < count; index += 1) {
@@ -5023,12 +5482,12 @@ function decodeCompactMgetFixed(data, budget) {
5023
5482
  requireAvailable(data, 0, 9);
5024
5483
  const count = data.readUInt32BE(1);
5025
5484
  const size = data.readUInt32BE(5);
5026
- requireCompactContainer(count, budget);
5485
+ requireCompactContainer2(count, budget);
5027
5486
  const expected = 9 + count * size;
5028
5487
  if (size === NULL_U32 || data.byteLength !== expected) {
5029
5488
  throw new FerricStoreError("invalid compact fixed MGET response");
5030
5489
  }
5031
- if (size === 0) return new Array(count).fill(import_node_buffer16.Buffer.alloc(0));
5490
+ if (size === 0) return new Array(count).fill(import_node_buffer19.Buffer.alloc(0));
5032
5491
  const values = new Array(count);
5033
5492
  for (let index = 0, offset = 9; index < count; index += 1, offset += size) {
5034
5493
  values[index] = data.subarray(offset, offset + size);
@@ -5038,7 +5497,7 @@ function decodeCompactMgetFixed(data, budget) {
5038
5497
  function decodeCompactPipeline(data, budget, claimModes) {
5039
5498
  requireAvailable(data, 0, 5);
5040
5499
  const count = data.readUInt32BE(1);
5041
- requireCompactContainer(count, budget);
5500
+ requireCompactContainer2(count, budget);
5042
5501
  if (count > Math.floor((data.byteLength - 5) / 2)) {
5043
5502
  throw new FerricStoreError("compact pipeline item count exceeds response bytes");
5044
5503
  }
@@ -5100,13 +5559,12 @@ function decodeCompactPipeline(data, budget, claimModes) {
5100
5559
  }
5101
5560
  }
5102
5561
  if (offset !== data.byteLength) throw new FerricStoreError("trailing compact pipeline bytes");
5103
- Object.defineProperty(values, COMPACT_PIPELINE_DECODED, { value: true });
5104
- return values;
5562
+ return markCompactPipelineDecoded(values);
5105
5563
  }
5106
5564
  function decodeCompactClaimJobs(data, budget, mode) {
5107
5565
  requireAvailable(data, 0, 5);
5108
5566
  const count = data.readUInt32BE(1);
5109
- requireCompactContainer(count, budget);
5567
+ requireCompactContainer2(count, budget);
5110
5568
  if (mode != null) {
5111
5569
  const values = [];
5112
5570
  let offset = 5;
@@ -5190,7 +5648,7 @@ function readCompactFlowRecord(data, offset, budget = { remainingItems: DEFAULT_
5190
5648
  if (data.readUInt8(offset) !== COMPACT_FLOW_RECORD) throw new FerricStoreError("expected compact Flow record");
5191
5649
  offset += 1;
5192
5650
  const count = data.readUInt32BE(offset);
5193
- requireCompactContainer(count, budget);
5651
+ requireCompactContainer2(count, budget);
5194
5652
  offset += 4;
5195
5653
  const record = {};
5196
5654
  for (let index = 0; index < count; index += 1) {
@@ -5218,7 +5676,7 @@ function readCompactFlowRecordList(data, offset, budget = { remainingItems: DEFA
5218
5676
  }
5219
5677
  offset += 1;
5220
5678
  const count = data.readUInt32BE(offset);
5221
- requireCompactContainer(count, budget);
5679
+ requireCompactContainer2(count, budget);
5222
5680
  offset += 4;
5223
5681
  const records = [];
5224
5682
  for (let index = 0; index < count; index += 1) {
@@ -5228,33 +5686,6 @@ function readCompactFlowRecordList(data, offset, budget = { remainingItems: DEFA
5228
5686
  }
5229
5687
  return { value: records, offset };
5230
5688
  }
5231
- function readCompactBinaryList(data, offset, budget) {
5232
- requireAvailable(data, offset, 4);
5233
- const count = data.readUInt32BE(offset);
5234
- requireCompactContainer(count, budget);
5235
- offset += 4;
5236
- const values = [];
5237
- for (let index = 0; index < count; index += 1) {
5238
- const read = readBinary(data, offset);
5239
- values.push(read.value);
5240
- offset = read.offset;
5241
- }
5242
- return { value: values, offset };
5243
- }
5244
- function readCompactBinaryMap(data, offset, budget) {
5245
- requireAvailable(data, offset, 4);
5246
- const count = data.readUInt32BE(offset);
5247
- requireCompactContainer(count, budget);
5248
- offset += 4;
5249
- const values = {};
5250
- for (let index = 0; index < count; index += 1) {
5251
- const key = readBinary(data, offset);
5252
- const value = readBinary(data, key.offset);
5253
- setOwnValue2(values, key.value.toString("utf8"), value.value);
5254
- offset = value.offset;
5255
- }
5256
- return { value: values, offset };
5257
- }
5258
5689
  function readOptionalBinary(data, offset) {
5259
5690
  requireAvailable(data, offset, 4);
5260
5691
  const size = data.readUInt32BE(offset);
@@ -5263,7 +5694,7 @@ function readOptionalBinary(data, offset) {
5263
5694
  requireAvailable(data, offset, size);
5264
5695
  return { value: data.subarray(offset, offset + size), offset: offset + size };
5265
5696
  }
5266
- function requireCompactContainer(count, budget) {
5697
+ function requireCompactContainer2(count, budget) {
5267
5698
  if (count > DEFAULT_MAX_VALUE_ITEMS) {
5268
5699
  throw new FerricStoreError("native compact response container exceeds max items");
5269
5700
  }
@@ -5271,7 +5702,7 @@ function requireCompactContainer(count, budget) {
5271
5702
  }
5272
5703
  function errorMessage(status, value) {
5273
5704
  if (typeof value === "string") return value;
5274
- if (import_node_buffer16.Buffer.isBuffer(value)) return value.toString("utf8");
5705
+ if (import_node_buffer19.Buffer.isBuffer(value)) return value.toString("utf8");
5275
5706
  if (typeof value === "object" && value != null && Object.hasOwn(value, "message")) {
5276
5707
  const message = value.message;
5277
5708
  return typeof message === "string" ? message : String(message);
@@ -5351,7 +5782,7 @@ function unwrapPipelineResponse(value, options = {}, expectedItems) {
5351
5782
  return out;
5352
5783
  }
5353
5784
  function pipelineStatus(value) {
5354
- if (typeof value !== "string" && !import_node_buffer17.Buffer.isBuffer(value) && !(value instanceof Uint8Array)) return null;
5785
+ if (typeof value !== "string" && !import_node_buffer20.Buffer.isBuffer(value) && !(value instanceof Uint8Array)) return null;
5355
5786
  const status = asText(value).toLowerCase();
5356
5787
  return status === "ok" || status === "busy" || status === "error" ? status : null;
5357
5788
  }
@@ -5366,7 +5797,7 @@ function decodeResponseValue(opcode, body, hints) {
5366
5797
  }
5367
5798
  function errorMessage2(status, value) {
5368
5799
  if (typeof value === "string") return value;
5369
- if (import_node_buffer17.Buffer.isBuffer(value)) return value.toString("utf8");
5800
+ if (import_node_buffer20.Buffer.isBuffer(value)) return value.toString("utf8");
5370
5801
  if (typeof value === "object" && value != null && Object.hasOwn(value, "message")) {
5371
5802
  const message = value.message;
5372
5803
  return typeof message === "string" ? message : String(message);
@@ -5382,7 +5813,7 @@ function encodeRequest(command, requestId, maxBodyBytes = Number.MAX_SAFE_INTEGE
5382
5813
  const bodyLength = customPayload ? binaryValueByteLength(command.payload) : plan?.byteLength ?? 0;
5383
5814
  if (bodyLength > bodyLimit) throw requestFrameTooLarge(bodyLimit);
5384
5815
  const flags = command.flags ?? 0;
5385
- const frame = import_node_buffer18.Buffer.allocUnsafe(HEADER_SIZE + bodyLength);
5816
+ const frame = import_node_buffer21.Buffer.allocUnsafe(HEADER_SIZE + bodyLength);
5386
5817
  frame.write(MAGIC, 0, "ascii");
5387
5818
  frame.writeUInt8(REQUEST_VERSION, 4);
5388
5819
  frame.writeUInt8(flags, 5);
@@ -5433,6 +5864,9 @@ function buildProtocolCommand(args, maxBodyBytes = Number.MAX_SAFE_INTEGER, allo
5433
5864
  }
5434
5865
  const command = asText(args[0]).toUpperCase();
5435
5866
  assertNormalizedCommandDoesNotRequirePinnedConnection(args, command);
5867
+ if (command === "MSET" || command === "MSETNX") {
5868
+ assertKeyValueCommandSharesSlot(args, command);
5869
+ }
5436
5870
  const commandArgs2 = args.slice(1);
5437
5871
  if (command === "COMMAND_EXEC" && commandArgs2.length >= 1) {
5438
5872
  return commandExec(commandArgs2);
@@ -5570,20 +6004,7 @@ function buildProtocolCommand(args, maxBodyBytes = Number.MAX_SAFE_INTEGER, allo
5570
6004
  ])) ?? commandExec(args);
5571
6005
  }
5572
6006
  if (command === "FLOW.SIGNAL") {
5573
- return flowCommandExecWithRouting(command, commandArgs2, 1, /* @__PURE__ */ new Set([
5574
- "SIGNAL",
5575
- "PARTITION",
5576
- "IDEMPOTENCY",
5577
- "IF_STATE",
5578
- "TRANSITION_TO",
5579
- "RUN_AT",
5580
- "NOW",
5581
- "PRIORITY",
5582
- "VALUE",
5583
- "VALUE_REF",
5584
- "DROP_VALUE",
5585
- "OVERRIDE_VALUE"
5586
- ]));
6007
+ return flowSignalPayload(commandArgs2) ?? commandExec(args);
5587
6008
  }
5588
6009
  if (command === "FLOW.CANCEL") {
5589
6010
  return flowCommandExecWithRouting(command, commandArgs2, 1, /* @__PURE__ */ new Set([
@@ -5752,6 +6173,7 @@ var DEFAULT_MAX_PENDING_CONTROL_REQUESTS = 4096;
5752
6173
  var DEFAULT_MAX_RESPONSE_BYTES = 64 * 1024 * 1024;
5753
6174
  var DEFAULT_MAX_QUEUED_REQUESTS = 65536;
5754
6175
  var DEFAULT_MAX_QUEUED_WRITE_BYTES = 64 * 1024 * 1024;
6176
+ var UNAUTHENTICATED_MAX_FRAME_BYTES = 64 * 1024;
5755
6177
  function assertNativeAdapterOptions(options) {
5756
6178
  const supplied = options;
5757
6179
  for (const name of ["autoReconnect", "haRouting", "seeds"]) {
@@ -5771,7 +6193,7 @@ var import_node_net2 = require("net");
5771
6193
  var import_node_tls2 = require("tls");
5772
6194
 
5773
6195
  // src/client-native-options.ts
5774
- var import_node_buffer19 = require("buffer");
6196
+ var import_node_buffer22 = require("buffer");
5775
6197
 
5776
6198
  // src/string-array-snapshot.ts
5777
6199
  function snapshotOwnStringArray(values, name) {
@@ -5854,7 +6276,7 @@ function snapshotTlsOptions(options) {
5854
6276
  return Object.freeze(snapshot);
5855
6277
  }
5856
6278
  function snapshotTlsValue(value, name) {
5857
- if (import_node_buffer19.Buffer.isBuffer(value)) return import_node_buffer19.Buffer.from(value);
6279
+ if (import_node_buffer22.Buffer.isBuffer(value)) return import_node_buffer22.Buffer.from(value);
5858
6280
  if (value instanceof Uint8Array) return value.slice();
5859
6281
  if (Array.isArray(value)) {
5860
6282
  const snapshot = new Array(value.length);
@@ -6324,6 +6746,9 @@ var NativeChunkAssembler = class {
6324
6746
  framesByKey = /* @__PURE__ */ new Map();
6325
6747
  totalBytes = 0;
6326
6748
  totalFrames = 0;
6749
+ updateMaxResponseBytes(limit) {
6750
+ this.maxResponseBytes = Math.min(this.maxResponseBytes, limit);
6751
+ }
6327
6752
  assemble(frame) {
6328
6753
  const key = `${frame.requestId}:${frame.opcode}:${frame.laneId}`;
6329
6754
  const previous = this.chunks.get(key);
@@ -6406,7 +6831,7 @@ var NativeChunkAssembler = class {
6406
6831
  };
6407
6832
 
6408
6833
  // src/native-response-handler.ts
6409
- var import_node_buffer20 = require("buffer");
6834
+ var import_node_buffer23 = require("buffer");
6410
6835
 
6411
6836
  // src/native-receive-buffer.ts
6412
6837
  var FRAME_ASSEMBLY_PAGE_BYTES = 64 * 1024;
@@ -6568,12 +6993,18 @@ var NativeReceiveBuffer = class {
6568
6993
  var NativeResponseHandler = class {
6569
6994
  constructor(options) {
6570
6995
  this.options = options;
6996
+ this.maxResponseBytes = options.maxResponseBytes;
6571
6997
  }
6572
6998
  options;
6573
6999
  receiveBuffer = new NativeReceiveBuffer();
6574
7000
  drainScheduled = false;
6575
7001
  paused = false;
6576
7002
  stopped = false;
7003
+ maxResponseBytes;
7004
+ updateMaxResponseBytes(limit) {
7005
+ this.maxResponseBytes = Math.min(this.maxResponseBytes, limit);
7006
+ this.options.chunkAssembler.updateMaxResponseBytes(this.maxResponseBytes);
7007
+ }
6577
7008
  onData(chunk) {
6578
7009
  if (this.stopped) return;
6579
7010
  try {
@@ -6655,15 +7086,18 @@ var NativeResponseHandler = class {
6655
7086
  }
6656
7087
  const completeFrame = this.options.chunkAssembler.assemble(frame);
6657
7088
  if (completeFrame == null) return;
6658
- if (completeFrame.body.byteLength > this.options.maxResponseBytes) {
7089
+ if (completeFrame.body.byteLength > this.maxResponseBytes) {
6659
7090
  throw new FerricStoreError(
6660
- `native protocol response exceeded ${this.options.maxResponseBytes} bytes`
7091
+ `native protocol response exceeded ${this.maxResponseBytes} bytes`
6661
7092
  );
6662
7093
  }
6663
7094
  let value;
6664
7095
  let responseError;
6665
7096
  try {
6666
- value = decodeResponse(completeFrame, pending.opcode, pending);
7097
+ value = decodeResponse(completeFrame, pending.opcode, {
7098
+ ...pending,
7099
+ compactResponseOpcodes: this.options.compactResponseOpcodes?.() ?? EMPTY_COMPACT_RESPONSE_OPCODES
7100
+ });
6667
7101
  if (pending.opcode === OPCODES.windowUpdate) this.options.applyFlowControlLimits(value);
6668
7102
  } catch (error) {
6669
7103
  responseError = error;
@@ -6679,7 +7113,7 @@ var NativeResponseHandler = class {
6679
7113
  pending.discardedResponseBytes = discardedResponseBytes;
6680
7114
  pending.discardedResponseFrames = discardedResponseFrames;
6681
7115
  const chunked = discardedResponseFrames > 1 || (frame.flags & FLAG_MORE_CHUNKS) !== 0;
6682
- if (discardedResponseBytes > this.options.maxResponseBytes || chunked && discardedResponseBytes > this.options.maxChunkBytes) {
7116
+ if (discardedResponseBytes > this.maxResponseBytes || chunked && discardedResponseBytes > this.options.maxChunkBytes) {
6683
7117
  throw new FerricStoreError("native protocol discarded response exceeded configured byte limits");
6684
7118
  }
6685
7119
  if (discardedResponseFrames > this.options.maxChunkFrames) {
@@ -6688,12 +7122,14 @@ var NativeResponseHandler = class {
6688
7122
  if ((frame.flags & FLAG_MORE_CHUNKS) === 0) this.options.takePending(frame.requestId);
6689
7123
  }
6690
7124
  handleManagementFrame(frame) {
6691
- if (frame.body.byteLength > this.options.maxResponseBytes) {
7125
+ if (frame.body.byteLength > this.maxResponseBytes) {
6692
7126
  throw new FerricStoreError(
6693
- `native protocol response exceeded ${this.options.maxResponseBytes} bytes`
7127
+ `native protocol response exceeded ${this.maxResponseBytes} bytes`
6694
7128
  );
6695
7129
  }
6696
- const value = decodeResponse(frame, frame.opcode);
7130
+ const value = decodeResponse(frame, frame.opcode, {
7131
+ compactResponseOpcodes: this.options.compactResponseOpcodes?.() ?? EMPTY_COMPACT_RESPONSE_OPCODES
7132
+ });
6697
7133
  if (frame.opcode === OPCODES.windowUpdate) this.options.applyFlowControlLimits(value);
6698
7134
  const event = {
6699
7135
  flags: frame.flags,
@@ -6730,7 +7166,7 @@ var NativeRequestScheduler = class {
6730
7166
  };
6731
7167
 
6732
7168
  // src/native-write-queue.ts
6733
- var import_node_buffer21 = require("buffer");
7169
+ var import_node_buffer24 = require("buffer");
6734
7170
  var NativeWriteQueue = class {
6735
7171
  constructor(socket, maxQueuedWriteBytes, isClosed, hasPending, rejectPending) {
6736
7172
  this.socket = socket;
@@ -6858,6 +7294,40 @@ var NativeWriteQueue = class {
6858
7294
  }
6859
7295
  };
6860
7296
 
7297
+ // src/native-connection-capabilities.ts
7298
+ var NativeConnectionCapabilities = class {
7299
+ constructor(configuredRequestFrameBytes) {
7300
+ this.configuredRequestFrameBytes = configuredRequestFrameBytes;
7301
+ this.negotiatedRequestFrameBytes = configuredRequestFrameBytes;
7302
+ this.requestFrameBytes = Math.min(configuredRequestFrameBytes, UNAUTHENTICATED_MAX_FRAME_BYTES);
7303
+ }
7304
+ configuredRequestFrameBytes;
7305
+ compactResponseOpcodes = EMPTY_COMPACT_RESPONSE_OPCODES;
7306
+ requestFrameBytes;
7307
+ negotiatedRequestFrameBytes;
7308
+ apply(value) {
7309
+ const limits = startupLimits(value);
7310
+ const negotiation = nativeNegotiation(value);
7311
+ this.compactResponseOpcodes = negotiation.compactResponseOpcodes;
7312
+ if (limits.frameBytes != null) {
7313
+ this.negotiatedRequestFrameBytes = Math.min(
7314
+ this.configuredRequestFrameBytes,
7315
+ limits.frameBytes
7316
+ );
7317
+ this.requestFrameBytes = Math.min(this.requestFrameBytes, this.negotiatedRequestFrameBytes);
7318
+ }
7319
+ return {
7320
+ ...limits.laneQueue == null ? {} : { laneQueue: limits.laneQueue },
7321
+ ...limits.lanes == null ? {} : { lanes: limits.lanes },
7322
+ ...negotiation.maxResponseBytes == null ? {} : { maxResponseBytes: negotiation.maxResponseBytes },
7323
+ ...limits.pipelineCommands == null ? {} : { pipelineCommands: limits.pipelineCommands }
7324
+ };
7325
+ }
7326
+ activateAuthenticated() {
7327
+ this.requestFrameBytes = this.negotiatedRequestFrameBytes;
7328
+ }
7329
+ };
7330
+
6861
7331
  // src/native-adapter.ts
6862
7332
  var NativeAdapter = class _NativeAdapter {
6863
7333
  socket;
@@ -6866,9 +7336,9 @@ var NativeAdapter = class _NativeAdapter {
6866
7336
  closedWaiters = /* @__PURE__ */ new Set();
6867
7337
  chunkAssembler;
6868
7338
  closed = false;
7339
+ capabilities;
6869
7340
  protocolLanes;
6870
7341
  maxPipelineCommands = Number.MAX_SAFE_INTEGER;
6871
- maxRequestFrameBytes;
6872
7342
  pendingControlRequests = 0;
6873
7343
  maxPendingControlRequests;
6874
7344
  heartbeat;
@@ -6883,7 +7353,7 @@ var NativeAdapter = class _NativeAdapter {
6883
7353
  const normalizedMaxChunkBytes = normalizePositiveLimit(maxChunkBytes, DEFAULT_MAX_CHUNK_BYTES);
6884
7354
  const normalizedMaxChunkFrames = normalizePositiveLimit(maxChunkFrames, DEFAULT_MAX_CHUNK_FRAMES);
6885
7355
  const normalizedMaxFrameBytes = normalizePositiveLimit(maxFrameBytes, DEFAULT_MAX_FRAME_BYTES);
6886
- this.maxRequestFrameBytes = normalizedMaxFrameBytes;
7356
+ this.capabilities = new NativeConnectionCapabilities(normalizedMaxFrameBytes);
6887
7357
  const normalizedMaxResponseBytes = normalizePositiveLimit(maxResponseBytes, DEFAULT_MAX_RESPONSE_BYTES);
6888
7358
  this.chunkAssembler = new NativeChunkAssembler(
6889
7359
  normalizedMaxChunkBytes,
@@ -6910,7 +7380,7 @@ var NativeAdapter = class _NativeAdapter {
6910
7380
  this.heartbeat = new NativeHeartbeat(
6911
7381
  this.heartbeatIntervalMs,
6912
7382
  async () => {
6913
- await this.request(buildProtocolCommand(["PING"], this.maxRequestFrameBytes), true);
7383
+ await this.request(buildProtocolCommand(["PING"], this.capabilities.requestFrameBytes), true);
6914
7384
  },
6915
7385
  (error) => {
6916
7386
  this.failAll(new FerricStoreError("FerricStore protocol heartbeat failed", { cause: error }), true);
@@ -6921,6 +7391,7 @@ var NativeAdapter = class _NativeAdapter {
6921
7391
  applyFlowControlLimits: (value) => this.applyFlowControlLimits(value),
6922
7392
  beginDraining: () => this.beginDraining(),
6923
7393
  chunkAssembler: this.chunkAssembler,
7394
+ compactResponseOpcodes: () => this.capabilities.compactResponseOpcodes,
6924
7395
  destroy: (error) => this.socket.destroy(error),
6925
7396
  failAll: (reason, connectionClosed, message) => this.failAll(reason, connectionClosed, message),
6926
7397
  heartbeat: this.heartbeat,
@@ -6946,6 +7417,7 @@ var NativeAdapter = class _NativeAdapter {
6946
7417
  adapter,
6947
7418
  auth: async (username, password) => {
6948
7419
  await adapter.request({ laneId: 0, opcode: OPCODES.auth, payload: { password, username } });
7420
+ adapter.capabilities.activateAuthenticated();
6949
7421
  },
6950
7422
  close: async () => {
6951
7423
  await adapter.close();
@@ -6963,13 +7435,13 @@ var NativeAdapter = class _NativeAdapter {
6963
7435
  return await this.executeCommandArgs(args);
6964
7436
  }
6965
7437
  async executeCommandArgs(args) {
6966
- const command = buildProtocolCommand(args, this.maxRequestFrameBytes);
7438
+ const command = buildProtocolCommand(args, this.capabilities.requestFrameBytes);
6967
7439
  return await this.request(command);
6968
7440
  }
6969
7441
  /** @internal Execute raw command arguments on a topology-selected lane. */
6970
7442
  async executeCommandOnLane(args, laneId) {
6971
7443
  return await this.executeProtocolCommand(
6972
- buildProtocolCommand(args, this.maxRequestFrameBytes),
7444
+ buildProtocolCommand(args, this.capabilities.requestFrameBytes),
6973
7445
  laneId
6974
7446
  );
6975
7447
  }
@@ -6991,7 +7463,7 @@ var NativeAdapter = class _NativeAdapter {
6991
7463
  laneId,
6992
7464
  options,
6993
7465
  this.maxPipelineCommands,
6994
- this.maxRequestFrameBytes
7466
+ this.capabilities.requestFrameBytes
6995
7467
  );
6996
7468
  }
6997
7469
  /** @internal Execute an ordered pipeline on a topology-selected lane. */
@@ -7002,13 +7474,11 @@ var NativeAdapter = class _NativeAdapter {
7002
7474
  laneId,
7003
7475
  options,
7004
7476
  this.maxPipelineCommands,
7005
- this.maxRequestFrameBytes
7477
+ this.capabilities.requestFrameBytes
7006
7478
  );
7007
7479
  }
7008
7480
  async close() {
7009
- if (this.closed) {
7010
- return;
7011
- }
7481
+ if (this.closed) return;
7012
7482
  this.failAll(new FerricStoreError("FerricStore connection closed"), true);
7013
7483
  this.socket.destroy();
7014
7484
  }
@@ -7026,7 +7496,9 @@ var NativeAdapter = class _NativeAdapter {
7026
7496
  });
7027
7497
  this.applyStartupLimits(response);
7028
7498
  const authRequired = field(response, "auth_required");
7029
- return authRequired == null ? false : booleanResponse(authRequired);
7499
+ const required = authRequired == null ? false : booleanResponse(authRequired);
7500
+ if (authRequired != null && !required) this.capabilities.activateAuthenticated();
7501
+ return required;
7030
7502
  }
7031
7503
  request(command, allowWhileDraining = false) {
7032
7504
  if (this.closed || this.draining && !allowWhileDraining) {
@@ -7067,7 +7539,7 @@ var NativeAdapter = class _NativeAdapter {
7067
7539
  let frame;
7068
7540
  try {
7069
7541
  requestId = this.requestScheduler.nextRequestId();
7070
- frame = encodeRequest(command, requestId, this.maxRequestFrameBytes);
7542
+ frame = encodeRequest(command, requestId, this.capabilities.requestFrameBytes);
7071
7543
  } catch (error) {
7072
7544
  if (hasFlowControlCredit) this.flowControl.release(laneId);
7073
7545
  return Promise.reject(error instanceof Error ? error : new FerricStoreError(String(error), { raw: error }));
@@ -7121,9 +7593,7 @@ var NativeAdapter = class _NativeAdapter {
7121
7593
  this.resolveClosedWaiters();
7122
7594
  }
7123
7595
  failAll(reason, connectionClosed = false, dispatchedMessage) {
7124
- if (this.closed) {
7125
- return;
7126
- }
7596
+ if (this.closed) return;
7127
7597
  this.closed = true;
7128
7598
  this.responseHandler.stop();
7129
7599
  this.resolveClosedWaiters();
@@ -7189,18 +7659,18 @@ var NativeAdapter = class _NativeAdapter {
7189
7659
  }
7190
7660
  applyStartupLimits(value) {
7191
7661
  this.applyFlowControlLimits(value);
7192
- const limits = startupLimits(value);
7193
- if (limits.laneQueue != null) {
7194
- this.flowControl.updateLaneQueueLimit(limits.laneQueue);
7662
+ const capabilities = this.capabilities.apply(value);
7663
+ if (capabilities.maxResponseBytes != null) {
7664
+ this.responseHandler.updateMaxResponseBytes(capabilities.maxResponseBytes);
7195
7665
  }
7196
- if (limits.lanes != null) {
7197
- this.protocolLanes = Math.min(this.protocolLanes, limits.lanes);
7666
+ if (capabilities.laneQueue != null) {
7667
+ this.flowControl.updateLaneQueueLimit(capabilities.laneQueue);
7198
7668
  }
7199
- if (limits.pipelineCommands != null) {
7200
- this.maxPipelineCommands = limits.pipelineCommands;
7669
+ if (capabilities.lanes != null) {
7670
+ this.protocolLanes = Math.min(this.protocolLanes, capabilities.lanes);
7201
7671
  }
7202
- if (limits.frameBytes != null) {
7203
- this.maxRequestFrameBytes = Math.min(this.maxRequestFrameBytes, limits.frameBytes);
7672
+ if (capabilities.pipelineCommands != null) {
7673
+ this.maxPipelineCommands = capabilities.pipelineCommands;
7204
7674
  }
7205
7675
  }
7206
7676
  };
@@ -7213,7 +7683,7 @@ function executeCommandArgs(executor, args) {
7213
7683
  }
7214
7684
 
7215
7685
  // src/reconnecting-executor.ts
7216
- var import_node_buffer23 = require("buffer");
7686
+ var import_node_buffer26 = require("buffer");
7217
7687
  var ReconnectingExecutor = class {
7218
7688
  constructor(createExecutor, options = {}) {
7219
7689
  this.createExecutor = createExecutor;
@@ -7408,217 +7878,11 @@ function normalizeNonNegativeInteger2(value, fallback) {
7408
7878
  }
7409
7879
 
7410
7880
  // src/topology.ts
7411
- var import_node_buffer26 = require("buffer");
7881
+ var import_node_buffer28 = require("buffer");
7412
7882
 
7413
7883
  // src/topology-routing.ts
7414
- var import_node_buffer25 = require("buffer");
7884
+ var import_node_buffer27 = require("buffer");
7415
7885
  var import_node_crypto = require("crypto");
7416
-
7417
- // src/topology-utilities.ts
7418
- var import_node_buffer24 = require("buffer");
7419
- function isPlainObject3(value) {
7420
- return typeof value === "object" && value != null && !Array.isArray(value) && !import_node_buffer24.Buffer.isBuffer(value);
7421
- }
7422
- function getField(source, ...keys) {
7423
- if (source instanceof Map) {
7424
- for (const key of keys) {
7425
- if (source.has(key)) return source.get(key);
7426
- const bufferKey = import_node_buffer24.Buffer.from(key);
7427
- for (const [itemKey, value] of source.entries()) {
7428
- if (import_node_buffer24.Buffer.isBuffer(itemKey) && itemKey.equals(bufferKey)) return value;
7429
- }
7430
- }
7431
- return void 0;
7432
- }
7433
- if (isPlainObject3(source)) {
7434
- for (const key of keys) {
7435
- if (Object.hasOwn(source, key)) return source[key];
7436
- }
7437
- }
7438
- return void 0;
7439
- }
7440
- function textOrUndefined(value) {
7441
- if (typeof value === "string") return value;
7442
- if (import_node_buffer24.Buffer.isBuffer(value)) return value.toString("utf8");
7443
- return void 0;
7444
- }
7445
- function numberOrUndefined(value) {
7446
- return typeof value === "number" && Number.isSafeInteger(value) ? value : void 0;
7447
- }
7448
- function nativeEventName(event) {
7449
- return textOrUndefined(getField(event.value, "event"))?.toUpperCase();
7450
- }
7451
- function endpointFromRange(item) {
7452
- const endpointValue = getField(item, "endpoint");
7453
- if (endpointValue != null && !isPlainObject3(endpointValue) && !(endpointValue instanceof Map)) {
7454
- throw new FerricStoreError("invalid SHARDS endpoint", { raw: item });
7455
- }
7456
- const raw = endpointValue ?? item;
7457
- const host = textOrUndefined(getField(raw, "host", "native_host"));
7458
- const nativePort = numberOrUndefined(getField(raw, "native_port"));
7459
- if (host == null || !validEndpointHost(host) || nativePort == null || nativePort <= 0 || nativePort > 65535) {
7460
- throw new FerricStoreError("invalid SHARDS endpoint", { raw: item });
7461
- }
7462
- const nativeTlsPortValue = getField(raw, "native_tls_port");
7463
- const nativeTlsPort = numberOrUndefined(nativeTlsPortValue);
7464
- if (nativeTlsPortValue != null && (nativeTlsPort == null || nativeTlsPort <= 0 || nativeTlsPort > 65535)) {
7465
- throw new FerricStoreError("invalid SHARDS endpoint", { raw: item });
7466
- }
7467
- return {
7468
- host,
7469
- nativePort,
7470
- node: textOrUndefined(getField(raw, "node", "leader_node", "owner_node")) ?? host,
7471
- ...nativeTlsPort == null ? {} : { nativeTlsPort }
7472
- };
7473
- }
7474
- function validEndpointHost(host) {
7475
- if (host.length === 0 || host.trim() !== host || /[\s\\/?#@]/u.test(host)) return false;
7476
- const authorityHost = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
7477
- try {
7478
- const url = new URL(`ferric://${authorityHost}:6388`);
7479
- return url.hostname !== "" && url.port === "6388" && url.username === "" && url.password === "";
7480
- } catch {
7481
- return false;
7482
- }
7483
- }
7484
- function sameEndpoint(left, right) {
7485
- return normalizedEndpointHost(left.host) === normalizedEndpointHost(right.host) && left.nativePort === right.nativePort && left.nativeTlsPort === right.nativeTlsPort && left.node === right.node;
7486
- }
7487
- function parseFerricUrl2(value) {
7488
- const url = new URL(value);
7489
- if (url.protocol !== "ferric:" && url.protocol !== "ferrics:") {
7490
- throw new FerricStoreError(`unsupported FerricStore URL scheme: ${url.protocol}`);
7491
- }
7492
- return {
7493
- host: normalizeFerricUrlHost(url.hostname),
7494
- ...url.password === "" ? {} : { password: decodeURIComponent(url.password) },
7495
- port: Number(url.port || (url.protocol === "ferrics:" ? 6389 : 6388)),
7496
- tls: url.protocol === "ferrics:",
7497
- ...url.username === "" ? {} : { username: decodeURIComponent(url.username) }
7498
- };
7499
- }
7500
- function endpointKeyFor(endpoint) {
7501
- return `${normalizedEndpointHost(endpoint.host)}:${endpoint.nativePort}`;
7502
- }
7503
- function connectionKeyForEndpoint(endpoint, useTls) {
7504
- const port = useTls && endpoint.nativeTlsPort != null ? endpoint.nativeTlsPort : endpoint.nativePort;
7505
- return `${useTls ? "ferrics" : "ferric"}://${normalizedEndpointHost(endpoint.host)}:${port}`;
7506
- }
7507
- function connectionKeyFromUrl(url) {
7508
- const parsed = parseFerricUrl2(url);
7509
- return `${parsed.tls ? "ferrics" : "ferric"}://${normalizedEndpointHost(parsed.host)}:${parsed.port}`;
7510
- }
7511
- function normalizedEndpointHost(host) {
7512
- const lower = host.toLowerCase();
7513
- return lower.startsWith("[") && lower.endsWith("]") ? lower.slice(1, -1) : lower;
7514
- }
7515
- function urlFromEndpoint(endpoint, useTls) {
7516
- const port = useTls && endpoint.nativeTlsPort != null ? endpoint.nativeTlsPort : endpoint.nativePort;
7517
- const host = endpoint.host.includes(":") && !endpoint.host.startsWith("[") ? `[${endpoint.host}]` : endpoint.host;
7518
- return `${useTls ? "ferrics" : "ferric"}://${host}:${port}`;
7519
- }
7520
- async function mapSettledWithConcurrency(items, concurrency, operation) {
7521
- const results = new Array(items.length);
7522
- let nextIndex = 0;
7523
- const worker = async () => {
7524
- while (nextIndex < items.length) {
7525
- const index = nextIndex++;
7526
- const item = items[index];
7527
- try {
7528
- results[index] = { status: "fulfilled", value: await operation(item, index) };
7529
- } catch (reason) {
7530
- results[index] = { status: "rejected", reason };
7531
- }
7532
- }
7533
- };
7534
- await Promise.all(Array.from(
7535
- { length: Math.min(concurrency, items.length) },
7536
- async () => await worker()
7537
- ));
7538
- return results;
7539
- }
7540
- function throwFirstRejected(results) {
7541
- for (const result of results) {
7542
- if (result.status === "rejected") throw result.reason;
7543
- }
7544
- }
7545
- var TaskConcurrencyLimiter = class {
7546
- constructor(concurrency) {
7547
- this.concurrency = concurrency;
7548
- }
7549
- concurrency;
7550
- active = 0;
7551
- head = 0;
7552
- pending = [];
7553
- async run(operation) {
7554
- await this.acquire();
7555
- try {
7556
- return await operation();
7557
- } finally {
7558
- this.release();
7559
- }
7560
- }
7561
- acquire() {
7562
- if (this.active < this.concurrency) {
7563
- this.active += 1;
7564
- return Promise.resolve();
7565
- }
7566
- return new Promise((resolve) => this.pending.push(resolve));
7567
- }
7568
- release() {
7569
- const next = this.pending[this.head];
7570
- if (next == null) {
7571
- this.active -= 1;
7572
- return;
7573
- }
7574
- this.head += 1;
7575
- next();
7576
- if (this.head === this.pending.length) {
7577
- this.pending.length = 0;
7578
- this.head = 0;
7579
- } else if (this.head >= 1024 && this.head * 2 >= this.pending.length) {
7580
- this.pending.splice(0, this.head);
7581
- this.head = 0;
7582
- }
7583
- }
7584
- };
7585
- function normalizedHostSet(hosts) {
7586
- return new Set(
7587
- hosts.filter((host) => host != null && host !== "").map((host) => normalizedEndpointHost(host))
7588
- );
7589
- }
7590
- function bufferStartsWith(value, prefix) {
7591
- return value.byteLength >= prefix.byteLength && value.subarray(0, prefix.byteLength).equals(prefix);
7592
- }
7593
- var OPEN_BRACE = "{".charCodeAt(0);
7594
- var CLOSE_BRACE = "}".charCodeAt(0);
7595
- function hashTagOrKey(key) {
7596
- const start = key.indexOf(OPEN_BRACE);
7597
- if (start < 0) return key;
7598
- const end = key.indexOf(CLOSE_BRACE, start + 1);
7599
- return end > start + 1 ? key.subarray(start + 1, end) : key;
7600
- }
7601
- function flowHashTag(rest, fallbackKey) {
7602
- const end = rest.indexOf(CLOSE_BRACE);
7603
- return end > 0 ? rest.subarray(0, end) : hashTagOrKey(fallbackKey);
7604
- }
7605
- var ROUTE_SLOT_MASK = 1023;
7606
- var FLOW_KEY_PREFIX = import_node_buffer24.Buffer.from("f:{");
7607
- var VALUE_REF_FLOW_KEY_PREFIX = import_node_buffer24.Buffer.from("X:f:{");
7608
- function routingSlotForKey(key) {
7609
- const keyBytes = import_node_buffer24.Buffer.isBuffer(key) ? key : import_node_buffer24.Buffer.from(key);
7610
- let hashInput;
7611
- if (bufferStartsWith(keyBytes, FLOW_KEY_PREFIX)) {
7612
- hashInput = flowHashTag(keyBytes.subarray(FLOW_KEY_PREFIX.byteLength), keyBytes);
7613
- } else if (bufferStartsWith(keyBytes, VALUE_REF_FLOW_KEY_PREFIX)) {
7614
- hashInput = flowHashTag(keyBytes.subarray(VALUE_REF_FLOW_KEY_PREFIX.byteLength), keyBytes);
7615
- } else {
7616
- hashInput = hashTagOrKey(keyBytes);
7617
- }
7618
- return crc32(hashInput) & ROUTE_SLOT_MASK;
7619
- }
7620
-
7621
- // src/topology-routing.ts
7622
7886
  var FLOW_PARTITION_ROUTE_CACHE_MAX = 1024;
7623
7887
  var flowPartitionRouteCache = /* @__PURE__ */ new Map();
7624
7888
  function routingKeyFromProtocolPayload(name, command) {
@@ -7626,9 +7890,18 @@ function routingKeyFromProtocolPayload(name, command) {
7626
7890
  return void 0;
7627
7891
  }
7628
7892
  if (isPlainObject3(command.payload)) {
7629
- for (const field2 of ["key", "partition_key", "id", "owner_flow_id", "parent_id", "root_id", "correlation_id", "scope"]) {
7893
+ for (const field2 of [
7894
+ "key",
7895
+ "partition_key",
7896
+ "id",
7897
+ "owner_flow_id",
7898
+ "parent_flow_id",
7899
+ "root_flow_id",
7900
+ "correlation_id",
7901
+ "scope"
7902
+ ]) {
7630
7903
  const value = getField(command.payload, field2);
7631
- if (typeof value === "string" || import_node_buffer25.Buffer.isBuffer(value)) {
7904
+ if (typeof value === "string" || import_node_buffer27.Buffer.isBuffer(value)) {
7632
7905
  return value;
7633
7906
  }
7634
7907
  }
@@ -7675,9 +7948,9 @@ function flowRoutingData(name, args) {
7675
7948
  if (typeof partition === "string" && partition.toUpperCase() !== "AUTO" && partition.toUpperCase() !== "MIXED") {
7676
7949
  return flowRoutingResult(flowLogicalPartitionRoutingKey(partition));
7677
7950
  }
7678
- if (import_node_buffer25.Buffer.isBuffer(partition)) {
7679
- const text2 = partition.toString("utf8").toUpperCase();
7680
- if (text2 !== "AUTO" && text2 !== "MIXED") {
7951
+ if (import_node_buffer27.Buffer.isBuffer(partition)) {
7952
+ const text3 = partition.toString("utf8").toUpperCase();
7953
+ if (text3 !== "AUTO" && text3 !== "MIXED") {
7681
7954
  return flowRoutingResult(flowLogicalPartitionRoutingKey(partition));
7682
7955
  }
7683
7956
  }
@@ -7766,22 +8039,22 @@ function flowPartitionRoutingKeyFromCommand(command, claim) {
7766
8039
  return { handled: false };
7767
8040
  }
7768
8041
  function isRoutingKey(value) {
7769
- return typeof value === "string" || import_node_buffer25.Buffer.isBuffer(value);
8042
+ return typeof value === "string" || import_node_buffer27.Buffer.isBuffer(value);
7770
8043
  }
7771
8044
  function flowLogicalPartitionRoutingKey(value) {
7772
- if (typeof value !== "string" && !import_node_buffer25.Buffer.isBuffer(value)) {
8045
+ if (typeof value !== "string" && !import_node_buffer27.Buffer.isBuffer(value)) {
7773
8046
  return void 0;
7774
8047
  }
7775
- const bytes2 = import_node_buffer25.Buffer.isBuffer(value) ? value : import_node_buffer25.Buffer.from(value);
7776
- const text2 = bytes2.toString("utf8");
7777
- const autoMatch = /^__flow_auto__:(0|[1-9]\d{0,2})$/u.exec(text2);
8048
+ const bytes2 = import_node_buffer27.Buffer.isBuffer(value) ? value : import_node_buffer27.Buffer.from(value);
8049
+ const text3 = bytes2.toString("utf8");
8050
+ const autoMatch = /^__flow_auto__:(0|[1-9]\d{0,2})$/u.exec(text3);
7778
8051
  if (autoMatch != null) {
7779
8052
  const bucket = Number(autoMatch[1]);
7780
8053
  if (bucket < 256) {
7781
- return `f:{fa:${bucket}}:route`;
8054
+ return `{fa:${bucket}}`;
7782
8055
  }
7783
8056
  }
7784
- const cacheKey = `${import_node_buffer25.Buffer.isBuffer(value) ? "b" : "s"}:${bytes2.toString("base64")}`;
8057
+ const cacheKey = `${import_node_buffer27.Buffer.isBuffer(value) ? "b" : "s"}:${bytes2.toString("base64")}`;
7785
8058
  const cached = flowPartitionRouteCache.get(cacheKey);
7786
8059
  if (cached != null) {
7787
8060
  flowPartitionRouteCache.delete(cacheKey);
@@ -7789,7 +8062,7 @@ function flowLogicalPartitionRoutingKey(value) {
7789
8062
  return cached;
7790
8063
  }
7791
8064
  const digest = (0, import_node_crypto.createHash)("sha256").update(bytes2).digest("base64url");
7792
- const routeKey = `f:{f:${digest}}:route`;
8065
+ const routeKey = `{f:${digest}}`;
7793
8066
  if (flowPartitionRouteCache.size >= FLOW_PARTITION_ROUTE_CACHE_MAX) {
7794
8067
  const oldest = flowPartitionRouteCache.keys().next().value;
7795
8068
  if (oldest != null) flowPartitionRouteCache.delete(oldest);
@@ -7798,18 +8071,17 @@ function flowLogicalPartitionRoutingKey(value) {
7798
8071
  return routeKey;
7799
8072
  }
7800
8073
  function flowAutoIdRoutingKey(value) {
7801
- if (typeof value !== "string" && !import_node_buffer25.Buffer.isBuffer(value)) {
8074
+ if (typeof value !== "string" && !import_node_buffer27.Buffer.isBuffer(value)) {
7802
8075
  return void 0;
7803
8076
  }
7804
- const bytes2 = import_node_buffer25.Buffer.isBuffer(value) ? value : import_node_buffer25.Buffer.from(value);
7805
- const bucket = crc32(bytes2) & 255;
7806
- return `f:{fa:${bucket}}:route`;
8077
+ const bucket = (import_node_buffer27.Buffer.isBuffer(value) ? crc32(value) : crc32Utf8(value)) & 255;
8078
+ return `{fa:${bucket}}`;
7807
8079
  }
7808
8080
  function flowClaimLogicalPartitionRoutingKey(value) {
7809
- if (typeof value !== "string" && !import_node_buffer25.Buffer.isBuffer(value)) return void 0;
8081
+ if (typeof value !== "string" && !import_node_buffer27.Buffer.isBuffer(value)) return void 0;
7810
8082
  const selector = commandPart(value);
7811
8083
  if (selector === "AUTO" || selector === "ANY") return void 0;
7812
- if (selector === "GLOBAL") return "f:{f}:route";
8084
+ if (selector === "GLOBAL") return "{f}";
7813
8085
  return flowLogicalPartitionRoutingKey(value);
7814
8086
  }
7815
8087
  function singleShardFlowPartitionKey(values) {
@@ -7821,7 +8093,7 @@ function singleShardFlowClaimPartitionKey(values) {
7821
8093
  return keys.some((key) => key == null) ? void 0 : singleShardKey(keys);
7822
8094
  }
7823
8095
  function singleShardKey(keys) {
7824
- if (keys.length === 0 || keys.some((key) => typeof key !== "string" && !import_node_buffer25.Buffer.isBuffer(key))) {
8096
+ if (keys.length === 0 || keys.some((key) => typeof key !== "string" && !import_node_buffer27.Buffer.isBuffer(key))) {
7825
8097
  return void 0;
7826
8098
  }
7827
8099
  const usable = keys;
@@ -7854,7 +8126,7 @@ function routedKeyGroups(keys, routeKey) {
7854
8126
  const groups = /* @__PURE__ */ new Map();
7855
8127
  for (let index = 0; index < keys.length; index += 1) {
7856
8128
  const key = keys[index];
7857
- if (typeof key !== "string" && !import_node_buffer25.Buffer.isBuffer(key)) return void 0;
8129
+ if (typeof key !== "string" && !import_node_buffer27.Buffer.isBuffer(key)) return void 0;
7858
8130
  const route = routeKey(key);
7859
8131
  const groupKey = `${route.endpointKey}\0${route.laneId}`;
7860
8132
  const group = groups.get(groupKey);
@@ -8095,7 +8367,16 @@ function isExplicitlySafeReroute(error) {
8095
8367
  if (error instanceof ConnectionClosedError) {
8096
8368
  return error.requestDisposition === "unsent";
8097
8369
  }
8098
- return error instanceof RerouteError && getField(error.raw, "safe_to_retry") === true;
8370
+ return error instanceof RerouteError && error.retryable === true && error.safeToRetry === true;
8371
+ }
8372
+ function retryAfterMs(error) {
8373
+ return error instanceof FerricStoreError ? error.retryAfterMs ?? 0 : 0;
8374
+ }
8375
+ async function waitForExplicitlySafeReroute(error) {
8376
+ if (!isExplicitlySafeReroute(error)) return false;
8377
+ const delayMs = retryAfterMs(error);
8378
+ if (delayMs > 0) await sleep(delayMs);
8379
+ return true;
8099
8380
  }
8100
8381
 
8101
8382
  // src/topology-endpoint-trust.ts
@@ -8829,7 +9110,9 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
8829
9110
  () => true,
8830
9111
  () => false
8831
9112
  );
8832
- return refreshed && isExplicitlySafeReroute(error);
9113
+ if (!refreshed || !await waitForExplicitlySafeReroute(error)) return false;
9114
+ this.assertOpen();
9115
+ return true;
8833
9116
  }
8834
9117
  async executePipelineOnRoute(commands, route, options) {
8835
9118
  const adapter = await this.adapterForCurrentRoute(route);
@@ -8919,7 +9202,7 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
8919
9202
  };
8920
9203
 
8921
9204
  // src/response-map-preservation.ts
8922
- var import_node_buffer27 = require("buffer");
9205
+ var import_node_buffer29 = require("buffer");
8923
9206
  function toStringKeyMapPreservingValues(value) {
8924
9207
  if (value == null) return void 0;
8925
9208
  const result = {};
@@ -8929,7 +9212,7 @@ function toStringKeyMapPreservingValues(value) {
8929
9212
  }
8930
9213
  return result;
8931
9214
  }
8932
- if (typeof value === "object" && !Array.isArray(value) && !import_node_buffer27.Buffer.isBuffer(value) && !(value instanceof Uint8Array)) {
9215
+ if (typeof value === "object" && !Array.isArray(value) && !import_node_buffer29.Buffer.isBuffer(value) && !(value instanceof Uint8Array)) {
8933
9216
  for (const [key, item] of Object.entries(value)) {
8934
9217
  setOwnValue(result, text(key), normalizeMapStructurePreservingBytes(item));
8935
9218
  }
@@ -8938,7 +9221,7 @@ function toStringKeyMapPreservingValues(value) {
8938
9221
  return void 0;
8939
9222
  }
8940
9223
  function normalizeMapStructurePreservingBytes(value) {
8941
- if (import_node_buffer27.Buffer.isBuffer(value) || value instanceof Uint8Array) return value;
9224
+ if (import_node_buffer29.Buffer.isBuffer(value) || value instanceof Uint8Array) return value;
8942
9225
  if (value instanceof Map) {
8943
9226
  const result = {};
8944
9227
  for (const [key, item] of value.entries()) {
@@ -8960,7 +9243,7 @@ function normalizeMapStructurePreservingBytes(value) {
8960
9243
  }
8961
9244
 
8962
9245
  // src/native-kv-responses.ts
8963
- var import_node_buffer28 = require("buffer");
9246
+ var import_node_buffer30 = require("buffer");
8964
9247
  function rateLimitResultFromResp(value) {
8965
9248
  if (!Array.isArray(value) || value.length !== 4) {
8966
9249
  throw new TypeError("RATELIMIT.ADD returned an unexpected response");
@@ -9003,30 +9286,27 @@ function fetchOrComputeResultFromResp(value, codec) {
9003
9286
  shouldCompute: false
9004
9287
  };
9005
9288
  }
9006
- if (status !== "compute") throw new TypeError("FETCH_OR_COMPUTE returned an unexpected response");
9289
+ if (status !== "compute" || value.length !== 3) {
9290
+ throw new TypeError("FETCH_OR_COMPUTE returned an unexpected response");
9291
+ }
9007
9292
  return {
9008
9293
  status,
9009
9294
  computeHint: responseBytes(value[1], "FETCH_OR_COMPUTE"),
9010
- ...value.length === 3 ? {
9011
- computeMode: "fenced",
9012
- computeToken: responseBytes(value[2], "FETCH_OR_COMPUTE")
9013
- } : {
9014
- computeMode: "legacy",
9015
- computeToken: null
9016
- },
9295
+ computeMode: "fenced",
9296
+ computeToken: responseBytes(value[2], "FETCH_OR_COMPUTE"),
9017
9297
  hit: false,
9018
9298
  shouldCompute: true
9019
9299
  };
9020
9300
  }
9021
9301
  function decodePayload(codec, value) {
9022
9302
  if (value == null) return null;
9023
- if (import_node_buffer28.Buffer.isBuffer(value)) return codec.decode(value);
9024
- if (value instanceof Uint8Array) return codec.decode(import_node_buffer28.Buffer.from(value));
9025
- if (typeof value === "string") return codec.decode(import_node_buffer28.Buffer.from(value));
9303
+ if (import_node_buffer30.Buffer.isBuffer(value)) return codec.decode(value);
9304
+ if (value instanceof Uint8Array) return codec.decode(import_node_buffer30.Buffer.from(value));
9305
+ if (typeof value === "string") return codec.decode(import_node_buffer30.Buffer.from(value));
9026
9306
  return normalizeRefMeta(value);
9027
9307
  }
9028
9308
  function requiredResponseString(value, context) {
9029
- if (typeof value !== "string" && !import_node_buffer28.Buffer.isBuffer(value) && !(value instanceof Uint8Array)) {
9309
+ if (typeof value !== "string" && !import_node_buffer30.Buffer.isBuffer(value) && !(value instanceof Uint8Array)) {
9030
9310
  throw new TypeError(`${context} returned an unexpected response`);
9031
9311
  }
9032
9312
  const result = text(value);
@@ -9043,7 +9323,7 @@ function requiredNonNegativeInteger(value, context) {
9043
9323
  return result;
9044
9324
  }
9045
9325
  function responseBytes(value, context) {
9046
- if (typeof value !== "string" && !import_node_buffer28.Buffer.isBuffer(value) && !(value instanceof Uint8Array)) {
9326
+ if (typeof value !== "string" && !import_node_buffer30.Buffer.isBuffer(value) && !(value instanceof Uint8Array)) {
9047
9327
  throw new TypeError(`${context} returned an unexpected response`);
9048
9328
  }
9049
9329
  return bytes(value);
@@ -9128,6 +9408,9 @@ function flowRecordFromResp(value, codec) {
9128
9408
  field(value, "max_active_ms"),
9129
9409
  "FLOW record max_active_ms"
9130
9410
  );
9411
+ const rawError = field(value, "error");
9412
+ const error = flowError(rawError, codec);
9413
+ const failureReason = optionalResponseString(field(rawError, "reason"), "FLOW record error reason");
9131
9414
  return {
9132
9415
  id: requiredTextField(value, "id", "FLOW record"),
9133
9416
  type: requiredTextField(value, "type", "FLOW record"),
@@ -9142,6 +9425,8 @@ function flowRecordFromResp(value, codec) {
9142
9425
  rootFlowId: optionalResponseString(field(value, "root_flow_id"), "FLOW record root_flow_id"),
9143
9426
  correlationId: optionalResponseString(field(value, "correlation_id"), "FLOW record correlation_id"),
9144
9427
  ...maxActiveMs == null ? {} : { maxActiveMs },
9428
+ ...error == null ? {} : { error },
9429
+ ...failureReason == null ? {} : { failureReason },
9145
9430
  valueRefs: optionalMapField(value, "value_refs", "FLOW record"),
9146
9431
  values,
9147
9432
  valueSizes: optionalMapField(value, "value_sizes", "FLOW record"),
@@ -9153,6 +9438,21 @@ function flowRecordFromResp(value, codec) {
9153
9438
  raw: value
9154
9439
  };
9155
9440
  }
9441
+ function flowError(value, codec) {
9442
+ if (value == null) return void 0;
9443
+ const reason = optionalResponseString(field(value, "reason"), "FLOW record error reason");
9444
+ if (reason === "max_active_ms") {
9445
+ const maxActiveMs = optionalPositiveResponseInteger(
9446
+ field(value, "max_active_ms"),
9447
+ "FLOW record error max_active_ms"
9448
+ );
9449
+ if (maxActiveMs == null) {
9450
+ throw new TypeError("FLOW record error max_active_ms returned an unexpected response");
9451
+ }
9452
+ return { maxActiveMs, reason };
9453
+ }
9454
+ return decodePayload2(codec, value);
9455
+ }
9156
9456
  function decodePayload2(codec, value) {
9157
9457
  if (value == null) {
9158
9458
  return null;
@@ -9733,7 +10033,7 @@ function groupAutoPartitionItems(items) {
9733
10033
  }
9734
10034
 
9735
10035
  // src/client-values.ts
9736
- var import_node_buffer29 = require("buffer");
10036
+ var import_node_buffer31 = require("buffer");
9737
10037
  async function valueMGetEntries(client, refs, options = {}) {
9738
10038
  const refCount = refs.length;
9739
10039
  if (refCount === 0) {
@@ -9768,12 +10068,12 @@ async function valueMGetEntries(client, refs, options = {}) {
9768
10068
  const item = response[index];
9769
10069
  if (item == null) {
9770
10070
  entries[index] = { found: false };
9771
- } else if (import_node_buffer29.Buffer.isBuffer(item)) {
10071
+ } else if (import_node_buffer31.Buffer.isBuffer(item)) {
9772
10072
  entries[index] = { found: true, value: client.codec.decode(item) };
9773
10073
  } else if (item instanceof Uint8Array) {
9774
- entries[index] = { found: true, value: client.codec.decode(import_node_buffer29.Buffer.from(item)) };
10074
+ entries[index] = { found: true, value: client.codec.decode(import_node_buffer31.Buffer.from(item)) };
9775
10075
  } else if (typeof item === "string") {
9776
- entries[index] = { found: true, value: client.codec.decode(import_node_buffer29.Buffer.from(item)) };
10076
+ entries[index] = { found: true, value: client.codec.decode(import_node_buffer31.Buffer.from(item)) };
9777
10077
  } else {
9778
10078
  entries[index] = { found: true, value: item };
9779
10079
  }
@@ -9782,10 +10082,10 @@ async function valueMGetEntries(client, refs, options = {}) {
9782
10082
  }
9783
10083
 
9784
10084
  // src/auto-batch.ts
9785
- var import_node_buffer31 = require("buffer");
10085
+ var import_node_buffer33 = require("buffer");
9786
10086
 
9787
10087
  // src/auto-batch-ordering.ts
9788
- var import_node_buffer30 = require("buffer");
10088
+ var import_node_buffer32 = require("buffer");
9789
10089
  function autoBatchOrderingPlan(batch) {
9790
10090
  const accesses = /* @__PURE__ */ new Map();
9791
10091
  const fallbackDependencies = [];
@@ -9900,13 +10200,13 @@ function flowManyAutoBatchIds(command, name) {
9900
10200
  return fixedFlowItemIds(
9901
10201
  command,
9902
10202
  mixed ? 4 : 3,
9903
- (itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && isFencingToken(command[itemIndex + (mixed ? 2 : 1)]) && import_node_buffer30.Buffer.isBuffer(command[itemIndex + (mixed ? 3 : 2)])
10203
+ (itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && isFencingToken(command[itemIndex + (mixed ? 2 : 1)]) && import_node_buffer32.Buffer.isBuffer(command[itemIndex + (mixed ? 3 : 2)])
9904
10204
  );
9905
10205
  }
9906
10206
  return fixedFlowItemIds(
9907
10207
  command,
9908
10208
  mixed ? 4 : 3,
9909
- (itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && import_node_buffer30.Buffer.isBuffer(command[itemIndex + (mixed ? 2 : 1)]) && isFencingToken(command[itemIndex + (mixed ? 3 : 2)])
10209
+ (itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && import_node_buffer32.Buffer.isBuffer(command[itemIndex + (mixed ? 2 : 1)]) && isFencingToken(command[itemIndex + (mixed ? 3 : 2)])
9910
10210
  );
9911
10211
  }
9912
10212
  function createManyAutoBatchIds(command) {
@@ -9919,7 +10219,7 @@ function createManyAutoBatchIds(command) {
9919
10219
  const ids = fixedFlowItemIds(
9920
10220
  command,
9921
10221
  width,
9922
- (itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && import_node_buffer30.Buffer.isBuffer(command[itemIndex + width - 1]),
10222
+ (itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && import_node_buffer32.Buffer.isBuffer(command[itemIndex + width - 1]),
9923
10223
  markerIndex
9924
10224
  );
9925
10225
  if (ids != null) return ids;
@@ -9937,7 +10237,7 @@ function extendedCreateManyAutoBatchIds(command, markerIndex) {
9937
10237
  let cursor = markerIndex + 2;
9938
10238
  for (let itemIndex = 0; itemIndex < itemCount; itemIndex += 1) {
9939
10239
  const id = command[cursor];
9940
- if (!isAutoBatchResourceValue(id) || !isAutoBatchResourceValue(command[cursor + 1]) || !import_node_buffer30.Buffer.isBuffer(command[cursor + 2])) return void 0;
10240
+ if (!isAutoBatchResourceValue(id) || !isAutoBatchResourceValue(command[cursor + 1]) || !import_node_buffer32.Buffer.isBuffer(command[cursor + 2])) return void 0;
9941
10241
  ids.push(id);
9942
10242
  cursor += 3;
9943
10243
  const afterValues = skipExtendedNamedItems(command, cursor, true);
@@ -9956,7 +10256,7 @@ function skipExtendedNamedItems(command, countIndex, encodedValues) {
9956
10256
  for (let index = 0; index < count; index += 1) {
9957
10257
  const name = command[firstItem + index * 2];
9958
10258
  const value = command[firstItem + index * 2 + 1];
9959
- if (!isAutoBatchResourceValue(name) || (encodedValues ? !import_node_buffer30.Buffer.isBuffer(value) : !isAutoBatchResourceValue(value))) return void 0;
10259
+ if (!isAutoBatchResourceValue(name) || (encodedValues ? !import_node_buffer32.Buffer.isBuffer(value) : !isAutoBatchResourceValue(value))) return void 0;
9960
10260
  }
9961
10261
  return firstItem + count * 2;
9962
10262
  }
@@ -9971,7 +10271,7 @@ function runStepsManyAutoBatchIds(command) {
9971
10271
  ids.push(item);
9972
10272
  continue;
9973
10273
  }
9974
- if (typeof item !== "object" || item == null || Array.isArray(item) || import_node_buffer30.Buffer.isBuffer(item)) return void 0;
10274
+ if (typeof item !== "object" || item == null || Array.isArray(item) || import_node_buffer32.Buffer.isBuffer(item)) return void 0;
9975
10275
  const id = item.id;
9976
10276
  if (!isAutoBatchResourceValue(id)) return void 0;
9977
10277
  ids.push(id);
@@ -10012,7 +10312,7 @@ function flowValuePutOwner(command, start) {
10012
10312
  }
10013
10313
  var flowValuePutOptionTokens = /* @__PURE__ */ new Set(["NAME", "NOW", "OVERRIDE", "OWNER_FLOW_ID", "PARTITION", "TTL", "TTL_MS"]);
10014
10314
  function isAutoBatchResourceValue(value) {
10015
- return typeof value === "string" || import_node_buffer30.Buffer.isBuffer(value);
10315
+ return typeof value === "string" || import_node_buffer32.Buffer.isBuffer(value);
10016
10316
  }
10017
10317
  function isFencingToken(value) {
10018
10318
  return typeof value === "number" && Number.isSafeInteger(value) || typeof value === "bigint";
@@ -10021,7 +10321,7 @@ function nonNegativeItemCount(value) {
10021
10321
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
10022
10322
  }
10023
10323
  function autoBatchResourceKey(namespace, value) {
10024
- return `${namespace}:${import_node_buffer30.Buffer.from(value).toString("base64")}`;
10324
+ return `${namespace}:${import_node_buffer32.Buffer.from(value).toString("base64")}`;
10025
10325
  }
10026
10326
  function autoBatchCommandName(command) {
10027
10327
  return commandView(command).name ?? null;
@@ -10430,15 +10730,15 @@ function claimFailure(error) {
10430
10730
  }
10431
10731
 
10432
10732
  // src/client-flow-support.ts
10433
- var import_node_buffer37 = require("buffer");
10733
+ var import_node_buffer39 = require("buffer");
10434
10734
 
10435
10735
  // src/client-core.ts
10436
- var import_node_buffer36 = require("buffer");
10736
+ var import_node_buffer38 = require("buffer");
10437
10737
 
10438
10738
  // src/client-core-helpers.ts
10439
- var import_node_buffer32 = require("buffer");
10739
+ var import_node_buffer34 = require("buffer");
10440
10740
  function bgsaveResponse(response) {
10441
- if ((typeof response === "string" || import_node_buffer32.Buffer.isBuffer(response) || response instanceof Uint8Array) && text(response) === "Background saving started") {
10741
+ if ((typeof response === "string" || import_node_buffer34.Buffer.isBuffer(response) || response instanceof Uint8Array) && text(response) === "Background saving started") {
10442
10742
  return true;
10443
10743
  }
10444
10744
  return okResponse(response);
@@ -10449,11 +10749,11 @@ function clientNameResponse(response) {
10449
10749
  function fetchOrComputeCompletionToken(options) {
10450
10750
  if (options == null || !Object.hasOwn(options, "computeToken") || options.computeToken === void 0) {
10451
10751
  throw new TypeError(
10452
- "fetch-or-compute completion requires computeToken; pass null only for a legacy tokenless lease"
10752
+ "fetch-or-compute completion requires computeToken"
10453
10753
  );
10454
10754
  }
10455
- if (options.computeToken !== null && !import_node_buffer32.Buffer.isBuffer(options.computeToken)) {
10456
- throw new TypeError("fetch-or-compute computeToken must be a Buffer or explicit null for a legacy lease");
10755
+ if (!import_node_buffer34.Buffer.isBuffer(options.computeToken)) {
10756
+ throw new TypeError("fetch-or-compute computeToken must be a Buffer");
10457
10757
  }
10458
10758
  return options.computeToken;
10459
10759
  }
@@ -10475,10 +10775,10 @@ function unsupportedClientCaching() {
10475
10775
  }
10476
10776
 
10477
10777
  // src/client-base.ts
10478
- var import_node_buffer34 = require("buffer");
10778
+ var import_node_buffer36 = require("buffer");
10479
10779
 
10480
10780
  // src/client-executor.ts
10481
- var import_node_buffer33 = require("buffer");
10781
+ var import_node_buffer35 = require("buffer");
10482
10782
  var ErrorMappingExecutor = class {
10483
10783
  constructor(executor) {
10484
10784
  this.executor = executor;
@@ -10575,14 +10875,17 @@ var FerricStoreClientBase = class {
10575
10875
  };
10576
10876
  }
10577
10877
  async command(...args) {
10878
+ assertAtomicKeyValueCommandSharesSlot(args);
10578
10879
  return await executeCommandArgs(this.executor, args);
10579
10880
  }
10580
10881
  /** Execute an already-built command without a JavaScript variadic-call limit. */
10581
10882
  async commandArgs(args) {
10883
+ assertAtomicKeyValueCommandSharesSlot(args);
10582
10884
  return await executeCommandArgs(this.executor, args);
10583
10885
  }
10584
10886
  async pipeline(commands, options) {
10585
10887
  const snapshot = snapshotPipelineCommands(commands);
10888
+ for (const command of snapshot) assertAtomicKeyValueCommandSharesSlot(command);
10586
10889
  const snapshotOptions = snapshotPipelineOptions(options);
10587
10890
  const results = this.executor.executePipeline != null ? await this.executor.executePipeline(snapshot, snapshotOptions) : await executeCommandArraysIndividually(
10588
10891
  async (command) => await this.commandArgs(command),
@@ -10809,14 +11112,14 @@ var FerricStoreAdministrationClient = class extends FerricStoreClientBase {
10809
11112
  };
10810
11113
 
10811
11114
  // src/store-utilities.ts
10812
- var import_node_buffer35 = require("buffer");
11115
+ var import_node_buffer37 = require("buffer");
10813
11116
  function encode(codec, value) {
10814
11117
  return codec.encode(value);
10815
11118
  }
10816
11119
  function decode(codec, value) {
10817
11120
  if (value == null) return null;
10818
- if (import_node_buffer35.Buffer.isBuffer(value)) return codec.decode(value);
10819
- if (value instanceof Uint8Array) return codec.decode(import_node_buffer35.Buffer.from(value));
11121
+ if (import_node_buffer37.Buffer.isBuffer(value)) return codec.decode(value);
11122
+ if (value instanceof Uint8Array) return codec.decode(import_node_buffer37.Buffer.from(value));
10820
11123
  return value;
10821
11124
  }
10822
11125
  function number(value) {
@@ -11222,12 +11525,15 @@ var TopKStore = class {
11222
11525
  const width = ownOption(options, "width");
11223
11526
  const depth = ownOption(options, "depth");
11224
11527
  const decay = ownOption(options, "decay");
11225
- const tuningCount = [width, depth, decay].filter((value) => value != null).length;
11226
- if (tuningCount !== 0 && tuningCount !== 3) {
11227
- throw new TypeError("TOPK.RESERVE width, depth, and decay must be provided together");
11528
+ if (decay != null || Object.hasOwn(options, "decay")) {
11529
+ throw new TypeError("TOPK.RESERVE decay is not supported by FerricStore 0.8");
11530
+ }
11531
+ const tuningCount = [width, depth].filter((value) => value != null).length;
11532
+ if (tuningCount !== 0 && tuningCount !== 2) {
11533
+ throw new TypeError("TOPK.RESERVE width and depth must be provided together");
11228
11534
  }
11229
- if (tuningCount === 3) {
11230
- args.push(width, depth, decay);
11535
+ if (tuningCount === 2) {
11536
+ args.push(width, depth);
11231
11537
  }
11232
11538
  return okResponse(await commandArgs(this.client, args));
11233
11539
  }
@@ -11633,10 +11939,14 @@ var KeyValueStore = class {
11633
11939
  );
11634
11940
  }
11635
11941
  async mset(entries) {
11636
- return okResponse(await commandArgs(this.client, keyValueArgs(["MSET"], this.client.codec, entries)));
11942
+ const args = keyValueArgs(["MSET"], this.client.codec, entries);
11943
+ assertKeyValueCommandSharesSlot(args, "MSET");
11944
+ return okResponse(await commandArgs(this.client, args));
11637
11945
  }
11638
11946
  async msetnx(entries) {
11639
- return binaryBooleanResponse(await commandArgs(this.client, keyValueArgs(["MSETNX"], this.client.codec, entries)));
11947
+ const args = keyValueArgs(["MSETNX"], this.client.codec, entries);
11948
+ assertKeyValueCommandSharesSlot(args, "MSETNX");
11949
+ return binaryBooleanResponse(await commandArgs(this.client, args));
11640
11950
  }
11641
11951
  async incr(key) {
11642
11952
  return integerReply(await this.client.command("INCR", key));
@@ -12706,7 +13016,8 @@ var FerricStoreClientCore = class extends FerricStoreAdministrationClient {
12706
13016
  return okResponse(await this.command(
12707
13017
  "FETCH_OR_COMPUTE_RESULT",
12708
13018
  key,
12709
- ...computeToken === null ? [encoded] : [computeToken, encoded],
13019
+ computeToken,
13020
+ encoded,
12710
13021
  options.ttlMs
12711
13022
  ));
12712
13023
  }
@@ -12715,7 +13026,7 @@ var FerricStoreClientCore = class extends FerricStoreAdministrationClient {
12715
13026
  return okResponse(await this.command(
12716
13027
  "FETCH_OR_COMPUTE_ERROR",
12717
13028
  key,
12718
- ...computeToken === null ? [] : [computeToken],
13029
+ computeToken,
12719
13030
  message
12720
13031
  ));
12721
13032
  }
@@ -12841,7 +13152,7 @@ var FerricStoreManagementClient = class extends FerricStoreClientCore {
12841
13152
  }
12842
13153
  async effectGet(id, effectKey, options = {}) {
12843
13154
  const args = ["FLOW.EFFECT.GET", id, "EFFECT_KEY", effectKey];
12844
- append(args, "PARTITION", options.partitionKey ?? autoPartitionKeyForId(id));
13155
+ append(args, "PARTITION", options.partitionKey);
12845
13156
  return optionalAdminRecord(await this.commandArgs(args), "FLOW.EFFECT.GET");
12846
13157
  }
12847
13158
  async effectStatus(command, id, effectKey, options) {
@@ -13013,7 +13324,7 @@ var FerricStoreManagementClient = class extends FerricStoreClientCore {
13013
13324
  }
13014
13325
  async governanceLedger(id, options = {}) {
13015
13326
  const args = ["FLOW.GOVERNANCE.LEDGER", id];
13016
- append(args, "PARTITION", options.partitionKey ?? autoPartitionKeyForId(id));
13327
+ append(args, "PARTITION", options.partitionKey);
13017
13328
  append(args, "LIMIT", options.limit);
13018
13329
  append(args, "FROM_MS", options.fromMs);
13019
13330
  append(args, "TO_MS", options.toMs);
@@ -13029,7 +13340,7 @@ async function executeProducerWriteWithBackpressure(execute, policy, signal) {
13029
13340
  try {
13030
13341
  return await execute();
13031
13342
  } catch (error) {
13032
- if (!(error instanceof OverloadedError) || attempt >= policy.maxRetries) throw error;
13343
+ if (!(error instanceof OverloadedError) || error.retryable !== true || error.safeToRetry !== true || attempt >= policy.maxRetries) throw error;
13033
13344
  const exponential = Math.min(policy.maxDelayMs, policy.baseDelayMs * 2 ** attempt);
13034
13345
  const base = Math.min(policy.maxDelayMs, error.retryAfterMs ?? exponential);
13035
13346
  const jitter = base * (policy.jitterPct / 100) * Math.random();
@@ -13294,7 +13605,7 @@ var FerricStoreFlowSupportClient = class extends FerricStoreManagementClient {
13294
13605
  };
13295
13606
 
13296
13607
  // src/flow-many-snapshot.ts
13297
- var import_node_buffer38 = require("buffer");
13608
+ var import_node_buffer40 = require("buffer");
13298
13609
  var encodedOptionFields = ["error", "payload", "reason", "result"];
13299
13610
  function snapshotCreateItem(item, codec) {
13300
13611
  const snapshot = {
@@ -13334,7 +13645,7 @@ function snapshotFlowManyOptions(options, codec) {
13334
13645
  }
13335
13646
  function snapshotClaimedItem(item) {
13336
13647
  const wire = item[CLAIMED_ITEM_WIRE];
13337
- const leaseToken = import_node_buffer38.Buffer.from(wire?.leaseToken ?? item.leaseToken);
13648
+ const leaseToken = import_node_buffer40.Buffer.from(wire?.leaseToken ?? item.leaseToken);
13338
13649
  const snapshot = {
13339
13650
  ...item,
13340
13651
  fencingToken: wire?.fencingToken ?? item.fencingToken,
@@ -13351,15 +13662,15 @@ function snapshotClaimedItem(item) {
13351
13662
  function snapshotFencedItem(item) {
13352
13663
  return Object.freeze({
13353
13664
  ...item,
13354
- ...item.leaseToken == null ? {} : { leaseToken: import_node_buffer38.Buffer.from(item.leaseToken) }
13665
+ ...item.leaseToken == null ? {} : { leaseToken: import_node_buffer40.Buffer.from(item.leaseToken) }
13355
13666
  });
13356
13667
  }
13357
13668
  function snapshotClaimedItemWire(wire, leaseToken) {
13358
13669
  return Object.freeze({
13359
13670
  fencingToken: wire.fencingToken,
13360
- id: import_node_buffer38.Buffer.from(wire.id),
13671
+ id: import_node_buffer40.Buffer.from(wire.id),
13361
13672
  leaseToken,
13362
- partitionKey: wire.partitionKey == null ? wire.partitionKey : import_node_buffer38.Buffer.from(wire.partitionKey)
13673
+ partitionKey: wire.partitionKey == null ? wire.partitionKey : import_node_buffer40.Buffer.from(wire.partitionKey)
13363
13674
  });
13364
13675
  }
13365
13676
  function snapshotArray(values) {
@@ -13370,7 +13681,7 @@ function snapshotArray(values) {
13370
13681
  return Object.freeze(snapshot);
13371
13682
  }
13372
13683
  function snapshotStateMeta(stateMeta) {
13373
- return snapshotRecord(stateMeta, (value) => import_node_buffer38.Buffer.isBuffer(value) ? import_node_buffer38.Buffer.from(value) : value);
13684
+ return snapshotRecord(stateMeta, (value) => import_node_buffer40.Buffer.isBuffer(value) ? import_node_buffer40.Buffer.from(value) : value);
13374
13685
  }
13375
13686
  function snapshotCommandRecord(values) {
13376
13687
  const seen = /* @__PURE__ */ new WeakMap();
@@ -13388,7 +13699,7 @@ function snapshotRecord(values, capture) {
13388
13699
  }
13389
13700
  function snapshotCommandArgument(value, seen) {
13390
13701
  if (typeof value !== "object" || value == null) return value;
13391
- if (import_node_buffer38.Buffer.isBuffer(value) || value instanceof Uint8Array) return import_node_buffer38.Buffer.from(value);
13702
+ if (import_node_buffer40.Buffer.isBuffer(value) || value instanceof Uint8Array) return import_node_buffer40.Buffer.from(value);
13392
13703
  const objectValue = value;
13393
13704
  const existing = seen.get(objectValue);
13394
13705
  if (existing != null) return existing;
@@ -14186,6 +14497,9 @@ var FerricStoreClient = class _FerricStoreClient extends FerricStoreProducerClie
14186
14497
  return new _FerricStoreClient(executor, clientOptions);
14187
14498
  }
14188
14499
  async valuePut(value, options = {}) {
14500
+ if (options.ownerFlowId != null && options.name != null && options.ttlMs != null) {
14501
+ throw new TypeError("named Flow values cannot have a TTL");
14502
+ }
14189
14503
  const args = ["FLOW.VALUE.PUT", this.codec.encode(value), "NOW", options.nowMs ?? nowMs()];
14190
14504
  append(args, "PARTITION", options.partitionKey);
14191
14505
  append(args, "OWNER_FLOW_ID", options.ownerFlowId);
@@ -14217,7 +14531,6 @@ var FerricStoreClient = class _FerricStoreClient extends FerricStoreProducerClie
14217
14531
  append(args, "TRANSITION_TO", options.transitionTo);
14218
14532
  append(args, "RUN_AT", options.runAtMs);
14219
14533
  append(args, "NOW", options.nowMs ?? nowMs());
14220
- append(args, "PRIORITY", options.priority);
14221
14534
  appendNamedValues(args, this.codec, options);
14222
14535
  return await this.commandArgs(args);
14223
14536
  }
@@ -14247,6 +14560,7 @@ var FerricStoreClient = class _FerricStoreClient extends FerricStoreProducerClie
14247
14560
  append(args, "CORRELATION_ID", options.correlationId);
14248
14561
  append(args, "PRIORITY", options.priority);
14249
14562
  append(args, "RETENTION_TTL_MS", options.retentionTtlMs);
14563
+ append(args, "MAX_ACTIVE_MS", options.maxActiveMs);
14250
14564
  appendAttributes(args, options.attributes);
14251
14565
  appendStateMeta(args, options.stateMeta);
14252
14566
  appendNamedValues(args, this.codec, options);
@@ -16352,16 +16666,23 @@ var WorkflowWorker = class {
16352
16666
  );
16353
16667
  }
16354
16668
  };
16669
+
16670
+ // src/version.ts
16671
+ var FERRICSTORE_SDK_VERSION = "0.2.0";
16672
+ var FERRICSTORE_MINIMUM_SERVER_VERSION = "0.8.0";
16673
+ var FERRICSTORE_NATIVE_PROTOCOL_VERSION = 1;
16355
16674
  // Annotate the CommonJS export names for ESM import in node:
16356
16675
  0 && (module.exports = {
16357
16676
  BitmapStore,
16358
16677
  BloomFilterStore,
16359
16678
  COMMAND_OPCODES,
16360
- COMPACT_RESPONSE_OPCODES,
16361
16679
  ClaimHydrationError,
16362
16680
  ConnectionClosedError,
16363
16681
  CountMinSketchStore,
16364
16682
  CuckooFilterStore,
16683
+ FERRICSTORE_MINIMUM_SERVER_VERSION,
16684
+ FERRICSTORE_NATIVE_PROTOCOL_VERSION,
16685
+ FERRICSTORE_SDK_VERSION,
16365
16686
  FerricStoreClient,
16366
16687
  FerricStoreError,
16367
16688
  FlowAlreadyExistsError,