@ferricstore/ferricstore 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +1 -1
  2. package/dist/index.d.ts +23 -1
  3. package/dist/index.js +78 -2
  4. package/dist/index.js.map +1 -1
  5. package/docs/api/assets/hierarchy.js +1 -1
  6. package/docs/api/assets/navigation.js +1 -1
  7. package/docs/api/assets/search.js +1 -1
  8. package/docs/api/classes/FerricStoreClient.html +2 -2
  9. package/docs/api/classes/FerricStoreError.html +1 -1
  10. package/docs/api/classes/FlowAlreadyExistsError.html +1 -1
  11. package/docs/api/classes/FlowNotFoundError.html +1 -1
  12. package/docs/api/classes/FlowWrongStateError.html +1 -1
  13. package/docs/api/classes/InvalidCommandError.html +1 -1
  14. package/docs/api/classes/LockHeldError.html +1 -1
  15. package/docs/api/classes/LockNotOwnedError.html +1 -1
  16. package/docs/api/classes/OverloadedError.html +1 -1
  17. package/docs/api/classes/Queue.html +2 -2
  18. package/docs/api/classes/QueueClient.html +2 -2
  19. package/docs/api/classes/QueueWorker.html +2 -2
  20. package/docs/api/classes/StaleLeaseError.html +1 -1
  21. package/docs/api/classes/Workflow.html +2 -2
  22. package/docs/api/classes/WorkflowClient.html +2 -2
  23. package/docs/api/classes/WorkflowContext.html +4 -2
  24. package/docs/api/classes/WorkflowFlowCommands.html +2 -2
  25. package/docs/api/classes/WorkflowWorker.html +2 -2
  26. package/docs/api/functions/complete.html +1 -1
  27. package/docs/api/functions/fail.html +1 -1
  28. package/docs/api/functions/retry.html +1 -1
  29. package/docs/api/functions/transition.html +1 -1
  30. package/docs/api/hierarchy.html +1 -1
  31. package/docs/api/index.html +1 -1
  32. package/docs/api/interfaces/AutoBatchOptions.html +2 -2
  33. package/docs/api/interfaces/CancelOptions.html +3 -2
  34. package/docs/api/interfaces/ClaimDueOptions.html +2 -2
  35. package/docs/api/interfaces/ClaimedItem.html +2 -2
  36. package/docs/api/interfaces/CompleteOptions.html +3 -2
  37. package/docs/api/interfaces/CompleteOutcome.html +3 -2
  38. package/docs/api/interfaces/CreateItem.html +3 -2
  39. package/docs/api/interfaces/CreateManyOptions.html +3 -2
  40. package/docs/api/interfaces/CreateOptions.html +3 -2
  41. package/docs/api/interfaces/FailOptions.html +3 -2
  42. package/docs/api/interfaces/FailOutcome.html +3 -2
  43. package/docs/api/interfaces/FencedItem.html +2 -2
  44. package/docs/api/interfaces/FerricStoreClientOptions.html +2 -2
  45. package/docs/api/interfaces/FetchOrComputeResult.html +2 -2
  46. package/docs/api/interfaces/FlowRecord.html +4 -2
  47. package/docs/api/interfaces/KeyInfo.html +2 -2
  48. package/docs/api/interfaces/MutateOptions.html +3 -2
  49. package/docs/api/interfaces/NamedValueMutation.html +3 -2
  50. package/docs/api/interfaces/QueueOptions.html +2 -2
  51. package/docs/api/interfaces/QueueWorkerResult.html +2 -2
  52. package/docs/api/interfaces/RateLimitResult.html +2 -2
  53. package/docs/api/interfaces/ReadOptions.html +2 -2
  54. package/docs/api/interfaces/ReclaimOptions.html +2 -2
  55. package/docs/api/interfaces/RetryOptions.html +3 -2
  56. package/docs/api/interfaces/RetryOutcome.html +3 -2
  57. package/docs/api/interfaces/StateOptions.html +2 -2
  58. package/docs/api/interfaces/StateRegistration.html +2 -2
  59. package/docs/api/interfaces/TDigestCreateOptions.html +1 -1
  60. package/docs/api/interfaces/TDigestMergeOptions.html +1 -1
  61. package/docs/api/interfaces/TransitionOptions.html +3 -2
  62. package/docs/api/interfaces/TransitionOutcome.html +3 -2
  63. package/docs/api/interfaces/WorkflowOptions.html +2 -2
  64. package/docs/api/interfaces/WorkflowWorkerResult.html +2 -2
  65. package/docs/api/modules.html +1 -1
  66. package/docs/api/types/Outcome.html +1 -1
  67. package/docs/api/types/QueueBatchHandler.html +1 -1
  68. package/docs/api/types/QueueHandler.html +1 -1
  69. package/docs/api/types/StateMeta.html +1 -0
  70. package/docs/api/types/StateMetaValue.html +1 -0
  71. package/docs/api/types/WorkflowHandler.html +1 -1
  72. package/package.json +1 -1
package/README.md CHANGED
@@ -22,7 +22,7 @@ Requires Node.js 24 or newer. The SDK is ESM-only and tested with Node 24 and 26
22
22
  docker run -p 6388:6388 \
23
23
  -e FERRICSTORE_PROTECTED_MODE=false \
24
24
  -v ferricstore_data:/data \
25
- ghcr.io/ferricstore/ferricstore:0.5.2
25
+ ghcr.io/ferricstore/ferricstore:0.6.0
26
26
  ```
27
27
 
28
28
  ## Durable Queue
package/dist/index.d.ts CHANGED
@@ -484,12 +484,15 @@ interface ChildSpec {
484
484
  values?: Record<string, unknown>;
485
485
  valueRefs?: Record<string, string>;
486
486
  }
487
+ type StateMetaValue = string | number | boolean | Buffer;
488
+ type StateMeta = Record<string, StateMetaValue>;
487
489
  interface CreateItem {
488
490
  id: string;
489
491
  payload?: unknown;
490
492
  partitionKey?: string;
491
493
  values?: Record<string, unknown>;
492
494
  valueRefs?: Record<string, string>;
495
+ stateMeta?: StateMeta;
493
496
  }
494
497
  declare const CLAIMED_ITEM_WIRE: unique symbol;
495
498
  interface ClaimedItemWire {
@@ -557,6 +560,8 @@ interface FlowRecord<TPayload = unknown> {
557
560
  valueOmitted?: Record<string, unknown>;
558
561
  valueMissing?: Record<string, unknown>;
559
562
  attributes?: Record<string, unknown>;
563
+ stateMeta?: Record<string, unknown>;
564
+ indexedStateMeta?: string;
560
565
  raw?: unknown;
561
566
  }
562
567
 
@@ -586,6 +591,7 @@ interface CreateOptions {
586
591
  retentionTtlMs?: number;
587
592
  values?: Record<string, unknown>;
588
593
  valueRefs?: Record<string, string>;
594
+ stateMeta?: StateMeta;
589
595
  returnRecord?: boolean;
590
596
  }
591
597
  interface CreateManyOptions extends Omit<CreateOptions, "payload" | "partitionKey" | "returnRecord"> {
@@ -622,6 +628,7 @@ interface MutateOptions {
622
628
  valueRefs?: Record<string, string>;
623
629
  dropValues?: string[];
624
630
  overrideValues?: string[];
631
+ stateMeta?: StateMeta;
625
632
  nowMs?: number;
626
633
  returnRecord?: boolean;
627
634
  }
@@ -654,6 +661,7 @@ interface CancelOptions {
654
661
  reason?: unknown;
655
662
  ttlMs?: number;
656
663
  nowMs?: number;
664
+ stateMeta?: StateMeta;
657
665
  returnRecord?: boolean;
658
666
  }
659
667
  interface ReadOptions {
@@ -836,6 +844,7 @@ declare class FerricStoreClient {
836
844
  valueRefs?: Record<string, string>;
837
845
  dropValues?: string[];
838
846
  overrideValues?: string[];
847
+ stateMeta?: StateMeta;
839
848
  ttlMs?: number;
840
849
  nowMs?: number;
841
850
  independent?: boolean;
@@ -851,6 +860,7 @@ declare class FerricStoreClient {
851
860
  valueRefs?: Record<string, string>;
852
861
  dropValues?: string[];
853
862
  overrideValues?: string[];
863
+ stateMeta?: StateMeta;
854
864
  runAtMs?: number;
855
865
  nowMs?: number;
856
866
  priority?: number;
@@ -864,6 +874,7 @@ declare class FerricStoreClient {
864
874
  valueRefs?: Record<string, string>;
865
875
  dropValues?: string[];
866
876
  overrideValues?: string[];
877
+ stateMeta?: StateMeta;
867
878
  runAtMs?: number;
868
879
  nowMs?: number;
869
880
  independent?: boolean;
@@ -876,6 +887,7 @@ declare class FerricStoreClient {
876
887
  valueRefs?: Record<string, string>;
877
888
  dropValues?: string[];
878
889
  overrideValues?: string[];
890
+ stateMeta?: StateMeta;
879
891
  ttlMs?: number;
880
892
  nowMs?: number;
881
893
  independent?: boolean;
@@ -883,6 +895,7 @@ declare class FerricStoreClient {
883
895
  cancel(id: string, options: CancelOptions): Promise<FlowRecord | Buffer | unknown>;
884
896
  cancelMany(partitionKey: string | undefined, items: FencedItem[], options?: {
885
897
  reason?: unknown;
898
+ stateMeta?: StateMeta;
886
899
  ttlMs?: number;
887
900
  nowMs?: number;
888
901
  independent?: boolean;
@@ -937,6 +950,7 @@ declare class FerricStoreClient {
937
950
  state?: string;
938
951
  retry?: RetryPolicy;
939
952
  retentionTtlMs?: number;
953
+ indexedStateMeta?: string;
940
954
  }): Promise<unknown>;
941
955
  policyGet(type: string, options?: {
942
956
  state?: string;
@@ -999,6 +1013,7 @@ interface NamedValueMutation {
999
1013
  valueRefs?: Record<string, string>;
1000
1014
  dropValues?: string[];
1001
1015
  overrideValues?: string[];
1016
+ stateMeta?: StateMeta;
1002
1017
  }
1003
1018
  interface TransitionOutcome extends NamedValueMutation {
1004
1019
  readonly kind: "transition";
@@ -1065,6 +1080,7 @@ declare class Queue {
1065
1080
  retentionTtlMs?: number;
1066
1081
  values?: Record<string, unknown>;
1067
1082
  valueRefs?: Record<string, string>;
1083
+ stateMeta?: StateMeta;
1068
1084
  returnRecord?: boolean;
1069
1085
  }): Promise<FlowRecord | Buffer | unknown>;
1070
1086
  enqueueMany(items: CreateItem[], options?: {
@@ -1077,6 +1093,7 @@ declare class Queue {
1077
1093
  retentionTtlMs?: number;
1078
1094
  values?: Record<string, unknown>;
1079
1095
  valueRefs?: Record<string, string>;
1096
+ stateMeta?: StateMeta;
1080
1097
  }): Promise<unknown[] | unknown>;
1081
1098
  worker(options?: WorkerConfig): QueueWorker;
1082
1099
  }
@@ -1167,6 +1184,7 @@ declare class Workflow {
1167
1184
  retentionTtlMs?: number;
1168
1185
  values?: Record<string, unknown>;
1169
1186
  valueRefs?: Record<string, string>;
1187
+ stateMeta?: StateMeta;
1170
1188
  returnRecord?: boolean;
1171
1189
  }): Promise<FlowRecord | Buffer | unknown>;
1172
1190
  startMany(items: {
@@ -1175,6 +1193,7 @@ declare class Workflow {
1175
1193
  partitionKey?: string;
1176
1194
  values?: Record<string, unknown>;
1177
1195
  valueRefs?: Record<string, string>;
1196
+ stateMeta?: StateMeta;
1178
1197
  }[], options?: {
1179
1198
  state?: string;
1180
1199
  partitionKey?: string;
@@ -1186,6 +1205,7 @@ declare class Workflow {
1186
1205
  retentionTtlMs?: number;
1187
1206
  values?: Record<string, unknown>;
1188
1207
  valueRefs?: Record<string, string>;
1208
+ stateMeta?: StateMeta;
1189
1209
  }): Promise<unknown[] | unknown>;
1190
1210
  signal(id: string, options: Parameters<FerricStoreClient["signal"]>[1]): Promise<unknown>;
1191
1211
  get(id: string, options?: Parameters<FerricStoreClient["get"]>[1]): Promise<FlowRecord | undefined>;
@@ -1211,6 +1231,8 @@ declare class WorkflowContext {
1211
1231
  get partitionKey(): string | undefined;
1212
1232
  get payload(): unknown;
1213
1233
  get values(): Record<string, unknown>;
1234
+ get stateMeta(): Record<string, unknown>;
1235
+ get indexedStateMeta(): string | undefined;
1214
1236
  get valueRefs(): Record<string, unknown>;
1215
1237
  get leaseToken(): Buffer;
1216
1238
  get fencingToken(): number;
@@ -1267,4 +1289,4 @@ declare class WorkflowWorker {
1267
1289
  private applyHandlerError;
1268
1290
  }
1269
1291
 
1270
- export { type AutoBatchOptions, type BackoffKind, type BackpressurePolicy, BitmapStore, BloomFilterStore, type CancelOptions, type ChildSpec, type ClaimDueOptions, type ClaimedItem, type Codec, type Command, type CommandArgument, type CommandExecutor, type CompleteOptions, type CompleteOutcome, type CountMinMergeOptions, CountMinSketchStore, type CreateItem, type CreateManyOptions, type CreateOptions, CuckooFilterStore, type ExceptionPolicy, type ExecutePipelineOptions, type FailOptions, type FailOutcome, type FencedItem, FerricStoreClient, type FerricStoreClientOptions, FerricStoreError, type FetchOrComputeResult, FlowAlreadyExistsError, FlowNotFoundError, type FlowRecord, FlowWrongStateError, type GeoAddOptions, type GeoMember, GeoStore, type GetExOptions, HashStore, HyperLogLogStore, InvalidCommandError, JsonCodec, type JsonSetOptions, JsonStore, type KeyInfo, KeyValueStore, ListStore, LockHeldError, LockNotOwnedError, type MutateOptions, type NamedValueMutation, NativeAdapter, type NativeAdapterOptions, type Outcome, OverloadedError, Queue, type QueueBatchHandler, QueueClient, type QueueHandler, type QueueOptions, QueueWorker, type QueueWorkerResult, type RangeLimit, type RateLimitResult, RawCodec, type ReadOptions, type ReclaimOptions, type RetryOptions, type RetryOutcome, type RetryPolicy, type ScanOptions, type SetOptions, SetStore, SortedSetStore, StaleLeaseError, type StateOptions, type StateRegistration, type StoreCommandClient, StreamStore, type TDigestCreateOptions, type TDigestMergeOptions, TDigestStore, type TopKReserveOptions, TopKStore, type TransitionOptions, type TransitionOutcome, type ValueConfig, type WorkerConfig, type WorkerProfile, Workflow, WorkflowClient, WorkflowContext, WorkflowFlowCommands, type WorkflowHandler, type WorkflowOptions, WorkflowWorker, type WorkflowWorkerResult, type XReadStream, type ZAddMember, type ZAddOptions, classifyServerError, complete, fail, mapException, retry, transition };
1292
+ export { type AutoBatchOptions, type BackoffKind, type BackpressurePolicy, BitmapStore, BloomFilterStore, type CancelOptions, type ChildSpec, type ClaimDueOptions, type ClaimedItem, type Codec, type Command, type CommandArgument, type CommandExecutor, type CompleteOptions, type CompleteOutcome, type CountMinMergeOptions, CountMinSketchStore, type CreateItem, type CreateManyOptions, type CreateOptions, CuckooFilterStore, type ExceptionPolicy, type ExecutePipelineOptions, type FailOptions, type FailOutcome, type FencedItem, FerricStoreClient, type FerricStoreClientOptions, FerricStoreError, type FetchOrComputeResult, FlowAlreadyExistsError, FlowNotFoundError, type FlowRecord, FlowWrongStateError, type GeoAddOptions, type GeoMember, GeoStore, type GetExOptions, HashStore, HyperLogLogStore, InvalidCommandError, JsonCodec, type JsonSetOptions, JsonStore, type KeyInfo, KeyValueStore, ListStore, LockHeldError, LockNotOwnedError, type MutateOptions, type NamedValueMutation, NativeAdapter, type NativeAdapterOptions, type Outcome, OverloadedError, Queue, type QueueBatchHandler, QueueClient, type QueueHandler, type QueueOptions, QueueWorker, type QueueWorkerResult, type RangeLimit, type RateLimitResult, RawCodec, type ReadOptions, type ReclaimOptions, type RetryOptions, type RetryOutcome, type RetryPolicy, type ScanOptions, type SetOptions, SetStore, SortedSetStore, StaleLeaseError, type StateMeta, type StateMetaValue, type StateOptions, type StateRegistration, type StoreCommandClient, StreamStore, type TDigestCreateOptions, type TDigestMergeOptions, TDigestStore, type TopKReserveOptions, TopKStore, type TransitionOptions, type TransitionOutcome, type ValueConfig, type WorkerConfig, type WorkerProfile, Workflow, WorkflowClient, WorkflowContext, WorkflowFlowCommands, type WorkflowHandler, type WorkflowOptions, WorkflowWorker, type WorkflowWorkerResult, type XReadStream, type ZAddMember, type ZAddOptions, classifyServerError, complete, fail, mapException, retry, transition };
package/dist/index.js CHANGED
@@ -284,6 +284,9 @@ function buildProtocolCommand(args) {
284
284
  if (command === "DEL") {
285
285
  return { opcode: OPCODES.del, payload: { keys: commandArgs } };
286
286
  }
287
+ if (command.startsWith("FLOW.") && hasFlowCommandOnlyOption(commandArgs)) {
288
+ return commandExec(args);
289
+ }
287
290
  if (command === "FLOW.CREATE") {
288
291
  return flowCreatePayload(commandArgs) ?? commandExec(args);
289
292
  }
@@ -643,6 +646,15 @@ function writeOptionalBinary(out, offset, value) {
643
646
  }
644
647
  return writeBinary(out, offset, value);
645
648
  }
649
+ function hasFlowCommandOnlyOption(args) {
650
+ return args.some((arg) => {
651
+ if (typeof arg !== "string" && !Buffer2.isBuffer(arg)) {
652
+ return false;
653
+ }
654
+ const token = asText(arg).toUpperCase();
655
+ return token === "STATE_META" || token === "INDEXED_STATE_META";
656
+ });
657
+ }
646
658
  function flowCreatePayload(args) {
647
659
  if (args.length < 7) return void 0;
648
660
  const id = args[0];
@@ -2858,6 +2870,8 @@ function flowRecordFromResp(value, codec) {
2858
2870
  valueOmitted: toStringKeyMap(field(value, "value_omitted")),
2859
2871
  valueMissing: toStringKeyMap(field(value, "value_missing")),
2860
2872
  attributes: plainObjectField(value, "attributes"),
2873
+ stateMeta: toStringKeyMap(field(value, "state_meta")),
2874
+ indexedStateMeta: optionalString(field(value, "indexed_state_meta")),
2861
2875
  raw: value
2862
2876
  };
2863
2877
  }
@@ -3242,6 +3256,7 @@ var FerricStoreClient = class _FerricStoreClient {
3242
3256
  append(args, "PRIORITY", options.priority);
3243
3257
  appendBool(args, "IDEMPOTENT", options.idempotent);
3244
3258
  append(args, "RETENTION_TTL_MS", options.retentionTtlMs);
3259
+ appendStateMeta(args, options.stateMeta);
3245
3260
  appendNamedValues(args, this.codec, options);
3246
3261
  const response = await this.executeProducerWrite(args);
3247
3262
  if (options.returnRecord === true) {
@@ -3301,6 +3316,7 @@ var FerricStoreClient = class _FerricStoreClient {
3301
3316
  }
3302
3317
  }
3303
3318
  const currentNowMs = options.nowMs ?? nowMs();
3319
+ const stateMeta = sharedCreateManyStateMeta(items, options.stateMeta);
3304
3320
  const mixed = partitionKey == null && items.some((item) => item.partitionKey != null);
3305
3321
  const auto = partitionKey == null && !mixed;
3306
3322
  const wirePartition = mixed ? "MIXED" : auto ? "AUTO" : partitionKey;
@@ -3319,6 +3335,7 @@ var FerricStoreClient = class _FerricStoreClient {
3319
3335
  appendBool(args, "IDEMPOTENT", options.idempotent);
3320
3336
  appendBool(args, "INDEPENDENT", options.independent);
3321
3337
  append(args, "RETENTION_TTL_MS", options.retentionTtlMs);
3338
+ appendStateMeta(args, stateMeta);
3322
3339
  const extendedItems = items.some((item) => item.values != null || item.valueRefs != null) || mixed && items.some((item) => item.partitionKey == null);
3323
3340
  if (extendedItems) {
3324
3341
  args.push("ITEMS_EXT", items.length);
@@ -3499,6 +3516,7 @@ var FerricStoreClient = class _FerricStoreClient {
3499
3516
  appendEncoded(args, "PAYLOAD", this.codec, options.payload);
3500
3517
  append(args, "RUN_AT", options.runAtMs ?? currentNowMs);
3501
3518
  append(args, "PRIORITY", options.priority);
3519
+ appendStateMeta(args, options.stateMeta);
3502
3520
  appendNamedValues(args, this.codec, options);
3503
3521
  const response = await this.command(...args);
3504
3522
  if (options.returnRecord === true) {
@@ -3520,6 +3538,7 @@ var FerricStoreClient = class _FerricStoreClient {
3520
3538
  appendEncoded(args, "RESULT", this.codec, options.result);
3521
3539
  appendEncoded(args, "PAYLOAD", this.codec, options.payload);
3522
3540
  append(args, "TTL", options.ttlMs);
3541
+ appendStateMeta(args, options.stateMeta);
3523
3542
  appendNamedValues(args, this.codec, options);
3524
3543
  const response = await this.command(...args);
3525
3544
  if (options.returnRecord === true) {
@@ -3540,6 +3559,7 @@ var FerricStoreClient = class _FerricStoreClient {
3540
3559
  if (options.returnOkOnSuccess === true) {
3541
3560
  args.push("RETURN", "OK_ON_SUCCESS");
3542
3561
  }
3562
+ appendStateMeta(args, options.stateMeta);
3543
3563
  appendNamedValues(args, this.codec, options);
3544
3564
  appendClaimedItems(args, partitionKey, items, "FLOW.COMPLETE_MANY");
3545
3565
  return this.recordsOrResponse(await this.command(...args));
@@ -3566,6 +3586,7 @@ var FerricStoreClient = class _FerricStoreClient {
3566
3586
  append(args, "PRIORITY", options.priority);
3567
3587
  append(args, "NOW", options.nowMs ?? nowMs());
3568
3588
  appendBool(args, "INDEPENDENT", options.independent);
3589
+ appendStateMeta(args, options.stateMeta);
3569
3590
  appendNamedValues(args, this.codec, options);
3570
3591
  appendFencedItems(args, partitionKey, options.items, "FLOW.TRANSITION_MANY", true);
3571
3592
  return this.recordsOrResponse(await this.command(...args));
@@ -3584,6 +3605,7 @@ var FerricStoreClient = class _FerricStoreClient {
3584
3605
  appendEncoded(args, "ERROR", this.codec, options.error);
3585
3606
  appendEncoded(args, "PAYLOAD", this.codec, options.payload);
3586
3607
  append(args, "RUN_AT", options.runAtMs);
3608
+ appendStateMeta(args, options.stateMeta);
3587
3609
  appendNamedValues(args, this.codec, options);
3588
3610
  const response = await this.command(...args);
3589
3611
  if (options.returnRecord === true) {
@@ -3601,6 +3623,7 @@ var FerricStoreClient = class _FerricStoreClient {
3601
3623
  append(args, "RUN_AT", options.runAtMs);
3602
3624
  append(args, "NOW", options.nowMs ?? nowMs());
3603
3625
  appendBool(args, "INDEPENDENT", options.independent);
3626
+ appendStateMeta(args, options.stateMeta);
3604
3627
  appendNamedValues(args, this.codec, options);
3605
3628
  appendClaimedItems(args, partitionKey, items, "FLOW.RETRY_MANY");
3606
3629
  return this.recordsOrResponse(await this.command(...args));
@@ -3619,6 +3642,7 @@ var FerricStoreClient = class _FerricStoreClient {
3619
3642
  appendEncoded(args, "ERROR", this.codec, options.error);
3620
3643
  appendEncoded(args, "PAYLOAD", this.codec, options.payload);
3621
3644
  append(args, "TTL", options.ttlMs);
3645
+ appendStateMeta(args, options.stateMeta);
3622
3646
  appendNamedValues(args, this.codec, options);
3623
3647
  const response = await this.command(...args);
3624
3648
  if (options.returnRecord === true) {
@@ -3636,6 +3660,7 @@ var FerricStoreClient = class _FerricStoreClient {
3636
3660
  append(args, "TTL", options.ttlMs);
3637
3661
  append(args, "NOW", options.nowMs ?? nowMs());
3638
3662
  appendBool(args, "INDEPENDENT", options.independent);
3663
+ appendStateMeta(args, options.stateMeta);
3639
3664
  appendNamedValues(args, this.codec, options);
3640
3665
  appendClaimedItems(args, partitionKey, items, "FLOW.FAIL_MANY");
3641
3666
  return this.recordsOrResponse(await this.command(...args));
@@ -3646,6 +3671,7 @@ var FerricStoreClient = class _FerricStoreClient {
3646
3671
  append(args, "PARTITION", options.partitionKey);
3647
3672
  appendEncoded(args, "REASON", this.codec, options.reason);
3648
3673
  append(args, "TTL", options.ttlMs);
3674
+ appendStateMeta(args, options.stateMeta);
3649
3675
  const response = await this.command(...args);
3650
3676
  if (options.returnRecord === true) {
3651
3677
  return await this.recordOrGet(response, id, options.partitionKey);
@@ -3661,7 +3687,8 @@ var FerricStoreClient = class _FerricStoreClient {
3661
3687
  append(args, "TTL", options.ttlMs);
3662
3688
  append(args, "NOW", options.nowMs ?? nowMs());
3663
3689
  appendBool(args, "INDEPENDENT", options.independent);
3664
- appendFencedItems(args, partitionKey, items, "FLOW.CANCEL_MANY", true);
3690
+ appendStateMeta(args, options.stateMeta);
3691
+ appendFencedItems(args, partitionKey, items, "FLOW.CANCEL_MANY", false);
3665
3692
  return this.recordsOrResponse(await this.command(...args));
3666
3693
  }
3667
3694
  async rewind(id, options = {}) {
@@ -3762,6 +3789,7 @@ var FerricStoreClient = class _FerricStoreClient {
3762
3789
  }
3763
3790
  async installPolicy(type, options = {}) {
3764
3791
  const args = ["FLOW.POLICY.SET", type];
3792
+ append(args, "INDEXED_STATE_META", options.indexedStateMeta);
3765
3793
  append(args, "STATE", options.state);
3766
3794
  if (options.retry != null) {
3767
3795
  appendRetryPolicy(args, options.retry);
@@ -4092,6 +4120,41 @@ function appendReadOptions(args, options) {
4092
4120
  appendBool(args, "INCLUDE_COLD", options.includeCold);
4093
4121
  appendBool(args, "CONSISTENT_PROJECTION", options.consistentProjection);
4094
4122
  }
4123
+ function appendStateMeta(args, stateMeta) {
4124
+ for (const [name, value] of Object.entries(stateMeta ?? {})) {
4125
+ args.push("STATE_META", name, value);
4126
+ }
4127
+ }
4128
+ function sharedCreateManyStateMeta(items, stateMeta) {
4129
+ const itemMetas = items.map((item) => item.stateMeta).filter((meta) => meta != null);
4130
+ if (itemMetas.length === 0) {
4131
+ return stateMeta;
4132
+ }
4133
+ const first = itemMetas[0];
4134
+ if (first == null) {
4135
+ return stateMeta;
4136
+ }
4137
+ if (itemMetas.some((meta) => !stateMetaEquals(meta, first))) {
4138
+ throw new Error("createMany supports shared stateMeta only; use stateMeta or separate create calls for per-item stateMeta");
4139
+ }
4140
+ if (stateMeta != null && !stateMetaEquals(stateMeta, first)) {
4141
+ throw new Error("createMany item stateMeta must match shared stateMeta when both are provided");
4142
+ }
4143
+ return first;
4144
+ }
4145
+ function stateMetaEquals(left, right) {
4146
+ const leftEntries = Object.entries(left);
4147
+ if (leftEntries.length !== Object.keys(right).length) {
4148
+ return false;
4149
+ }
4150
+ return leftEntries.every(([key, value]) => stateMetaValueEquals(value, right[key]));
4151
+ }
4152
+ function stateMetaValueEquals(left, right) {
4153
+ if (Buffer.isBuffer(left) || Buffer.isBuffer(right)) {
4154
+ return Buffer.isBuffer(left) && Buffer.isBuffer(right) && left.equals(right);
4155
+ }
4156
+ return Object.is(left, right);
4157
+ }
4095
4158
  function appendNamedCounts(args, codec, values, valueRefs) {
4096
4159
  args.push(Object.keys(values).length);
4097
4160
  for (const [name, value] of Object.entries(values)) {
@@ -4516,6 +4579,7 @@ var QueueWorker = class {
4516
4579
  partitionKey: job.partitionKey,
4517
4580
  payload: outcome.payload,
4518
4581
  runAtMs: outcome.runAtMs,
4582
+ stateMeta: outcome.stateMeta,
4519
4583
  valueRefs: outcome.valueRefs,
4520
4584
  values: outcome.values
4521
4585
  });
@@ -4528,6 +4592,7 @@ var QueueWorker = class {
4528
4592
  leaseToken: job.leaseToken,
4529
4593
  partitionKey: job.partitionKey,
4530
4594
  payload: outcome.payload,
4595
+ stateMeta: outcome.stateMeta,
4531
4596
  ttlMs: outcome.ttlMs,
4532
4597
  valueRefs: outcome.valueRefs,
4533
4598
  values: outcome.values
@@ -4540,6 +4605,7 @@ var QueueWorker = class {
4540
4605
  partitionKey: job.partitionKey,
4541
4606
  payload: outcome.payload,
4542
4607
  result: outcome.result,
4608
+ stateMeta: outcome.stateMeta,
4543
4609
  ttlMs: outcome.ttlMs,
4544
4610
  valueRefs: outcome.valueRefs,
4545
4611
  values: outcome.values
@@ -4559,7 +4625,7 @@ var QueueWorker = class {
4559
4625
  }
4560
4626
  };
4561
4627
  function isBatchableComplete(outcome) {
4562
- return outcome.kind === "complete" && outcome.payload === void 0 && outcome.result === void 0 && outcome.ttlMs === void 0 && outcome.values === void 0 && outcome.valueRefs === void 0 && outcome.dropValues === void 0 && outcome.overrideValues === void 0;
4628
+ return outcome.kind === "complete" && outcome.payload === void 0 && outcome.result === void 0 && outcome.ttlMs === void 0 && outcome.values === void 0 && outcome.valueRefs === void 0 && outcome.dropValues === void 0 && outcome.overrideValues === void 0 && outcome.stateMeta === void 0;
4563
4629
  }
4564
4630
  function normalizeWorkerConfig(options) {
4565
4631
  if (options.profile !== "throughput") {
@@ -4686,6 +4752,12 @@ var WorkflowContext = class {
4686
4752
  get values() {
4687
4753
  return "values" in this.job && this.job.values != null ? this.job.values : {};
4688
4754
  }
4755
+ get stateMeta() {
4756
+ return "stateMeta" in this.job && this.job.stateMeta != null ? this.job.stateMeta : {};
4757
+ }
4758
+ get indexedStateMeta() {
4759
+ return "indexedStateMeta" in this.job ? this.job.indexedStateMeta : void 0;
4760
+ }
4689
4761
  get valueRefs() {
4690
4762
  return "valueRefs" in this.job && this.job.valueRefs != null ? this.job.valueRefs : {};
4691
4763
  }
@@ -4945,6 +5017,7 @@ async function applyTransition(client, ctx, outcome, returnRecord) {
4945
5017
  priority: outcome.priority,
4946
5018
  returnRecord,
4947
5019
  runAtMs: outcome.runAtMs,
5020
+ stateMeta: outcome.stateMeta,
4948
5021
  toState: outcome.toState,
4949
5022
  valueRefs: outcome.valueRefs,
4950
5023
  values: outcome.values
@@ -4960,6 +5033,7 @@ async function applyComplete(client, ctx, outcome, returnRecord) {
4960
5033
  payload: outcome.payload,
4961
5034
  result: outcome.result,
4962
5035
  returnRecord,
5036
+ stateMeta: outcome.stateMeta,
4963
5037
  ttlMs: outcome.ttlMs,
4964
5038
  valueRefs: outcome.valueRefs,
4965
5039
  values: outcome.values
@@ -4976,6 +5050,7 @@ async function applyRetry(client, ctx, outcome, returnRecord) {
4976
5050
  payload: outcome.payload,
4977
5051
  returnRecord,
4978
5052
  runAtMs: outcome.runAtMs,
5053
+ stateMeta: outcome.stateMeta,
4979
5054
  valueRefs: outcome.valueRefs,
4980
5055
  values: outcome.values
4981
5056
  });
@@ -4990,6 +5065,7 @@ async function applyFail(client, ctx, outcome, returnRecord) {
4990
5065
  partitionKey: ctx.partitionKey,
4991
5066
  payload: outcome.payload,
4992
5067
  returnRecord,
5068
+ stateMeta: outcome.stateMeta,
4993
5069
  ttlMs: outcome.ttlMs,
4994
5070
  valueRefs: outcome.valueRefs,
4995
5071
  values: outcome.values