react-pyworkflow 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.
package/dist/index.mjs ADDED
@@ -0,0 +1,448 @@
1
+ // src/Task.ts
2
+ var Task = class {
3
+ constructor(options) {
4
+ this.state = "PENDING";
5
+ this.history = [];
6
+ this.attempts = 0;
7
+ this.name = options.name;
8
+ this.fn = options.fn;
9
+ this.description = options.description || "";
10
+ this.retries = options.retries || 0;
11
+ this.retryDelay = options.retryDelay || 0;
12
+ this.timeout = options.timeout;
13
+ this.dependsOn = options.dependsOn || [];
14
+ this.condition = options.condition;
15
+ this.onFailure = options.onFailure;
16
+ this.continueOnFailure = options.continueOnFailure || false;
17
+ }
18
+ reset() {
19
+ this.state = "PENDING";
20
+ this.output = void 0;
21
+ this.error = void 0;
22
+ this.history = [];
23
+ this.startedAt = void 0;
24
+ this.finishedAt = void 0;
25
+ this.attempts = 0;
26
+ }
27
+ async run(context) {
28
+ if (this.condition) {
29
+ try {
30
+ const shouldRun = await this.condition(context);
31
+ if (!shouldRun) {
32
+ this.state = "SKIPPED";
33
+ const skippedResult = {
34
+ state: "SKIPPED",
35
+ attempt: 0,
36
+ startedAt: Date.now(),
37
+ finishedAt: Date.now()
38
+ };
39
+ this.history.push(skippedResult);
40
+ return skippedResult;
41
+ }
42
+ } catch (err) {
43
+ this.state = "FAILED";
44
+ const condError = err instanceof Error ? err : new Error(String(err));
45
+ this.error = `Condition error: ${condError.message}`;
46
+ const failedResult = {
47
+ state: "FAILED",
48
+ attempt: 1,
49
+ error: this.error,
50
+ exception: condError,
51
+ startedAt: Date.now(),
52
+ finishedAt: Date.now()
53
+ };
54
+ this.history.push(failedResult);
55
+ if (this.onFailure) {
56
+ try {
57
+ await this.onFailure(this.name, condError);
58
+ } catch (_) {
59
+ }
60
+ }
61
+ throw condError;
62
+ }
63
+ }
64
+ const maxAttempts = this.retries + 1;
65
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
66
+ this.attempts = attempt;
67
+ this.state = attempt === 1 ? "RUNNING" : "RETRYING";
68
+ const started = Date.now();
69
+ try {
70
+ let taskPromise = Promise.resolve(this.fn(context));
71
+ if (this.timeout && this.timeout > 0) {
72
+ const timeoutPromise = new Promise(
73
+ (_, reject) => setTimeout(() => reject(new Error(`Timeout of ${this.timeout}ms exceeded`)), this.timeout)
74
+ );
75
+ taskPromise = Promise.race([taskPromise, timeoutPromise]);
76
+ }
77
+ const result = await taskPromise;
78
+ const finished = Date.now();
79
+ this.state = "COMPLETED";
80
+ this.output = result;
81
+ this.startedAt = started;
82
+ this.finishedAt = finished;
83
+ const successResult = {
84
+ state: "COMPLETED",
85
+ output: result,
86
+ startedAt: started,
87
+ finishedAt: finished,
88
+ attempt
89
+ };
90
+ this.history.push(successResult);
91
+ return successResult;
92
+ } catch (err) {
93
+ const finished = Date.now();
94
+ const errorMsg = err instanceof Error ? err.message : String(err);
95
+ const exception = err instanceof Error ? err : new Error(errorMsg);
96
+ const attemptResult = {
97
+ state: "FAILED",
98
+ error: errorMsg,
99
+ exception,
100
+ startedAt: started,
101
+ finishedAt: finished,
102
+ attempt
103
+ };
104
+ this.history.push(attemptResult);
105
+ if (attempt < maxAttempts) {
106
+ if (this.retryDelay > 0) {
107
+ await new Promise((resolve) => setTimeout(resolve, this.retryDelay));
108
+ }
109
+ continue;
110
+ }
111
+ this.state = "FAILED";
112
+ this.error = errorMsg;
113
+ this.startedAt = started;
114
+ this.finishedAt = finished;
115
+ if (this.onFailure) {
116
+ try {
117
+ await this.onFailure(this.name, exception);
118
+ } catch (_) {
119
+ }
120
+ }
121
+ if (!this.continueOnFailure) {
122
+ throw exception;
123
+ }
124
+ return attemptResult;
125
+ }
126
+ }
127
+ throw new Error("Unexpected end of retry loop");
128
+ }
129
+ };
130
+
131
+ // src/Workflow.ts
132
+ var Workflow = class {
133
+ constructor(name) {
134
+ this.tasks = /* @__PURE__ */ new Map();
135
+ this.state = "CREATED";
136
+ this.context = {};
137
+ // Order of insertion to support fluent .then() chaining
138
+ this.insertionOrder = [];
139
+ // Listeners for real-time reactivity
140
+ this.stateChangeListeners = [];
141
+ this.taskStateChangeListeners = [];
142
+ this.name = name;
143
+ }
144
+ addTask(task) {
145
+ if (this.tasks.has(task.name)) {
146
+ throw new Error(`Task with name '${task.name}' already exists in workflow '${this.name}'`);
147
+ }
148
+ this.tasks.set(task.name, task);
149
+ this.insertionOrder.push(task.name);
150
+ return this;
151
+ }
152
+ addTasks(tasks) {
153
+ tasks.forEach((t) => this.addTask(t));
154
+ return this;
155
+ }
156
+ then(task) {
157
+ if (this.insertionOrder.length > 0) {
158
+ const lastTaskName = this.insertionOrder[this.insertionOrder.length - 1];
159
+ if (!task.dependsOn.includes(lastTaskName)) {
160
+ task.dependsOn.push(lastTaskName);
161
+ }
162
+ }
163
+ return this.addTask(task);
164
+ }
165
+ reset() {
166
+ this.state = "CREATED";
167
+ this.context = {};
168
+ this.startedAt = void 0;
169
+ this.finishedAt = void 0;
170
+ this.tasks.forEach((t) => t.reset());
171
+ this.notifyStateChange("CREATED");
172
+ }
173
+ // Subscribe to workflow state changes
174
+ onStateChange(listener) {
175
+ this.stateChangeListeners.push(listener);
176
+ return () => {
177
+ this.stateChangeListeners = this.stateChangeListeners.filter((l) => l !== listener);
178
+ };
179
+ }
180
+ // Subscribe to task state changes
181
+ onTaskStateChange(listener) {
182
+ this.taskStateChangeListeners.push(listener);
183
+ return () => {
184
+ this.taskStateChangeListeners = this.taskStateChangeListeners.filter((l) => l !== listener);
185
+ };
186
+ }
187
+ notifyStateChange(state) {
188
+ this.state = state;
189
+ this.stateChangeListeners.forEach((l) => l(state));
190
+ }
191
+ notifyTaskStateChange(taskName, state) {
192
+ const task = this.tasks.get(taskName);
193
+ if (task) {
194
+ task.state = state;
195
+ }
196
+ this.taskStateChangeListeners.forEach((l) => l(taskName, state));
197
+ }
198
+ validate() {
199
+ this.tasks.forEach((task) => {
200
+ task.dependsOn.forEach((dep) => {
201
+ if (!this.tasks.has(dep)) {
202
+ throw new Error(
203
+ `Task '${task.name}' depends on missing task '${dep}' in workflow '${this.name}'`
204
+ );
205
+ }
206
+ });
207
+ });
208
+ this.getTopologicalLevels();
209
+ }
210
+ getTopologicalLevels() {
211
+ const inDegree = {};
212
+ const dependents = {};
213
+ this.tasks.forEach((_, name) => {
214
+ inDegree[name] = 0;
215
+ dependents[name] = [];
216
+ });
217
+ this.tasks.forEach((task, name) => {
218
+ task.dependsOn.forEach((dep) => {
219
+ inDegree[name]++;
220
+ dependents[dep].push(name);
221
+ });
222
+ });
223
+ const levels = [];
224
+ let remaining = { ...inDegree };
225
+ let placedCount = 0;
226
+ let current = Object.keys(remaining).filter((n) => remaining[n] === 0);
227
+ current.sort((a, b) => this.insertionOrder.indexOf(a) - this.insertionOrder.indexOf(b));
228
+ while (current.length > 0) {
229
+ levels.push(current);
230
+ placedCount += current.length;
231
+ const nextLevel = [];
232
+ current.forEach((node) => {
233
+ delete remaining[node];
234
+ dependents[node].forEach((dep) => {
235
+ remaining[dep]--;
236
+ if (remaining[dep] === 0) {
237
+ nextLevel.push(dep);
238
+ }
239
+ });
240
+ });
241
+ nextLevel.sort((a, b) => this.insertionOrder.indexOf(a) - this.insertionOrder.indexOf(b));
242
+ current = nextLevel;
243
+ }
244
+ if (placedCount !== this.tasks.size) {
245
+ throw new Error(`Workflow '${this.name}' contains a cyclic dependency`);
246
+ }
247
+ return levels;
248
+ }
249
+ async run(options = {}) {
250
+ if (this.state === "RUNNING") {
251
+ throw new Error(`Workflow '${this.name}' is already running`);
252
+ }
253
+ this.validate();
254
+ this.startedAt = Date.now();
255
+ this.notifyStateChange("RUNNING");
256
+ const parallel = options.parallel ?? false;
257
+ const failedTasks = [];
258
+ const skippedTasks = [];
259
+ let globalError = void 0;
260
+ try {
261
+ const levels = this.getTopologicalLevels();
262
+ if (parallel) {
263
+ for (const level of levels) {
264
+ if (globalError) break;
265
+ const levelPromises = level.map(async (taskName) => {
266
+ const task = this.tasks.get(taskName);
267
+ const depFailedOrSkipped = task.dependsOn.some(
268
+ (dep) => failedTasks.includes(dep) || skippedTasks.includes(dep)
269
+ );
270
+ if (depFailedOrSkipped) {
271
+ skippedTasks.push(taskName);
272
+ this.notifyTaskStateChange(taskName, "SKIPPED");
273
+ return;
274
+ }
275
+ this.notifyTaskStateChange(taskName, "RUNNING");
276
+ try {
277
+ task.onFailure = (name) => {
278
+ this.notifyTaskStateChange(name, "FAILED");
279
+ };
280
+ const taskResult = await task.run(this.context);
281
+ if (taskResult.state === "COMPLETED") {
282
+ this.context[taskName] = taskResult.output;
283
+ this.notifyTaskStateChange(taskName, "COMPLETED");
284
+ } else if (taskResult.state === "SKIPPED") {
285
+ this.notifyTaskStateChange(taskName, "SKIPPED");
286
+ skippedTasks.push(taskName);
287
+ } else {
288
+ failedTasks.push(taskName);
289
+ this.notifyTaskStateChange(taskName, "FAILED");
290
+ }
291
+ } catch (err) {
292
+ failedTasks.push(taskName);
293
+ this.notifyTaskStateChange(taskName, "FAILED");
294
+ if (!task.continueOnFailure) {
295
+ globalError = err instanceof Error ? err : new Error(String(err));
296
+ }
297
+ }
298
+ });
299
+ await Promise.all(levelPromises);
300
+ }
301
+ } else {
302
+ for (const level of levels) {
303
+ if (globalError) break;
304
+ for (const taskName of level) {
305
+ const task = this.tasks.get(taskName);
306
+ const depFailedOrSkipped = task.dependsOn.some(
307
+ (dep) => failedTasks.includes(dep) || skippedTasks.includes(dep)
308
+ );
309
+ if (depFailedOrSkipped) {
310
+ skippedTasks.push(taskName);
311
+ this.notifyTaskStateChange(taskName, "SKIPPED");
312
+ continue;
313
+ }
314
+ this.notifyTaskStateChange(taskName, "RUNNING");
315
+ try {
316
+ task.onFailure = (name) => {
317
+ this.notifyTaskStateChange(name, "FAILED");
318
+ };
319
+ const taskResult = await task.run(this.context);
320
+ if (taskResult.state === "COMPLETED") {
321
+ this.context[taskName] = taskResult.output;
322
+ this.notifyTaskStateChange(taskName, "COMPLETED");
323
+ } else if (taskResult.state === "SKIPPED") {
324
+ this.notifyTaskStateChange(taskName, "SKIPPED");
325
+ skippedTasks.push(taskName);
326
+ } else {
327
+ failedTasks.push(taskName);
328
+ this.notifyTaskStateChange(taskName, "FAILED");
329
+ }
330
+ } catch (err) {
331
+ failedTasks.push(taskName);
332
+ this.notifyTaskStateChange(taskName, "FAILED");
333
+ if (!task.continueOnFailure) {
334
+ globalError = err instanceof Error ? err : new Error(String(err));
335
+ break;
336
+ }
337
+ }
338
+ }
339
+ }
340
+ }
341
+ this.finishedAt = Date.now();
342
+ const success = failedTasks.length === 0 && !globalError;
343
+ this.notifyStateChange(success ? "COMPLETED" : "FAILED");
344
+ return {
345
+ success,
346
+ results: { ...this.context },
347
+ error: globalError,
348
+ failedTasks,
349
+ skippedTasks
350
+ };
351
+ } catch (err) {
352
+ this.finishedAt = Date.now();
353
+ const mainError = err instanceof Error ? err : new Error(String(err));
354
+ this.notifyStateChange("FAILED");
355
+ return {
356
+ success: false,
357
+ results: { ...this.context },
358
+ error: mainError,
359
+ failedTasks,
360
+ skippedTasks
361
+ };
362
+ }
363
+ }
364
+ };
365
+
366
+ // src/useWorkflow.ts
367
+ import { useState, useEffect, useCallback, useRef } from "react";
368
+ function useWorkflow(workflow) {
369
+ const [workflowState, setWorkflowState] = useState(workflow.state);
370
+ const [taskStates, setTaskStates] = useState(() => {
371
+ const initialStates = {};
372
+ workflow.tasks.forEach((task, name) => {
373
+ initialStates[name] = task.state;
374
+ });
375
+ return initialStates;
376
+ });
377
+ const [outputs, setOutputs] = useState({});
378
+ const [errors, setErrors] = useState({});
379
+ const workflowRef = useRef(workflow);
380
+ useEffect(() => {
381
+ workflowRef.current = workflow;
382
+ }, [workflow]);
383
+ const syncState = useCallback(() => {
384
+ const wf = workflowRef.current;
385
+ setWorkflowState(wf.state);
386
+ const nextTaskStates = {};
387
+ const nextOutputs = {};
388
+ const nextErrors = {};
389
+ wf.tasks.forEach((task, name) => {
390
+ nextTaskStates[name] = task.state;
391
+ if (task.output !== void 0) nextOutputs[name] = task.output;
392
+ if (task.error !== void 0) nextErrors[name] = task.error;
393
+ });
394
+ setTaskStates(nextTaskStates);
395
+ setOutputs(nextOutputs);
396
+ setErrors(nextErrors);
397
+ }, []);
398
+ useEffect(() => {
399
+ const wf = workflow;
400
+ syncState();
401
+ const unsubscribeWf = wf.onStateChange((state) => {
402
+ setWorkflowState(state);
403
+ });
404
+ const unsubscribeTasks = wf.onTaskStateChange((taskName, state) => {
405
+ setTaskStates((prev) => ({ ...prev, [taskName]: state }));
406
+ const task = wf.tasks.get(taskName);
407
+ if (task) {
408
+ if (task.output !== void 0) {
409
+ setOutputs((prev) => ({ ...prev, [taskName]: task.output }));
410
+ }
411
+ if (task.error !== void 0) {
412
+ setErrors((prev) => ({ ...prev, [taskName]: task.error }));
413
+ }
414
+ }
415
+ });
416
+ return () => {
417
+ unsubscribeWf();
418
+ unsubscribeTasks();
419
+ };
420
+ }, [workflow, syncState]);
421
+ const run = useCallback(
422
+ async (options) => {
423
+ const report = await workflowRef.current.run(options);
424
+ syncState();
425
+ return report;
426
+ },
427
+ [syncState]
428
+ );
429
+ const reset = useCallback(() => {
430
+ workflowRef.current.reset();
431
+ syncState();
432
+ }, [syncState]);
433
+ return {
434
+ state: workflowState,
435
+ taskStates,
436
+ outputs,
437
+ errors,
438
+ isRunning: workflowState === "RUNNING",
439
+ run,
440
+ reset
441
+ };
442
+ }
443
+ export {
444
+ Task,
445
+ Workflow,
446
+ useWorkflow
447
+ };
448
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/Task.ts","../src/Workflow.ts","../src/useWorkflow.ts"],"sourcesContent":["import { TaskOptions, TaskState, TaskResult } from \"./types\";\n\nexport class Task<T = any> {\n public name: string;\n public fn: (context: Record<string, any>) => Promise<T> | T;\n public description: string;\n public retries: number;\n public retryDelay: number;\n public timeout?: number;\n public dependsOn: string[];\n public condition?: (context: Record<string, any>) => boolean | Promise<boolean>;\n public onFailure?: (taskName: string, error: Error) => void | Promise<void>;\n public continueOnFailure: boolean;\n\n public state: TaskState = \"PENDING\";\n public output?: T;\n public error?: string;\n public history: TaskResult<T>[] = [];\n public startedAt?: number;\n public finishedAt?: number;\n public attempts: number = 0;\n\n constructor(options: TaskOptions<T>) {\n this.name = options.name;\n this.fn = options.fn;\n this.description = options.description || \"\";\n this.retries = options.retries || 0;\n this.retryDelay = options.retryDelay || 0;\n this.timeout = options.timeout;\n this.dependsOn = options.dependsOn || [];\n this.condition = options.condition;\n this.onFailure = options.onFailure;\n this.continueOnFailure = options.continueOnFailure || false;\n }\n\n public reset(): void {\n this.state = \"PENDING\";\n this.output = undefined;\n this.error = undefined;\n this.history = [];\n this.startedAt = undefined;\n this.finishedAt = undefined;\n this.attempts = 0;\n }\n\n public async run(context: Record<string, any>): Promise<TaskResult<T>> {\n // Check condition first\n if (this.condition) {\n try {\n const shouldRun = await this.condition(context);\n if (!shouldRun) {\n this.state = \"SKIPPED\";\n const skippedResult: TaskResult<T> = {\n state: \"SKIPPED\",\n attempt: 0,\n startedAt: Date.now(),\n finishedAt: Date.now(),\n };\n this.history.push(skippedResult);\n return skippedResult;\n }\n } catch (err: any) {\n this.state = \"FAILED\";\n const condError = err instanceof Error ? err : new Error(String(err));\n this.error = `Condition error: ${condError.message}`;\n const failedResult: TaskResult<T> = {\n state: \"FAILED\",\n attempt: 1,\n error: this.error,\n exception: condError,\n startedAt: Date.now(),\n finishedAt: Date.now(),\n };\n this.history.push(failedResult);\n if (this.onFailure) {\n try {\n await this.onFailure(this.name, condError);\n } catch (_) {}\n }\n throw condError;\n }\n }\n\n const maxAttempts = this.retries + 1;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n this.attempts = attempt;\n this.state = attempt === 1 ? \"RUNNING\" : \"RETRYING\";\n const started = Date.now();\n\n try {\n let taskPromise = Promise.resolve(this.fn(context));\n\n if (this.timeout && this.timeout > 0) {\n const timeoutPromise = new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(`Timeout of ${this.timeout}ms exceeded`)), this.timeout)\n );\n taskPromise = Promise.race([taskPromise, timeoutPromise]);\n }\n\n const result = await taskPromise;\n const finished = Date.now();\n\n this.state = \"COMPLETED\";\n this.output = result;\n this.startedAt = started;\n this.finishedAt = finished;\n\n const successResult: TaskResult<T> = {\n state: \"COMPLETED\",\n output: result,\n startedAt: started,\n finishedAt: finished,\n attempt,\n };\n this.history.push(successResult);\n return successResult;\n } catch (err: any) {\n const finished = Date.now();\n const errorMsg = err instanceof Error ? err.message : String(err);\n const exception = err instanceof Error ? err : new Error(errorMsg);\n\n const attemptResult: TaskResult<T> = {\n state: \"FAILED\",\n error: errorMsg,\n exception,\n startedAt: started,\n finishedAt: finished,\n attempt,\n };\n this.history.push(attemptResult);\n\n if (attempt < maxAttempts) {\n if (this.retryDelay > 0) {\n await new Promise((resolve) => setTimeout(resolve, this.retryDelay));\n }\n continue;\n }\n\n // Exhausted all retries\n this.state = \"FAILED\";\n this.error = errorMsg;\n this.startedAt = started;\n this.finishedAt = finished;\n\n if (this.onFailure) {\n try {\n await this.onFailure(this.name, exception);\n } catch (_) {}\n }\n\n if (!this.continueOnFailure) {\n throw exception;\n }\n\n return attemptResult;\n }\n }\n\n throw new Error(\"Unexpected end of retry loop\");\n }\n}\n","import { Task } from \"./Task\";\nimport { WorkflowState, ExecutionReport, TaskState } from \"./types\";\n\nexport class Workflow {\n public name: string;\n public tasks: Map<string, Task> = new Map();\n public state: WorkflowState = \"CREATED\";\n public context: Record<string, any> = {};\n public startedAt?: number;\n public finishedAt?: number;\n\n // Order of insertion to support fluent .then() chaining\n private insertionOrder: string[] = [];\n\n // Listeners for real-time reactivity\n private stateChangeListeners: ((state: WorkflowState) => void)[] = [];\n private taskStateChangeListeners: ((taskName: string, state: TaskState) => void)[] = [];\n\n constructor(name: string) {\n this.name = name;\n }\n\n public addTask(task: Task): this {\n if (this.tasks.has(task.name)) {\n throw new Error(`Task with name '${task.name}' already exists in workflow '${this.name}'`);\n }\n this.tasks.set(task.name, task);\n this.insertionOrder.push(task.name);\n return this;\n }\n\n public addTasks(tasks: Task[]): this {\n tasks.forEach((t) => this.addTask(t));\n return this;\n }\n\n public then(task: Task): this {\n if (this.insertionOrder.length > 0) {\n const lastTaskName = this.insertionOrder[this.insertionOrder.length - 1];\n if (!task.dependsOn.includes(lastTaskName)) {\n task.dependsOn.push(lastTaskName);\n }\n }\n return this.addTask(task);\n }\n\n public reset(): void {\n this.state = \"CREATED\";\n this.context = {};\n this.startedAt = undefined;\n this.finishedAt = undefined;\n this.tasks.forEach((t) => t.reset());\n this.notifyStateChange(\"CREATED\");\n }\n\n // Subscribe to workflow state changes\n public onStateChange(listener: (state: WorkflowState) => void): () => void {\n this.stateChangeListeners.push(listener);\n return () => {\n this.stateChangeListeners = this.stateChangeListeners.filter((l) => l !== listener);\n };\n }\n\n // Subscribe to task state changes\n public onTaskStateChange(listener: (taskName: string, state: TaskState) => void): () => void {\n this.taskStateChangeListeners.push(listener);\n return () => {\n this.taskStateChangeListeners = this.taskStateChangeListeners.filter((l) => l !== listener);\n };\n }\n\n private notifyStateChange(state: WorkflowState): void {\n this.state = state;\n this.stateChangeListeners.forEach((l) => l(state));\n }\n\n private notifyTaskStateChange(taskName: string, state: TaskState): void {\n const task = this.tasks.get(taskName);\n if (task) {\n task.state = state;\n }\n this.taskStateChangeListeners.forEach((l) => l(taskName, state));\n }\n\n public validate(): void {\n // 1. Check for missing dependencies\n this.tasks.forEach((task) => {\n task.dependsOn.forEach((dep) => {\n if (!this.tasks.has(dep)) {\n throw new Error(\n `Task '${task.name}' depends on missing task '${dep}' in workflow '${this.name}'`\n );\n }\n });\n });\n\n // 2. Check for cycle by calling topological sort\n this.getTopologicalLevels();\n }\n\n public getTopologicalLevels(): string[][] {\n const inDegree: Record<string, number> = {};\n const dependents: Record<string, string[]> = {};\n\n this.tasks.forEach((_, name) => {\n inDegree[name] = 0;\n dependents[name] = [];\n });\n\n this.tasks.forEach((task, name) => {\n task.dependsOn.forEach((dep) => {\n inDegree[name]++;\n dependents[dep].push(name);\n });\n });\n\n const levels: string[][] = [];\n let remaining = { ...inDegree };\n let placedCount = 0;\n\n let current = Object.keys(remaining).filter((n) => remaining[n] === 0);\n\n // Sort current level by insertion order\n current.sort((a, b) => this.insertionOrder.indexOf(a) - this.insertionOrder.indexOf(b));\n\n while (current.length > 0) {\n levels.push(current);\n placedCount += current.length;\n\n const nextLevel: string[] = [];\n current.forEach((node) => {\n delete remaining[node];\n dependents[node].forEach((dep) => {\n remaining[dep]--;\n if (remaining[dep] === 0) {\n nextLevel.push(dep);\n }\n });\n });\n\n nextLevel.sort((a, b) => this.insertionOrder.indexOf(a) - this.insertionOrder.indexOf(b));\n current = nextLevel;\n }\n\n if (placedCount !== this.tasks.size) {\n throw new Error(`Workflow '${this.name}' contains a cyclic dependency`);\n }\n\n return levels;\n }\n\n public async run(options: { parallel?: boolean } = {}): Promise<ExecutionReport> {\n if (this.state === \"RUNNING\") {\n throw new Error(`Workflow '${this.name}' is already running`);\n }\n\n this.validate();\n this.startedAt = Date.now();\n this.notifyStateChange(\"RUNNING\");\n\n const parallel = options.parallel ?? false;\n const failedTasks: string[] = [];\n const skippedTasks: string[] = [];\n let globalError: Error | undefined = undefined;\n\n try {\n const levels = this.getTopologicalLevels();\n\n if (parallel) {\n // Execute level-by-level, running tasks within each level concurrently\n for (const level of levels) {\n // Check if previous levels had non-continuable failures\n if (globalError) break;\n\n const levelPromises = level.map(async (taskName) => {\n const task = this.tasks.get(taskName)!;\n\n // Check if any dependencies failed or were skipped\n const depFailedOrSkipped = task.dependsOn.some(\n (dep) => failedTasks.includes(dep) || skippedTasks.includes(dep)\n );\n\n if (depFailedOrSkipped) {\n skippedTasks.push(taskName);\n this.notifyTaskStateChange(taskName, \"SKIPPED\");\n return;\n }\n\n this.notifyTaskStateChange(taskName, \"RUNNING\");\n try {\n // Wrap running status changes during execution loop\n task.onFailure = (name) => {\n this.notifyTaskStateChange(name, \"FAILED\");\n };\n const taskResult = await task.run(this.context);\n if (taskResult.state === \"COMPLETED\") {\n this.context[taskName] = taskResult.output;\n this.notifyTaskStateChange(taskName, \"COMPLETED\");\n } else if (taskResult.state === \"SKIPPED\") {\n this.notifyTaskStateChange(taskName, \"SKIPPED\");\n skippedTasks.push(taskName);\n } else {\n failedTasks.push(taskName);\n this.notifyTaskStateChange(taskName, \"FAILED\");\n }\n } catch (err: any) {\n failedTasks.push(taskName);\n this.notifyTaskStateChange(taskName, \"FAILED\");\n if (!task.continueOnFailure) {\n globalError = err instanceof Error ? err : new Error(String(err));\n }\n }\n });\n\n await Promise.all(levelPromises);\n }\n } else {\n // Execute sequentially node by node in topological levels\n for (const level of levels) {\n if (globalError) break;\n\n for (const taskName of level) {\n const task = this.tasks.get(taskName)!;\n\n const depFailedOrSkipped = task.dependsOn.some(\n (dep) => failedTasks.includes(dep) || skippedTasks.includes(dep)\n );\n\n if (depFailedOrSkipped) {\n skippedTasks.push(taskName);\n this.notifyTaskStateChange(taskName, \"SKIPPED\");\n continue;\n }\n\n this.notifyTaskStateChange(taskName, \"RUNNING\");\n try {\n task.onFailure = (name) => {\n this.notifyTaskStateChange(name, \"FAILED\");\n };\n const taskResult = await task.run(this.context);\n if (taskResult.state === \"COMPLETED\") {\n this.context[taskName] = taskResult.output;\n this.notifyTaskStateChange(taskName, \"COMPLETED\");\n } else if (taskResult.state === \"SKIPPED\") {\n this.notifyTaskStateChange(taskName, \"SKIPPED\");\n skippedTasks.push(taskName);\n } else {\n failedTasks.push(taskName);\n this.notifyTaskStateChange(taskName, \"FAILED\");\n }\n } catch (err: any) {\n failedTasks.push(taskName);\n this.notifyTaskStateChange(taskName, \"FAILED\");\n if (!task.continueOnFailure) {\n globalError = err instanceof Error ? err : new Error(String(err));\n break;\n }\n }\n }\n }\n }\n\n this.finishedAt = Date.now();\n const success = failedTasks.length === 0 && !globalError;\n this.notifyStateChange(success ? \"COMPLETED\" : \"FAILED\");\n\n return {\n success,\n results: { ...this.context },\n error: globalError,\n failedTasks,\n skippedTasks,\n };\n } catch (err: any) {\n this.finishedAt = Date.now();\n const mainError = err instanceof Error ? err : new Error(String(err));\n this.notifyStateChange(\"FAILED\");\n return {\n success: false,\n results: { ...this.context },\n error: mainError,\n failedTasks,\n skippedTasks,\n };\n }\n }\n}\n","import { useState, useEffect, useCallback, useRef } from \"react\";\nimport { Workflow } from \"./Workflow\";\nimport { WorkflowState, TaskState, ExecutionReport } from \"./types\";\n\nexport function useWorkflow(workflow: Workflow) {\n const [workflowState, setWorkflowState] = useState<WorkflowState>(workflow.state);\n const [taskStates, setTaskStates] = useState<Record<string, TaskState>>(() => {\n const initialStates: Record<string, TaskState> = {};\n workflow.tasks.forEach((task, name) => {\n initialStates[name] = task.state;\n });\n return initialStates;\n });\n\n const [outputs, setOutputs] = useState<Record<string, any>>({});\n const [errors, setErrors] = useState<Record<string, string>>({});\n\n // Keep a mutable ref to workflow for stable execution callback\n const workflowRef = useRef(workflow);\n useEffect(() => {\n workflowRef.current = workflow;\n }, [workflow]);\n\n // Synchronize state helpers\n const syncState = useCallback(() => {\n const wf = workflowRef.current;\n setWorkflowState(wf.state);\n\n const nextTaskStates: Record<string, TaskState> = {};\n const nextOutputs: Record<string, any> = {};\n const nextErrors: Record<string, string> = {};\n\n wf.tasks.forEach((task, name) => {\n nextTaskStates[name] = task.state;\n if (task.output !== undefined) nextOutputs[name] = task.output;\n if (task.error !== undefined) nextErrors[name] = task.error;\n });\n\n setTaskStates(nextTaskStates);\n setOutputs(nextOutputs);\n setErrors(nextErrors);\n }, []);\n\n useEffect(() => {\n const wf = workflow;\n // Initial sync\n syncState();\n\n const unsubscribeWf = wf.onStateChange((state) => {\n setWorkflowState(state);\n });\n\n const unsubscribeTasks = wf.onTaskStateChange((taskName, state) => {\n setTaskStates((prev) => ({ ...prev, [taskName]: state }));\n\n const task = wf.tasks.get(taskName);\n if (task) {\n if (task.output !== undefined) {\n setOutputs((prev) => ({ ...prev, [taskName]: task.output }));\n }\n if (task.error !== undefined) {\n setErrors((prev) => ({ ...prev, [taskName]: task.error! }));\n }\n }\n });\n\n return () => {\n unsubscribeWf();\n unsubscribeTasks();\n };\n }, [workflow, syncState]);\n\n const run = useCallback(\n async (options?: { parallel?: boolean }): Promise<ExecutionReport> => {\n const report = await workflowRef.current.run(options);\n syncState();\n return report;\n },\n [syncState]\n );\n\n const reset = useCallback(() => {\n workflowRef.current.reset();\n syncState();\n }, [syncState]);\n\n return {\n state: workflowState,\n taskStates,\n outputs,\n errors,\n isRunning: workflowState === \"RUNNING\",\n run,\n reset,\n };\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "react-pyworkflow",
3
+ "version": "0.1.2",
4
+ "description": "A client-side JavaScript/TypeScript workflow automation and orchestration library for React.",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "require": "./dist/index.js",
12
+ "import": "./dist/index.mjs"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsup",
20
+ "test": "vitest run",
21
+ "test:watch": "vitest",
22
+ "prepublishOnly": "npm run build"
23
+ },
24
+ "keywords": [
25
+ "react",
26
+ "workflow",
27
+ "orchestration",
28
+ "pipeline",
29
+ "tasks",
30
+ "state-machine",
31
+ "async",
32
+ "promise"
33
+ ],
34
+ "author": "PyWorkflow Contributors",
35
+ "license": "MIT",
36
+ "peerDependencies": {
37
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/react": "^18.2.0",
41
+ "react": "^18.2.0",
42
+ "tsup": "^8.0.2",
43
+ "typescript": "^5.3.3",
44
+ "vitest": "^1.3.1"
45
+ }
46
+ }