@ferricstore/ferricstore 0.5.2 → 0.11.5

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 (111) hide show
  1. package/README.md +45 -5
  2. package/dist/index.cjs +996 -314
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +90 -26
  5. package/dist/index.d.ts +90 -26
  6. package/dist/index.js +996 -314
  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/ConnectionClosedError.html +1 -1
  12. package/docs/api/classes/FerricStoreClient.html +3 -3
  13. package/docs/api/classes/FerricStoreError.html +1 -1
  14. package/docs/api/classes/FlowAlreadyExistsError.html +1 -1
  15. package/docs/api/classes/FlowBatchError.html +1 -1
  16. package/docs/api/classes/FlowNotFoundError.html +1 -1
  17. package/docs/api/classes/FlowQueryError.html +1 -1
  18. package/docs/api/classes/FlowWrongStateError.html +1 -1
  19. package/docs/api/classes/InvalidCommandError.html +1 -1
  20. package/docs/api/classes/LeaseRenewalError.html +1 -1
  21. package/docs/api/classes/LockHeldError.html +1 -1
  22. package/docs/api/classes/LockNotOwnedError.html +1 -1
  23. package/docs/api/classes/OverloadedError.html +1 -1
  24. package/docs/api/classes/QueueCompletionError.html +1 -1
  25. package/docs/api/classes/RequestTimeoutError.html +1 -1
  26. package/docs/api/classes/RerouteError.html +1 -1
  27. package/docs/api/classes/StaleLeaseError.html +1 -1
  28. package/docs/api/classes/StalePolicyGenerationError.html +1 -1
  29. package/docs/api/hierarchy.html +1 -1
  30. package/docs/api/index.html +35 -5
  31. package/docs/api/interfaces/AdminListOptions.html +2 -2
  32. package/docs/api/interfaces/ApprovalListOptions.html +2 -2
  33. package/docs/api/interfaces/ApprovalRequestOptions.html +2 -2
  34. package/docs/api/interfaces/AttributeQueryOptions.html +2 -2
  35. package/docs/api/interfaces/AutoBatchOptions.html +2 -2
  36. package/docs/api/interfaces/BudgetCommitOptions.html +2 -2
  37. package/docs/api/interfaces/BudgetReserveOptions.html +2 -2
  38. package/docs/api/interfaces/CancelOptions.html +2 -2
  39. package/docs/api/interfaces/CircuitOpenOptions.html +2 -2
  40. package/docs/api/interfaces/ClaimDueOptions.html +3 -3
  41. package/docs/api/interfaces/ClaimHydrationItem.html +2 -2
  42. package/docs/api/interfaces/CompleteJobsAndClaimJobsResult.html +6 -6
  43. package/docs/api/interfaces/CompleteManyOptions.html +2 -2
  44. package/docs/api/interfaces/CompleteOptions.html +2 -2
  45. package/docs/api/interfaces/CompleteOutcome.html +1 -1
  46. package/docs/api/interfaces/CreateManyOptions.html +5 -5
  47. package/docs/api/interfaces/CreateOptions.html +3 -3
  48. package/docs/api/interfaces/EffectCompensateOptions.html +2 -2
  49. package/docs/api/interfaces/EffectConfirmOptions.html +2 -2
  50. package/docs/api/interfaces/EffectFailOptions.html +2 -2
  51. package/docs/api/interfaces/EffectReserveOptions.html +2 -2
  52. package/docs/api/interfaces/EffectStatusOptions.html +2 -2
  53. package/docs/api/interfaces/ExtendLeaseOptions.html +2 -2
  54. package/docs/api/interfaces/FailOptions.html +2 -2
  55. package/docs/api/interfaces/FailOutcome.html +1 -1
  56. package/docs/api/interfaces/FerricStoreClientFromUrlOptions.html +4 -4
  57. package/docs/api/interfaces/FerricStoreClientOptions.html +4 -4
  58. package/docs/api/interfaces/FlowBatchCompletedItem.html +2 -2
  59. package/docs/api/interfaces/FlowPolicyOptions.html +5 -5
  60. package/docs/api/interfaces/FlowQueryCountResult.html +1 -1
  61. package/docs/api/interfaces/FlowQueryIndexBuild.html +1 -1
  62. package/docs/api/interfaces/FlowQueryIndexProgress.html +1 -1
  63. package/docs/api/interfaces/FlowQueryIndexValidation.html +1 -1
  64. package/docs/api/interfaces/FlowQueryRecordsResult.html +1 -1
  65. package/docs/api/interfaces/FlowStatePolicy.html +2 -2
  66. package/docs/api/interfaces/FlowStatsOptions.html +2 -2
  67. package/docs/api/interfaces/GovernanceLedgerOptions.html +2 -2
  68. package/docs/api/interfaces/HistoryOptions.html +2 -2
  69. package/docs/api/interfaces/InvocationCreateOptions.html +2 -2
  70. package/docs/api/interfaces/LeaseMutationOptions.html +2 -2
  71. package/docs/api/interfaces/LimitAmountOptions.html +2 -2
  72. package/docs/api/interfaces/LimitLeaseOptions.html +2 -2
  73. package/docs/api/interfaces/LimitListOptions.html +2 -2
  74. package/docs/api/interfaces/LimitReleaseOptions.html +2 -2
  75. package/docs/api/interfaces/MutateOptions.html +2 -2
  76. package/docs/api/interfaces/NamedValueMutation.html +1 -1
  77. package/docs/api/interfaces/ReadOptions.html +3 -3
  78. package/docs/api/interfaces/ReclaimOptions.html +2 -2
  79. package/docs/api/interfaces/RequestContext.html +2 -2
  80. package/docs/api/interfaces/RequestContextOptions.html +2 -2
  81. package/docs/api/interfaces/RetryOptions.html +2 -2
  82. package/docs/api/interfaces/RetryOutcome.html +1 -1
  83. package/docs/api/interfaces/RunStepsItem.html +2 -2
  84. package/docs/api/interfaces/RunStepsManyOptions.html +2 -2
  85. package/docs/api/interfaces/ScheduleFireDueOptions.html +3 -2
  86. package/docs/api/interfaces/ScheduleFireOptions.html +3 -0
  87. package/docs/api/interfaces/ScheduleListOptions.html +2 -2
  88. package/docs/api/interfaces/ScheduleOptions.html +4 -2
  89. package/docs/api/interfaces/SearchOptions.html +3 -3
  90. package/docs/api/interfaces/StartAndClaimOptions.html +3 -3
  91. package/docs/api/interfaces/StepContinueOptions.html +3 -3
  92. package/docs/api/interfaces/TDigestCreateOptions.html +1 -1
  93. package/docs/api/interfaces/TDigestMergeOptions.html +1 -1
  94. package/docs/api/interfaces/TransitionOptions.html +2 -2
  95. package/docs/api/interfaces/TransitionOutcome.html +1 -1
  96. package/docs/api/modules.html +1 -1
  97. package/docs/api/types/ConnectionRequestDisposition.html +1 -1
  98. package/docs/api/types/FlowStateMode.html +1 -1
  99. package/docs/api/types/FlowStatePolicyLike.html +1 -1
  100. package/docs/api/types/ManagementPairs.html +1 -1
  101. package/docs/api/types/ScheduleCatchupPolicy.html +2 -0
  102. package/docs/api/types/ScheduleFireDueResult.html +3 -0
  103. package/docs/api/types/ScheduleFireResult.html +2 -0
  104. package/docs/api/types/ScheduleKind.html +1 -0
  105. package/docs/api/types/ScheduleOverlapPolicy.html +1 -0
  106. package/docs/api/types/ScheduleRecord.html +12 -0
  107. package/docs/api/types/ScheduleState.html +1 -0
  108. package/docs/api/types/SearchStateMeta.html +1 -1
  109. package/docs/api/variables/FERRICSTORE_MINIMUM_SERVER_VERSION.html +1 -1
  110. package/docs/api/variables/FERRICSTORE_SDK_VERSION.html +1 -1
  111. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -3090,6 +3090,7 @@ var FLOW_ADMIN_FIELDS = {
3090
3090
  AT_MS: "at_ms",
3091
3091
  BLOCK: "block_ms",
3092
3092
  BLOCK_MS: "block_ms",
3093
+ CATCHUP_POLICY: "catchup_policy",
3093
3094
  CONSISTENT_PROJECTION: "consistent_projection",
3094
3095
  CORRELATION_ID: "correlation_id",
3095
3096
  COUNT: "count",
@@ -4534,7 +4535,7 @@ function compactKeyPipelinePayload(opcode, args, mode, maxBodyBytes) {
4534
4535
  }
4535
4536
  return { flags: FLAG_CUSTOM_PAYLOAD, opcode, payload: out };
4536
4537
  }
4537
- function compactPipelinePayload(commands, maxBodyBytes) {
4538
+ function compactPipelinePayload(commands, maxBodyBytes, allowStreamXAdd = true, allowPubSubPublish = true) {
4538
4539
  if (commands.length === 0) {
4539
4540
  assertCompactPayloadFits(6, maxBodyBytes);
4540
4541
  const out = Buffer15.allocUnsafe(6);
@@ -4546,8 +4547,115 @@ function compactPipelinePayload(commands, maxBodyBytes) {
4546
4547
  }
4547
4548
  if (commandNameIs(commands[0]?.[0], "SET")) return compactSetPipelinePayload(commands, maxBodyBytes);
4548
4549
  if (commandNameIs(commands[0]?.[0], "GET")) return compactGetPipelinePayload(commands, maxBodyBytes);
4550
+ if (commandNameIs(commands[0]?.[0], "XADD")) {
4551
+ return allowStreamXAdd ? compactStreamXAddPipelinePayload(commands, maxBodyBytes) : void 0;
4552
+ }
4553
+ if (commandNameIs(commands[0]?.[0], "PUBLISH")) {
4554
+ return allowPubSubPublish ? compactPubSubPublishPipelinePayload(commands, maxBodyBytes) : void 0;
4555
+ }
4549
4556
  return void 0;
4550
4557
  }
4558
+ function compactPubSubPublishPipelinePayload(commands, maxBodyBytes) {
4559
+ const minimum = 6 + commands.length * 8;
4560
+ if (!compactPayloadFits(minimum, maxBodyBytes)) {
4561
+ if (!compactPipelineEligible(commands, "PUBLISH", 3)) return void 0;
4562
+ assertCompactPayloadFits(minimum, maxBodyBytes);
4563
+ }
4564
+ const argumentByteLengths = new Uint32Array(commands.length * 2);
4565
+ const argumentValues = new Array(commands.length * 2);
4566
+ let total = 6;
4567
+ for (let index = 0; index < commands.length; index += 1) {
4568
+ const command = commands[index];
4569
+ if (!Object.hasOwn(commands, index) || !Array.isArray(command)) {
4570
+ throw new TypeError("pipeline commands must be a dense array of command arrays");
4571
+ }
4572
+ if (command.length !== 3 || !Object.hasOwn(command, 0) || !Object.hasOwn(command, 1) || !Object.hasOwn(command, 2)) {
4573
+ if (command.length === 3) throw new TypeError("pipeline command arguments must be dense");
4574
+ return void 0;
4575
+ }
4576
+ if (!commandNameIs(command[0], "PUBLISH")) return void 0;
4577
+ const channel = command[1];
4578
+ const message = command[2];
4579
+ if (!isCompactBinaryScalar(channel) || !isCompactBinaryScalar(message)) return void 0;
4580
+ const channelByteLength = compactBinaryByteLength(channel);
4581
+ const messageByteLength = compactBinaryByteLength(message);
4582
+ argumentValues[index * 2] = channel;
4583
+ argumentValues[index * 2 + 1] = message;
4584
+ argumentByteLengths[index * 2] = channelByteLength;
4585
+ argumentByteLengths[index * 2 + 1] = messageByteLength;
4586
+ total += 8 + channelByteLength + messageByteLength;
4587
+ }
4588
+ assertCompactPayloadFits(total, maxBodyBytes);
4589
+ const out = Buffer15.allocUnsafe(total);
4590
+ let offset = writeCompactPipelineHeader(out, 128 | 35, commands.length);
4591
+ for (let index = 0; index < commands.length; index += 1) {
4592
+ offset = writeBinaryValue(
4593
+ out,
4594
+ offset,
4595
+ argumentValues[index * 2],
4596
+ argumentByteLengths[index * 2] ?? 0
4597
+ );
4598
+ offset = writeBinaryValue(
4599
+ out,
4600
+ offset,
4601
+ argumentValues[index * 2 + 1],
4602
+ argumentByteLengths[index * 2 + 1] ?? 0
4603
+ );
4604
+ }
4605
+ return out;
4606
+ }
4607
+ function compactStreamXAddPipelinePayload(commands, maxBodyBytes) {
4608
+ let argumentCount = 0;
4609
+ let minimum = 6;
4610
+ for (const command of commands) {
4611
+ if (!Array.isArray(command)) {
4612
+ throw new TypeError("pipeline commands must be a dense array of command arrays");
4613
+ }
4614
+ if (command.length < 5 || (command.length - 3) % 2 !== 0) return void 0;
4615
+ for (let argumentIndex = 0; argumentIndex < command.length; argumentIndex += 1) {
4616
+ if (!Object.hasOwn(command, argumentIndex)) {
4617
+ throw new TypeError("pipeline command arguments must be dense");
4618
+ }
4619
+ }
4620
+ if (!commandTokenIs(command[0], "XADD") || !commandTokenIs(command[2], "*")) return void 0;
4621
+ if ((command.length - 3) / 2 > 65535) return void 0;
4622
+ for (let argumentIndex = 1; argumentIndex < command.length; argumentIndex += 1) {
4623
+ if (argumentIndex !== 2 && !isCompactBinaryScalar(command[argumentIndex])) return void 0;
4624
+ }
4625
+ argumentCount += command.length - 2;
4626
+ minimum += 2 + (command.length - 2) * 4;
4627
+ }
4628
+ assertCompactPayloadFits(minimum, maxBodyBytes);
4629
+ const byteLengths = new Uint32Array(argumentCount);
4630
+ let lengthIndex = 0;
4631
+ let total = 6;
4632
+ for (const command of commands) {
4633
+ total += 2;
4634
+ for (let argumentIndex = 1; argumentIndex < command.length; argumentIndex += 1) {
4635
+ if (argumentIndex === 2) continue;
4636
+ const value = command[argumentIndex];
4637
+ const byteLength = compactBinaryByteLength(value);
4638
+ byteLengths[lengthIndex] = byteLength;
4639
+ lengthIndex += 1;
4640
+ total += 4 + byteLength;
4641
+ }
4642
+ }
4643
+ assertCompactPayloadFits(total, maxBodyBytes);
4644
+ const out = Buffer15.allocUnsafe(total);
4645
+ let offset = writeCompactPipelineHeader(out, 128 | 34, commands.length);
4646
+ lengthIndex = 0;
4647
+ for (const command of commands) {
4648
+ offset = writeBinaryValue(out, offset, command[1], byteLengths[lengthIndex] ?? 0);
4649
+ lengthIndex += 1;
4650
+ out.writeUInt16BE((command.length - 3) / 2, offset);
4651
+ offset += 2;
4652
+ for (let argumentIndex = 3; argumentIndex < command.length; argumentIndex += 1) {
4653
+ offset = writeBinaryValue(out, offset, command[argumentIndex], byteLengths[lengthIndex] ?? 0);
4654
+ lengthIndex += 1;
4655
+ }
4656
+ }
4657
+ return out;
4658
+ }
4551
4659
  function compactSetPipelinePayload(commands, maxBodyBytes) {
4552
4660
  let total = 6;
4553
4661
  const minimum = total + commands.length * 8;
@@ -5129,10 +5237,19 @@ function decodeValueAt(data, offset, limits, budget, depth) {
5129
5237
  const count = data.readUInt32BE(offset);
5130
5238
  requireValueContainer(count, depth, limits, budget);
5131
5239
  offset += 4;
5132
- const values = [];
5240
+ const values = new Array(count);
5241
+ if (count === 3) {
5242
+ const first = decodeValueAt(data, offset, limits, budget, depth + 1);
5243
+ const second = decodeValueAt(data, first.offset, limits, budget, depth + 1);
5244
+ const third = decodeValueAt(data, second.offset, limits, budget, depth + 1);
5245
+ values[0] = first.value;
5246
+ values[1] = second.value;
5247
+ values[2] = third.value;
5248
+ return { value: values, offset: third.offset };
5249
+ }
5133
5250
  for (let index = 0; index < count; index += 1) {
5134
5251
  const read = decodeValueAt(data, offset, limits, budget, depth + 1);
5135
- values.push(read.value);
5252
+ values[index] = read.value;
5136
5253
  offset = read.offset;
5137
5254
  }
5138
5255
  return { value: values, offset };
@@ -5449,6 +5566,8 @@ function nativeNegotiation(value) {
5449
5566
  compactResponseOpcodes: parseCompactResponseOpcodes(
5450
5567
  field(responseCodecs, "compact_response_opcodes")
5451
5568
  ),
5569
+ compactPubSubPublish: strictUnsigned16(field(field(field(capabilities, "pipeline"), "modes"), "pubsub_publish")) === 35,
5570
+ compactStreamXAdd: strictUnsigned16(field(field(field(capabilities, "pipeline"), "modes"), "stream_xadd_auto")) === 34,
5452
5571
  flowQuery: parseFlowQueryNegotiation(capabilities, schemas),
5453
5572
  ...maxResponseBytes == null ? {} : { maxResponseBytes }
5454
5573
  };
@@ -5523,15 +5642,15 @@ function requiredMap(value, context) {
5523
5642
  }
5524
5643
  throw incompatibleServer(`${context} is missing or invalid`);
5525
5644
  }
5526
- function requiredBoundedText(mapping, name) {
5527
- const value = strictText(field(mapping, name));
5645
+ function requiredBoundedText(mapping2, name) {
5646
+ const value = strictText(field(mapping2, name));
5528
5647
  if (value == null || value.length === 0 || Buffer20.byteLength(value) > 256) {
5529
5648
  throw incompatibleServer(`HELLO flow_query ${name} must be bounded non-empty text`);
5530
5649
  }
5531
5650
  return value;
5532
5651
  }
5533
- function boundedTextSet(mapping, name, maximum) {
5534
- const raw = field(mapping, name);
5652
+ function boundedTextSet(mapping2, name, maximum) {
5653
+ const raw = field(mapping2, name);
5535
5654
  if (!Array.isArray(raw) || raw.length < 1 || raw.length > maximum) {
5536
5655
  throw incompatibleServer(`HELLO ${name} must contain 1..${maximum} entries`);
5537
5656
  }
@@ -6741,8 +6860,13 @@ function buildProtocolCommand(args, maxBodyBytes = Number.MAX_SAFE_INTEGER, allo
6741
6860
  }
6742
6861
  return commandExec(args);
6743
6862
  }
6744
- function tryPipelineCommand(commands, maxBodyBytes = Number.MAX_SAFE_INTEGER) {
6745
- const compact = compactPipelinePayload(commands, maxBodyBytes);
6863
+ function tryPipelineCommand(commands, maxBodyBytes = Number.MAX_SAFE_INTEGER, allowStreamXAdd = true, allowPubSubPublish = true) {
6864
+ const compact = compactPipelinePayload(
6865
+ commands,
6866
+ maxBodyBytes,
6867
+ allowStreamXAdd,
6868
+ allowPubSubPublish
6869
+ );
6746
6870
  if (compact != null) {
6747
6871
  return {
6748
6872
  compactResponseItems: commands.length,
@@ -6854,15 +6978,15 @@ function snapshotOwnStringArray(values, name) {
6854
6978
 
6855
6979
  // src/client-native-options.ts
6856
6980
  function snapshotNativeClientOptions(options) {
6857
- const own = { ...options };
6981
+ const own2 = { ...options };
6858
6982
  const snapshot = {
6859
- ...own,
6860
- ...typeof own.autoReconnect === "object" && own.autoReconnect != null ? { autoReconnect: Object.freeze({ ...own.autoReconnect }) } : {},
6861
- ...own.endpointPolicy == null ? {} : { endpointPolicy: snapshotEndpointPolicy(own.endpointPolicy) },
6862
- ...own.events == null ? {} : { events: snapshotOwnStringArray(own.events, "events") },
6863
- ...own.seeds == null ? {} : { seeds: snapshotOwnStringArray(own.seeds, "seeds") },
6864
- ...own.tlsOptions == null ? {} : { tlsOptions: snapshotTlsOptions(own.tlsOptions) },
6865
- ...own.trustedHosts == null ? {} : { trustedHosts: snapshotOwnStringArray(own.trustedHosts, "trustedHosts") }
6983
+ ...own2,
6984
+ ...typeof own2.autoReconnect === "object" && own2.autoReconnect != null ? { autoReconnect: Object.freeze({ ...own2.autoReconnect }) } : {},
6985
+ ...own2.endpointPolicy == null ? {} : { endpointPolicy: snapshotEndpointPolicy(own2.endpointPolicy) },
6986
+ ...own2.events == null ? {} : { events: snapshotOwnStringArray(own2.events, "events") },
6987
+ ...own2.seeds == null ? {} : { seeds: snapshotOwnStringArray(own2.seeds, "seeds") },
6988
+ ...own2.tlsOptions == null ? {} : { tlsOptions: snapshotTlsOptions(own2.tlsOptions) },
6989
+ ...own2.trustedHosts == null ? {} : { trustedHosts: snapshotOwnStringArray(own2.trustedHosts, "trustedHosts") }
6866
6990
  };
6867
6991
  return Object.freeze(snapshot);
6868
6992
  }
@@ -6903,12 +7027,12 @@ function topologyNativeOptions(options) {
6903
7027
  }
6904
7028
  function snapshotEndpointPolicy(policy) {
6905
7029
  if (typeof policy !== "object") return policy;
6906
- const own = { ...policy };
6907
- if (!Object.hasOwn(own, "allowHosts") || !Array.isArray(own.allowHosts)) {
7030
+ const own2 = { ...policy };
7031
+ if (!Object.hasOwn(own2, "allowHosts") || !Array.isArray(own2.allowHosts)) {
6908
7032
  throw new TypeError("endpointPolicy.allowHosts must be an own array of strings");
6909
7033
  }
6910
7034
  return Object.freeze({
6911
- allowHosts: snapshotOwnStringArray(own.allowHosts, "endpointPolicy.allowHosts")
7035
+ allowHosts: snapshotOwnStringArray(own2.allowHosts, "endpointPolicy.allowHosts")
6912
7036
  });
6913
7037
  }
6914
7038
  function snapshotTlsOptions(options) {
@@ -7243,13 +7367,18 @@ function surfaceIndividualCommandErrors(results, rejected, hasRejected, options)
7243
7367
  }
7244
7368
 
7245
7369
  // src/native-pipeline-execution.ts
7246
- async function executeNativeFusedPipeline(host, commands, laneId, options, maxPipelineCommands, maxRequestFrameBytes) {
7370
+ async function executeNativeFusedPipeline(host, commands, laneId, options, maxPipelineCommands, maxRequestFrameBytes, compactStreamXAdd = true, compactPubSubPublish = true) {
7247
7371
  commands = snapshotPipelineCommands(commands);
7248
7372
  options = snapshotPipelineOptions(options) ?? options;
7249
7373
  if (commands.length === 0) return [];
7250
7374
  if (maxPipelineCommands === 0 || commands.length > maxPipelineCommands) return void 0;
7251
7375
  try {
7252
- const pipeline = tryPipelineCommand(commands, maxRequestFrameBytes);
7376
+ const pipeline = tryPipelineCommand(
7377
+ commands,
7378
+ maxRequestFrameBytes,
7379
+ compactStreamXAdd,
7380
+ compactPubSubPublish
7381
+ );
7253
7382
  if (pipeline == null) return void 0;
7254
7383
  const response = await host.executeProtocolCommand(pipeline, laneId);
7255
7384
  return unwrapPipelineResponse(response, options, commands.length);
@@ -7258,7 +7387,7 @@ async function executeNativeFusedPipeline(host, commands, laneId, options, maxPi
7258
7387
  throw error;
7259
7388
  }
7260
7389
  }
7261
- async function executeNativePipeline(host, commands, laneId, options, maxPipelineCommands, maxRequestFrameBytes) {
7390
+ async function executeNativePipeline(host, commands, laneId, options, maxPipelineCommands, maxRequestFrameBytes, compactStreamXAdd = true, compactPubSubPublish = true) {
7262
7391
  commands = snapshotPipelineCommands(commands);
7263
7392
  options = snapshotPipelineOptions(options) ?? options;
7264
7393
  if (commands.length === 0) return [];
@@ -7266,7 +7395,15 @@ async function executeNativePipeline(host, commands, laneId, options, maxPipelin
7266
7395
  return await executeIndividually(host, commands, laneId, pipelineFallbackOptions(commands, options));
7267
7396
  }
7268
7397
  if (commands.length <= maxPipelineCommands) {
7269
- return await executeChunk(host, commands, laneId, options, maxRequestFrameBytes);
7398
+ return await executeChunk(
7399
+ host,
7400
+ commands,
7401
+ laneId,
7402
+ options,
7403
+ maxRequestFrameBytes,
7404
+ compactStreamXAdd,
7405
+ compactPubSubPublish
7406
+ );
7270
7407
  }
7271
7408
  const collectingOptions = pipelineErrorCollectingOptions(options);
7272
7409
  const results = new Array(commands.length);
@@ -7278,7 +7415,9 @@ async function executeNativePipeline(host, commands, laneId, options, maxPipelin
7278
7415
  chunk,
7279
7416
  laneId,
7280
7417
  pipelineSliceOptions(collectingOptions, start, start + chunk.length),
7281
- maxRequestFrameBytes
7418
+ maxRequestFrameBytes,
7419
+ compactStreamXAdd,
7420
+ compactPubSubPublish
7282
7421
  );
7283
7422
  for (let index = 0; index < chunkResults.length; index += 1) results[start + index] = chunkResults[index];
7284
7423
  rejected = collectPipelineRejections(chunkResults, start, rejected);
@@ -7286,9 +7425,14 @@ async function executeNativePipeline(host, commands, laneId, options, maxPipelin
7286
7425
  if (rejected != null) attachPipelineItemRejectionFlags(results, rejected);
7287
7426
  return surfaceFirstPipelineItemError(results, options);
7288
7427
  }
7289
- async function executeChunk(host, commands, laneId, options, maxRequestFrameBytes) {
7428
+ async function executeChunk(host, commands, laneId, options, maxRequestFrameBytes, compactStreamXAdd, compactPubSubPublish) {
7290
7429
  try {
7291
- const pipeline = tryPipelineCommand(commands, maxRequestFrameBytes);
7430
+ const pipeline = tryPipelineCommand(
7431
+ commands,
7432
+ maxRequestFrameBytes,
7433
+ compactStreamXAdd,
7434
+ compactPubSubPublish
7435
+ );
7292
7436
  if (pipeline != null) {
7293
7437
  const response = await host.executeProtocolCommand(pipeline, laneId);
7294
7438
  return unwrapPipelineResponse(response, options, commands.length);
@@ -7306,14 +7450,18 @@ async function executeChunk(host, commands, laneId, options, maxRequestFrameByte
7306
7450
  commands.slice(0, middle),
7307
7451
  laneId,
7308
7452
  pipelineSliceOptions(collectingOptions, 0, middle),
7309
- maxRequestFrameBytes
7453
+ maxRequestFrameBytes,
7454
+ compactStreamXAdd,
7455
+ compactPubSubPublish
7310
7456
  );
7311
7457
  const second = await executeChunk(
7312
7458
  host,
7313
7459
  commands.slice(middle),
7314
7460
  laneId,
7315
7461
  pipelineSliceOptions(collectingOptions, middle, commands.length),
7316
- maxRequestFrameBytes
7462
+ maxRequestFrameBytes,
7463
+ compactStreamXAdd,
7464
+ compactPubSubPublish
7317
7465
  );
7318
7466
  return surfaceFirstPipelineItemError(mergePipelineResults(first, second), options);
7319
7467
  }
@@ -7947,6 +8095,8 @@ var NativeConnectionCapabilities = class {
7947
8095
  }
7948
8096
  configuredRequestFrameBytes;
7949
8097
  compactResponseOpcodes = EMPTY_COMPACT_RESPONSE_OPCODES;
8098
+ compactPubSubPublish = false;
8099
+ compactStreamXAdd = false;
7950
8100
  flowQuery;
7951
8101
  requestFrameBytes;
7952
8102
  negotiatedRequestFrameBytes;
@@ -7954,6 +8104,8 @@ var NativeConnectionCapabilities = class {
7954
8104
  const limits = startupLimits(value);
7955
8105
  const negotiation = nativeNegotiation(value);
7956
8106
  this.compactResponseOpcodes = negotiation.compactResponseOpcodes;
8107
+ this.compactPubSubPublish = negotiation.compactPubSubPublish;
8108
+ this.compactStreamXAdd = negotiation.compactStreamXAdd;
7957
8109
  this.flowQuery = negotiation.flowQuery;
7958
8110
  if (limits.frameBytes != null) {
7959
8111
  this.negotiatedRequestFrameBytes = Math.min(
@@ -8179,7 +8331,9 @@ var NativeAdapter = class _NativeAdapter {
8179
8331
  laneId,
8180
8332
  options,
8181
8333
  this.maxPipelineCommands,
8182
- this.capabilities.requestFrameBytes
8334
+ this.capabilities.requestFrameBytes,
8335
+ this.capabilities.compactStreamXAdd,
8336
+ this.capabilities.compactPubSubPublish
8183
8337
  );
8184
8338
  }
8185
8339
  /** @internal Execute an ordered pipeline on a topology-selected lane. */
@@ -8190,7 +8344,9 @@ var NativeAdapter = class _NativeAdapter {
8190
8344
  laneId,
8191
8345
  options,
8192
8346
  this.maxPipelineCommands,
8193
- this.capabilities.requestFrameBytes
8347
+ this.capabilities.requestFrameBytes,
8348
+ this.capabilities.compactStreamXAdd,
8349
+ this.capabilities.compactPubSubPublish
8194
8350
  );
8195
8351
  }
8196
8352
  async close() {
@@ -11988,36 +12144,36 @@ function isPlainObject6(value) {
11988
12144
  const prototype = Object.getPrototypeOf(value);
11989
12145
  return prototype === Object.prototype || prototype === null;
11990
12146
  }
11991
- function requireContract(mapping, name, expected, context) {
11992
- const actual = requiredText2(mapping, name, context);
12147
+ function requireContract(mapping2, name, expected, context) {
12148
+ const actual = requiredText2(mapping2, name, context);
11993
12149
  if (actual !== expected) {
11994
12150
  throw decodeError(
11995
12151
  `${context} has unsupported contract ${JSON.stringify(actual)}`,
11996
- mapping
12152
+ mapping2
11997
12153
  );
11998
12154
  }
11999
12155
  }
12000
- function requiredText2(mapping, name, context) {
12001
- const value = strictText2(field(mapping, name));
12156
+ function requiredText2(mapping2, name, context) {
12157
+ const value = strictText2(field(mapping2, name));
12002
12158
  if (value == null || value.length === 0) {
12003
- throw decodeError(`${context} ${name} must be non-empty text`, mapping);
12159
+ throw decodeError(`${context} ${name} must be non-empty text`, mapping2);
12004
12160
  }
12005
12161
  return value;
12006
12162
  }
12007
- function optionalText2(mapping, name, context) {
12008
- const raw = field(mapping, name);
12163
+ function optionalText2(mapping2, name, context) {
12164
+ const raw = field(mapping2, name);
12009
12165
  if (raw == null) return void 0;
12010
12166
  const value = strictText2(raw);
12011
12167
  if (value == null)
12012
- throw decodeError(`${context} ${name} must be text`, mapping);
12168
+ throw decodeError(`${context} ${name} must be text`, mapping2);
12013
12169
  return value;
12014
12170
  }
12015
- function requiredBoundedText2(mapping, name, context, maximumBytes) {
12016
- const value = requiredText2(mapping, name, context);
12171
+ function requiredBoundedText2(mapping2, name, context, maximumBytes) {
12172
+ const value = requiredText2(mapping2, name, context);
12017
12173
  if (Buffer45.byteLength(value, "utf8") > maximumBytes) {
12018
12174
  throw decodeError(
12019
12175
  `${context} ${name} exceeds ${maximumBytes} bytes`,
12020
- mapping
12176
+ mapping2
12021
12177
  );
12022
12178
  }
12023
12179
  return value;
@@ -12032,10 +12188,10 @@ function boundedText(value, context, maximumBytes) {
12032
12188
  }
12033
12189
  return decoded;
12034
12190
  }
12035
- function requiredBoolean(mapping, name, context) {
12036
- const value = field(mapping, name);
12191
+ function requiredBoolean(mapping2, name, context) {
12192
+ const value = field(mapping2, name);
12037
12193
  if (typeof value !== "boolean") {
12038
- throw decodeError(`${context} ${name} must be boolean`, mapping);
12194
+ throw decodeError(`${context} ${name} must be boolean`, mapping2);
12039
12195
  }
12040
12196
  return value;
12041
12197
  }
@@ -12078,11 +12234,11 @@ function positiveBoundedInteger(value, maximum, context) {
12078
12234
  if (parsed === 0) throw decodeError(`${context} must be positive`, value);
12079
12235
  return parsed;
12080
12236
  }
12081
- function hasKey(mapping, name) {
12082
- if (!(mapping instanceof Map)) return Object.hasOwn(mapping, name);
12083
- if (mapping.has(name)) return true;
12237
+ function hasKey(mapping2, name) {
12238
+ if (!(mapping2 instanceof Map)) return Object.hasOwn(mapping2, name);
12239
+ if (mapping2.has(name)) return true;
12084
12240
  const binaryName = Buffer45.from(name);
12085
- for (const key of mapping.keys()) {
12241
+ for (const key of mapping2.keys()) {
12086
12242
  if (Buffer45.isBuffer(key) && key.equals(binaryName)) return true;
12087
12243
  if (key instanceof Uint8Array && Buffer45.from(key).equals(binaryName))
12088
12244
  return true;
@@ -12139,28 +12295,28 @@ var DIAGNOSTIC_CONTEXT_DEPTH = 6;
12139
12295
  var DIAGNOSTIC_CONTEXT_NODES = 512;
12140
12296
  function tryDecodeFlowQueryError(value, cause) {
12141
12297
  try {
12142
- const mapping = requiredMap2(value, "FLOW.QUERY diagnostic");
12143
- const context = decodeDiagnosticContext(field(mapping, "context"));
12144
- const position = decodePosition(field(mapping, "position"));
12298
+ const mapping2 = requiredMap2(value, "FLOW.QUERY diagnostic");
12299
+ const context = decodeDiagnosticContext(field(mapping2, "context"));
12300
+ const position = decodePosition(field(mapping2, "position"));
12145
12301
  return new FlowQueryError({
12146
12302
  code: requiredBoundedText2(
12147
- mapping,
12303
+ mapping2,
12148
12304
  "code",
12149
12305
  "FLOW.QUERY diagnostic",
12150
12306
  DIAGNOSTIC_TEXT_BYTES
12151
12307
  ),
12152
12308
  message: requiredBoundedText2(
12153
- mapping,
12309
+ mapping2,
12154
12310
  "message",
12155
12311
  "FLOW.QUERY diagnostic",
12156
12312
  DIAGNOSTIC_TEXT_BYTES
12157
12313
  ),
12158
- detail: optionalDiagnosticText(mapping, "detail"),
12159
- hint: optionalDiagnosticText(mapping, "hint"),
12160
- retryable: requiredBoolean(mapping, "retryable", "FLOW.QUERY diagnostic"),
12161
- safeToRetry: requiredBoolean(mapping, "safe_to_retry", "FLOW.QUERY diagnostic"),
12314
+ detail: optionalDiagnosticText(mapping2, "detail"),
12315
+ hint: optionalDiagnosticText(mapping2, "hint"),
12316
+ retryable: requiredBoolean(mapping2, "retryable", "FLOW.QUERY diagnostic"),
12317
+ safeToRetry: requiredBoolean(mapping2, "safe_to_retry", "FLOW.QUERY diagnostic"),
12162
12318
  retryAfterMs: nonNegativeInteger(
12163
- field(mapping, "retry_after_ms"),
12319
+ field(mapping2, "retry_after_ms"),
12164
12320
  "FLOW.QUERY diagnostic retry_after_ms"
12165
12321
  ),
12166
12322
  position,
@@ -12173,29 +12329,29 @@ function tryDecodeFlowQueryError(value, cause) {
12173
12329
  throw error;
12174
12330
  }
12175
12331
  }
12176
- function optionalDiagnosticText(mapping, name) {
12177
- const value = optionalText2(mapping, name, "FLOW.QUERY diagnostic");
12332
+ function optionalDiagnosticText(mapping2, name) {
12333
+ const value = optionalText2(mapping2, name, "FLOW.QUERY diagnostic");
12178
12334
  if (value != null && Buffer46.byteLength(value, "utf8") > DIAGNOSTIC_TEXT_BYTES) {
12179
12335
  throw decodeError(
12180
12336
  `FLOW.QUERY diagnostic ${name} exceeds ${DIAGNOSTIC_TEXT_BYTES} bytes`,
12181
- mapping
12337
+ mapping2
12182
12338
  );
12183
12339
  }
12184
12340
  return value;
12185
12341
  }
12186
12342
  function decodeDiagnosticContext(value) {
12187
12343
  if (value == null) return void 0;
12188
- const mapping = requiredMap2(value, "FLOW.QUERY diagnostic context");
12189
- const size = mapping instanceof Map ? mapping.size : Object.keys(mapping).length;
12344
+ const mapping2 = requiredMap2(value, "FLOW.QUERY diagnostic context");
12345
+ const size = mapping2 instanceof Map ? mapping2.size : Object.keys(mapping2).length;
12190
12346
  if (size > DIAGNOSTIC_CONTEXT_ENTRIES) {
12191
12347
  throw decodeError("FLOW.QUERY diagnostic context contains too many entries", value);
12192
12348
  }
12193
12349
  validateDiagnosticContextValue(
12194
- mapping,
12350
+ mapping2,
12195
12351
  DIAGNOSTIC_CONTEXT_DEPTH,
12196
12352
  { remaining: DIAGNOSTIC_CONTEXT_NODES }
12197
12353
  );
12198
- return freezeMetadataMap(mapping, "FLOW.QUERY diagnostic context");
12354
+ return freezeMetadataMap(mapping2, "FLOW.QUERY diagnostic context");
12199
12355
  }
12200
12356
  function validateDiagnosticContextValue(value, depth, budget) {
12201
12357
  consumeDiagnosticContextNode(value, budget);
@@ -12267,12 +12423,12 @@ function isDiagnosticContextRecord(value) {
12267
12423
  }
12268
12424
  function decodePosition(value) {
12269
12425
  if (value == null) return void 0;
12270
- const mapping = requiredMap2(value, "FLOW.QUERY diagnostic position");
12426
+ const mapping2 = requiredMap2(value, "FLOW.QUERY diagnostic position");
12271
12427
  return Object.freeze({
12272
- byte: positiveInteger(field(mapping, "byte"), "FLOW.QUERY diagnostic position byte"),
12273
- line: positiveInteger(field(mapping, "line"), "FLOW.QUERY diagnostic position line"),
12428
+ byte: positiveInteger(field(mapping2, "byte"), "FLOW.QUERY diagnostic position byte"),
12429
+ line: positiveInteger(field(mapping2, "line"), "FLOW.QUERY diagnostic position line"),
12274
12430
  column: positiveInteger(
12275
- field(mapping, "column"),
12431
+ field(mapping2, "column"),
12276
12432
  "FLOW.QUERY diagnostic position column"
12277
12433
  )
12278
12434
  });
@@ -12572,25 +12728,25 @@ function decodeUniqueTextArray(value, context, maximum, maximumBytes) {
12572
12728
  }
12573
12729
  return Object.freeze(result);
12574
12730
  }
12575
- function requiredChoice(mapping, name, context, choices) {
12576
- const value = requiredBoundedText2(mapping, name, context, 64);
12731
+ function requiredChoice(mapping2, name, context, choices) {
12732
+ const value = requiredBoundedText2(mapping2, name, context, 64);
12577
12733
  if (!choices.includes(value)) {
12578
- throw decodeError(`${context} ${name} is unsupported`, mapping);
12734
+ throw decodeError(`${context} ${name} is unsupported`, mapping2);
12579
12735
  }
12580
12736
  return value;
12581
12737
  }
12582
- function optionalBoundedText(mapping, name, context, maximumBytes) {
12583
- const value = field(mapping, name);
12738
+ function optionalBoundedText(mapping2, name, context, maximumBytes) {
12739
+ const value = field(mapping2, name);
12584
12740
  if (value == null) return void 0;
12585
12741
  return boundedText(value, `${context} ${name}`, maximumBytes);
12586
12742
  }
12587
- function optionalIndexInteger(mapping, name, context) {
12588
- const value = field(mapping, name);
12743
+ function optionalIndexInteger(mapping2, name, context) {
12744
+ const value = field(mapping2, name);
12589
12745
  return value == null ? void 0 : unsignedIndexInteger(value, `${context} ${name}`);
12590
12746
  }
12591
- function indexCounter(mapping, name, section) {
12747
+ function indexCounter(mapping2, name, section) {
12592
12748
  return unsignedIndexInteger(
12593
- field(mapping, name),
12749
+ field(mapping2, name),
12594
12750
  `FLOW.QUERY.INDEXES index ${section} ${name}`
12595
12751
  );
12596
12752
  }
@@ -12607,13 +12763,13 @@ function indexInteger2(value) {
12607
12763
  // src/flow-query-index-lifecycle-response.ts
12608
12764
  function decodeIndexCoverage(value) {
12609
12765
  const context = "FLOW.QUERY.INDEXES index coverage";
12610
- const mapping = requiredMap2(value, context);
12766
+ const mapping2 = requiredMap2(value, context);
12611
12767
  const completeShards = unsignedIndexInteger(
12612
- field(mapping, "complete_shards"),
12768
+ field(mapping2, "complete_shards"),
12613
12769
  `${context} complete_shards`
12614
12770
  );
12615
12771
  const totalShards = positiveIndexInteger(
12616
- field(mapping, "total_shards"),
12772
+ field(mapping2, "total_shards"),
12617
12773
  `${context} total_shards`
12618
12774
  );
12619
12775
  if (indexInteger2(completeShards) > indexInteger2(totalShards)) {
@@ -12622,60 +12778,60 @@ function decodeIndexCoverage(value) {
12622
12778
  return Object.freeze({
12623
12779
  completeShards,
12624
12780
  totalShards,
12625
- validation: requiredChoice(mapping, "validation", context, [
12781
+ validation: requiredChoice(mapping2, "validation", context, [
12626
12782
  "pending",
12627
12783
  "passed",
12628
12784
  "failed"
12629
12785
  ]),
12630
- raw: freezeMap(mapping)
12786
+ raw: freezeMap(mapping2)
12631
12787
  });
12632
12788
  }
12633
12789
  function decodeIndexBuild(value) {
12634
- const mapping = requiredMap2(value, "FLOW.QUERY.INDEXES index build");
12790
+ const mapping2 = requiredMap2(value, "FLOW.QUERY.INDEXES index build");
12635
12791
  const progress = decodeIndexProgress(
12636
- mapping,
12792
+ mapping2,
12637
12793
  "build",
12638
12794
  FLOW_QUERY_BUILD_PHASES
12639
12795
  );
12640
12796
  return Object.freeze({
12641
12797
  ...progress,
12642
- scannedRecords: indexCounter(mapping, "scanned_records", "build"),
12643
- writtenEntries: indexCounter(mapping, "written_entries", "build"),
12644
- writtenBytes: indexCounter(mapping, "written_bytes", "build")
12798
+ scannedRecords: indexCounter(mapping2, "scanned_records", "build"),
12799
+ writtenEntries: indexCounter(mapping2, "written_entries", "build"),
12800
+ writtenBytes: indexCounter(mapping2, "written_bytes", "build")
12645
12801
  });
12646
12802
  }
12647
12803
  function decodeIndexValidation(value) {
12648
- const mapping = requiredMap2(value, "FLOW.QUERY.INDEXES index validation");
12649
- if (!hasKey(mapping, "failure_reason") || !hasKey(mapping, "validated_at_ms")) {
12804
+ const mapping2 = requiredMap2(value, "FLOW.QUERY.INDEXES index validation");
12805
+ if (!hasKey(mapping2, "failure_reason") || !hasKey(mapping2, "validated_at_ms")) {
12650
12806
  throw decodeError(
12651
12807
  "FLOW.QUERY.INDEXES index validation is missing nullable fields",
12652
12808
  value
12653
12809
  );
12654
12810
  }
12655
12811
  const progress = decodeIndexProgress(
12656
- mapping,
12812
+ mapping2,
12657
12813
  "validation",
12658
12814
  FLOW_QUERY_VALIDATION_PHASES
12659
12815
  );
12660
12816
  return Object.freeze({
12661
12817
  ...progress,
12662
12818
  status: requiredChoice(
12663
- mapping,
12819
+ mapping2,
12664
12820
  "status",
12665
12821
  "FLOW.QUERY.INDEXES index validation",
12666
12822
  ["pending", "passed", "failed"]
12667
12823
  ),
12668
- checkedRecords: indexCounter(mapping, "checked_records", "validation"),
12669
- checkedEntries: indexCounter(mapping, "checked_entries", "validation"),
12670
- mismatches: indexCounter(mapping, "mismatches", "validation"),
12824
+ checkedRecords: indexCounter(mapping2, "checked_records", "validation"),
12825
+ checkedEntries: indexCounter(mapping2, "checked_entries", "validation"),
12826
+ mismatches: indexCounter(mapping2, "mismatches", "validation"),
12671
12827
  failureReason: optionalBoundedText(
12672
- mapping,
12828
+ mapping2,
12673
12829
  "failure_reason",
12674
12830
  "FLOW.QUERY.INDEXES index validation",
12675
12831
  128
12676
12832
  ),
12677
12833
  validatedAtMs: optionalIndexInteger(
12678
- mapping,
12834
+ mapping2,
12679
12835
  "validated_at_ms",
12680
12836
  "FLOW.QUERY.INDEXES index validation"
12681
12837
  )
@@ -12683,77 +12839,77 @@ function decodeIndexValidation(value) {
12683
12839
  }
12684
12840
  function decodeIndexRetirement(value) {
12685
12841
  const context = "FLOW.QUERY.INDEXES index retirement";
12686
- const mapping = requiredMap2(value, context);
12687
- const status = requiredChoice(mapping, "status", context, [
12842
+ const mapping2 = requiredMap2(value, context);
12843
+ const status = requiredChoice(mapping2, "status", context, [
12688
12844
  "not_applicable",
12689
12845
  "pending",
12690
12846
  "complete"
12691
12847
  ]);
12692
12848
  if (status === "not_applicable") {
12693
- return Object.freeze({ status, raw: freezeMap(mapping) });
12849
+ return Object.freeze({ status, raw: freezeMap(mapping2) });
12694
12850
  }
12695
12851
  const completedShards = unsignedIndexInteger(
12696
- field(mapping, "completed_shards"),
12852
+ field(mapping2, "completed_shards"),
12697
12853
  `${context} completed_shards`
12698
12854
  );
12699
12855
  const totalShards = positiveIndexInteger(
12700
- field(mapping, "total_shards"),
12856
+ field(mapping2, "total_shards"),
12701
12857
  `${context} total_shards`
12702
12858
  );
12703
12859
  if (indexInteger2(completedShards) > indexInteger2(totalShards)) {
12704
12860
  throw decodeError(
12705
12861
  `${context} completed_shards exceeds total_shards`,
12706
- mapping
12862
+ mapping2
12707
12863
  );
12708
12864
  }
12709
12865
  return Object.freeze({
12710
12866
  status,
12711
12867
  phaseCounts: decodePhaseCounts(
12712
- field(mapping, "phase_counts"),
12868
+ field(mapping2, "phase_counts"),
12713
12869
  "retirement"
12714
12870
  ),
12715
12871
  currentPhases: decodeAllowedPhases(
12716
- field(mapping, "current_phases"),
12872
+ field(mapping2, "current_phases"),
12717
12873
  "retirement",
12718
12874
  FLOW_QUERY_RETIREMENT_PHASES
12719
12875
  ),
12720
12876
  completedShards,
12721
12877
  totalShards,
12722
- deletedEntries: indexCounter(mapping, "deleted_entries", "retirement"),
12723
- deletedBytes: indexCounter(mapping, "deleted_bytes", "retirement"),
12878
+ deletedEntries: indexCounter(mapping2, "deleted_entries", "retirement"),
12879
+ deletedBytes: indexCounter(mapping2, "deleted_bytes", "retirement"),
12724
12880
  rewrittenReverseRows: indexCounter(
12725
- mapping,
12881
+ mapping2,
12726
12882
  "rewritten_reverse_rows",
12727
12883
  "retirement"
12728
12884
  ),
12729
- raw: freezeMap(mapping)
12885
+ raw: freezeMap(mapping2)
12730
12886
  });
12731
12887
  }
12732
12888
  function decodeIndexStatistics(value) {
12733
12889
  const context = "FLOW.QUERY.INDEXES index statistics";
12734
- const mapping = requiredMap2(value, context);
12890
+ const mapping2 = requiredMap2(value, context);
12735
12891
  for (const name of [
12736
12892
  "oldest_collected_at_ms",
12737
12893
  "newest_collected_at_ms",
12738
12894
  "oldest_age_ms",
12739
12895
  "newest_age_ms"
12740
12896
  ]) {
12741
- if (!hasKey(mapping, name)) {
12897
+ if (!hasKey(mapping2, name)) {
12742
12898
  throw decodeError(
12743
12899
  `${context} is missing required nullable fields`,
12744
12900
  value
12745
12901
  );
12746
12902
  }
12747
12903
  }
12748
- const samples = indexCounter(mapping, "samples", "statistics");
12749
- const freshSamples = indexCounter(mapping, "fresh_samples", "statistics");
12750
- const staleSamples = indexCounter(mapping, "stale_samples", "statistics");
12751
- const futureSamples = indexCounter(mapping, "future_samples", "statistics");
12904
+ const samples = indexCounter(mapping2, "samples", "statistics");
12905
+ const freshSamples = indexCounter(mapping2, "fresh_samples", "statistics");
12906
+ const staleSamples = indexCounter(mapping2, "stale_samples", "statistics");
12907
+ const futureSamples = indexCounter(mapping2, "future_samples", "statistics");
12752
12908
  if (indexInteger2(freshSamples) + indexInteger2(staleSamples) !== indexInteger2(samples) || indexInteger2(futureSamples) > indexInteger2(staleSamples)) {
12753
12909
  throw decodeError(`${context} counters are inconsistent`, value);
12754
12910
  }
12755
12911
  return Object.freeze({
12756
- status: requiredChoice(mapping, "status", context, [
12912
+ status: requiredChoice(mapping2, "status", context, [
12757
12913
  "fresh",
12758
12914
  "stale",
12759
12915
  "future",
@@ -12766,53 +12922,53 @@ function decodeIndexStatistics(value) {
12766
12922
  staleSamples,
12767
12923
  futureSamples,
12768
12924
  oldestCollectedAtMs: optionalIndexInteger(
12769
- mapping,
12925
+ mapping2,
12770
12926
  "oldest_collected_at_ms",
12771
12927
  context
12772
12928
  ),
12773
12929
  newestCollectedAtMs: optionalIndexInteger(
12774
- mapping,
12930
+ mapping2,
12775
12931
  "newest_collected_at_ms",
12776
12932
  context
12777
12933
  ),
12778
- oldestAgeMs: optionalIndexInteger(mapping, "oldest_age_ms", context),
12779
- newestAgeMs: optionalIndexInteger(mapping, "newest_age_ms", context),
12780
- raw: freezeMap(mapping)
12934
+ oldestAgeMs: optionalIndexInteger(mapping2, "oldest_age_ms", context),
12935
+ newestAgeMs: optionalIndexInteger(mapping2, "newest_age_ms", context),
12936
+ raw: freezeMap(mapping2)
12781
12937
  });
12782
12938
  }
12783
- function decodeIndexProgress(mapping, section, allowedPhases) {
12939
+ function decodeIndexProgress(mapping2, section, allowedPhases) {
12784
12940
  const context = `FLOW.QUERY.INDEXES index ${section}`;
12785
12941
  const completedShards = unsignedIndexInteger(
12786
- field(mapping, "completed_shards"),
12942
+ field(mapping2, "completed_shards"),
12787
12943
  `${context} completed_shards`
12788
12944
  );
12789
12945
  const totalShards = positiveIndexInteger(
12790
- field(mapping, "total_shards"),
12946
+ field(mapping2, "total_shards"),
12791
12947
  `${context} total_shards`
12792
12948
  );
12793
12949
  if (indexInteger2(completedShards) > indexInteger2(totalShards)) {
12794
12950
  throw decodeError(
12795
12951
  `${context} completed_shards exceeds total_shards`,
12796
- mapping
12952
+ mapping2
12797
12953
  );
12798
12954
  }
12799
12955
  return Object.freeze({
12800
- scope: requiredChoice(mapping, "scope", context, ["catalog_build"]),
12801
- phaseCounts: decodePhaseCounts(field(mapping, "phase_counts"), section),
12956
+ scope: requiredChoice(mapping2, "scope", context, ["catalog_build"]),
12957
+ phaseCounts: decodePhaseCounts(field(mapping2, "phase_counts"), section),
12802
12958
  currentPhases: decodeAllowedPhases(
12803
- field(mapping, "current_phases"),
12959
+ field(mapping2, "current_phases"),
12804
12960
  section,
12805
12961
  allowedPhases
12806
12962
  ),
12807
12963
  completedShards,
12808
12964
  totalShards,
12809
- raw: freezeMap(mapping)
12965
+ raw: freezeMap(mapping2)
12810
12966
  });
12811
12967
  }
12812
12968
  function decodePhaseCounts(value, section) {
12813
12969
  const context = `FLOW.QUERY.INDEXES index ${section} phase_counts`;
12814
- const mapping = requiredMap2(value, context);
12815
- const entries = mapping instanceof Map ? [...mapping.entries()] : Object.entries(mapping);
12970
+ const mapping2 = requiredMap2(value, context);
12971
+ const entries = mapping2 instanceof Map ? [...mapping2.entries()] : Object.entries(mapping2);
12816
12972
  if (entries.length > 16) {
12817
12973
  throw decodeError(`${context} contains too many entries`, value);
12818
12974
  }
@@ -12845,19 +13001,19 @@ function decodeAllowedPhases(value, section, allowed) {
12845
13001
  // src/flow-query-index-response.ts
12846
13002
  var FLOW_QUERY_INDEXES_CONTRACT = "ferric.flow.query.indexes/v1";
12847
13003
  function decodeFlowQueryIndexStatus(value, expectedId) {
12848
- const mapping = requiredMap2(value, "FLOW.QUERY.INDEXES");
13004
+ const mapping2 = requiredMap2(value, "FLOW.QUERY.INDEXES");
12849
13005
  requireContract(
12850
- mapping,
13006
+ mapping2,
12851
13007
  "contract_version",
12852
13008
  FLOW_QUERY_INDEXES_CONTRACT,
12853
13009
  "FLOW.QUERY.INDEXES"
12854
13010
  );
12855
13011
  const registry = requiredMap2(
12856
- field(mapping, "registry"),
13012
+ field(mapping2, "registry"),
12857
13013
  "FLOW.QUERY.INDEXES registry"
12858
13014
  );
12859
- const services = decodeIndexServices(field(mapping, "services"));
12860
- const rawIndexes = field(mapping, "indexes");
13015
+ const services = decodeIndexServices(field(mapping2, "services"));
13016
+ const rawIndexes = field(mapping2, "indexes");
12861
13017
  if (!Array.isArray(rawIndexes) || rawIndexes.length > 32) {
12862
13018
  throw decodeError(
12863
13019
  "FLOW.QUERY.INDEXES indexes must contain at most 32 entries",
@@ -12877,11 +13033,11 @@ function decodeFlowQueryIndexStatus(value, expectedId) {
12877
13033
  const status = Object.freeze({
12878
13034
  contractVersion: FLOW_QUERY_INDEXES_CONTRACT,
12879
13035
  observedAtMs: unsignedIndexInteger(
12880
- field(mapping, "observed_at_ms"),
13036
+ field(mapping2, "observed_at_ms"),
12881
13037
  "FLOW.QUERY.INDEXES observed_at_ms"
12882
13038
  ),
12883
13039
  statisticsMaxAgeMs: unsignedIndexInteger(
12884
- field(mapping, "statistics_max_age_ms"),
13040
+ field(mapping2, "statistics_max_age_ms"),
12885
13041
  "FLOW.QUERY.INDEXES statistics_max_age_ms"
12886
13042
  ),
12887
13043
  registry: Object.freeze({
@@ -12896,30 +13052,30 @@ function decodeFlowQueryIndexStatus(value, expectedId) {
12896
13052
  }),
12897
13053
  services,
12898
13054
  indexes: Object.freeze(indexes),
12899
- raw: freezeMap(mapping)
13055
+ raw: freezeMap(mapping2)
12900
13056
  });
12901
13057
  validateFlowQueryIndexContract(status, expectedId);
12902
13058
  return status;
12903
13059
  }
12904
13060
  function decodeIndex(value, index) {
12905
- const mapping = requiredMap2(value, `FLOW.QUERY.INDEXES index ${index}`);
12906
- const fields = decodeIndexFields(field(mapping, "fields"));
13061
+ const mapping2 = requiredMap2(value, `FLOW.QUERY.INDEXES index ${index}`);
13062
+ const fields = decodeIndexFields(field(mapping2, "fields"));
12907
13063
  return Object.freeze({
12908
- id: requiredBoundedText2(mapping, "id", "FLOW.QUERY.INDEXES index", 64),
13064
+ id: requiredBoundedText2(mapping2, "id", "FLOW.QUERY.INDEXES index", 64),
12909
13065
  version: positiveIndexInteger(
12910
- field(mapping, "version"),
13066
+ field(mapping2, "version"),
12911
13067
  "FLOW.QUERY.INDEXES index version"
12912
13068
  ),
12913
13069
  buildId: requiredBoundedText2(
12914
- mapping,
13070
+ mapping2,
12915
13071
  "build_id",
12916
13072
  "FLOW.QUERY.INDEXES index",
12917
13073
  128
12918
13074
  ),
12919
- source: requiredChoice(mapping, "source", "FLOW.QUERY.INDEXES index", [
13075
+ source: requiredChoice(mapping2, "source", "FLOW.QUERY.INDEXES index", [
12920
13076
  "runs"
12921
13077
  ]),
12922
- state: requiredChoice(mapping, "state", "FLOW.QUERY.INDEXES index", [
13078
+ state: requiredChoice(mapping2, "state", "FLOW.QUERY.INDEXES index", [
12923
13079
  "building",
12924
13080
  "validating",
12925
13081
  "active",
@@ -12927,60 +13083,60 @@ function decodeIndex(value, index) {
12927
13083
  "failed"
12928
13084
  ]),
12929
13085
  queryable: requiredBoolean(
12930
- mapping,
13086
+ mapping2,
12931
13087
  "queryable",
12932
13088
  "FLOW.QUERY.INDEXES index"
12933
13089
  ),
12934
13090
  fields,
12935
13091
  workloads: decodeUniqueTextArray(
12936
- field(mapping, "workloads"),
13092
+ field(mapping2, "workloads"),
12937
13093
  "FLOW.QUERY.INDEXES index workloads",
12938
13094
  16,
12939
13095
  64
12940
13096
  ),
12941
13097
  countPrefixes: decodeCountPrefixes(
12942
- field(mapping, "count_prefixes"),
13098
+ field(mapping2, "count_prefixes"),
12943
13099
  fields.length
12944
13100
  ),
12945
- coveringFields: decodeCoveringFields(mapping),
12946
- format: decodeIndexFormat(mapping),
12947
- coverage: decodeIndexCoverage(field(mapping, "coverage")),
12948
- build: decodeIndexBuild(field(mapping, "build")),
12949
- validation: decodeIndexValidation(field(mapping, "validation")),
12950
- retirement: decodeIndexRetirement(field(mapping, "retirement")),
12951
- statistics: decodeIndexStatistics(field(mapping, "statistics")),
12952
- raw: freezeMap(mapping)
13101
+ coveringFields: decodeCoveringFields(mapping2),
13102
+ format: decodeIndexFormat(mapping2),
13103
+ coverage: decodeIndexCoverage(field(mapping2, "coverage")),
13104
+ build: decodeIndexBuild(field(mapping2, "build")),
13105
+ validation: decodeIndexValidation(field(mapping2, "validation")),
13106
+ retirement: decodeIndexRetirement(field(mapping2, "retirement")),
13107
+ statistics: decodeIndexStatistics(field(mapping2, "statistics")),
13108
+ raw: freezeMap(mapping2)
12953
13109
  });
12954
13110
  }
12955
13111
  function decodeIndexServices(value) {
12956
- const mapping = requiredMap2(value, "FLOW.QUERY.INDEXES services");
13112
+ const mapping2 = requiredMap2(value, "FLOW.QUERY.INDEXES services");
12957
13113
  const choices = ["ready", "unavailable"];
12958
13114
  return Object.freeze({
12959
13115
  registry: requiredChoice(
12960
- mapping,
13116
+ mapping2,
12961
13117
  "registry",
12962
13118
  "FLOW.QUERY.INDEXES services",
12963
13119
  choices
12964
13120
  ),
12965
13121
  lifecycleWorker: requiredChoice(
12966
- mapping,
13122
+ mapping2,
12967
13123
  "lifecycle_worker",
12968
13124
  "FLOW.QUERY.INDEXES services",
12969
13125
  choices
12970
13126
  ),
12971
13127
  statisticsStore: requiredChoice(
12972
- mapping,
13128
+ mapping2,
12973
13129
  "statistics_store",
12974
13130
  "FLOW.QUERY.INDEXES services",
12975
13131
  choices
12976
13132
  ),
12977
13133
  statisticsWorker: requiredChoice(
12978
- mapping,
13134
+ mapping2,
12979
13135
  "statistics_worker",
12980
13136
  "FLOW.QUERY.INDEXES services",
12981
13137
  choices
12982
13138
  ),
12983
- raw: freezeMap(mapping)
13139
+ raw: freezeMap(mapping2)
12984
13140
  });
12985
13141
  }
12986
13142
  function decodeIndexFields(value) {
@@ -12994,12 +13150,12 @@ function decodeIndexFields(value) {
12994
13150
  if (!Object.hasOwn(value, index)) {
12995
13151
  throw decodeError(`${context} must be dense`, value);
12996
13152
  }
12997
- const mapping = requiredMap2(
13153
+ const mapping2 = requiredMap2(
12998
13154
  value[index],
12999
13155
  `FLOW.QUERY.INDEXES index field ${index}`
13000
13156
  );
13001
13157
  const name = requiredBoundedText2(
13002
- mapping,
13158
+ mapping2,
13003
13159
  "name",
13004
13160
  "FLOW.QUERY.INDEXES index field",
13005
13161
  512
@@ -13011,18 +13167,18 @@ function decodeIndexFields(value) {
13011
13167
  fields[index] = Object.freeze({
13012
13168
  name,
13013
13169
  direction: requiredChoice(
13014
- mapping,
13170
+ mapping2,
13015
13171
  "direction",
13016
13172
  "FLOW.QUERY.INDEXES index field",
13017
13173
  ["asc", "desc"]
13018
13174
  ),
13019
13175
  encoding: requiredChoice(
13020
- mapping,
13176
+ mapping2,
13021
13177
  "encoding",
13022
13178
  "FLOW.QUERY.INDEXES index field",
13023
13179
  ["hashed", "ordered"]
13024
13180
  ),
13025
- raw: freezeMap(mapping)
13181
+ raw: freezeMap(mapping2)
13026
13182
  });
13027
13183
  }
13028
13184
  return Object.freeze(fields);
@@ -13047,8 +13203,8 @@ function decodeCountPrefixes(value, fieldCount) {
13047
13203
  }
13048
13204
  return Object.freeze(prefixes);
13049
13205
  }
13050
- function decodeCoveringFields(mapping) {
13051
- const raw = field(mapping, "covering_fields");
13206
+ function decodeCoveringFields(mapping2) {
13207
+ const raw = field(mapping2, "covering_fields");
13052
13208
  if (!Array.isArray(raw) || raw.length > 32) {
13053
13209
  throw decodeError(
13054
13210
  "FLOW.QUERY.INDEXES index covering_fields must contain at most 32 entries",
@@ -13080,9 +13236,9 @@ function decodeCoveringFields(mapping) {
13080
13236
  }
13081
13237
  return Object.freeze(fields);
13082
13238
  }
13083
- function decodeIndexFormat(mapping) {
13239
+ function decodeIndexFormat(mapping2) {
13084
13240
  const raw = requiredMap2(
13085
- field(mapping, "format"),
13241
+ field(mapping2, "format"),
13086
13242
  "FLOW.QUERY.INDEXES index format"
13087
13243
  );
13088
13244
  if (!hasKey(raw, "counter")) {
@@ -13151,7 +13307,7 @@ var QUALITY_VALUES2 = {
13151
13307
  pagination: ["none", "complete", "authenticated_seek", "live_seek"]
13152
13308
  };
13153
13309
  function decodeFlowQueryResult(value) {
13154
- const result = decodeFlowQueryResponse(value, (mapping) => freezeMap(mapping));
13310
+ const result = decodeFlowQueryResponse(value, (mapping2) => freezeMap(mapping2));
13155
13311
  if (result.kind === "records") {
13156
13312
  return Object.freeze({
13157
13313
  kind: "records",
@@ -13175,7 +13331,7 @@ function decodeFlowQueryResult(value) {
13175
13331
  function decodeFlowQueryRecords(value, decodeRecord) {
13176
13332
  const result = decodeFlowQueryResponse(
13177
13333
  value,
13178
- (mapping, index) => decodeRecord(mapping instanceof Map ? freezeMap(mapping) : mapping, index)
13334
+ (mapping2, index) => decodeRecord(mapping2 instanceof Map ? freezeMap(mapping2) : mapping2, index)
13179
13335
  );
13180
13336
  if (result.kind === "count") {
13181
13337
  throw new FerricStoreError("Flow record convenience query returned a count result", {
@@ -13185,18 +13341,18 @@ function decodeFlowQueryRecords(value, decodeRecord) {
13185
13341
  return result.records;
13186
13342
  }
13187
13343
  function decodeFlowQueryResponse(value, decodeRecord) {
13188
- const mapping = requiredMap2(value, "FLOW.QUERY result");
13189
- requireContract(mapping, "version", FLOW_QUERY_RESULT_CONTRACT, "FLOW.QUERY result");
13190
- const quality = decodeQuality(field(mapping, "quality"));
13191
- const usage = decodeUsage(field(mapping, "usage"));
13192
- const hasRecords = hasKey(mapping, "records");
13193
- const hasCount = hasKey(mapping, "result");
13344
+ const mapping2 = requiredMap2(value, "FLOW.QUERY result");
13345
+ requireContract(mapping2, "version", FLOW_QUERY_RESULT_CONTRACT, "FLOW.QUERY result");
13346
+ const quality = decodeQuality(field(mapping2, "quality"));
13347
+ const usage = decodeUsage(field(mapping2, "usage"));
13348
+ const hasRecords = hasKey(mapping2, "records");
13349
+ const hasCount = hasKey(mapping2, "result");
13194
13350
  if (hasRecords === hasCount) {
13195
13351
  throw decodeError("FLOW.QUERY result must contain exactly one records or count shape", value);
13196
13352
  }
13197
- const raw = freezeMap(mapping);
13353
+ const raw = freezeMap(mapping2);
13198
13354
  if (hasRecords) {
13199
- const rawRecords = field(mapping, "records");
13355
+ const rawRecords = field(mapping2, "records");
13200
13356
  if (!Array.isArray(rawRecords) || rawRecords.length > 100) {
13201
13357
  throw decodeError("FLOW.QUERY records must be an array of at most 100 maps", value);
13202
13358
  }
@@ -13216,16 +13372,16 @@ function decodeFlowQueryResponse(value, decodeRecord) {
13216
13372
  return {
13217
13373
  kind: "records",
13218
13374
  records,
13219
- page: decodePage(field(mapping, "page")),
13375
+ page: decodePage(field(mapping2, "page")),
13220
13376
  quality,
13221
13377
  usage,
13222
13378
  raw
13223
13379
  };
13224
13380
  }
13225
- if (hasKey(mapping, "page")) {
13381
+ if (hasKey(mapping2, "page")) {
13226
13382
  throw decodeError("FLOW.QUERY count result contains an unexpected page", value);
13227
13383
  }
13228
- const countResult = requiredMap2(field(mapping, "result"), "FLOW.QUERY count result");
13384
+ const countResult = requiredMap2(field(mapping2, "result"), "FLOW.QUERY count result");
13229
13385
  if (requiredText2(countResult, "kind", "FLOW.QUERY count result") !== "count") {
13230
13386
  throw decodeError("FLOW.QUERY count result kind must be count", value);
13231
13387
  }
@@ -13246,31 +13402,31 @@ function decodeFlowQueryResponse(value, decodeRecord) {
13246
13402
  };
13247
13403
  }
13248
13404
  function decodeFlowExplainResult(value) {
13249
- const mapping = requiredMap2(value, "FLOW.QUERY explain");
13250
- requireContract(mapping, "version", FLOW_EXPLAIN_CONTRACT, "FLOW.QUERY explain");
13251
- const queryFingerprint = requiredText2(mapping, "query_fingerprint", "FLOW.QUERY explain");
13405
+ const mapping2 = requiredMap2(value, "FLOW.QUERY explain");
13406
+ requireContract(mapping2, "version", FLOW_EXPLAIN_CONTRACT, "FLOW.QUERY explain");
13407
+ const queryFingerprint = requiredText2(mapping2, "query_fingerprint", "FLOW.QUERY explain");
13252
13408
  if (!/^[0-9a-f]{64}$/iu.test(queryFingerprint)) {
13253
13409
  throw decodeError("FLOW.QUERY explain query_fingerprint is invalid", value);
13254
13410
  }
13255
- const status = requiredText2(mapping, "status", "FLOW.QUERY explain");
13411
+ const status = requiredText2(mapping2, "status", "FLOW.QUERY explain");
13256
13412
  if (status !== "planned" && status !== "rejected" && status !== "executed") {
13257
13413
  throw decodeError(`FLOW.QUERY explain status ${JSON.stringify(status)} is unsupported`, value);
13258
13414
  }
13259
13415
  const plan = freezeMetadataMap(
13260
- requiredMap2(field(mapping, "plan"), "FLOW.QUERY explain plan"),
13416
+ requiredMap2(field(mapping2, "plan"), "FLOW.QUERY explain plan"),
13261
13417
  "FLOW.QUERY explain plan"
13262
13418
  );
13263
13419
  const estimate = freezeMetadataMap(
13264
- requiredMap2(field(mapping, "estimate"), "FLOW.QUERY explain estimate"),
13420
+ requiredMap2(field(mapping2, "estimate"), "FLOW.QUERY explain estimate"),
13265
13421
  "FLOW.QUERY explain estimate"
13266
13422
  );
13267
13423
  const bounds = freezeMetadataMap(
13268
- requiredMap2(field(mapping, "bounds"), "FLOW.QUERY explain bounds"),
13424
+ requiredMap2(field(mapping2, "bounds"), "FLOW.QUERY explain bounds"),
13269
13425
  "FLOW.QUERY explain bounds"
13270
13426
  );
13271
- const capabilities = decodeExplainCapabilities(mapping);
13427
+ const capabilities = decodeExplainCapabilities(mapping2);
13272
13428
  const extendedFields = ["stats", "quality", "pressure", "decision", "alternatives"];
13273
- const extendedPresence = extendedFields.map((name) => hasKey(mapping, name));
13429
+ const extendedPresence = extendedFields.map((name) => hasKey(mapping2, name));
13274
13430
  const specialized = capabilities != null && !extendedPresence.some(Boolean);
13275
13431
  let stats;
13276
13432
  let quality;
@@ -13281,30 +13437,30 @@ function decodeFlowExplainResult(value) {
13281
13437
  if (status !== "planned") {
13282
13438
  throw decodeError("FLOW.QUERY specialized explain must be planned", value);
13283
13439
  }
13284
- if (hasKey(mapping, "actual") || hasKey(mapping, "diagnostic")) {
13440
+ if (hasKey(mapping2, "actual") || hasKey(mapping2, "diagnostic")) {
13285
13441
  throw decodeError("FLOW.QUERY specialized explain has extended status fields", value);
13286
13442
  }
13287
13443
  alternatives = Object.freeze([]);
13288
13444
  } else {
13289
- if (!extendedPresence.every(Boolean) || !hasKey(mapping, "actual") || !hasKey(mapping, "diagnostic")) {
13445
+ if (!extendedPresence.every(Boolean) || !hasKey(mapping2, "actual") || !hasKey(mapping2, "diagnostic")) {
13290
13446
  throw decodeError("FLOW.QUERY explain is missing required v1 fields", value);
13291
13447
  }
13292
13448
  stats = freezeMetadataMap(
13293
- requiredMap2(field(mapping, "stats"), "FLOW.QUERY explain stats"),
13449
+ requiredMap2(field(mapping2, "stats"), "FLOW.QUERY explain stats"),
13294
13450
  "FLOW.QUERY explain stats"
13295
13451
  );
13296
- quality = decodeQuality(field(mapping, "quality"));
13452
+ quality = decodeQuality(field(mapping2, "quality"));
13297
13453
  pressure = freezeMetadataMap(
13298
- requiredMap2(field(mapping, "pressure"), "FLOW.QUERY explain pressure"),
13454
+ requiredMap2(field(mapping2, "pressure"), "FLOW.QUERY explain pressure"),
13299
13455
  "FLOW.QUERY explain pressure"
13300
13456
  );
13301
13457
  decision = freezeMetadataMap(
13302
- requiredMap2(field(mapping, "decision"), "FLOW.QUERY explain decision"),
13458
+ requiredMap2(field(mapping2, "decision"), "FLOW.QUERY explain decision"),
13303
13459
  "FLOW.QUERY explain decision"
13304
13460
  );
13305
- alternatives = decodeExplainAlternatives(field(mapping, "alternatives"));
13461
+ alternatives = decodeExplainAlternatives(field(mapping2, "alternatives"));
13306
13462
  }
13307
- const actualValue = field(mapping, "actual");
13463
+ const actualValue = field(mapping2, "actual");
13308
13464
  let actual;
13309
13465
  if (status === "executed") {
13310
13466
  if (actualValue == null) {
@@ -13314,7 +13470,7 @@ function decodeFlowExplainResult(value) {
13314
13470
  } else if (actualValue != null) {
13315
13471
  throw decodeError("FLOW.QUERY non-executed explain contains actual usage", value);
13316
13472
  }
13317
- const diagnosticValue = field(mapping, "diagnostic");
13473
+ const diagnosticValue = field(mapping2, "diagnostic");
13318
13474
  let diagnostic;
13319
13475
  if (status === "rejected") {
13320
13476
  diagnostic = tryDecodeFlowQueryError(diagnosticValue);
@@ -13339,13 +13495,13 @@ function decodeFlowExplainResult(value) {
13339
13495
  capabilities,
13340
13496
  actual,
13341
13497
  diagnostic,
13342
- raw: freezeMap(mapping)
13498
+ raw: freezeMap(mapping2)
13343
13499
  });
13344
13500
  }
13345
- function decodeExplainCapabilities(mapping) {
13346
- if (!hasKey(mapping, "capabilities")) return void 0;
13501
+ function decodeExplainCapabilities(mapping2) {
13502
+ if (!hasKey(mapping2, "capabilities")) return void 0;
13347
13503
  const value = requiredMap2(
13348
- field(mapping, "capabilities"),
13504
+ field(mapping2, "capabilities"),
13349
13505
  "FLOW.QUERY explain capabilities"
13350
13506
  );
13351
13507
  return Object.freeze({
@@ -13401,27 +13557,27 @@ function decodeExplainAlternatives(value) {
13401
13557
  return Object.freeze(alternatives);
13402
13558
  }
13403
13559
  function decodeQuality(value) {
13404
- const mapping = requiredMap2(value, "FLOW.QUERY quality");
13560
+ const mapping2 = requiredMap2(value, "FLOW.QUERY quality");
13405
13561
  return Object.freeze({
13406
- exactness: decodeQualityValue(mapping, "exactness", QUALITY_VALUES2.exactness),
13407
- freshness: decodeQualityValue(mapping, "freshness", QUALITY_VALUES2.freshness),
13408
- coverage: decodeQualityValue(mapping, "coverage", QUALITY_VALUES2.coverage),
13409
- pagination: decodeQualityValue(mapping, "pagination", QUALITY_VALUES2.pagination)
13562
+ exactness: decodeQualityValue(mapping2, "exactness", QUALITY_VALUES2.exactness),
13563
+ freshness: decodeQualityValue(mapping2, "freshness", QUALITY_VALUES2.freshness),
13564
+ coverage: decodeQualityValue(mapping2, "coverage", QUALITY_VALUES2.coverage),
13565
+ pagination: decodeQualityValue(mapping2, "pagination", QUALITY_VALUES2.pagination)
13410
13566
  });
13411
13567
  }
13412
- function decodeQualityValue(mapping, name, allowed) {
13413
- const value = requiredBoundedText2(mapping, name, "FLOW.QUERY quality", 64);
13568
+ function decodeQualityValue(mapping2, name, allowed) {
13569
+ const value = requiredBoundedText2(mapping2, name, "FLOW.QUERY quality", 64);
13414
13570
  if (!allowed.includes(value)) {
13415
- throw decodeError(`FLOW.QUERY quality ${name} is unsupported`, mapping);
13571
+ throw decodeError(`FLOW.QUERY quality ${name} is unsupported`, mapping2);
13416
13572
  }
13417
13573
  return value;
13418
13574
  }
13419
13575
  function decodeUsage(value) {
13420
- const mapping = requiredMap2(value, "FLOW.QUERY usage");
13576
+ const mapping2 = requiredMap2(value, "FLOW.QUERY usage");
13421
13577
  const usage = /* @__PURE__ */ Object.create(null);
13422
13578
  for (const [wireName, property] of USAGE_FIELDS2) {
13423
13579
  usage[property] = nonNegativeInteger(
13424
- field(mapping, wireName),
13580
+ field(mapping2, wireName),
13425
13581
  `FLOW.QUERY usage ${wireName}`
13426
13582
  );
13427
13583
  }
@@ -13432,9 +13588,9 @@ function decodeUsage(value) {
13432
13588
  return Object.freeze(decoded);
13433
13589
  }
13434
13590
  function decodePage(value) {
13435
- const mapping = requiredMap2(value, "FLOW.QUERY page");
13436
- const hasMore = requiredBoolean(mapping, "has_more", "FLOW.QUERY page");
13437
- const cursor = optionalText2(mapping, "cursor", "FLOW.QUERY page");
13591
+ const mapping2 = requiredMap2(value, "FLOW.QUERY page");
13592
+ const hasMore = requiredBoolean(mapping2, "has_more", "FLOW.QUERY page");
13593
+ const cursor = optionalText2(mapping2, "cursor", "FLOW.QUERY page");
13438
13594
  if (cursor != null && (!cursor.startsWith("fqc1_") || Buffer48.byteLength(cursor) < 16 || Buffer48.byteLength(cursor) > 4096)) {
13439
13595
  throw decodeError("FLOW.QUERY page cursor is invalid", value);
13440
13596
  }
@@ -13550,12 +13706,12 @@ var ErrorMappingExecutor = class {
13550
13706
 
13551
13707
  // src/client-config.ts
13552
13708
  function snapshotClientOptions(options) {
13553
- const own = { ...options };
13709
+ const own2 = { ...options };
13554
13710
  const snapshot = {
13555
- ...own,
13556
- ...typeof own.autoBatch === "object" && own.autoBatch != null ? { autoBatch: Object.freeze({ ...own.autoBatch }) } : {},
13557
- ...own.backpressure == null ? {} : { backpressure: Object.freeze({ ...own.backpressure }) },
13558
- ...typeof own.reconnect === "object" && own.reconnect != null ? { reconnect: Object.freeze({ ...own.reconnect }) } : {}
13711
+ ...own2,
13712
+ ...typeof own2.autoBatch === "object" && own2.autoBatch != null ? { autoBatch: Object.freeze({ ...own2.autoBatch }) } : {},
13713
+ ...own2.backpressure == null ? {} : { backpressure: Object.freeze({ ...own2.backpressure }) },
13714
+ ...typeof own2.reconnect === "object" && own2.reconnect != null ? { reconnect: Object.freeze({ ...own2.reconnect }) } : {}
13559
13715
  };
13560
13716
  return Object.freeze(snapshot);
13561
13717
  }
@@ -15744,33 +15900,511 @@ var FerricStoreClientCore = class extends FerricStoreAdministrationClient {
15744
15900
  }
15745
15901
  };
15746
15902
 
15747
- // src/client-management.ts
15748
- var FerricStoreManagementClient = class extends FerricStoreClientCore {
15749
- async stats(type, options = {}) {
15750
- const args = ["FLOW.STATS", type];
15751
- append(args, "STATE", options.state);
15752
- append(args, "COUNT", options.count);
15753
- append(args, "PARTITION", options.partitionKey);
15754
- appendAttributes(args, options.attributes);
15755
- appendBool(args, "CONSISTENT_PROJECTION", options.consistentProjection);
15756
- return adminRecordResponse(await this.commandArgs(args), "FLOW.STATS");
15903
+ // src/schedule-request.ts
15904
+ var MAX_EXACT_INTEGER = Number.MAX_SAFE_INTEGER;
15905
+ var SCHEDULE_KINDS = /* @__PURE__ */ new Set(["one_shot", "delay", "interval", "cron"]);
15906
+ var RECURRING_KINDS = /* @__PURE__ */ new Set(["interval", "cron"]);
15907
+ var OVERLAP_POLICIES = /* @__PURE__ */ new Set([
15908
+ "allow",
15909
+ "skip",
15910
+ "queue_after_previous",
15911
+ "fail_schedule"
15912
+ ]);
15913
+ var SCHEDULE_STATES = /* @__PURE__ */ new Set([
15914
+ "active",
15915
+ "paused",
15916
+ "running",
15917
+ "completed",
15918
+ "failed",
15919
+ "cancelled",
15920
+ "all"
15921
+ ]);
15922
+ var TARGET_FIELDS = /* @__PURE__ */ new Set([
15923
+ "correlation_id",
15924
+ "id",
15925
+ "id_prefix",
15926
+ "parent_flow_id",
15927
+ "partition_key",
15928
+ "payload",
15929
+ "payload_ref",
15930
+ "priority",
15931
+ "root_flow_id",
15932
+ "run_at_ms",
15933
+ "state",
15934
+ "type",
15935
+ "value_refs",
15936
+ "values"
15937
+ ]);
15938
+ var TARGET_TEXT_FIELDS = [
15939
+ "state",
15940
+ "id",
15941
+ "id_prefix",
15942
+ "partition_key",
15943
+ "correlation_id",
15944
+ "parent_flow_id",
15945
+ "root_flow_id",
15946
+ "payload_ref"
15947
+ ];
15948
+ var INTERNAL_SCHEDULE_TYPE = "__ferricstore_schedule";
15949
+ var INTERNAL_SCHEDULE_ID_PREFIX = "__ferricstore_schedule__:";
15950
+ function validateScheduleCreate(id, options) {
15951
+ requiredText3(id, "id");
15952
+ if (!mapping(options)) throw new TypeError("schedule options must be a mapping");
15953
+ const kind = effectiveKind(options);
15954
+ validateTiming(kind, options);
15955
+ const recurring = RECURRING_KINDS.has(kind);
15956
+ validateTarget(options.target, recurring);
15957
+ nonNegativeInteger2(options.atMs, "at_ms");
15958
+ nonNegativeInteger2(options.delayMs, "delay_ms");
15959
+ nonNegativeInteger2(options.startAtMs, "start_at_ms");
15960
+ positiveInteger2(options.everyMs, "every_ms");
15961
+ positiveInteger2(options.overlapRetryMs, "overlap_retry_ms");
15962
+ positiveInteger2(options.maxFires, "max_fires");
15963
+ nonNegativeInteger2(options.endAtMs, "end_at_ms");
15964
+ nonNegativeInteger2(options.nowMs, "now_ms");
15965
+ optionalBoolean(options.overwrite, "overwrite");
15966
+ if (kind === "delay") {
15967
+ if (options.delayMs == null) throw new TypeError("delay_ms is required for delay schedules");
15968
+ if (options.nowMs != null && options.nowMs > MAX_EXACT_INTEGER - options.delayMs) {
15969
+ throw new TypeError("now_ms plus delay_ms exceeds the exact integer range");
15970
+ }
15971
+ }
15972
+ if (kind === "interval" && options.everyMs == null) {
15973
+ throw new TypeError("every_ms is required for interval schedules");
15974
+ }
15975
+ if (kind === "cron") {
15976
+ requiredText3(options.cron, "cron");
15977
+ optionalText3(options.timezone, "timezone");
15978
+ } else if (options.timezone != null) {
15979
+ throw new TypeError("timezone is only supported for cron schedules");
15980
+ }
15981
+ if (kind === "interval") {
15982
+ if (options.catchupPolicy != null && options.catchupPolicy !== "fire_once") {
15983
+ throw new TypeError("catchup_policy must be fire_once");
15984
+ }
15985
+ } else if (options.catchupPolicy != null) {
15986
+ throw new TypeError("catchup_policy is only supported for interval schedules");
15987
+ }
15988
+ if (recurring) {
15989
+ if (options.overlapPolicy != null && !OVERLAP_POLICIES.has(options.overlapPolicy)) {
15990
+ throw new TypeError(
15991
+ "overlap_policy must be allow, skip, queue_after_previous, or fail_schedule"
15992
+ );
15993
+ }
15994
+ if (options.overlapRetryMs != null && options.overlapPolicy !== "queue_after_previous") {
15995
+ throw new TypeError("overlap_retry_ms requires overlap_policy queue_after_previous");
15996
+ }
15997
+ const firstRun = knownFirstRun(kind, options);
15998
+ if (options.endAtMs != null && firstRun != null && options.endAtMs < firstRun) {
15999
+ throw new TypeError("end_at_ms must be at or after first run");
16000
+ }
16001
+ } else {
16002
+ if (options.overlapPolicy != null) {
16003
+ throw new TypeError("overlap_policy is only supported for recurring schedules");
16004
+ }
16005
+ if (options.overlapRetryMs != null) {
16006
+ throw new TypeError("overlap_retry_ms requires overlap_policy queue_after_previous");
16007
+ }
16008
+ if (options.maxFires != null) {
16009
+ throw new TypeError("max_fires is only supported for recurring schedules");
16010
+ }
16011
+ if (options.endAtMs != null) {
16012
+ throw new TypeError("end_at_ms is only supported for recurring schedules");
16013
+ }
15757
16014
  }
15758
- async countByState(type, state, options = {}) {
15759
- const stats = await this.stats(type, { ...options, state });
15760
- if (!("count" in stats)) throw new TypeError("FLOW.STATS response missing count");
15761
- return integer(stats.count);
16015
+ }
16016
+ function validateScheduleID(id) {
16017
+ requiredText3(id, "id");
16018
+ }
16019
+ function validateScheduleFire(id, options) {
16020
+ validateScheduleID(id);
16021
+ nonNegativeInteger2(options.fireAtMs, "fire_at_ms");
16022
+ nonNegativeInteger2(options.nowMs, "now_ms");
16023
+ }
16024
+ function validateScheduleStatus(id, nowMs2) {
16025
+ validateScheduleID(id);
16026
+ nonNegativeInteger2(nowMs2, "now_ms");
16027
+ }
16028
+ function validateScheduleFireDue(options) {
16029
+ if (!mapping(options)) throw new TypeError("schedule fire-due options must be a mapping");
16030
+ nonNegativeInteger2(options.nowMs, "now_ms");
16031
+ optionalText3(options.worker, "worker");
16032
+ positiveInteger2(options.leaseMs, "lease_ms");
16033
+ nonNegativeInteger2(options.blockMs, "block_ms");
16034
+ positiveInteger2(options.limit, "limit");
16035
+ const leaseMs = options.leaseMs ?? 3e4;
16036
+ if (options.nowMs != null && options.nowMs > MAX_EXACT_INTEGER - leaseMs) {
16037
+ throw new TypeError("now_ms plus lease_ms exceeds the exact integer range");
15762
16038
  }
15763
- async attributes(type, options = {}) {
15764
- const args = ["FLOW.ATTRIBUTES", type];
15765
- appendAttributeQueryOptions(args, options);
15766
- return adminRecordList(await this.commandArgs(args), "FLOW.ATTRIBUTES");
16039
+ }
16040
+ function validateScheduleList(options) {
16041
+ if (!mapping(options)) throw new TypeError("schedule list options must be a mapping");
16042
+ if (options.kind != null && !SCHEDULE_KINDS.has(options.kind)) {
16043
+ throw new TypeError("kind must be one_shot, delay, interval, or cron");
15767
16044
  }
15768
- async attributeValues(type, attribute, options = {}) {
15769
- const args = ["FLOW.ATTRIBUTE_VALUES", type, attribute];
15770
- appendAttributeQueryOptions(args, options);
15771
- return adminRecordList(await this.commandArgs(args), "FLOW.ATTRIBUTE_VALUES");
16045
+ if (options.state != null && !SCHEDULE_STATES.has(options.state)) {
16046
+ throw new TypeError("state is invalid");
16047
+ }
16048
+ optionalText3(options.timezone, "timezone");
16049
+ optionalText3(options.targetType, "target_type");
16050
+ nonNegativeInteger2(options.fromMs, "from_ms");
16051
+ nonNegativeInteger2(options.toMs, "to_ms");
16052
+ if (options.fromMs != null && options.toMs != null && options.fromMs > options.toMs) {
16053
+ throw new TypeError("from_ms must not exceed to_ms");
16054
+ }
16055
+ positiveInteger2(options.count, "count");
16056
+ optionalBoolean(options.rev, "rev");
16057
+ }
16058
+ function effectiveKind(options) {
16059
+ if (options.kind != null) {
16060
+ if (!SCHEDULE_KINDS.has(options.kind)) {
16061
+ throw new TypeError("kind must be one_shot, delay, interval, or cron");
16062
+ }
16063
+ return options.kind;
16064
+ }
16065
+ if (options.cron != null) return "cron";
16066
+ if (options.everyMs != null) return "interval";
16067
+ if (options.delayMs != null) return "delay";
16068
+ return "one_shot";
16069
+ }
16070
+ function validateTiming(kind, options) {
16071
+ if (options.atMs != null && options.startAtMs != null) {
16072
+ throw new TypeError("cannot set both at_ms and start_at_ms");
16073
+ }
16074
+ if (options.delayMs != null && kind !== "delay") {
16075
+ throw new TypeError("delay_ms is only supported for delay schedules");
16076
+ }
16077
+ if (options.everyMs != null && kind !== "interval") {
16078
+ throw new TypeError("every_ms is only supported for interval schedules");
16079
+ }
16080
+ if (options.cron != null && kind !== "cron") {
16081
+ throw new TypeError("cron is only supported for cron schedules");
16082
+ }
16083
+ if (kind === "delay" && (options.atMs != null || options.startAtMs != null)) {
16084
+ throw new TypeError("at_ms and start_at_ms are not supported for delay schedules");
16085
+ }
16086
+ }
16087
+ function validateTarget(value, recurring) {
16088
+ if (!mapping(value)) throw new TypeError("target must be a mapping with a non-empty type");
16089
+ const target = value;
16090
+ for (const key of Object.keys(target)) {
16091
+ if (!TARGET_FIELDS.has(key)) throw new TypeError(`target contains unknown field ${key}`);
16092
+ }
16093
+ const type = own(target, "type");
16094
+ requiredText3(type, "target type");
16095
+ if (type === INTERNAL_SCHEDULE_TYPE) {
16096
+ throw new TypeError("target type is reserved for internal use");
16097
+ }
16098
+ for (const key of TARGET_TEXT_FIELDS) optionalText3(own(target, key), `target ${key}`);
16099
+ const id = own(target, "id");
16100
+ const idPrefix = own(target, "id_prefix");
16101
+ if (id != null && idPrefix != null) {
16102
+ throw new TypeError("target cannot set both id and id_prefix");
16103
+ }
16104
+ if (recurring && id != null) {
16105
+ throw new TypeError("target id is not supported for recurring schedules; use id_prefix");
16106
+ }
16107
+ if (typeof id === "string" && id.startsWith(INTERNAL_SCHEDULE_ID_PREFIX)) {
16108
+ throw new TypeError("target id is reserved for internal use");
16109
+ }
16110
+ if (typeof idPrefix === "string" && idPrefix.startsWith(INTERNAL_SCHEDULE_ID_PREFIX)) {
16111
+ throw new TypeError("target id_prefix is reserved for internal use");
16112
+ }
16113
+ nonNegativeInteger2(own(target, "run_at_ms"), "target run_at_ms");
16114
+ const priority = own(target, "priority");
16115
+ if (priority != null && (typeof priority !== "number" || !Number.isSafeInteger(priority) || priority < 0 || priority > 2)) {
16116
+ throw new TypeError("target priority must be an integer between 0 and 2");
16117
+ }
16118
+ }
16119
+ function knownFirstRun(kind, options) {
16120
+ if (kind === "delay") {
16121
+ if (options.nowMs == null || options.delayMs == null) return void 0;
16122
+ return options.nowMs + options.delayMs;
16123
+ }
16124
+ if (kind === "cron") return options.startAtMs ?? options.atMs ?? options.nowMs;
16125
+ return options.atMs ?? options.startAtMs ?? options.nowMs;
16126
+ }
16127
+ function requiredText3(value, name) {
16128
+ if (typeof value !== "string" || value.length === 0) {
16129
+ throw new TypeError(`${name} must be a non-empty string`);
16130
+ }
16131
+ }
16132
+ function optionalText3(value, name) {
16133
+ if (value != null) requiredText3(value, name);
16134
+ }
16135
+ function nonNegativeInteger2(value, name) {
16136
+ if (value != null && (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0)) {
16137
+ throw new TypeError(`${name} must be a non-negative exact integer`);
16138
+ }
16139
+ }
16140
+ function positiveInteger2(value, name) {
16141
+ if (value != null && (typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0)) {
16142
+ throw new TypeError(`${name} must be a positive exact integer`);
16143
+ }
16144
+ }
16145
+ function optionalBoolean(value, name) {
16146
+ if (value != null && typeof value !== "boolean") {
16147
+ throw new TypeError(`${name} must be a boolean`);
16148
+ }
16149
+ }
16150
+ function mapping(value) {
16151
+ return typeof value === "object" && value !== null && !Array.isArray(value);
16152
+ }
16153
+ function own(mapping2, key) {
16154
+ return Object.prototype.hasOwnProperty.call(mapping2, key) ? mapping2[key] : void 0;
16155
+ }
16156
+
16157
+ // src/schedule-response.ts
16158
+ var SCHEDULE_INTEGER_FIELDS = [
16159
+ "end_at_ms",
16160
+ "last_catchup_at_ms",
16161
+ "last_fire_at_ms",
16162
+ "last_overlap_at_ms",
16163
+ "last_skipped_at_ms",
16164
+ "max_fires",
16165
+ "next_run_at_ms",
16166
+ "overlap_queued_due_at_ms"
16167
+ ];
16168
+ var REQUIRED_SCHEDULE_INTEGER_FIELDS = [
16169
+ "attempts",
16170
+ "coalesced_count",
16171
+ "fire_count",
16172
+ "last_coalesced_count",
16173
+ "skipped_count"
16174
+ ];
16175
+ var OPTIONAL_SCHEDULE_TEXT_FIELDS = [
16176
+ "cron",
16177
+ "end_reason",
16178
+ "flow_id",
16179
+ "last_overlap_reason",
16180
+ "last_overlap_target_id",
16181
+ "last_planning_error",
16182
+ "last_target_id",
16183
+ "timezone"
16184
+ ];
16185
+ var SCHEDULE_KINDS2 = /* @__PURE__ */ new Set(["one_shot", "delay", "interval", "cron"]);
16186
+ var SCHEDULE_STATES2 = /* @__PURE__ */ new Set([
16187
+ "active",
16188
+ "paused",
16189
+ "running",
16190
+ "completed",
16191
+ "failed",
16192
+ "cancelled"
16193
+ ]);
16194
+ var SCHEDULE_OVERLAP_POLICIES = /* @__PURE__ */ new Set([
16195
+ "allow",
16196
+ "skip",
16197
+ "queue_after_previous",
16198
+ "fail_schedule"
16199
+ ]);
16200
+ function scheduleRecordResponse(value, context) {
16201
+ const record = adminRecordResponse(value, context);
16202
+ if (typeof record.id !== "string" || record.id.length === 0) {
16203
+ throw new TypeError(`${context} response missing id`);
16204
+ }
16205
+ if (typeof record.kind !== "string" || !SCHEDULE_KINDS2.has(record.kind)) {
16206
+ throw new TypeError(`${context} response missing or invalid kind`);
16207
+ }
16208
+ if (typeof record.state !== "string" || !SCHEDULE_STATES2.has(record.state)) {
16209
+ throw new TypeError(`${context} response missing or invalid state`);
16210
+ }
16211
+ if (typeof record.target !== "object" || record.target == null || Array.isArray(record.target)) {
16212
+ throw new TypeError(`${context} response missing or invalid target`);
16213
+ }
16214
+ const target = record.target;
16215
+ if (typeof target.type !== "string" || target.type.length === 0) {
16216
+ throw new TypeError(`${context} response missing or invalid target type`);
16217
+ }
16218
+ if (!("catchup_policy" in record) || record.kind === "interval" && record.catchup_policy !== "fire_once" || record.kind !== "interval" && record.catchup_policy != null) {
16219
+ throw new TypeError(`${context} returned an invalid catchup_policy`);
16220
+ }
16221
+ if (typeof record.overlap_policy !== "string" || !SCHEDULE_OVERLAP_POLICIES.has(record.overlap_policy)) {
16222
+ throw new TypeError(`${context} response missing or invalid overlap_policy`);
16223
+ }
16224
+ safeNonNegativeInteger(record, "created_at_ms", context, true);
16225
+ const everyMs = requiredNullableNonNegativeInteger(record, "every_ms", context);
16226
+ const cron = requiredNullableResponseText(record, "cron", context);
16227
+ const timezone = requiredNullableResponseText(record, "timezone", context);
16228
+ const overlapRetryMs = requiredNullableNonNegativeInteger(
16229
+ record,
16230
+ "overlap_retry_ms",
16231
+ context
16232
+ );
16233
+ validateRecurrence(record, context, everyMs, cron, timezone, overlapRetryMs);
16234
+ let coalescedCount = 0;
16235
+ let lastCoalescedCount = 0;
16236
+ for (const field3 of REQUIRED_SCHEDULE_INTEGER_FIELDS) {
16237
+ const value2 = safeNonNegativeInteger(record, field3, context, true);
16238
+ if (field3 === "coalesced_count") coalescedCount = value2;
16239
+ if (field3 === "last_coalesced_count") lastCoalescedCount = value2;
16240
+ }
16241
+ for (const field3 of SCHEDULE_INTEGER_FIELDS) {
16242
+ if (record[field3] != null) safeNonNegativeInteger(record, field3, context);
16243
+ }
16244
+ for (const field3 of OPTIONAL_SCHEDULE_TEXT_FIELDS) {
16245
+ optionalResponseText(record, field3, context);
16246
+ }
16247
+ validateCatchupState(record, context, coalescedCount, lastCoalescedCount);
16248
+ return record;
16249
+ }
16250
+ function validateRecurrence(record, context, everyMs, cron, timezone, overlapRetryMs) {
16251
+ if (record.kind === "interval") {
16252
+ if (everyMs == null || everyMs <= 0) {
16253
+ throw new TypeError(`${context} interval every_ms must be positive`);
16254
+ }
16255
+ } else if (everyMs != null) {
16256
+ throw new TypeError(`${context} every_ms is only valid for interval schedules`);
16257
+ }
16258
+ if (record.kind === "cron") {
16259
+ if (cron == null) throw new TypeError(`${context} cron schedule is missing cron`);
16260
+ if (timezone == null) throw new TypeError(`${context} cron schedule is missing timezone`);
16261
+ } else if (cron != null) {
16262
+ throw new TypeError(`${context} cron is only valid for cron schedules`);
16263
+ } else if (timezone != null) {
16264
+ throw new TypeError(`${context} timezone is only valid for cron schedules`);
16265
+ }
16266
+ if (record.kind !== "interval" && record.kind !== "cron" && record.overlap_policy !== "allow") {
16267
+ throw new TypeError(`${context} overlap_policy is only valid for recurring schedules`);
16268
+ }
16269
+ if (overlapRetryMs != null) {
16270
+ if (overlapRetryMs <= 0) {
16271
+ throw new TypeError(`${context} overlap_retry_ms must be positive`);
16272
+ }
16273
+ if (record.overlap_policy !== "queue_after_previous") {
16274
+ throw new TypeError(`${context} overlap_retry_ms requires queue_after_previous`);
16275
+ }
16276
+ }
16277
+ }
16278
+ function validateCatchupState(record, context, coalescedCount, lastCoalescedCount) {
16279
+ const lastCatchupAt = record.last_catchup_at_ms;
16280
+ if (record.kind !== "interval") {
16281
+ if (coalescedCount !== 0) {
16282
+ throw new TypeError(`${context} non-interval coalesced_count must be zero`);
16283
+ }
16284
+ if (lastCoalescedCount !== 0) {
16285
+ throw new TypeError(`${context} non-interval last_coalesced_count must be zero`);
16286
+ }
16287
+ if (lastCatchupAt != null) {
16288
+ throw new TypeError(`${context} non-interval last_catchup_at_ms must be null`);
16289
+ }
16290
+ return;
16291
+ }
16292
+ if (lastCoalescedCount > coalescedCount) {
16293
+ throw new TypeError(`${context} last_coalesced_count exceeds coalesced_count`);
16294
+ }
16295
+ if (lastCoalescedCount > 0 && lastCatchupAt == null) {
16296
+ throw new TypeError(`${context} response missing last_catchup_at_ms after catch-up`);
16297
+ }
16298
+ if (lastCoalescedCount === 0 && lastCatchupAt != null) {
16299
+ throw new TypeError(`${context} last_catchup_at_ms requires a catch-up`);
16300
+ }
16301
+ }
16302
+ function optionalScheduleRecord(value, context) {
16303
+ return value == null ? null : scheduleRecordResponse(value, context);
16304
+ }
16305
+ function scheduleRecordList(value, context) {
16306
+ return arrayResponse(value).map((item) => scheduleRecordResponse(item, context));
16307
+ }
16308
+ function scheduleFireDueResponse(value) {
16309
+ const context = "FLOW.SCHEDULE.FIRE_DUE";
16310
+ const record = adminRecordResponse(value, context);
16311
+ const claimed = safeNonNegativeInteger(record, "claimed", context, true);
16312
+ const fired = safeNonNegativeInteger(record, "fired", context, true);
16313
+ const skipped = safeNonNegativeInteger(record, "skipped", context, true);
16314
+ const coalesced = safeNonNegativeInteger(record, "coalesced", context, true);
16315
+ if (!Array.isArray(record.errors)) {
16316
+ throw new TypeError(`${context} response missing errors`);
16317
+ }
16318
+ for (const error of record.errors) {
16319
+ if (!Array.isArray(error) || error.length !== 2 || typeof error[0] !== "string" || error[0].length === 0 || typeof error[1] !== "string" || error[1].length === 0) {
16320
+ throw new TypeError(`${context} returned an invalid error entry`);
16321
+ }
15772
16322
  }
16323
+ if (fired + skipped + record.errors.length !== claimed) {
16324
+ throw new TypeError(`${context} outcomes do not equal claimed`);
16325
+ }
16326
+ optionalResponseText(record, "claim_error", context);
16327
+ const lastTargetId = optionalResponseText(record, "last_target_id", context);
16328
+ const lastSkipReason = optionalResponseText(record, "last_skip_reason", context);
16329
+ if (fired > 0 && lastTargetId == null) {
16330
+ throw new TypeError(`${context} response missing last_target_id`);
16331
+ }
16332
+ if (fired === 0 && lastTargetId != null) {
16333
+ throw new TypeError(`${context} last_target_id requires a fired outcome`);
16334
+ }
16335
+ if (skipped > 0 && lastSkipReason == null) {
16336
+ throw new TypeError(`${context} response missing last_skip_reason`);
16337
+ }
16338
+ if (skipped === 0 && lastSkipReason != null) {
16339
+ throw new TypeError(`${context} last_skip_reason requires a skipped outcome`);
16340
+ }
16341
+ if (coalesced > 0 && fired + skipped === 0) {
16342
+ throw new TypeError(`${context} coalesced count requires a fired or skipped outcome`);
16343
+ }
16344
+ return record;
16345
+ }
16346
+ function scheduleFireResponse(value) {
16347
+ const context = "FLOW.SCHEDULE.FIRE";
16348
+ const record = adminRecordResponse(value, context);
16349
+ const schedule = scheduleRecordResponse(record.schedule, `${context} schedule`);
16350
+ const fired = safeNonNegativeInteger(record, "fired", context, true);
16351
+ const skipped = record.skipped == null ? 0 : safeNonNegativeInteger(record, "skipped", context);
16352
+ if (fired > 1 || skipped > 1 || fired + skipped !== 1) {
16353
+ throw new TypeError(`${context} outcomes must equal one`);
16354
+ }
16355
+ if (fired === 1 && (typeof record.target_id !== "string" || record.target_id.length === 0)) {
16356
+ throw new TypeError(`${context} response missing target_id`);
16357
+ }
16358
+ if (skipped === 1 && (typeof record.reason !== "string" || record.reason.length === 0)) {
16359
+ throw new TypeError(`${context} response missing reason`);
16360
+ }
16361
+ if (fired === 0 && record.target_id != null) {
16362
+ throw new TypeError(`${context} target_id requires a fired outcome`);
16363
+ }
16364
+ if (skipped === 0 && record.reason != null) {
16365
+ throw new TypeError(`${context} reason requires a skipped outcome`);
16366
+ }
16367
+ return { ...record, fired, skipped, schedule };
16368
+ }
16369
+ function optionalResponseText(record, field3, context) {
16370
+ const value = record[field3];
16371
+ if (value == null) return void 0;
16372
+ if (typeof value !== "string" || value.length === 0) {
16373
+ throw new TypeError(`${context} ${field3} must be non-empty text`);
16374
+ }
16375
+ return value;
16376
+ }
16377
+ function requiredNullableResponseText(record, field3, context) {
16378
+ if (!(field3 in record)) throw new TypeError(`${context} response missing ${field3}`);
16379
+ if (record[field3] === void 0) {
16380
+ throw new TypeError(`${context} response missing ${field3}`);
16381
+ }
16382
+ return optionalResponseText(record, field3, context) ?? null;
16383
+ }
16384
+ function requiredNullableNonNegativeInteger(record, field3, context) {
16385
+ if (!(field3 in record)) throw new TypeError(`${context} response missing ${field3}`);
16386
+ if (record[field3] === void 0) {
16387
+ throw new TypeError(`${context} response missing ${field3}`);
16388
+ }
16389
+ if (record[field3] === null) return null;
16390
+ return safeNonNegativeInteger(record, field3, context);
16391
+ }
16392
+ function safeNonNegativeInteger(record, field3, context, required = false) {
16393
+ if (!(field3 in record) || record[field3] == null) {
16394
+ if (required) throw new TypeError(`${context} response missing ${field3}`);
16395
+ return 0;
16396
+ }
16397
+ const value = record[field3];
16398
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
16399
+ throw new TypeError(`${context} ${field3} must be a safe non-negative integer`);
16400
+ }
16401
+ return value;
16402
+ }
16403
+
16404
+ // src/client-schedules.ts
16405
+ var FerricStoreScheduleClient = class extends FerricStoreClientCore {
15773
16406
  async scheduleCreate(id, options) {
16407
+ validateScheduleCreate(id, options);
15774
16408
  const args = ["FLOW.SCHEDULE.CREATE", id];
15775
16409
  append(args, "KIND", options.kind);
15776
16410
  append(args, "AT_MS", options.atMs);
@@ -15780,6 +16414,7 @@ var FerricStoreManagementClient = class extends FerricStoreClientCore {
15780
16414
  append(args, "CRON", options.cron);
15781
16415
  append(args, "TIMEZONE", options.timezone);
15782
16416
  append(args, "TARGET", options.target);
16417
+ append(args, "CATCHUP_POLICY", options.catchupPolicy);
15783
16418
  append(args, "OVERLAP_POLICY", options.overlapPolicy);
15784
16419
  append(args, "OVERLAP_RETRY_MS", options.overlapRetryMs);
15785
16420
  append(args, "MAX_FIRES", options.maxFires);
@@ -15789,34 +16424,55 @@ var FerricStoreManagementClient = class extends FerricStoreClientCore {
15789
16424
  for (const [name, value] of Object.entries(options.extraOptions ?? {})) {
15790
16425
  args.push(name.toUpperCase(), value);
15791
16426
  }
15792
- return adminRecordResponse(await this.commandArgs(args), "FLOW.SCHEDULE.CREATE");
16427
+ return scheduleRecordResponse(await this.commandArgs(args), "FLOW.SCHEDULE.CREATE");
15793
16428
  }
15794
- async scheduleGet(id, options = {}) {
15795
- const args = ["FLOW.SCHEDULE.GET", id];
15796
- append(args, "NOW", options.nowMs);
15797
- return optionalAdminRecord(await this.commandArgs(args), "FLOW.SCHEDULE.GET");
16429
+ async scheduleGet(id) {
16430
+ validateScheduleID(id);
16431
+ return optionalScheduleRecord(
16432
+ await this.commandArgs(["FLOW.SCHEDULE.GET", id]),
16433
+ "FLOW.SCHEDULE.GET"
16434
+ );
15798
16435
  }
15799
16436
  async scheduleFire(id, options = {}) {
15800
- return await this.scheduleStatus("FLOW.SCHEDULE.FIRE", id, options.nowMs);
16437
+ validateScheduleFire(id, options);
16438
+ const args = ["FLOW.SCHEDULE.FIRE", id];
16439
+ append(args, "FIRE_AT_MS", options.fireAtMs);
16440
+ append(args, "NOW", options.nowMs);
16441
+ return scheduleFireResponse(await this.commandArgs(args));
15801
16442
  }
15802
16443
  async schedulePause(id, options = {}) {
15803
- return await this.scheduleStatus("FLOW.SCHEDULE.PAUSE", id, options.nowMs);
16444
+ validateScheduleStatus(id, options.nowMs);
16445
+ return scheduleRecordResponse(
16446
+ await this.scheduleStatusResponse("FLOW.SCHEDULE.PAUSE", id, options.nowMs),
16447
+ "FLOW.SCHEDULE.PAUSE"
16448
+ );
15804
16449
  }
15805
16450
  async scheduleResume(id, options = {}) {
15806
- return await this.scheduleStatus("FLOW.SCHEDULE.RESUME", id, options.nowMs);
16451
+ validateScheduleStatus(id, options.nowMs);
16452
+ return scheduleRecordResponse(
16453
+ await this.scheduleStatusResponse("FLOW.SCHEDULE.RESUME", id, options.nowMs),
16454
+ "FLOW.SCHEDULE.RESUME"
16455
+ );
15807
16456
  }
15808
16457
  async scheduleDelete(id, options = {}) {
15809
- return await this.scheduleStatus("FLOW.SCHEDULE.DELETE", id, options.nowMs);
16458
+ validateScheduleStatus(id, options.nowMs);
16459
+ const response = await this.scheduleStatusResponse("FLOW.SCHEDULE.DELETE", id, options.nowMs);
16460
+ if (!okLike(response)) {
16461
+ throw new TypeError("FLOW.SCHEDULE.DELETE response must be OK");
16462
+ }
15810
16463
  }
15811
16464
  async scheduleFireDue(options = {}) {
16465
+ validateScheduleFireDue(options);
15812
16466
  const args = ["FLOW.SCHEDULE.FIRE_DUE"];
15813
16467
  append(args, "NOW", options.nowMs);
15814
16468
  append(args, "WORKER", options.worker);
16469
+ append(args, "LEASE_MS", options.leaseMs);
15815
16470
  append(args, "BLOCK", options.blockMs);
15816
16471
  append(args, "LIMIT", options.limit);
15817
- return adminRecordResponse(await this.commandArgs(args), "FLOW.SCHEDULE.FIRE_DUE");
16472
+ return scheduleFireDueResponse(await this.commandArgs(args));
15818
16473
  }
15819
16474
  async scheduleList(options = {}) {
16475
+ validateScheduleList(options);
15820
16476
  const args = ["FLOW.SCHEDULE.LIST"];
15821
16477
  append(args, "KIND", options.kind);
15822
16478
  append(args, "STATE", options.state);
@@ -15826,14 +16482,40 @@ var FerricStoreManagementClient = class extends FerricStoreClientCore {
15826
16482
  append(args, "TO_MS", options.toMs);
15827
16483
  append(args, "COUNT", options.count);
15828
16484
  appendBool(args, "REV", options.rev);
15829
- return adminRecordList(await this.commandArgs(args), "FLOW.SCHEDULE.LIST");
16485
+ return scheduleRecordList(await this.commandArgs(args), "FLOW.SCHEDULE.LIST");
15830
16486
  }
15831
- async scheduleStatus(command, id, now) {
16487
+ async scheduleStatusResponse(command, id, now) {
15832
16488
  const args = [command, id];
15833
16489
  append(args, "NOW", now);
15834
- const response = await this.commandArgs(args);
15835
- if (okLike(response)) return { id, status: "deleted" };
15836
- return adminRecordResponse(response, command);
16490
+ return await this.commandArgs(args);
16491
+ }
16492
+ };
16493
+
16494
+ // src/client-management.ts
16495
+ var FerricStoreManagementClient = class extends FerricStoreScheduleClient {
16496
+ async stats(type, options = {}) {
16497
+ const args = ["FLOW.STATS", type];
16498
+ append(args, "STATE", options.state);
16499
+ append(args, "COUNT", options.count);
16500
+ append(args, "PARTITION", options.partitionKey);
16501
+ appendAttributes(args, options.attributes);
16502
+ appendBool(args, "CONSISTENT_PROJECTION", options.consistentProjection);
16503
+ return adminRecordResponse(await this.commandArgs(args), "FLOW.STATS");
16504
+ }
16505
+ async countByState(type, state, options = {}) {
16506
+ const stats = await this.stats(type, { ...options, state });
16507
+ if (!("count" in stats)) throw new TypeError("FLOW.STATS response missing count");
16508
+ return integer(stats.count);
16509
+ }
16510
+ async attributes(type, options = {}) {
16511
+ const args = ["FLOW.ATTRIBUTES", type];
16512
+ appendAttributeQueryOptions(args, options);
16513
+ return adminRecordList(await this.commandArgs(args), "FLOW.ATTRIBUTES");
16514
+ }
16515
+ async attributeValues(type, attribute, options = {}) {
16516
+ const args = ["FLOW.ATTRIBUTE_VALUES", type, attribute];
16517
+ appendAttributeQueryOptions(args, options);
16518
+ return adminRecordList(await this.commandArgs(args), "FLOW.ATTRIBUTE_VALUES");
15837
16519
  }
15838
16520
  async effectReserve(id, effectKey, effectType, options) {
15839
16521
  const args = [
@@ -16171,15 +16853,15 @@ function assertFlowPolicyGeneration(value) {
16171
16853
  function flowPolicySnapshotFromResp(value) {
16172
16854
  const policy = requiredRecord(value, "FLOW policy snapshot");
16173
16855
  const maxActiveMs = optionalPositiveInteger(field(policy, "max_active_ms"), "max_active_ms");
16174
- const state = optionalText3(field(policy, "state"), "state");
16856
+ const state = optionalText4(field(policy, "state"), "state");
16175
16857
  const mode = optionalMode(field(policy, "mode"), "mode");
16176
16858
  const version = optionalVersion(field(policy, "version"));
16177
- const indexedStateMeta = optionalText3(field(policy, "indexed_state_meta"), "indexed_state_meta");
16859
+ const indexedStateMeta = optionalText4(field(policy, "indexed_state_meta"), "indexed_state_meta");
16178
16860
  const governance = optionalRecord(field(policy, "governance"), "governance");
16179
16861
  const states = optionalStates(field(policy, "states"));
16180
16862
  return {
16181
- type: requiredText3(field(policy, "type"), "type"),
16182
- generation: nonNegativeInteger2(field(policy, "generation"), "generation"),
16863
+ type: requiredText4(field(policy, "type"), "type"),
16864
+ generation: nonNegativeInteger3(field(policy, "generation"), "generation"),
16183
16865
  ...state == null ? {} : { state },
16184
16866
  ...version == null ? {} : { version },
16185
16867
  ...mode == null ? {} : { mode },
@@ -16197,21 +16879,21 @@ function retrySnapshot(value, context) {
16197
16879
  const retry2 = requiredRecord(value, `FLOW policy ${context}`);
16198
16880
  const backoff = requiredRecord(field(retry2, "backoff"), `FLOW policy ${context}.backoff`);
16199
16881
  return {
16200
- maxRetries: nonNegativeInteger2(field(retry2, "max_retries"), `${context}.max_retries`),
16882
+ maxRetries: nonNegativeInteger3(field(retry2, "max_retries"), `${context}.max_retries`),
16201
16883
  backoff: {
16202
16884
  kind: backoffKind(field(backoff, "kind"), `${context}.backoff.kind`),
16203
- baseMs: nonNegativeInteger2(field(backoff, "base_ms"), `${context}.backoff.base_ms`),
16204
- maxMs: nonNegativeInteger2(field(backoff, "max_ms"), `${context}.backoff.max_ms`),
16205
- jitterPct: nonNegativeInteger2(field(backoff, "jitter_pct"), `${context}.backoff.jitter_pct`)
16885
+ baseMs: nonNegativeInteger3(field(backoff, "base_ms"), `${context}.backoff.base_ms`),
16886
+ maxMs: nonNegativeInteger3(field(backoff, "max_ms"), `${context}.backoff.max_ms`),
16887
+ jitterPct: nonNegativeInteger3(field(backoff, "jitter_pct"), `${context}.backoff.jitter_pct`)
16206
16888
  },
16207
- exhaustedTo: requiredText3(field(retry2, "exhausted_to"), `${context}.exhausted_to`)
16889
+ exhaustedTo: requiredText4(field(retry2, "exhausted_to"), `${context}.exhausted_to`)
16208
16890
  };
16209
16891
  }
16210
16892
  function retentionSnapshot(value, context) {
16211
16893
  const retention = requiredRecord(value, `FLOW policy ${context}`);
16212
16894
  return {
16213
- ttlMs: nonNegativeInteger2(field(retention, "ttl_ms"), `${context}.ttl_ms`),
16214
- historyMaxEvents: nonNegativeInteger2(
16895
+ ttlMs: nonNegativeInteger3(field(retention, "ttl_ms"), `${context}.ttl_ms`),
16896
+ historyMaxEvents: nonNegativeInteger3(
16215
16897
  field(retention, "history_max_events"),
16216
16898
  `${context}.history_max_events`
16217
16899
  )
@@ -16247,7 +16929,7 @@ function requiredRecord(value, context) {
16247
16929
  if (value instanceof Map) {
16248
16930
  const result = {};
16249
16931
  for (const [key, item] of value.entries()) {
16250
- setOwnValue(result, requiredText3(key, `${context} key`), item);
16932
+ setOwnValue(result, requiredText4(key, `${context} key`), item);
16251
16933
  }
16252
16934
  return result;
16253
16935
  }
@@ -16266,21 +16948,21 @@ function stringArray(value, context) {
16266
16948
  if (!Object.hasOwn(value, index)) {
16267
16949
  throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
16268
16950
  }
16269
- result[index] = requiredText3(value[index], `${context}[${index}]`);
16951
+ result[index] = requiredText4(value[index], `${context}[${index}]`);
16270
16952
  }
16271
16953
  return result;
16272
16954
  }
16273
- function requiredText3(value, context) {
16955
+ function requiredText4(value, context) {
16274
16956
  if (typeof value === "string") return value;
16275
16957
  if (Buffer54.isBuffer(value) || value instanceof Uint8Array) {
16276
16958
  return Buffer54.from(value).toString("utf8");
16277
16959
  }
16278
16960
  throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
16279
16961
  }
16280
- function optionalText3(value, context) {
16281
- return value == null ? void 0 : requiredText3(value, context);
16962
+ function optionalText4(value, context) {
16963
+ return value == null ? void 0 : requiredText4(value, context);
16282
16964
  }
16283
- function nonNegativeInteger2(value, context) {
16965
+ function nonNegativeInteger3(value, context) {
16284
16966
  let parsed;
16285
16967
  try {
16286
16968
  parsed = integer(value);
@@ -16292,26 +16974,26 @@ function nonNegativeInteger2(value, context) {
16292
16974
  }
16293
16975
  function optionalPositiveInteger(value, context) {
16294
16976
  if (value == null) return void 0;
16295
- const parsed = nonNegativeInteger2(value, context);
16977
+ const parsed = nonNegativeInteger3(value, context);
16296
16978
  if (parsed === 0) throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
16297
16979
  return parsed;
16298
16980
  }
16299
16981
  function optionalVersion(value) {
16300
16982
  if (value == null) return void 0;
16301
16983
  if (typeof value === "number" || typeof value === "bigint") {
16302
- return nonNegativeInteger2(value, "version");
16984
+ return nonNegativeInteger3(value, "version");
16303
16985
  }
16304
- return requiredText3(value, "version");
16986
+ return requiredText4(value, "version");
16305
16987
  }
16306
16988
  function backoffKind(value, context) {
16307
- const kind = requiredText3(value, context).toLowerCase();
16989
+ const kind = requiredText4(value, context).toLowerCase();
16308
16990
  if (kind === "none" || kind === "fixed" || kind === "linear" || kind === "exponential") {
16309
16991
  return kind;
16310
16992
  }
16311
16993
  throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
16312
16994
  }
16313
16995
  function requiredMode(value, context) {
16314
- const mode = requiredText3(value, context).toLowerCase();
16996
+ const mode = requiredText4(value, context).toLowerCase();
16315
16997
  if (mode === "fifo" || mode === "parallel") return mode;
16316
16998
  throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
16317
16999
  }
@@ -17843,7 +18525,7 @@ var LeaseRenewalGuard = class {
17843
18525
  if (options.leaseRenewal === false) {
17844
18526
  return;
17845
18527
  }
17846
- const intervalMs = positiveInteger2(options.leaseRenewIntervalMs, Math.max(1, Math.trunc(leaseMs / 2)));
18528
+ const intervalMs = positiveInteger3(options.leaseRenewIntervalMs, Math.max(1, Math.trunc(leaseMs / 2)));
17847
18529
  this.timer = setLongInterval(() => this.renew(), intervalMs);
17848
18530
  this.timer.unref();
17849
18531
  }
@@ -17915,7 +18597,7 @@ function snapshotLeasedJob(job) {
17915
18597
  return snapshot;
17916
18598
  }
17917
18599
  function workerConcurrency(options) {
17918
- return positiveInteger2(options.concurrency ?? options.workers, 1);
18600
+ return positiveInteger3(options.concurrency ?? options.workers, 1);
17919
18601
  }
17920
18602
  function workerRefillStrategy(options) {
17921
18603
  return options.refillStrategy === "wave" ? "wave" : "continuous";
@@ -17958,18 +18640,18 @@ function workerErrorPayload(error, options, codec) {
17958
18640
  }
17959
18641
  function workerBatchSize(options, flowManyBatchLimit = DEFAULT_FLOW_MANY_BATCH_LIMIT2) {
17960
18642
  return Math.min(
17961
- positiveInteger2(options.batchSize, 10),
17962
- positiveInteger2(flowManyBatchLimit, DEFAULT_FLOW_MANY_BATCH_LIMIT2)
18643
+ positiveInteger3(options.batchSize, 10),
18644
+ positiveInteger3(flowManyBatchLimit, DEFAULT_FLOW_MANY_BATCH_LIMIT2)
17963
18645
  );
17964
18646
  }
17965
18647
  function workerClaimLimit(options, flowManyBatchLimit = DEFAULT_FLOW_MANY_BATCH_LIMIT2) {
17966
18648
  return Math.min(workerBatchSize(options, flowManyBatchLimit), workerConcurrency(options));
17967
18649
  }
17968
18650
  function workerDrainBatches(options) {
17969
- return positiveInteger2(options.claimDrainBatches, 1);
18651
+ return positiveInteger3(options.claimDrainBatches, 1);
17970
18652
  }
17971
18653
  function workerLeaseMs(options, fallback = 3e4) {
17972
- return positiveInteger2(options.leaseMs, positiveInteger2(fallback, 3e4));
18654
+ return positiveInteger3(options.leaseMs, positiveInteger3(fallback, 3e4));
17973
18655
  }
17974
18656
  function workerIdleSleepMs(options) {
17975
18657
  return nonNegativeDuration(options.idleSleepMs, 250);
@@ -17981,7 +18663,7 @@ function workerClaimBlockMs(options, useBlocking) {
17981
18663
  if (options.signal == null || !Number.isFinite(options.blockMs) || options.blockMs < 0) {
17982
18664
  return options.blockMs;
17983
18665
  }
17984
- const abortPollMs = positiveInteger2(options.abortPollMs, 1e3);
18666
+ const abortPollMs = positiveInteger3(options.abortPollMs, 1e3);
17985
18667
  return options.blockMs === 0 ? abortPollMs : Math.min(Math.trunc(options.blockMs), abortPollMs);
17986
18668
  }
17987
18669
  function workerMaxIdleSleepMs(options, idleSleepMs = workerIdleSleepMs(options)) {
@@ -17992,14 +18674,14 @@ function nextWorkerIdleSleepMs(currentIdleSleepMs, maxIdleSleepMs) {
17992
18674
  return Math.min(maxIdleSleepMs, Math.max(1, currentIdleSleepMs * 2));
17993
18675
  }
17994
18676
  async function runContinuousWorkerPool(options) {
17995
- const concurrency = positiveInteger2(options.concurrency, 1);
17996
- const maxClaimSize = positiveInteger2(options.maxClaimSize, concurrency);
18677
+ const concurrency = positiveInteger3(options.concurrency, 1);
18678
+ const maxClaimSize = positiveInteger3(options.maxClaimSize, concurrency);
17997
18679
  const initialIdleSleepMs = nonNegativeDuration(options.idleSleepMs, 250);
17998
18680
  const maxIdleSleepMs = Math.max(
17999
18681
  initialIdleSleepMs,
18000
18682
  nonNegativeDuration(options.maxIdleSleepMs, 5e3)
18001
18683
  );
18002
- const refillDelayMs = nonNegativeInteger3(options.refillDelayMs, 0);
18684
+ const refillDelayMs = nonNegativeInteger4(options.refillDelayMs, 0);
18003
18685
  const active = /* @__PURE__ */ new Set();
18004
18686
  const pending = [];
18005
18687
  let pendingIndex = 0;
@@ -18115,10 +18797,10 @@ function normalizeWorkflowWorkerConfig(options) {
18115
18797
  ...captured
18116
18798
  });
18117
18799
  }
18118
- function positiveInteger2(value, fallback) {
18800
+ function positiveInteger3(value, fallback) {
18119
18801
  return value == null || !Number.isFinite(value) ? fallback : Math.max(1, Math.trunc(value));
18120
18802
  }
18121
- function nonNegativeInteger3(value, fallback) {
18803
+ function nonNegativeInteger4(value, fallback) {
18122
18804
  return value == null || !Number.isFinite(value) ? fallback : Math.max(0, Math.trunc(value));
18123
18805
  }
18124
18806
  function nonNegativeDuration(value, fallback) {
@@ -19002,13 +19684,13 @@ var QueueWorker = class {
19002
19684
 
19003
19685
  // src/flow-client-options.ts
19004
19686
  function snapshotFlowClientOptions(options, context) {
19005
- const own = { ...options };
19006
- if (typeof own.type !== "string" || own.type.length === 0) {
19687
+ const own2 = { ...options };
19688
+ if (typeof own2.type !== "string" || own2.type.length === 0) {
19007
19689
  throw new TypeError(`${context} type must be an own non-empty string`);
19008
19690
  }
19009
- const valueConfig = own.valueConfig;
19691
+ const valueConfig = own2.valueConfig;
19010
19692
  return Object.freeze({
19011
- ...own,
19693
+ ...own2,
19012
19694
  ...valueConfig == null ? {} : { valueConfig: Object.freeze({ ...valueConfig }) }
19013
19695
  });
19014
19696
  }
@@ -19431,19 +20113,19 @@ async function applyFail(client, ctx, outcome, returnRecord) {
19431
20113
 
19432
20114
  // src/workflow-registration.ts
19433
20115
  function createWorkflowStateRegistration(name, handler, options, defaultValueMaxBytes) {
19434
- const own = { ...options };
19435
- const claimValues = own.claimValues == null ? void 0 : snapshotOwnStringArray(own.claimValues, "claimValues");
19436
- const retryPolicy = own.retryPolicy == null ? void 0 : Object.freeze({ ...own.retryPolicy });
20116
+ const own2 = { ...options };
20117
+ const claimValues = own2.claimValues == null ? void 0 : snapshotOwnStringArray(own2.claimValues, "claimValues");
20118
+ const retryPolicy = own2.retryPolicy == null ? void 0 : Object.freeze({ ...own2.retryPolicy });
19437
20119
  return Object.freeze({
19438
- claimPayload: own.claimPayload ?? true,
19439
- claimRecord: own.claimRecord ?? true,
19440
- exceptionPolicy: normalizeExceptionPolicy(own.exceptionPolicy),
20120
+ claimPayload: own2.claimPayload ?? true,
20121
+ claimRecord: own2.claimRecord ?? true,
20122
+ exceptionPolicy: normalizeExceptionPolicy(own2.exceptionPolicy),
19441
20123
  handler,
19442
- leaseMs: own.leaseMs ?? 3e4,
19443
- ...own.mode == null ? {} : { mode: normalizeStateMode(own.mode) },
20124
+ leaseMs: own2.leaseMs ?? 3e4,
20125
+ ...own2.mode == null ? {} : { mode: normalizeStateMode(own2.mode) },
19444
20126
  name,
19445
- returnRecord: own.returnRecord ?? false,
19446
- valueMaxBytes: own.valueMaxBytes ?? defaultValueMaxBytes,
20127
+ returnRecord: own2.returnRecord ?? false,
20128
+ valueMaxBytes: own2.valueMaxBytes ?? defaultValueMaxBytes,
19447
20129
  ...claimValues == null ? {} : { claimValues },
19448
20130
  ...retryPolicy == null ? {} : { retryPolicy }
19449
20131
  });
@@ -19747,8 +20429,8 @@ var WorkflowWorker = class {
19747
20429
  };
19748
20430
 
19749
20431
  // src/version.ts
19750
- var FERRICSTORE_SDK_VERSION = "0.5.2";
19751
- var FERRICSTORE_MINIMUM_SERVER_VERSION = "0.11.0";
20432
+ var FERRICSTORE_SDK_VERSION = "0.11.5";
20433
+ var FERRICSTORE_MINIMUM_SERVER_VERSION = "0.11.4";
19752
20434
  var FERRICSTORE_NATIVE_PROTOCOL_VERSION = 1;
19753
20435
  export {
19754
20436
  BitmapStore,