@jagreehal/workflow 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/core.d.cts CHANGED
@@ -610,21 +610,24 @@ interface RunStep<E = unknown> {
610
610
  * Scope types for parallel and race operations.
611
611
  */
612
612
  type ScopeType = "parallel" | "race" | "allSettled";
613
- type WorkflowEvent<E> = {
613
+ type WorkflowEvent<E, C = unknown> = {
614
614
  type: "workflow_start";
615
615
  workflowId: string;
616
616
  ts: number;
617
+ context?: C;
617
618
  } | {
618
619
  type: "workflow_success";
619
620
  workflowId: string;
620
621
  ts: number;
621
622
  durationMs: number;
623
+ context?: C;
622
624
  } | {
623
625
  type: "workflow_error";
624
626
  workflowId: string;
625
627
  ts: number;
626
628
  durationMs: number;
627
629
  error: E;
630
+ context?: C;
628
631
  } | {
629
632
  type: "step_start";
630
633
  workflowId: string;
@@ -632,6 +635,7 @@ type WorkflowEvent<E> = {
632
635
  stepKey?: string;
633
636
  name?: string;
634
637
  ts: number;
638
+ context?: C;
635
639
  } | {
636
640
  type: "step_success";
637
641
  workflowId: string;
@@ -640,6 +644,7 @@ type WorkflowEvent<E> = {
640
644
  name?: string;
641
645
  ts: number;
642
646
  durationMs: number;
647
+ context?: C;
643
648
  } | {
644
649
  type: "step_error";
645
650
  workflowId: string;
@@ -649,6 +654,7 @@ type WorkflowEvent<E> = {
649
654
  ts: number;
650
655
  durationMs: number;
651
656
  error: E;
657
+ context?: C;
652
658
  } | {
653
659
  type: "step_aborted";
654
660
  workflowId: string;
@@ -657,6 +663,7 @@ type WorkflowEvent<E> = {
657
663
  name?: string;
658
664
  ts: number;
659
665
  durationMs: number;
666
+ context?: C;
660
667
  } | {
661
668
  type: "step_complete";
662
669
  workflowId: string;
@@ -666,18 +673,21 @@ type WorkflowEvent<E> = {
666
673
  durationMs: number;
667
674
  result: Result<unknown, unknown, unknown>;
668
675
  meta?: StepFailureMeta;
676
+ context?: C;
669
677
  } | {
670
678
  type: "step_cache_hit";
671
679
  workflowId: string;
672
680
  stepKey: string;
673
681
  name?: string;
674
682
  ts: number;
683
+ context?: C;
675
684
  } | {
676
685
  type: "step_cache_miss";
677
686
  workflowId: string;
678
687
  stepKey: string;
679
688
  name?: string;
680
689
  ts: number;
690
+ context?: C;
681
691
  } | {
682
692
  type: "step_skipped";
683
693
  workflowId: string;
@@ -686,6 +696,7 @@ type WorkflowEvent<E> = {
686
696
  reason?: string;
687
697
  decisionId?: string;
688
698
  ts: number;
699
+ context?: C;
689
700
  } | {
690
701
  type: "scope_start";
691
702
  workflowId: string;
@@ -693,6 +704,7 @@ type WorkflowEvent<E> = {
693
704
  scopeType: ScopeType;
694
705
  name?: string;
695
706
  ts: number;
707
+ context?: C;
696
708
  } | {
697
709
  type: "scope_end";
698
710
  workflowId: string;
@@ -700,6 +712,7 @@ type WorkflowEvent<E> = {
700
712
  ts: number;
701
713
  durationMs: number;
702
714
  winnerId?: string;
715
+ context?: C;
703
716
  } | {
704
717
  type: "step_retry";
705
718
  workflowId: string;
@@ -711,6 +724,7 @@ type WorkflowEvent<E> = {
711
724
  maxAttempts: number;
712
725
  delayMs: number;
713
726
  error: E;
727
+ context?: C;
714
728
  } | {
715
729
  type: "step_retries_exhausted";
716
730
  workflowId: string;
@@ -721,6 +735,7 @@ type WorkflowEvent<E> = {
721
735
  durationMs: number;
722
736
  attempts: number;
723
737
  lastError: E;
738
+ context?: C;
724
739
  } | {
725
740
  type: "step_timeout";
726
741
  workflowId: string;
@@ -730,6 +745,7 @@ type WorkflowEvent<E> = {
730
745
  ts: number;
731
746
  timeoutMs: number;
732
747
  attempt?: number;
748
+ context?: C;
733
749
  } | {
734
750
  type: "hook_should_run";
735
751
  workflowId: string;
@@ -737,12 +753,14 @@ type WorkflowEvent<E> = {
737
753
  durationMs: number;
738
754
  result: boolean;
739
755
  skipped: boolean;
756
+ context?: C;
740
757
  } | {
741
758
  type: "hook_should_run_error";
742
759
  workflowId: string;
743
760
  ts: number;
744
761
  durationMs: number;
745
762
  error: E;
763
+ context?: C;
746
764
  } | {
747
765
  type: "hook_before_start";
748
766
  workflowId: string;
@@ -750,18 +768,21 @@ type WorkflowEvent<E> = {
750
768
  durationMs: number;
751
769
  result: boolean;
752
770
  skipped: boolean;
771
+ context?: C;
753
772
  } | {
754
773
  type: "hook_before_start_error";
755
774
  workflowId: string;
756
775
  ts: number;
757
776
  durationMs: number;
758
777
  error: E;
778
+ context?: C;
759
779
  } | {
760
780
  type: "hook_after_step";
761
781
  workflowId: string;
762
782
  stepKey: string;
763
783
  ts: number;
764
784
  durationMs: number;
785
+ context?: C;
765
786
  } | {
766
787
  type: "hook_after_step_error";
767
788
  workflowId: string;
@@ -769,18 +790,22 @@ type WorkflowEvent<E> = {
769
790
  ts: number;
770
791
  durationMs: number;
771
792
  error: E;
793
+ context?: C;
772
794
  };
773
795
  type RunOptionsWithCatch<E, C = void> = {
774
796
  /**
775
797
  * Handler for expected errors.
776
798
  * Called when a step fails with a known error type.
777
799
  */
778
- onError?: (error: E, stepName?: string) => void;
800
+ onError?: (error: E, stepName?: string, ctx?: C) => void;
779
801
  /**
780
802
  * Listener for workflow events (start, success, error, step events).
781
803
  * Use this for logging, telemetry, or debugging.
804
+ *
805
+ * Context is automatically included in `event.context` when provided via the `context` option.
806
+ * The separate `ctx` parameter is provided for convenience.
782
807
  */
783
- onEvent?: (event: WorkflowEvent<E | UnexpectedError>, ctx: C) => void;
808
+ onEvent?: (event: WorkflowEvent<E | UnexpectedError, C>, ctx: C) => void;
784
809
  /**
785
810
  * Catch-all mapper for unexpected exceptions.
786
811
  * Required for "Strict Mode".
@@ -794,7 +819,7 @@ type RunOptionsWithCatch<E, C = void> = {
794
819
  */
795
820
  workflowId?: string;
796
821
  /**
797
- * Arbitrary context object passed to onEvent.
822
+ * Arbitrary context object passed to onEvent and onError.
798
823
  * Useful for passing request IDs, user IDs, or loggers.
799
824
  */
800
825
  context?: C;
@@ -804,8 +829,14 @@ type RunOptionsWithoutCatch<E, C = void> = {
804
829
  * Handler for expected errors AND unexpected errors.
805
830
  * Unexpected errors will be wrapped in `UnexpectedError`.
806
831
  */
807
- onError?: (error: E | UnexpectedError, stepName?: string) => void;
808
- onEvent?: (event: WorkflowEvent<E | UnexpectedError>, ctx: C) => void;
832
+ onError?: (error: E | UnexpectedError, stepName?: string, ctx?: C) => void;
833
+ /**
834
+ * Listener for workflow events (start, success, error, step events).
835
+ *
836
+ * Note: Context is available both on `event.context` and as the separate `ctx` parameter.
837
+ * The `ctx` parameter is provided for convenience and backward compatibility.
838
+ */
839
+ onEvent?: (event: WorkflowEvent<E | UnexpectedError, C>, ctx: C) => void;
809
840
  catchUnexpected?: undefined;
810
841
  workflowId?: string;
811
842
  context?: C;
@@ -915,8 +946,8 @@ declare function run<T, E, C = void>(fn: (step: RunStep<E>) => Promise<T> | T, o
915
946
  * @returns A Promise resolving to `Result<T, E | UnexpectedError>`
916
947
  */
917
948
  declare function run<T, E, C = void>(fn: (step: RunStep<E | UnexpectedError>) => Promise<T> | T, options: {
918
- onError: (error: E | UnexpectedError, stepName?: string) => void;
919
- onEvent?: (event: WorkflowEvent<E | UnexpectedError>, ctx: C) => void;
949
+ onError: (error: E | UnexpectedError, stepName?: string, ctx?: C) => void;
950
+ onEvent?: (event: WorkflowEvent<E | UnexpectedError, C>, ctx: C) => void;
920
951
  workflowId?: string;
921
952
  context?: C;
922
953
  }): AsyncResult<T, E | UnexpectedError, unknown>;
@@ -939,14 +970,20 @@ declare function run<T, E, C = void>(fn: (step: RunStep<E | UnexpectedError>) =>
939
970
  * ```
940
971
  */
941
972
  declare function run<T, C = void>(fn: (step: RunStep) => Promise<T> | T, options?: {
942
- onEvent?: (event: WorkflowEvent<UnexpectedError>, ctx: C) => void;
973
+ onEvent?: (event: WorkflowEvent<UnexpectedError, C>, ctx: C) => void;
943
974
  workflowId?: string;
944
975
  context?: C;
945
976
  }): AsyncResult<T, UnexpectedError, unknown>;
946
977
  declare namespace run {
947
978
  var strict: <T, E, C = void>(fn: (step: RunStep<E>) => Promise<T> | T, options: {
948
- onError?: (error: E, stepName?: string) => void;
949
- onEvent?: (event: WorkflowEvent<E | UnexpectedError>, ctx: C) => void;
979
+ onError?: (error: E, stepName?: string, ctx?: C) => void;
980
+ /**
981
+ * Listener for workflow events (start, success, error, step events).
982
+ *
983
+ * Note: Context is available both on `event.context` and as the separate `ctx` parameter.
984
+ * The `ctx` parameter is provided for convenience and backward compatibility.
985
+ */
986
+ onEvent?: (event: WorkflowEvent<E | UnexpectedError, C>, ctx: C) => void;
950
987
  catchUnexpected: (cause: unknown) => E;
951
988
  workflowId?: string;
952
989
  context?: C;
@@ -1836,6 +1873,55 @@ declare function recover<T, E, C>(r: Result<T, E, C>, fn: (error: E, cause?: C)
1836
1873
  * ```
1837
1874
  */
1838
1875
  declare function recoverAsync<T, E, C>(r: Result<T, E, C> | Promise<Result<T, E, C>>, fn: (error: E, cause?: C) => T | Promise<T>): Promise<Result<T, never, never>>;
1876
+ /**
1877
+ * Validates and type-narrows a value to a Result.
1878
+ *
1879
+ * Since this library uses plain objects for Results, serialization is trivial -
1880
+ * the serialized form IS the Result. This function validates the structure and
1881
+ * provides type-safe narrowing.
1882
+ *
1883
+ * ## When to Use
1884
+ *
1885
+ * Use `hydrate()` when:
1886
+ * - Receiving Results over RPC/network
1887
+ * - Deserializing Results from storage
1888
+ * - Validating untrusted data as Results
1889
+ *
1890
+ * @param value - The unknown value to validate as a Result
1891
+ * @returns The value as a typed Result, or null if invalid
1892
+ *
1893
+ * @example
1894
+ * ```typescript
1895
+ * // Deserialize from JSON
1896
+ * const parsed = JSON.parse(jsonString);
1897
+ * const result = hydrate<User, ApiError>(parsed);
1898
+ * if (result) {
1899
+ * // result is Result<User, ApiError>
1900
+ * }
1901
+ *
1902
+ * // Validate RPC response
1903
+ * const rpcResponse = await fetchFromService();
1904
+ * const result = hydrate<Data, ServiceError>(rpcResponse);
1905
+ * ```
1906
+ */
1907
+ declare function hydrate<T, E, C = unknown>(value: unknown): Result<T, E, C> | null;
1908
+ /**
1909
+ * Type guard to check if a value is a valid serialized Result.
1910
+ *
1911
+ * @param value - The value to check
1912
+ * @returns True if the value is a valid Result structure
1913
+ *
1914
+ * @example
1915
+ * ```typescript
1916
+ * if (isSerializedResult(data)) {
1917
+ * // data is Result<unknown, unknown, unknown>
1918
+ * if (data.ok) {
1919
+ * console.log(data.value);
1920
+ * }
1921
+ * }
1922
+ * ```
1923
+ */
1924
+ declare function isSerializedResult(value: unknown): value is Result<unknown, unknown, unknown>;
1839
1925
  type AllValues<T extends readonly Result<unknown, unknown, unknown>[]> = {
1840
1926
  [K in keyof T]: T[K] extends Result<infer V, unknown, unknown> ? V : never;
1841
1927
  };
@@ -2223,4 +2309,4 @@ type AllAsyncCauses<T extends readonly MaybeAsyncResult<unknown, unknown, unknow
2223
2309
  */
2224
2310
  declare function allSettledAsync<const T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]>(results: T): Promise<Result<AllAsyncValues<T>, SettledError<AllAsyncErrors<T> | PromiseRejectedError, AllAsyncCauses<T> | PromiseRejectionCause>[]>>;
2225
2311
 
2226
- export { type AsyncResult, type BackoffStrategy, type CauseOf, EARLY_EXIT_SYMBOL, type EarlyExit, type EmptyInputError, type ErrorOf, type Errors, type ExtractCause, type ExtractError, type ExtractValue, type MaybeAsyncResult, type PromiseRejectedError, type PromiseRejectionCause, type Result, type RetryOptions, type RunOptions, type RunOptionsWithCatch, type RunOptionsWithoutCatch, type RunStep, STEP_TIMEOUT_MARKER, type ScopeType, type SettledError, type StepFailureMeta, type StepOptions, type StepTimeoutError, type StepTimeoutMarkerMeta, type TimeoutOptions, type UnexpectedCause, type UnexpectedError, type UnexpectedStepFailureCause, UnwrapError, type WorkflowEvent, all, allAsync, allSettled, allSettledAsync, andThen, any, anyAsync, bimap, createEarlyExit, err, from, fromNullable, fromPromise, getStepTimeoutMeta, isEarlyExit, isErr, isOk, isStepTimeoutError, isUnexpectedError, map, mapError, mapErrorTry, mapTry, match, ok, orElse, orElseAsync, partition, recover, recoverAsync, run, tap, tapError, tryAsync, unwrap, unwrapOr, unwrapOrElse };
2312
+ export { type AsyncResult, type BackoffStrategy, type CauseOf, EARLY_EXIT_SYMBOL, type EarlyExit, type EmptyInputError, type ErrorOf, type Errors, type ExtractCause, type ExtractError, type ExtractValue, type MaybeAsyncResult, type PromiseRejectedError, type PromiseRejectionCause, type Result, type RetryOptions, type RunOptions, type RunOptionsWithCatch, type RunOptionsWithoutCatch, type RunStep, STEP_TIMEOUT_MARKER, type ScopeType, type SettledError, type StepFailureMeta, type StepOptions, type StepTimeoutError, type StepTimeoutMarkerMeta, type TimeoutOptions, type UnexpectedCause, type UnexpectedError, type UnexpectedStepFailureCause, UnwrapError, type WorkflowEvent, all, allAsync, allSettled, allSettledAsync, andThen, any, anyAsync, bimap, createEarlyExit, err, from, fromNullable, fromPromise, getStepTimeoutMeta, hydrate, isEarlyExit, isErr, isOk, isSerializedResult, isStepTimeoutError, isUnexpectedError, map, mapError, mapErrorTry, mapTry, match, ok, orElse, orElseAsync, partition, recover, recoverAsync, run, tap, tapError, tryAsync, unwrap, unwrapOr, unwrapOrElse };
package/dist/core.d.ts CHANGED
@@ -610,21 +610,24 @@ interface RunStep<E = unknown> {
610
610
  * Scope types for parallel and race operations.
611
611
  */
612
612
  type ScopeType = "parallel" | "race" | "allSettled";
613
- type WorkflowEvent<E> = {
613
+ type WorkflowEvent<E, C = unknown> = {
614
614
  type: "workflow_start";
615
615
  workflowId: string;
616
616
  ts: number;
617
+ context?: C;
617
618
  } | {
618
619
  type: "workflow_success";
619
620
  workflowId: string;
620
621
  ts: number;
621
622
  durationMs: number;
623
+ context?: C;
622
624
  } | {
623
625
  type: "workflow_error";
624
626
  workflowId: string;
625
627
  ts: number;
626
628
  durationMs: number;
627
629
  error: E;
630
+ context?: C;
628
631
  } | {
629
632
  type: "step_start";
630
633
  workflowId: string;
@@ -632,6 +635,7 @@ type WorkflowEvent<E> = {
632
635
  stepKey?: string;
633
636
  name?: string;
634
637
  ts: number;
638
+ context?: C;
635
639
  } | {
636
640
  type: "step_success";
637
641
  workflowId: string;
@@ -640,6 +644,7 @@ type WorkflowEvent<E> = {
640
644
  name?: string;
641
645
  ts: number;
642
646
  durationMs: number;
647
+ context?: C;
643
648
  } | {
644
649
  type: "step_error";
645
650
  workflowId: string;
@@ -649,6 +654,7 @@ type WorkflowEvent<E> = {
649
654
  ts: number;
650
655
  durationMs: number;
651
656
  error: E;
657
+ context?: C;
652
658
  } | {
653
659
  type: "step_aborted";
654
660
  workflowId: string;
@@ -657,6 +663,7 @@ type WorkflowEvent<E> = {
657
663
  name?: string;
658
664
  ts: number;
659
665
  durationMs: number;
666
+ context?: C;
660
667
  } | {
661
668
  type: "step_complete";
662
669
  workflowId: string;
@@ -666,18 +673,21 @@ type WorkflowEvent<E> = {
666
673
  durationMs: number;
667
674
  result: Result<unknown, unknown, unknown>;
668
675
  meta?: StepFailureMeta;
676
+ context?: C;
669
677
  } | {
670
678
  type: "step_cache_hit";
671
679
  workflowId: string;
672
680
  stepKey: string;
673
681
  name?: string;
674
682
  ts: number;
683
+ context?: C;
675
684
  } | {
676
685
  type: "step_cache_miss";
677
686
  workflowId: string;
678
687
  stepKey: string;
679
688
  name?: string;
680
689
  ts: number;
690
+ context?: C;
681
691
  } | {
682
692
  type: "step_skipped";
683
693
  workflowId: string;
@@ -686,6 +696,7 @@ type WorkflowEvent<E> = {
686
696
  reason?: string;
687
697
  decisionId?: string;
688
698
  ts: number;
699
+ context?: C;
689
700
  } | {
690
701
  type: "scope_start";
691
702
  workflowId: string;
@@ -693,6 +704,7 @@ type WorkflowEvent<E> = {
693
704
  scopeType: ScopeType;
694
705
  name?: string;
695
706
  ts: number;
707
+ context?: C;
696
708
  } | {
697
709
  type: "scope_end";
698
710
  workflowId: string;
@@ -700,6 +712,7 @@ type WorkflowEvent<E> = {
700
712
  ts: number;
701
713
  durationMs: number;
702
714
  winnerId?: string;
715
+ context?: C;
703
716
  } | {
704
717
  type: "step_retry";
705
718
  workflowId: string;
@@ -711,6 +724,7 @@ type WorkflowEvent<E> = {
711
724
  maxAttempts: number;
712
725
  delayMs: number;
713
726
  error: E;
727
+ context?: C;
714
728
  } | {
715
729
  type: "step_retries_exhausted";
716
730
  workflowId: string;
@@ -721,6 +735,7 @@ type WorkflowEvent<E> = {
721
735
  durationMs: number;
722
736
  attempts: number;
723
737
  lastError: E;
738
+ context?: C;
724
739
  } | {
725
740
  type: "step_timeout";
726
741
  workflowId: string;
@@ -730,6 +745,7 @@ type WorkflowEvent<E> = {
730
745
  ts: number;
731
746
  timeoutMs: number;
732
747
  attempt?: number;
748
+ context?: C;
733
749
  } | {
734
750
  type: "hook_should_run";
735
751
  workflowId: string;
@@ -737,12 +753,14 @@ type WorkflowEvent<E> = {
737
753
  durationMs: number;
738
754
  result: boolean;
739
755
  skipped: boolean;
756
+ context?: C;
740
757
  } | {
741
758
  type: "hook_should_run_error";
742
759
  workflowId: string;
743
760
  ts: number;
744
761
  durationMs: number;
745
762
  error: E;
763
+ context?: C;
746
764
  } | {
747
765
  type: "hook_before_start";
748
766
  workflowId: string;
@@ -750,18 +768,21 @@ type WorkflowEvent<E> = {
750
768
  durationMs: number;
751
769
  result: boolean;
752
770
  skipped: boolean;
771
+ context?: C;
753
772
  } | {
754
773
  type: "hook_before_start_error";
755
774
  workflowId: string;
756
775
  ts: number;
757
776
  durationMs: number;
758
777
  error: E;
778
+ context?: C;
759
779
  } | {
760
780
  type: "hook_after_step";
761
781
  workflowId: string;
762
782
  stepKey: string;
763
783
  ts: number;
764
784
  durationMs: number;
785
+ context?: C;
765
786
  } | {
766
787
  type: "hook_after_step_error";
767
788
  workflowId: string;
@@ -769,18 +790,22 @@ type WorkflowEvent<E> = {
769
790
  ts: number;
770
791
  durationMs: number;
771
792
  error: E;
793
+ context?: C;
772
794
  };
773
795
  type RunOptionsWithCatch<E, C = void> = {
774
796
  /**
775
797
  * Handler for expected errors.
776
798
  * Called when a step fails with a known error type.
777
799
  */
778
- onError?: (error: E, stepName?: string) => void;
800
+ onError?: (error: E, stepName?: string, ctx?: C) => void;
779
801
  /**
780
802
  * Listener for workflow events (start, success, error, step events).
781
803
  * Use this for logging, telemetry, or debugging.
804
+ *
805
+ * Context is automatically included in `event.context` when provided via the `context` option.
806
+ * The separate `ctx` parameter is provided for convenience.
782
807
  */
783
- onEvent?: (event: WorkflowEvent<E | UnexpectedError>, ctx: C) => void;
808
+ onEvent?: (event: WorkflowEvent<E | UnexpectedError, C>, ctx: C) => void;
784
809
  /**
785
810
  * Catch-all mapper for unexpected exceptions.
786
811
  * Required for "Strict Mode".
@@ -794,7 +819,7 @@ type RunOptionsWithCatch<E, C = void> = {
794
819
  */
795
820
  workflowId?: string;
796
821
  /**
797
- * Arbitrary context object passed to onEvent.
822
+ * Arbitrary context object passed to onEvent and onError.
798
823
  * Useful for passing request IDs, user IDs, or loggers.
799
824
  */
800
825
  context?: C;
@@ -804,8 +829,14 @@ type RunOptionsWithoutCatch<E, C = void> = {
804
829
  * Handler for expected errors AND unexpected errors.
805
830
  * Unexpected errors will be wrapped in `UnexpectedError`.
806
831
  */
807
- onError?: (error: E | UnexpectedError, stepName?: string) => void;
808
- onEvent?: (event: WorkflowEvent<E | UnexpectedError>, ctx: C) => void;
832
+ onError?: (error: E | UnexpectedError, stepName?: string, ctx?: C) => void;
833
+ /**
834
+ * Listener for workflow events (start, success, error, step events).
835
+ *
836
+ * Note: Context is available both on `event.context` and as the separate `ctx` parameter.
837
+ * The `ctx` parameter is provided for convenience and backward compatibility.
838
+ */
839
+ onEvent?: (event: WorkflowEvent<E | UnexpectedError, C>, ctx: C) => void;
809
840
  catchUnexpected?: undefined;
810
841
  workflowId?: string;
811
842
  context?: C;
@@ -915,8 +946,8 @@ declare function run<T, E, C = void>(fn: (step: RunStep<E>) => Promise<T> | T, o
915
946
  * @returns A Promise resolving to `Result<T, E | UnexpectedError>`
916
947
  */
917
948
  declare function run<T, E, C = void>(fn: (step: RunStep<E | UnexpectedError>) => Promise<T> | T, options: {
918
- onError: (error: E | UnexpectedError, stepName?: string) => void;
919
- onEvent?: (event: WorkflowEvent<E | UnexpectedError>, ctx: C) => void;
949
+ onError: (error: E | UnexpectedError, stepName?: string, ctx?: C) => void;
950
+ onEvent?: (event: WorkflowEvent<E | UnexpectedError, C>, ctx: C) => void;
920
951
  workflowId?: string;
921
952
  context?: C;
922
953
  }): AsyncResult<T, E | UnexpectedError, unknown>;
@@ -939,14 +970,20 @@ declare function run<T, E, C = void>(fn: (step: RunStep<E | UnexpectedError>) =>
939
970
  * ```
940
971
  */
941
972
  declare function run<T, C = void>(fn: (step: RunStep) => Promise<T> | T, options?: {
942
- onEvent?: (event: WorkflowEvent<UnexpectedError>, ctx: C) => void;
973
+ onEvent?: (event: WorkflowEvent<UnexpectedError, C>, ctx: C) => void;
943
974
  workflowId?: string;
944
975
  context?: C;
945
976
  }): AsyncResult<T, UnexpectedError, unknown>;
946
977
  declare namespace run {
947
978
  var strict: <T, E, C = void>(fn: (step: RunStep<E>) => Promise<T> | T, options: {
948
- onError?: (error: E, stepName?: string) => void;
949
- onEvent?: (event: WorkflowEvent<E | UnexpectedError>, ctx: C) => void;
979
+ onError?: (error: E, stepName?: string, ctx?: C) => void;
980
+ /**
981
+ * Listener for workflow events (start, success, error, step events).
982
+ *
983
+ * Note: Context is available both on `event.context` and as the separate `ctx` parameter.
984
+ * The `ctx` parameter is provided for convenience and backward compatibility.
985
+ */
986
+ onEvent?: (event: WorkflowEvent<E | UnexpectedError, C>, ctx: C) => void;
950
987
  catchUnexpected: (cause: unknown) => E;
951
988
  workflowId?: string;
952
989
  context?: C;
@@ -1836,6 +1873,55 @@ declare function recover<T, E, C>(r: Result<T, E, C>, fn: (error: E, cause?: C)
1836
1873
  * ```
1837
1874
  */
1838
1875
  declare function recoverAsync<T, E, C>(r: Result<T, E, C> | Promise<Result<T, E, C>>, fn: (error: E, cause?: C) => T | Promise<T>): Promise<Result<T, never, never>>;
1876
+ /**
1877
+ * Validates and type-narrows a value to a Result.
1878
+ *
1879
+ * Since this library uses plain objects for Results, serialization is trivial -
1880
+ * the serialized form IS the Result. This function validates the structure and
1881
+ * provides type-safe narrowing.
1882
+ *
1883
+ * ## When to Use
1884
+ *
1885
+ * Use `hydrate()` when:
1886
+ * - Receiving Results over RPC/network
1887
+ * - Deserializing Results from storage
1888
+ * - Validating untrusted data as Results
1889
+ *
1890
+ * @param value - The unknown value to validate as a Result
1891
+ * @returns The value as a typed Result, or null if invalid
1892
+ *
1893
+ * @example
1894
+ * ```typescript
1895
+ * // Deserialize from JSON
1896
+ * const parsed = JSON.parse(jsonString);
1897
+ * const result = hydrate<User, ApiError>(parsed);
1898
+ * if (result) {
1899
+ * // result is Result<User, ApiError>
1900
+ * }
1901
+ *
1902
+ * // Validate RPC response
1903
+ * const rpcResponse = await fetchFromService();
1904
+ * const result = hydrate<Data, ServiceError>(rpcResponse);
1905
+ * ```
1906
+ */
1907
+ declare function hydrate<T, E, C = unknown>(value: unknown): Result<T, E, C> | null;
1908
+ /**
1909
+ * Type guard to check if a value is a valid serialized Result.
1910
+ *
1911
+ * @param value - The value to check
1912
+ * @returns True if the value is a valid Result structure
1913
+ *
1914
+ * @example
1915
+ * ```typescript
1916
+ * if (isSerializedResult(data)) {
1917
+ * // data is Result<unknown, unknown, unknown>
1918
+ * if (data.ok) {
1919
+ * console.log(data.value);
1920
+ * }
1921
+ * }
1922
+ * ```
1923
+ */
1924
+ declare function isSerializedResult(value: unknown): value is Result<unknown, unknown, unknown>;
1839
1925
  type AllValues<T extends readonly Result<unknown, unknown, unknown>[]> = {
1840
1926
  [K in keyof T]: T[K] extends Result<infer V, unknown, unknown> ? V : never;
1841
1927
  };
@@ -2223,4 +2309,4 @@ type AllAsyncCauses<T extends readonly MaybeAsyncResult<unknown, unknown, unknow
2223
2309
  */
2224
2310
  declare function allSettledAsync<const T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]>(results: T): Promise<Result<AllAsyncValues<T>, SettledError<AllAsyncErrors<T> | PromiseRejectedError, AllAsyncCauses<T> | PromiseRejectionCause>[]>>;
2225
2311
 
2226
- export { type AsyncResult, type BackoffStrategy, type CauseOf, EARLY_EXIT_SYMBOL, type EarlyExit, type EmptyInputError, type ErrorOf, type Errors, type ExtractCause, type ExtractError, type ExtractValue, type MaybeAsyncResult, type PromiseRejectedError, type PromiseRejectionCause, type Result, type RetryOptions, type RunOptions, type RunOptionsWithCatch, type RunOptionsWithoutCatch, type RunStep, STEP_TIMEOUT_MARKER, type ScopeType, type SettledError, type StepFailureMeta, type StepOptions, type StepTimeoutError, type StepTimeoutMarkerMeta, type TimeoutOptions, type UnexpectedCause, type UnexpectedError, type UnexpectedStepFailureCause, UnwrapError, type WorkflowEvent, all, allAsync, allSettled, allSettledAsync, andThen, any, anyAsync, bimap, createEarlyExit, err, from, fromNullable, fromPromise, getStepTimeoutMeta, isEarlyExit, isErr, isOk, isStepTimeoutError, isUnexpectedError, map, mapError, mapErrorTry, mapTry, match, ok, orElse, orElseAsync, partition, recover, recoverAsync, run, tap, tapError, tryAsync, unwrap, unwrapOr, unwrapOrElse };
2312
+ export { type AsyncResult, type BackoffStrategy, type CauseOf, EARLY_EXIT_SYMBOL, type EarlyExit, type EmptyInputError, type ErrorOf, type Errors, type ExtractCause, type ExtractError, type ExtractValue, type MaybeAsyncResult, type PromiseRejectedError, type PromiseRejectionCause, type Result, type RetryOptions, type RunOptions, type RunOptionsWithCatch, type RunOptionsWithoutCatch, type RunStep, STEP_TIMEOUT_MARKER, type ScopeType, type SettledError, type StepFailureMeta, type StepOptions, type StepTimeoutError, type StepTimeoutMarkerMeta, type TimeoutOptions, type UnexpectedCause, type UnexpectedError, type UnexpectedStepFailureCause, UnwrapError, type WorkflowEvent, all, allAsync, allSettled, allSettledAsync, andThen, any, anyAsync, bimap, createEarlyExit, err, from, fromNullable, fromPromise, getStepTimeoutMeta, hydrate, isEarlyExit, isErr, isOk, isSerializedResult, isStepTimeoutError, isUnexpectedError, map, mapError, mapErrorTry, mapTry, match, ok, orElse, orElseAsync, partition, recover, recoverAsync, run, tap, tapError, tryAsync, unwrap, unwrapOr, unwrapOrElse };