@stepflowjs/react 0.0.1

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.
@@ -0,0 +1,205 @@
1
+ import React from 'react';
2
+ import { StepflowClientConfig, StepflowClient, StepExecution, Execution, ExecutionStatus, TriggerResult } from '@stepflowjs/client-ts';
3
+
4
+ interface StepflowContextValue {
5
+ client: StepflowClient;
6
+ config: StepflowClientConfig;
7
+ }
8
+ interface StepflowProviderProps {
9
+ children: React.ReactNode;
10
+ config: StepflowClientConfig;
11
+ }
12
+ declare function StepflowProvider({ children, config, }: StepflowProviderProps): React.ReactElement;
13
+ declare function useStepflow(): StepflowContextValue;
14
+
15
+ interface UseWorkflowRunOptions {
16
+ /**
17
+ * The run ID to subscribe to
18
+ */
19
+ runId: string;
20
+ /**
21
+ * Public access token for the run
22
+ */
23
+ accessToken?: string;
24
+ /**
25
+ * Callback when a step completes
26
+ */
27
+ onStepComplete?: (step: StepExecution) => void;
28
+ /**
29
+ * Callback when the workflow completes
30
+ */
31
+ onComplete?: (result: unknown) => void;
32
+ /**
33
+ * Callback when the workflow fails
34
+ */
35
+ onError?: (error: Error) => void;
36
+ /**
37
+ * Throttle updates (ms)
38
+ */
39
+ throttleMs?: number;
40
+ /**
41
+ * Enable/disable the subscription
42
+ */
43
+ enabled?: boolean;
44
+ }
45
+ interface UseWorkflowRunResult<TPayload = unknown, TResult = unknown> {
46
+ /**
47
+ * The current execution state
48
+ */
49
+ run: Execution<TPayload, TResult> | null;
50
+ /**
51
+ * Current execution status
52
+ */
53
+ status: ExecutionStatus;
54
+ /**
55
+ * Completed steps
56
+ */
57
+ steps: StepExecution[];
58
+ /**
59
+ * Execution metadata
60
+ */
61
+ metadata: Record<string, unknown>;
62
+ /**
63
+ * Error if any
64
+ */
65
+ error: Error | null;
66
+ /**
67
+ * Loading state
68
+ */
69
+ isLoading: boolean;
70
+ /**
71
+ * Connection state
72
+ */
73
+ isConnected: boolean;
74
+ /**
75
+ * Refetch the run data
76
+ */
77
+ refetch: () => Promise<void>;
78
+ }
79
+ declare function useWorkflowRun<TPayload = unknown, TResult = unknown>(options: UseWorkflowRunOptions): UseWorkflowRunResult<TPayload, TResult>;
80
+
81
+ interface UseWorkflowTriggerOptions {
82
+ /**
83
+ * The workflow ID to trigger
84
+ */
85
+ workflowId: string;
86
+ /**
87
+ * Callback on successful trigger
88
+ */
89
+ onSuccess?: (result: TriggerResult) => void;
90
+ /**
91
+ * Callback on error
92
+ */
93
+ onError?: (error: Error) => void;
94
+ }
95
+ interface UseWorkflowTriggerResult<TPayload = unknown> {
96
+ /**
97
+ * Trigger the workflow with payload
98
+ */
99
+ trigger: (payload: TPayload, options?: TriggerOptions) => Promise<TriggerResult>;
100
+ /**
101
+ * The run ID from the last trigger
102
+ */
103
+ runId: string | null;
104
+ /**
105
+ * The execution ID from the last trigger
106
+ */
107
+ executionId: string | null;
108
+ /**
109
+ * Public access token for the run
110
+ */
111
+ accessToken: string | null;
112
+ /**
113
+ * Whether a trigger is in progress
114
+ */
115
+ isTriggering: boolean;
116
+ /**
117
+ * Error from the last trigger
118
+ */
119
+ error: Error | null;
120
+ /**
121
+ * Reset the state
122
+ */
123
+ reset: () => void;
124
+ }
125
+ interface TriggerOptions {
126
+ /**
127
+ * Custom run ID
128
+ */
129
+ runId?: string;
130
+ /**
131
+ * Additional metadata
132
+ */
133
+ metadata?: Record<string, unknown>;
134
+ /**
135
+ * Delay before execution (ms)
136
+ */
137
+ delay?: number;
138
+ }
139
+ declare function useWorkflowTrigger<TPayload = unknown>(options: UseWorkflowTriggerOptions): UseWorkflowTriggerResult<TPayload>;
140
+
141
+ interface UseWorkflowStreamOptions<TPayload, TResult> {
142
+ /**
143
+ * The workflow ID to execute
144
+ */
145
+ workflowId: string;
146
+ /**
147
+ * The payload to send
148
+ */
149
+ payload: TPayload;
150
+ /**
151
+ * Auto-start the stream
152
+ */
153
+ autoStart?: boolean;
154
+ /**
155
+ * Callback on workflow completion
156
+ */
157
+ onComplete?: (result: TResult) => void;
158
+ /**
159
+ * Callback on error
160
+ */
161
+ onError?: (error: Error) => void;
162
+ }
163
+ interface UseWorkflowStreamResult<TResult = unknown> {
164
+ /**
165
+ * Start the workflow stream
166
+ */
167
+ start: () => Promise<void>;
168
+ /**
169
+ * Stop/abort the stream
170
+ */
171
+ stop: () => void;
172
+ /**
173
+ * All received events
174
+ */
175
+ events: WorkflowEvent[];
176
+ /**
177
+ * Final result (when complete)
178
+ */
179
+ result: TResult | null;
180
+ /**
181
+ * Current status
182
+ */
183
+ status: ExecutionStatus;
184
+ /**
185
+ * Whether streaming is active
186
+ */
187
+ isStreaming: boolean;
188
+ /**
189
+ * Error if any
190
+ */
191
+ error: Error | null;
192
+ /**
193
+ * Reset the state
194
+ */
195
+ reset: () => void;
196
+ }
197
+ interface WorkflowEvent {
198
+ type: string;
199
+ data: unknown;
200
+ timestamp: Date;
201
+ stepName?: string;
202
+ }
203
+ declare function useWorkflowStream<TPayload = unknown, TResult = unknown>(options: UseWorkflowStreamOptions<TPayload, TResult>): UseWorkflowStreamResult<TResult>;
204
+
205
+ export { StepflowProvider, type StepflowProviderProps, type TriggerOptions, type UseWorkflowRunOptions, type UseWorkflowRunResult, type UseWorkflowStreamOptions, type UseWorkflowStreamResult, type UseWorkflowTriggerOptions, type UseWorkflowTriggerResult, type WorkflowEvent, useStepflow, useWorkflowRun, useWorkflowStream, useWorkflowTrigger };
package/dist/index.js ADDED
@@ -0,0 +1,321 @@
1
+ "use client";
2
+
3
+ // src/providers/stepflow-provider.tsx
4
+ import { createContext, useContext, useMemo } from "react";
5
+ import { StepflowClient } from "@stepflowjs/client-ts";
6
+ import { jsx } from "react/jsx-runtime";
7
+ var StepflowContext = createContext(null);
8
+ function StepflowProvider({
9
+ children,
10
+ config
11
+ }) {
12
+ const client = useMemo(
13
+ () => new StepflowClient(config),
14
+ [config.baseUrl, config.apiKey, config.publicApiKey, config.wsUrl]
15
+ );
16
+ const value = useMemo(() => ({ client, config }), [client, config]);
17
+ return /* @__PURE__ */ jsx(StepflowContext.Provider, { value, children });
18
+ }
19
+ function useStepflow() {
20
+ const context = useContext(StepflowContext);
21
+ if (!context) {
22
+ throw new Error("useStepflow must be used within a StepflowProvider");
23
+ }
24
+ return context;
25
+ }
26
+
27
+ // src/hooks/use-workflow-run.ts
28
+ import { useState, useEffect, useCallback } from "react";
29
+ function useWorkflowRun(options) {
30
+ const { client } = useStepflow();
31
+ const {
32
+ runId,
33
+ accessToken,
34
+ onStepComplete,
35
+ onComplete,
36
+ onError,
37
+ throttleMs,
38
+ enabled = true
39
+ } = options;
40
+ const [state, setState] = useState({
41
+ run: null,
42
+ status: "pending",
43
+ steps: [],
44
+ metadata: {},
45
+ error: null,
46
+ isLoading: true,
47
+ isConnected: false
48
+ });
49
+ const refetch = useCallback(async () => {
50
+ if (!enabled) return;
51
+ try {
52
+ setState((prev) => ({ ...prev, isLoading: true }));
53
+ const run = await client.getRun(runId, {
54
+ accessToken
55
+ });
56
+ if (run) {
57
+ setState((prev) => ({
58
+ ...prev,
59
+ run,
60
+ status: run.status,
61
+ steps: run.steps,
62
+ metadata: run.metadata,
63
+ isLoading: false
64
+ }));
65
+ }
66
+ } catch (err) {
67
+ setState((prev) => ({
68
+ ...prev,
69
+ error: err instanceof Error ? err : new Error(String(err)),
70
+ isLoading: false
71
+ }));
72
+ }
73
+ }, [client, runId, accessToken, enabled]);
74
+ useEffect(() => {
75
+ if (!enabled) return;
76
+ refetch();
77
+ const unsubscribe = client.subscribeToRun(runId, {
78
+ accessToken,
79
+ throttleMs,
80
+ onUpdate: (run) => {
81
+ setState((prev) => ({
82
+ ...prev,
83
+ run,
84
+ status: run.status,
85
+ steps: run.steps,
86
+ metadata: run.metadata,
87
+ isLoading: false
88
+ }));
89
+ },
90
+ onStepComplete: (step) => {
91
+ setState((prev) => ({
92
+ ...prev,
93
+ steps: [...prev.steps.filter((s) => s.name !== step.name), step]
94
+ }));
95
+ onStepComplete?.(step);
96
+ },
97
+ onComplete: (result) => {
98
+ setState((prev) => ({
99
+ ...prev,
100
+ status: "completed",
101
+ isLoading: false
102
+ }));
103
+ onComplete?.(result);
104
+ },
105
+ onError: (error) => {
106
+ setState((prev) => ({
107
+ ...prev,
108
+ error,
109
+ status: "failed",
110
+ isLoading: false
111
+ }));
112
+ onError?.(error);
113
+ },
114
+ onConnect: () => {
115
+ setState((prev) => ({ ...prev, isConnected: true }));
116
+ },
117
+ onDisconnect: () => {
118
+ setState((prev) => ({ ...prev, isConnected: false }));
119
+ }
120
+ });
121
+ return () => {
122
+ unsubscribe();
123
+ };
124
+ }, [
125
+ client,
126
+ runId,
127
+ accessToken,
128
+ enabled,
129
+ throttleMs,
130
+ onStepComplete,
131
+ onComplete,
132
+ onError,
133
+ refetch
134
+ ]);
135
+ return {
136
+ ...state,
137
+ refetch
138
+ };
139
+ }
140
+
141
+ // src/hooks/use-workflow-trigger.ts
142
+ import { useState as useState2, useCallback as useCallback2 } from "react";
143
+ function useWorkflowTrigger(options) {
144
+ const { client } = useStepflow();
145
+ const { workflowId, onSuccess, onError } = options;
146
+ const [state, setState] = useState2({
147
+ runId: null,
148
+ executionId: null,
149
+ accessToken: null,
150
+ isTriggering: false,
151
+ error: null
152
+ });
153
+ const trigger = useCallback2(
154
+ async (payload, triggerOptions) => {
155
+ setState((prev) => ({
156
+ ...prev,
157
+ isTriggering: true,
158
+ error: null
159
+ }));
160
+ try {
161
+ const result = await client.trigger(
162
+ workflowId,
163
+ payload,
164
+ triggerOptions
165
+ );
166
+ setState({
167
+ runId: result.runId,
168
+ executionId: result.executionId,
169
+ accessToken: result.publicAccessToken,
170
+ isTriggering: false,
171
+ error: null
172
+ });
173
+ onSuccess?.(result);
174
+ return result;
175
+ } catch (err) {
176
+ const error = err instanceof Error ? err : new Error(String(err));
177
+ setState((prev) => ({
178
+ ...prev,
179
+ isTriggering: false,
180
+ error
181
+ }));
182
+ onError?.(error);
183
+ throw error;
184
+ }
185
+ },
186
+ [client, workflowId, onSuccess, onError]
187
+ );
188
+ const reset = useCallback2(() => {
189
+ setState({
190
+ runId: null,
191
+ executionId: null,
192
+ accessToken: null,
193
+ isTriggering: false,
194
+ error: null
195
+ });
196
+ }, []);
197
+ return {
198
+ trigger,
199
+ ...state,
200
+ reset
201
+ };
202
+ }
203
+
204
+ // src/hooks/use-workflow-stream.ts
205
+ import { useState as useState3, useCallback as useCallback3, useRef, useEffect as useEffect2 } from "react";
206
+ function useWorkflowStream(options) {
207
+ const { client } = useStepflow();
208
+ const {
209
+ workflowId,
210
+ payload,
211
+ autoStart = false,
212
+ onComplete,
213
+ onError
214
+ } = options;
215
+ const [state, setState] = useState3({
216
+ events: [],
217
+ result: null,
218
+ status: "pending",
219
+ isStreaming: false,
220
+ error: null
221
+ });
222
+ const abortControllerRef = useRef(null);
223
+ const start = useCallback3(async () => {
224
+ abortControllerRef.current?.abort();
225
+ abortControllerRef.current = new AbortController();
226
+ setState((prev) => ({
227
+ ...prev,
228
+ events: [],
229
+ result: null,
230
+ status: "running",
231
+ isStreaming: true,
232
+ error: null
233
+ }));
234
+ try {
235
+ const stream = client.stream(workflowId, payload, {
236
+ signal: abortControllerRef.current.signal
237
+ });
238
+ for await (const event of stream) {
239
+ const workflowEvent = {
240
+ type: event.type,
241
+ data: event.data,
242
+ timestamp: /* @__PURE__ */ new Date(),
243
+ stepName: event.stepName
244
+ };
245
+ setState((prev) => ({
246
+ ...prev,
247
+ events: [...prev.events, workflowEvent]
248
+ }));
249
+ if (event.type === "execution:complete") {
250
+ const result = event.data;
251
+ setState((prev) => ({
252
+ ...prev,
253
+ result,
254
+ status: "completed",
255
+ isStreaming: false
256
+ }));
257
+ onComplete?.(result);
258
+ }
259
+ if (event.type === "execution:failed") {
260
+ const error = new Error(event.data.message);
261
+ setState((prev) => ({
262
+ ...prev,
263
+ error,
264
+ status: "failed",
265
+ isStreaming: false
266
+ }));
267
+ onError?.(error);
268
+ }
269
+ }
270
+ } catch (err) {
271
+ if (err.name === "AbortError") {
272
+ setState((prev) => ({ ...prev, isStreaming: false }));
273
+ return;
274
+ }
275
+ const error = err instanceof Error ? err : new Error(String(err));
276
+ setState((prev) => ({
277
+ ...prev,
278
+ error,
279
+ status: "failed",
280
+ isStreaming: false
281
+ }));
282
+ onError?.(error);
283
+ }
284
+ }, [client, workflowId, payload, onComplete, onError]);
285
+ const stop = useCallback3(() => {
286
+ abortControllerRef.current?.abort();
287
+ setState((prev) => ({ ...prev, isStreaming: false }));
288
+ }, []);
289
+ const reset = useCallback3(() => {
290
+ abortControllerRef.current?.abort();
291
+ setState({
292
+ events: [],
293
+ result: null,
294
+ status: "pending",
295
+ isStreaming: false,
296
+ error: null
297
+ });
298
+ }, []);
299
+ useEffect2(() => {
300
+ if (autoStart) {
301
+ start();
302
+ }
303
+ return () => {
304
+ abortControllerRef.current?.abort();
305
+ };
306
+ }, [autoStart, start]);
307
+ return {
308
+ start,
309
+ stop,
310
+ reset,
311
+ ...state
312
+ };
313
+ }
314
+ export {
315
+ StepflowProvider,
316
+ useStepflow,
317
+ useWorkflowRun,
318
+ useWorkflowStream,
319
+ useWorkflowTrigger
320
+ };
321
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/providers/stepflow-provider.tsx","../src/hooks/use-workflow-run.ts","../src/hooks/use-workflow-trigger.ts","../src/hooks/use-workflow-stream.ts"],"sourcesContent":["// ============================================================================\n// StepflowProvider - React context for Stepflow client\n// ============================================================================\n\nimport React, { createContext, useContext, useMemo } from \"react\";\nimport { StepflowClient, type StepflowClientConfig } from \"@stepflowjs/client-ts\";\n\n// ============================================================================\n// Context\n// ============================================================================\n\ninterface StepflowContextValue {\n client: StepflowClient;\n config: StepflowClientConfig;\n}\n\nconst StepflowContext = createContext<StepflowContextValue | null>(null);\n\n// ============================================================================\n// Provider\n// ============================================================================\n\nexport interface StepflowProviderProps {\n children: React.ReactNode;\n config: StepflowClientConfig;\n}\n\nexport function StepflowProvider({\n children,\n config,\n}: StepflowProviderProps): React.ReactElement {\n const client = useMemo(\n () => new StepflowClient(config),\n [config.baseUrl, config.apiKey, config.publicApiKey, config.wsUrl],\n );\n\n const value = useMemo(() => ({ client, config }), [client, config]);\n\n return (\n <StepflowContext.Provider value={value}>\n {children}\n </StepflowContext.Provider>\n );\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function useStepflow(): StepflowContextValue {\n const context = useContext(StepflowContext);\n\n if (!context) {\n throw new Error(\"useStepflow must be used within a StepflowProvider\");\n }\n\n return context;\n}\n","// ============================================================================\n// useWorkflowRun - Subscribe to workflow run updates\n// ============================================================================\n\nimport { useState, useEffect, useCallback } from \"react\";\nimport { useStepflow } from \"../providers/stepflow-provider.js\";\nimport type {\n Execution,\n ExecutionStatus,\n StepExecution,\n} from \"@stepflowjs/client-ts\";\n\nexport interface UseWorkflowRunOptions {\n /**\n * The run ID to subscribe to\n */\n runId: string;\n\n /**\n * Public access token for the run\n */\n accessToken?: string;\n\n /**\n * Callback when a step completes\n */\n onStepComplete?: (step: StepExecution) => void;\n\n /**\n * Callback when the workflow completes\n */\n onComplete?: (result: unknown) => void;\n\n /**\n * Callback when the workflow fails\n */\n onError?: (error: Error) => void;\n\n /**\n * Throttle updates (ms)\n */\n throttleMs?: number;\n\n /**\n * Enable/disable the subscription\n */\n enabled?: boolean;\n}\n\nexport interface UseWorkflowRunResult<TPayload = unknown, TResult = unknown> {\n /**\n * The current execution state\n */\n run: Execution<TPayload, TResult> | null;\n\n /**\n * Current execution status\n */\n status: ExecutionStatus;\n\n /**\n * Completed steps\n */\n steps: StepExecution[];\n\n /**\n * Execution metadata\n */\n metadata: Record<string, unknown>;\n\n /**\n * Error if any\n */\n error: Error | null;\n\n /**\n * Loading state\n */\n isLoading: boolean;\n\n /**\n * Connection state\n */\n isConnected: boolean;\n\n /**\n * Refetch the run data\n */\n refetch: () => Promise<void>;\n}\n\nexport function useWorkflowRun<TPayload = unknown, TResult = unknown>(\n options: UseWorkflowRunOptions,\n): UseWorkflowRunResult<TPayload, TResult> {\n const { client } = useStepflow();\n const {\n runId,\n accessToken,\n onStepComplete,\n onComplete,\n onError,\n throttleMs,\n enabled = true,\n } = options;\n\n const [state, setState] = useState<{\n run: Execution<TPayload, TResult> | null;\n status: ExecutionStatus;\n steps: StepExecution[];\n metadata: Record<string, unknown>;\n error: Error | null;\n isLoading: boolean;\n isConnected: boolean;\n }>({\n run: null,\n status: \"pending\",\n steps: [],\n metadata: {},\n error: null,\n isLoading: true,\n isConnected: false,\n });\n\n const refetch = useCallback(async () => {\n if (!enabled) return;\n\n try {\n setState((prev) => ({ ...prev, isLoading: true }));\n const run = await client.getRun<TPayload, TResult>(runId, {\n accessToken,\n });\n\n if (run) {\n setState((prev) => ({\n ...prev,\n run,\n status: run.status,\n steps: run.steps,\n metadata: run.metadata,\n isLoading: false,\n }));\n }\n } catch (err) {\n setState((prev) => ({\n ...prev,\n error: err instanceof Error ? err : new Error(String(err)),\n isLoading: false,\n }));\n }\n }, [client, runId, accessToken, enabled]);\n\n useEffect(() => {\n if (!enabled) return;\n\n // Initial fetch\n refetch();\n\n // Subscribe to updates\n const unsubscribe = client.subscribeToRun<TPayload, TResult>(runId, {\n accessToken,\n throttleMs,\n onUpdate: (run) => {\n setState((prev) => ({\n ...prev,\n run,\n status: run.status,\n steps: run.steps,\n metadata: run.metadata,\n isLoading: false,\n }));\n },\n onStepComplete: (step) => {\n setState((prev) => ({\n ...prev,\n steps: [...prev.steps.filter((s) => s.name !== step.name), step],\n }));\n onStepComplete?.(step);\n },\n onComplete: (result) => {\n setState((prev) => ({\n ...prev,\n status: \"completed\",\n isLoading: false,\n }));\n onComplete?.(result);\n },\n onError: (error) => {\n setState((prev) => ({\n ...prev,\n error,\n status: \"failed\",\n isLoading: false,\n }));\n onError?.(error);\n },\n onConnect: () => {\n setState((prev) => ({ ...prev, isConnected: true }));\n },\n onDisconnect: () => {\n setState((prev) => ({ ...prev, isConnected: false }));\n },\n });\n\n return () => {\n unsubscribe();\n };\n }, [\n client,\n runId,\n accessToken,\n enabled,\n throttleMs,\n onStepComplete,\n onComplete,\n onError,\n refetch,\n ]);\n\n return {\n ...state,\n refetch,\n };\n}\n","// ============================================================================\n// useWorkflowTrigger - Trigger a workflow and get access token\n// ============================================================================\n\nimport { useState, useCallback } from \"react\";\nimport { useStepflow } from \"../providers/stepflow-provider.js\";\nimport type { TriggerResult } from \"@stepflowjs/client-ts\";\n\nexport interface UseWorkflowTriggerOptions {\n /**\n * The workflow ID to trigger\n */\n workflowId: string;\n\n /**\n * Callback on successful trigger\n */\n onSuccess?: (result: TriggerResult) => void;\n\n /**\n * Callback on error\n */\n onError?: (error: Error) => void;\n}\n\nexport interface UseWorkflowTriggerResult<TPayload = unknown> {\n /**\n * Trigger the workflow with payload\n */\n trigger: (\n payload: TPayload,\n options?: TriggerOptions,\n ) => Promise<TriggerResult>;\n\n /**\n * The run ID from the last trigger\n */\n runId: string | null;\n\n /**\n * The execution ID from the last trigger\n */\n executionId: string | null;\n\n /**\n * Public access token for the run\n */\n accessToken: string | null;\n\n /**\n * Whether a trigger is in progress\n */\n isTriggering: boolean;\n\n /**\n * Error from the last trigger\n */\n error: Error | null;\n\n /**\n * Reset the state\n */\n reset: () => void;\n}\n\nexport interface TriggerOptions {\n /**\n * Custom run ID\n */\n runId?: string;\n\n /**\n * Additional metadata\n */\n metadata?: Record<string, unknown>;\n\n /**\n * Delay before execution (ms)\n */\n delay?: number;\n}\n\nexport function useWorkflowTrigger<TPayload = unknown>(\n options: UseWorkflowTriggerOptions,\n): UseWorkflowTriggerResult<TPayload> {\n const { client } = useStepflow();\n const { workflowId, onSuccess, onError } = options;\n\n const [state, setState] = useState<{\n runId: string | null;\n executionId: string | null;\n accessToken: string | null;\n isTriggering: boolean;\n error: Error | null;\n }>({\n runId: null,\n executionId: null,\n accessToken: null,\n isTriggering: false,\n error: null,\n });\n\n const trigger = useCallback(\n async (\n payload: TPayload,\n triggerOptions?: TriggerOptions,\n ): Promise<TriggerResult> => {\n setState((prev) => ({\n ...prev,\n isTriggering: true,\n error: null,\n }));\n\n try {\n const result = await client.trigger(\n workflowId,\n payload,\n triggerOptions,\n );\n\n setState({\n runId: result.runId,\n executionId: result.executionId,\n accessToken: result.publicAccessToken,\n isTriggering: false,\n error: null,\n });\n\n onSuccess?.(result);\n return result;\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n\n setState((prev) => ({\n ...prev,\n isTriggering: false,\n error,\n }));\n\n onError?.(error);\n throw error;\n }\n },\n [client, workflowId, onSuccess, onError],\n );\n\n const reset = useCallback(() => {\n setState({\n runId: null,\n executionId: null,\n accessToken: null,\n isTriggering: false,\n error: null,\n });\n }, []);\n\n return {\n trigger,\n ...state,\n reset,\n };\n}\n","// ============================================================================\n// useWorkflowStream - Stream workflow execution with real-time events\n// ============================================================================\n\nimport { useState, useCallback, useRef, useEffect } from \"react\";\nimport { useStepflow } from \"../providers/stepflow-provider.js\";\nimport type { ExecutionStatus } from \"@stepflowjs/client-ts\";\n\nexport interface UseWorkflowStreamOptions<TPayload, TResult> {\n /**\n * The workflow ID to execute\n */\n workflowId: string;\n\n /**\n * The payload to send\n */\n payload: TPayload;\n\n /**\n * Auto-start the stream\n */\n autoStart?: boolean;\n\n /**\n * Callback on workflow completion\n */\n onComplete?: (result: TResult) => void;\n\n /**\n * Callback on error\n */\n onError?: (error: Error) => void;\n}\n\nexport interface UseWorkflowStreamResult<TResult = unknown> {\n /**\n * Start the workflow stream\n */\n start: () => Promise<void>;\n\n /**\n * Stop/abort the stream\n */\n stop: () => void;\n\n /**\n * All received events\n */\n events: WorkflowEvent[];\n\n /**\n * Final result (when complete)\n */\n result: TResult | null;\n\n /**\n * Current status\n */\n status: ExecutionStatus;\n\n /**\n * Whether streaming is active\n */\n isStreaming: boolean;\n\n /**\n * Error if any\n */\n error: Error | null;\n\n /**\n * Reset the state\n */\n reset: () => void;\n}\n\nexport interface WorkflowEvent {\n type: string;\n data: unknown;\n timestamp: Date;\n stepName?: string;\n}\n\nexport function useWorkflowStream<TPayload = unknown, TResult = unknown>(\n options: UseWorkflowStreamOptions<TPayload, TResult>,\n): UseWorkflowStreamResult<TResult> {\n const { client } = useStepflow();\n const {\n workflowId,\n payload,\n autoStart = false,\n onComplete,\n onError,\n } = options;\n\n const [state, setState] = useState<{\n events: WorkflowEvent[];\n result: TResult | null;\n status: ExecutionStatus;\n isStreaming: boolean;\n error: Error | null;\n }>({\n events: [],\n result: null,\n status: \"pending\",\n isStreaming: false,\n error: null,\n });\n\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const start = useCallback(async () => {\n // Abort any existing stream\n abortControllerRef.current?.abort();\n abortControllerRef.current = new AbortController();\n\n setState((prev) => ({\n ...prev,\n events: [],\n result: null,\n status: \"running\",\n isStreaming: true,\n error: null,\n }));\n\n try {\n const stream = client.stream<TPayload, TResult>(workflowId, payload, {\n signal: abortControllerRef.current.signal,\n });\n\n for await (const event of stream) {\n const workflowEvent: WorkflowEvent = {\n type: event.type,\n data: event.data,\n timestamp: new Date(),\n stepName: event.stepName,\n };\n\n setState((prev) => ({\n ...prev,\n events: [...prev.events, workflowEvent],\n }));\n\n if (event.type === \"execution:complete\") {\n const result = event.data as TResult;\n setState((prev) => ({\n ...prev,\n result,\n status: \"completed\",\n isStreaming: false,\n }));\n onComplete?.(result);\n }\n\n if (event.type === \"execution:failed\") {\n const error = new Error((event.data as { message: string }).message);\n setState((prev) => ({\n ...prev,\n error,\n status: \"failed\",\n isStreaming: false,\n }));\n onError?.(error);\n }\n }\n } catch (err) {\n if ((err as Error).name === \"AbortError\") {\n setState((prev) => ({ ...prev, isStreaming: false }));\n return;\n }\n\n const error = err instanceof Error ? err : new Error(String(err));\n setState((prev) => ({\n ...prev,\n error,\n status: \"failed\",\n isStreaming: false,\n }));\n onError?.(error);\n }\n }, [client, workflowId, payload, onComplete, onError]);\n\n const stop = useCallback(() => {\n abortControllerRef.current?.abort();\n setState((prev) => ({ ...prev, isStreaming: false }));\n }, []);\n\n const reset = useCallback(() => {\n abortControllerRef.current?.abort();\n setState({\n events: [],\n result: null,\n status: \"pending\",\n isStreaming: false,\n error: null,\n });\n }, []);\n\n useEffect(() => {\n if (autoStart) {\n start();\n }\n\n return () => {\n abortControllerRef.current?.abort();\n };\n }, [autoStart, start]); // Only run on mount and autoStart change\n\n return {\n start,\n stop,\n reset,\n ...state,\n };\n}\n"],"mappings":"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","names":["useState","useCallback","useState","useCallback","useState","useCallback","useEffect","useState","useCallback","useEffect"]}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@stepflowjs/react",
3
+ "version": "0.0.1",
4
+ "description": "React hooks for Stepflow workflow orchestration",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "dependencies": {
19
+ "@stepflowjs/client-ts": "0.0.1"
20
+ },
21
+ "peerDependencies": {
22
+ "react": "^18.0.0 || ^19.0.0",
23
+ "typescript": "^5.0.0"
24
+ },
25
+ "devDependencies": {
26
+ "@types/react": "^19.2.8",
27
+ "@types/react-dom": "^19.2.3",
28
+ "react": "^19.2.3",
29
+ "tsup": "^8.5.1",
30
+ "vitest": "^4.0.17"
31
+ },
32
+ "license": "MIT",
33
+ "author": "Stepflow Contributors",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://stepflow-production.up.railway.app",
37
+ "directory": "packages/client-react"
38
+ },
39
+ "homepage": "https://stepflow-production.up.railway.app",
40
+ "bugs": {
41
+ "url": "https://stepflow-production.up.railway.app"
42
+ },
43
+ "keywords": [
44
+ "stepflow",
45
+ "workflow",
46
+ "orchestration",
47
+ "react",
48
+ "hooks",
49
+ "client",
50
+ "sdk"
51
+ ],
52
+ "publishConfig": {
53
+ "access": "public"
54
+ },
55
+ "scripts": {
56
+ "build": "tsup",
57
+ "dev": "tsup --watch",
58
+ "typecheck": "tsc --noEmit",
59
+ "test": "vitest",
60
+ "clean": "rm -rf dist"
61
+ }
62
+ }