@workglow/tasks 0.0.52

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/README.md ADDED
@@ -0,0 +1,585 @@
1
+ # @workglow/tasks
2
+
3
+ A package of task types for common operations, workflow management, and data processing. This package provides building blocks for creating complex task graphs with support for HTTP requests, JavaScript execution, delays, logging, and dynamic task creation.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Table of Contents](#table-of-contents)
8
+ - [Installation](#installation)
9
+ - [Quick Start](#quick-start)
10
+ - [Available Tasks](#available-tasks)
11
+ - [FetchTask](#fetchtask)
12
+ - [DebugLogTask](#debuglogtask)
13
+ - [DelayTask](#delaytask)
14
+ - [JavaScriptTask](#javascripttask)
15
+ - [LambdaTask](#lambdatask)
16
+ - [JsonTask](#jsontask)
17
+ - [Workflow Integration](#workflow-integration)
18
+ - [Error Handling](#error-handling)
19
+ - [Configuration](#configuration)
20
+ - [Testing](#testing)
21
+ - [License](#license)
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ bun add @workglow/tasks
27
+ ```
28
+
29
+ ## Quick Start
30
+
31
+ ```typescript
32
+ import { Workflow, Fetch, DebugLog, Delay } from "@workglow/tasks";
33
+
34
+ // Simple workflow example (fluent API)
35
+ const workflow = new Workflow()
36
+ .Fetch({ url: "https://api.example.com/data", response_type: "json" })
37
+ .DebugLog({ log_level: "info" })
38
+ .Delay({ delay: 1000 });
39
+
40
+ const results = await workflow.run();
41
+ ```
42
+
43
+ ```typescript
44
+ import { FetchTask, DebugLogTask, DelayTask } from "@workglow/tasks";
45
+
46
+ // Simple sequence using Task classes directly
47
+ const fetchResult = await new FetchTask({
48
+ url: "https://api.example.com/data",
49
+ response_type: "json",
50
+ }).run();
51
+
52
+ await new DebugLogTask({
53
+ console: fetchResult.json,
54
+ log_level: "info",
55
+ }).run();
56
+
57
+ await new DelayTask({ delay: 1000 }).run();
58
+ ```
59
+
60
+ ```typescript
61
+ import { Fetch, DebugLog, Delay } from "@workglow/tasks";
62
+
63
+ const data = await Fetch({
64
+ url: "https://example.com/readme.txt",
65
+ response_type: "text",
66
+ });
67
+ await DebugLog({
68
+ console: data.text,
69
+ log_level: "info",
70
+ });
71
+ ```
72
+
73
+ ## Available Tasks
74
+
75
+ ### FetchTask
76
+
77
+ Makes HTTP requests with built-in retry logic, progress tracking, and multiple response types.
78
+
79
+ **Input Schema:**
80
+
81
+ - `url` (string, required): The URL to fetch from
82
+ - `method` (string, optional): HTTP method ("GET", "POST", "PUT", "DELETE", "PATCH"). Default: "GET"
83
+ - `headers` (object, optional): Headers to send with the request
84
+ - `body` (string, optional): Request body for POST/PUT requests
85
+ - `response_type` (string, optional): Response format ("json", "text", "blob", "arraybuffer"). Default: "json"
86
+ - `timeout` (number, optional): Request timeout in milliseconds
87
+ - `queue` (boolean|string, optional): Queue handling (`false` runs inline when possible, `true` uses the task's default queue, strings target a specific registered queue). Default: `true`
88
+
89
+ **Output Schema:**
90
+
91
+ - `json` (any, optional): JSON response data
92
+ - `text` (string, optional): Text response data
93
+ - `blob` (Blob, optional): Blob response data
94
+ - `arraybuffer` (ArrayBuffer, optional): ArrayBuffer response data
95
+
96
+ **Examples:**
97
+
98
+ ```typescript
99
+ // Simple GET request
100
+ const response = await new FetchTask({
101
+ url: "https://api.example.com/users",
102
+ response_type: "json",
103
+ }).run();
104
+ console.log(response.json);
105
+
106
+ // POST request with headers
107
+ const postResponse = await new FetchTask({
108
+ url: "https://api.example.com/users",
109
+ method: "POST",
110
+ headers: {
111
+ "Content-Type": "application/json",
112
+ Authorization: "Bearer token",
113
+ },
114
+ body: JSON.stringify({ name: "John", email: "john@example.com" }),
115
+ response_type: "json",
116
+ }).run();
117
+
118
+ // Text response
119
+ const textResponse = await new FetchTask({
120
+ url: "https://example.com/readme.txt",
121
+ response_type: "text",
122
+ }).run();
123
+ console.log(textResponse.text);
124
+ ```
125
+
126
+ **Features:**
127
+
128
+ - Automatic retry on 429/503 status codes with Retry-After header support (requires creation of a `@workglow/job-queue` instance)
129
+ - Progress tracking for large downloads
130
+ - Request timeout handling
131
+ - Queue-based rate limiting (requires creation of a `@workglow/job-queue` instance)
132
+ - Comprehensive error handling
133
+
134
+ ### DebugLogTask
135
+
136
+ Provides console logging functionality with multiple log levels for debugging task graphs.
137
+
138
+ **Input Schema:**
139
+
140
+ - `console` (any, optional): The message/data to log
141
+ - `log_level` (string, optional): Log level ("dir", "log", "debug", "info", "warn", "error"). Default: "log"
142
+
143
+ **Output Schema:**
144
+
145
+ - `console` (any): The logged message (passed through)
146
+
147
+ **Examples:**
148
+
149
+ ```typescript
150
+ // Basic logging
151
+ await new DebugLogTask({
152
+ console: "Processing user data",
153
+ log_level: "info",
154
+ }).run();
155
+
156
+ // Object inspection with dir
157
+ await new DebugLogTask({
158
+ console: { user: { id: 1, name: "John" }, status: "active" },
159
+ log_level: "dir",
160
+ }).run();
161
+
162
+ // In workflow with data flow
163
+ const workflow = new Workflow()
164
+ .Fetch({ url: "https://api.example.com/data" })
165
+ .DebugLog({ log_level: "dir" }) // Logs the fetched data
166
+ .Delay({ delay: 1000 });
167
+ ```
168
+
169
+ **Features:**
170
+
171
+ - Multiple log levels for different debugging needs
172
+ - Deep object inspection with `dir` level
173
+ - Pass-through functionality preserves data flow
174
+ - Non-cacheable for real-time debugging
175
+
176
+ ### DelayTask
177
+
178
+ Introduces timed delays in workflows with progress tracking and cancellation support.
179
+
180
+ **Input Schema:**
181
+
182
+ - `delay` (number, optional): Delay duration in milliseconds. Default: 1
183
+ - `pass_through` (any, optional): Data to pass through to the output
184
+
185
+ **Output Schema:**
186
+
187
+ - Returns the `pass_through` data unchanged
188
+
189
+ **Examples:**
190
+
191
+ ```typescript
192
+ // Simple delay
193
+ await Delay({ delay: 5000 }); // 5 second delay
194
+
195
+ // Delay with data pass-through
196
+ const result = await new DelayTask({
197
+ delay: 3000,
198
+ pass_through: { message: "Data preserved through delay" },
199
+ }).run();
200
+ console.log(result); // { message: "Data preserved through delay" }
201
+
202
+ // In workflow
203
+ const workflow = new Workflow()
204
+ .Fetch({ url: "https://api.example.com/data" })
205
+ .Delay({ delay: 2000 }) // 2 second delay
206
+ .DebugLog({ log_level: "info" });
207
+ ```
208
+
209
+ **Features:**
210
+
211
+ - Progress tracking for delays over 100ms
212
+ - Cancellation support via AbortSignal
213
+ - Chunked delay execution for responsiveness
214
+ - Data pass-through capability
215
+
216
+ ### JavaScriptTask
217
+
218
+ Executes JavaScript code strings using a safe interpreter with input/output handling.
219
+
220
+ **Input Schema:**
221
+
222
+ - `code` (string, required): JavaScript code to execute
223
+ - `input` (any, optional): Input data available to the code
224
+
225
+ **Output Schema:**
226
+
227
+ - `output` (any): The result of the JavaScript execution
228
+
229
+ **Examples:**
230
+
231
+ ```typescript
232
+ // Simple calculation
233
+ const result = await JavaScript({
234
+ code: "2 + 3 * 4",
235
+ });
236
+ console.log(result.output); // 14
237
+
238
+ // Using input data
239
+ const processed = await new JavaScriptTask({
240
+ code: `
241
+ const numbers = input.values;
242
+ const sum = numbers.reduce((a, b) => a + b, 0);
243
+ const average = sum / numbers.length;
244
+ return { sum, average, count: numbers.length };
245
+ `,
246
+ input: { values: [1, 2, 3, 4, 5] },
247
+ }).run();
248
+ console.log(processed.output); // { sum: 15, average: 3, count: 5 }
249
+
250
+ // In workflow
251
+ const workflow = new Workflow()
252
+ .Fetch({ url: "https://api.example.com/data" })
253
+ .JavaScript({
254
+ code: `
255
+ const data = input.json;
256
+ return data.filter(item => item.active === true);
257
+ `,
258
+ })
259
+ .DebugLog({ log_level: "info" });
260
+ ```
261
+
262
+ **Features:**
263
+
264
+ - Safe JavaScript execution using interpreter
265
+ - Access to input data within code
266
+ - Error handling and logging
267
+ - Suitable for data transformation and filtering
268
+
269
+ ### LambdaTask
270
+
271
+ Executes custom JavaScript functions with full access to task context and configuration.
272
+
273
+ **Input Schema:**
274
+
275
+ - Accepts any input data (flexible schema)
276
+
277
+ **Output Schema:**
278
+
279
+ - Returns whatever the provided function outputs
280
+
281
+ **Configuration:**
282
+
283
+ - `execute`: Function for standard execution
284
+ - `executeReactive`: Function for reactive execution with output parameter
285
+
286
+ **Examples:**
287
+
288
+ ```typescript
289
+ // Function with execute pattern
290
+ const result = await Lambda(
291
+ { numbers: [1, 2, 3, 4, 5] },
292
+ {
293
+ execute: async (input, context) => {
294
+ const sum = input.numbers.reduce((a, b) => a + b, 0);
295
+ await context.updateProgress(50, "Calculating sum");
296
+ const average = sum / input.numbers.length;
297
+ await context.updateProgress(100, "Complete");
298
+ return { sum, average };
299
+ },
300
+ }
301
+ );
302
+
303
+ // Reactive pattern with output parameter
304
+ const reactiveResult = await new LambdaTask(
305
+ { message: "Hello" },
306
+ {
307
+ executeReactive: async (input, output, context) => {
308
+ output.processed = input.message.toUpperCase();
309
+ output.timestamp = new Date().toISOString();
310
+ return output;
311
+ },
312
+ }
313
+ ).run();
314
+
315
+ // Data transformation function
316
+ const transformer = await new LambdaTask(
317
+ {
318
+ data: [
319
+ { name: "John", age: 30 },
320
+ { name: "Jane", age: 25 },
321
+ ],
322
+ },
323
+ {
324
+ execute: async (input) => {
325
+ return {
326
+ users: input.data.map((user) => ({
327
+ ...user,
328
+ isAdult: user.age >= 18,
329
+ category: user.age < 30 ? "young" : "mature",
330
+ })),
331
+ };
332
+ },
333
+ }
334
+ ).run();
335
+
336
+ // Async operation with external API
337
+ const apiProcessor = await new LambdaTask(
338
+ { userId: 123 },
339
+ {
340
+ execute: async (input, context) => {
341
+ await context.updateProgress(25, "Fetching user data");
342
+ const userData = await fetch(`/api/users/${input.userId}`).then((r) => r.json());
343
+
344
+ await context.updateProgress(75, "Processing data");
345
+ const enrichedData = {
346
+ ...userData,
347
+ processedAt: new Date().toISOString(),
348
+ isActive: userData.lastLogin > Date.now() - 86400000, // 24 hours
349
+ };
350
+
351
+ await context.updateProgress(100, "Complete");
352
+ return enrichedData;
353
+ },
354
+ }
355
+ ).run();
356
+ ```
357
+
358
+ **Features:**
359
+
360
+ - Full access to execution context and progress tracking
361
+ - Support for both standard and reactive execution patterns
362
+ - Async/await support
363
+ - Flexible input/output schemas
364
+ - Cacheable by default
365
+
366
+ ### JsonTask
367
+
368
+ Creates and executes task graphs from JSON configurations, enabling dynamic workflow creation.
369
+
370
+ **Input Schema:**
371
+
372
+ - `json` (string, required): JSON string defining tasks and their dependencies
373
+
374
+ **Output Schema:**
375
+
376
+ - `output` (any): Output depends on the generated task graph
377
+
378
+ **JSON Format:**
379
+
380
+ ```typescript
381
+ interface JsonTaskItem {
382
+ id: string; // Unique task identifier
383
+ type: string; // Task type (e.g., "FetchTask", "DelayTask")
384
+ input?: any; // Task input data
385
+ config?: any; // Task configuration
386
+ dependencies?: {
387
+ // Input dependencies from other tasks
388
+ [inputField: string]:
389
+ | {
390
+ id: string; // Source task ID
391
+ output: string; // Output field from source task
392
+ }
393
+ | Array<{ id: string; output: string }>;
394
+ };
395
+ }
396
+ ```
397
+
398
+ **Examples:**
399
+
400
+ ```typescript
401
+ // Simple linear workflow
402
+ const linearWorkflow = await new JsonTask({
403
+ json: JSON.stringify([
404
+ {
405
+ id: "fetch-data",
406
+ type: "FetchTask",
407
+ input: {
408
+ url: "https://api.example.com/users",
409
+ response_type: "json",
410
+ },
411
+ },
412
+ {
413
+ id: "log-data",
414
+ type: "DebugLogTask",
415
+ input: {
416
+ log_level: "info",
417
+ },
418
+ dependencies: {
419
+ console: { id: "fetch-data", output: "json" },
420
+ },
421
+ },
422
+ {
423
+ id: "delay",
424
+ type: "DelayTask",
425
+ input: { delay: 1000 },
426
+ },
427
+ ]),
428
+ }).run();
429
+
430
+ // Complex workflow with data dependencies
431
+ const complexWorkflow = await new JsonTask({
432
+ json: JSON.stringify([
433
+ {
434
+ id: "fetch-users",
435
+ type: "FetchTask",
436
+ input: {
437
+ url: "https://api.example.com/users",
438
+ response_type: "json",
439
+ },
440
+ },
441
+ {
442
+ id: "fetch-posts",
443
+ type: "FetchTask",
444
+ input: {
445
+ url: "https://api.example.com/posts",
446
+ response_type: "json",
447
+ },
448
+ },
449
+ {
450
+ id: "combine-data",
451
+ type: "JavaScriptTask",
452
+ input: {
453
+ code: `
454
+ const users = input.users;
455
+ const posts = input.posts;
456
+ return users.map(user => ({
457
+ ...user,
458
+ posts: posts.filter(post => post.userId === user.id)
459
+ }));
460
+ `,
461
+ },
462
+ dependencies: {
463
+ input: [
464
+ { id: "fetch-users", output: "json" },
465
+ { id: "fetch-posts", output: "json" },
466
+ ],
467
+ },
468
+ },
469
+ {
470
+ id: "log-result",
471
+ type: "DebugLogTask",
472
+ input: { log_level: "dir" },
473
+ dependencies: {
474
+ console: { id: "combine-data", output: "output" },
475
+ },
476
+ },
477
+ ]),
478
+ }).run();
479
+
480
+ // Dynamic task creation from external config
481
+ const configResponse = await fetch("/api/workflow-config");
482
+ const workflowConfig = await configResponse.json();
483
+
484
+ const dynamicWorkflow = await new JsonTask({
485
+ json: JSON.stringify(workflowConfig.tasks),
486
+ }).run();
487
+ ```
488
+
489
+ **Features:**
490
+
491
+ - Dynamic task graph creation from JSON
492
+ - Support for complex dependency relationships
493
+ - All registered task types are available
494
+ - Automatic data flow between tasks
495
+ - Enables configuration-driven workflows
496
+
497
+ ## Workflow Integration
498
+
499
+ All tasks can be used standalone or integrated into workflows:
500
+
501
+ ```typescript
502
+ import { Workflow } from "@workglow/tasks";
503
+
504
+ // Fluent workflow API
505
+ const workflow = new Workflow()
506
+ .Fetch({
507
+ url: "https://api.example.com/data",
508
+ response_type: "json",
509
+ })
510
+ .JavaScript({
511
+ code: "return input.json.filter(item => item.status === 'active');",
512
+ })
513
+ .DebugLog({ log_level: "info" })
514
+ .Delay({ delay: 500 })
515
+ .Lambda(
516
+ {},
517
+ {
518
+ execute: async (input) => ({
519
+ processed: true,
520
+ count: input.output.length,
521
+ timestamp: new Date().toISOString(),
522
+ }),
523
+ }
524
+ );
525
+
526
+ const result = await workflow.run();
527
+ ```
528
+
529
+ ## Error Handling
530
+
531
+ Tasks include comprehensive error handling:
532
+
533
+ ```typescript
534
+ try {
535
+ const result = await new FetchTask({
536
+ url: "https://api.example.com/data",
537
+ response_type: "json",
538
+ timeout: 5000,
539
+ }).run();
540
+ } catch (error) {
541
+ if (error instanceof TaskInvalidInputError) {
542
+ console.error("Invalid input:", error.message);
543
+ } else if (error instanceof RetryableJobError) {
544
+ console.error("Retryable error:", error.message);
545
+ // Will be retried automatically
546
+ } else if (error instanceof PermanentJobError) {
547
+ console.error("Permanent error:", error.message);
548
+ // Will not be retried
549
+ }
550
+ }
551
+ ```
552
+
553
+ ## Configuration
554
+
555
+ Tasks support various configuration options:
556
+
557
+ ```typescript
558
+ // Task-specific configuration
559
+ const fetchTask = new FetchTask(
560
+ {
561
+ url: "https://api.example.com/data",
562
+ },
563
+ {
564
+ queue: "api-requests",
565
+ timeout: 10000,
566
+ retryAttempts: 3,
567
+ }
568
+ );
569
+
570
+ // Global workflow configuration
571
+ const workflow = new Workflow({
572
+ maxConcurrency: 5,
573
+ timeout: 30000,
574
+ });
575
+ ```
576
+
577
+ ## Testing
578
+
579
+ ```bash
580
+ bun test
581
+ ```
582
+
583
+ ## License
584
+
585
+ Apache 2.0 - See [LICENSE](./LICENSE) for details.
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export * from "./task/DebugLogTask";
7
+ export * from "./task/DelayTask";
8
+ export * from "./task/FetchTask";
9
+ export * from "./task/JavaScriptTask";
10
+ export * from "./task/JsonTask";
11
+ export * from "./task/LambdaTask";
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC"}