Skip to content

Commit ab2afbb

Browse files
authored
Merge pull request #36 from sontx/task-icon
Task and task group icon
2 parents 9b69313 + 30dd3c4 commit ab2afbb

29 files changed

+183
-14
lines changed

docs/task/task-handler.md

+7-4
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ A task handler should have the following structure:
5454
- `name`: The name of the task, we'll use the file name or package name as the task name if not defined. This is optional.
5555
- `description`: A brief description of the task, this is optional.
5656
- `version`: The version of the task, we'll use the package version if not defined. This is optional.
57+
- `icon`: The icon url of the task, this is optional.
5758
- `parameters`: An object that describes the input parameters of the task for showing help, set null if the task doesn't have parameters. This is optional.
5859
- `output`: An object that describes the output of the task for showing help, set null if the task doesn't have output. This is optional.
5960
- `handle`: The function that executes the task. This is required.
@@ -63,6 +64,7 @@ There are alternative ways to define those fields by using these corresponding d
6364
- `@Name`: The name of the task.
6465
- `@Description`: A brief description of the task.
6566
- `@Version`: The version of the task.
67+
- `@Icon`: The icon url of the task.
6668
- `@Parameters`: An object that describes the input parameters of the task for showing help. No value or null means the task doesn't have parameters.
6769
- `@Output`: An object that describes the output of the task for showing help. No value or null means the task doesn't have output.
6870

@@ -219,9 +221,10 @@ For example, the handler for `Task1Handler` will be `package:my-group:task1`.
219221

220222
The group information will be obtained from the package.json:
221223

222-
- `name`: The name of the task group.
223-
- `description`: A brief description of the task group.
224-
- `version`: The version of the task group.
225-
- `author`: The author of the task group.
224+
- `name`: The name of the task group. Corresponds to the package name.
225+
- `description`: A brief description of the task group. Corresponds to the package description.
226+
- `version`: The version of the task group. Corresponds to the package version.
227+
- `icon`: The icon url of the task group. Corresponds to the package.json `letrun.icon` field.
228+
- `author`: The author of the task group. Corresponds to the package author.
226229

227230
> We recommend you use scoped package and name the package with `@letrun-task-` prefix.

icons/catch.svg

+9
Loading

icons/delay.svg

+6
Loading

icons/for.svg

+1
Loading

icons/http.svg

+4
Loading

icons/if.svg

+7
Loading

icons/iterate.svg

+7
Loading

icons/lambda.svg

+5
Loading

icons/log.svg

+7
Loading

icons/switch.svg

+9
Loading

icons/while.svg

+1
Loading

icons/workflow.svg

+1
Loading

package-lock.json

+3-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/common/src/model/task-group.ts

+54
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,73 @@ export const SYSTEM_TASK_GROUP: TaskGroup = {
2222
export interface TaskGroup {
2323
/**
2424
* The name of the task group.
25+
* This name should be unique across all task groups.
26+
* You can define group's name in the name field of package.json.
27+
*
28+
* @example
29+
* ```json
30+
* {
31+
* "name": "my-task-group"
32+
* ...
33+
* }
34+
* ```
2535
*/
2636
name: string;
2737
/**
2838
* A brief description of the task group.
39+
* This description will be shown in the help output.
40+
* You can define group's description in the description field of package.json.
41+
*
42+
* @example
43+
* ```json
44+
* {
45+
* "description": "This is an awesome task group"
46+
* ...
47+
* }
48+
* ```
2949
*/
3050
description?: string;
3151
/**
3252
* The version of the task group.
53+
* You can define group's version in the version field of package.json.
54+
*
55+
* @example
56+
* ```json
57+
* {
58+
* "version": "1.0.0"
59+
* ...
60+
* }
61+
* ```
3362
*/
3463
version?: string;
3564
/**
3665
* The author of the task group.
66+
* You can define group's author in the author field of package.json.
67+
*
68+
* @example
69+
* ```json
70+
* {
71+
* "author": "John Doe"
72+
* ...
73+
* }
74+
* ```
3775
*/
3876
author?: string;
77+
/**
78+
* The icon url of the task group.
79+
* You can define group's icon in the letrun.icon field of package.json.
80+
*
81+
* @example
82+
* ```json
83+
* {
84+
* "letrun": {
85+
* "icon": "https://example.com/icon.png"
86+
* }
87+
* ...
88+
* }
89+
* ```
90+
*/
91+
icon?: string;
3992
/**
4093
* The tasks that belong to this group. This map contains the name of the task as the key and the task handler as the value.
4194
*/
@@ -57,6 +110,7 @@ export interface TaskGroupMetadata {
57110
description?: string;
58111
version?: string;
59112
author?: string;
113+
icon?: string;
60114
type?: 'package' | 'script';
61115
tasks: TaskMetadata[];
62116
}

packages/common/src/model/task-handler.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,19 @@ export interface TaskHandlerInput {
2222
* Keeps the logic stateless because it will be recalled multiple times with different task data.
2323
*/
2424
export interface TaskHandler<T = any> {
25-
/** The name of the task handler. */
25+
/**
26+
* The name of the task handler.
27+
* This name should be unique across all task handlers of the same {@link TaskGroup}.
28+
*/
2629
name?: string;
2730
/** The version of the task handler. */
2831
version?: string;
2932
/** Optional description of the task handler. */
3033
description?: string;
34+
/**
35+
* The icon url of the task handler.
36+
*/
37+
icon?: string;
3138
/**
3239
* An object that describes the input parameters of the task for showing help.
3340
* If the task does not require any input, set this to null.
@@ -58,6 +65,7 @@ export interface TaskMetadata {
5865
name: string;
5966
version?: string;
6067
description?: string;
68+
icon?: string;
6169
parameters?: Joi.Description | null;
6270
output?: Joi.Description | null;
6371
}

packages/core/src/decorator/task-handler.ts

+16
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,22 @@ export function Description(value: string) {
5050
return injectFieldDecorator('description', value);
5151
}
5252

53+
/**
54+
* A decorator that injects the icon field to a {@link TaskHandler}. See {@link TaskHandler.icon}.
55+
* @param value
56+
* @constructor
57+
*
58+
* @example
59+
* ```ts
60+
* @Icon('https://example.com/icon.png')
61+
* class MyTaskHandler implements TaskHandler {
62+
* }
63+
* ```
64+
*/
65+
export function Icon(value: string) {
66+
return injectFieldDecorator('icon', value);
67+
}
68+
5369
/**
5470
* A decorator that injects the parameters field to a {@link TaskHandler}. See {@link TaskHandler.parameters}.
5571
* @param value - task handler parameters. If value is not provided, the parameters field will be set to null (no parameters are required).

packages/core/tests/decorator/task-handler.test.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Description, Name, Output, Parameters, Version } from '@src/decorator/task-handler';
1+
import { Description, Icon, Name, Output, Parameters, Version } from '@src/decorator/task-handler';
22
import Joi from 'joi';
33

44
describe('TaskHandler Decorators', () => {
@@ -100,6 +100,7 @@ describe('TaskHandler Decorators', () => {
100100
@Name('my-task-handler')
101101
@Version('1.0.0')
102102
@Description('This is a task handler')
103+
@Icon('https://example.com/icon.png')
103104
@Parameters(Joi.object({ name: Joi.string().required() }))
104105
@Output(Joi.object({ value: Joi.string().required() }))
105106
class MyTaskHandler extends BaseClass {}
@@ -121,13 +122,23 @@ describe('TaskHandler Decorators', () => {
121122
@Description('This is a task handler')
122123
@Parameters(schema)
123124
@Output(outputSchema)
125+
@Icon('https://example.com/icon.png')
124126
class MyTaskHandler {}
125127

126128
const instance = new MyTaskHandler();
127129
expect((instance as any).name).toBe('my-task-handler');
128130
expect((instance as any).version).toBe('1.0.0');
129131
expect((instance as any).description).toBe('This is a task handler');
132+
expect((instance as any).icon).toBe('https://example.com/icon.png');
130133
expect((instance as any).parameters).toEqual(schema.describe());
131134
expect((instance as any).output).toEqual(outputSchema.describe());
132135
});
136+
137+
it('should inject icon field into TaskHandler', () => {
138+
@Icon('https://example.com/icon.png')
139+
class MyTaskHandler {}
140+
141+
const instance = new MyTaskHandler();
142+
expect((instance as any).icon).toBe('https://example.com/icon.png');
143+
});
133144
});

packages/engine/src/system-task/catch.ts

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
countTasks,
33
Description,
44
getTasksByStatus,
5+
Icon,
56
isWorkflowTaskDefsEmpty,
67
Name,
78
Output,
@@ -49,6 +50,7 @@ const OutputSchema = Joi.object({
4950

5051
@Name('catch')
5152
@Description('Handles errors during task execution')
53+
@Icon('https://raw.githubusercontent.com/sontx/letrun/main/icons/catch.svg')
5254
@Parameters(Schema)
5355
@Output(OutputSchema)
5456
export class CatchTaskHandler implements TaskHandler {

packages/engine/src/system-task/delay.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { delayMs, Description, Name, Output, Parameters, validateParameters } from '@letrun/core';
1+
import { delayMs, Description, Icon, Name, Output, Parameters, validateParameters } from '@letrun/core';
22
import { TaskHandler, TaskHandlerInput } from '@letrun/common';
33
import Joi from 'joi';
44
import ms from 'ms';
@@ -19,6 +19,7 @@ const OutputSchema = Joi.any().description('The "data" field from the input para
1919

2020
@Name('delay')
2121
@Description('Delays the execution of the workflow for a specified amount of time')
22+
@Icon('https://raw.githubusercontent.com/sontx/letrun/main/icons/delay.svg')
2223
@Parameters(Schema)
2324
@Output(OutputSchema)
2425
export class DelayTaskHandler implements TaskHandler {

packages/engine/src/system-task/for.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Description, Name, Output, Parameters, validateParameters } from '@letrun/core';
1+
import { Description, Icon, Name, Output, Parameters, validateParameters } from '@letrun/core';
22
import { RerunError, TaskDef, TaskHandler, TaskHandlerInput } from '@letrun/common';
33
import Joi from 'joi';
44
import { initNewIteration, validateLoopTask } from './loop-task';
@@ -42,6 +42,7 @@ const OutputSchema = Joi.object({
4242

4343
@Name('for')
4444
@Description('Loops through a specified range and performs tasks')
45+
@Icon('https://raw.githubusercontent.com/sontx/letrun/main/icons/for.svg')
4546
@Parameters(Schema)
4647
@Output(OutputSchema)
4748
export class ForTaskHandler implements TaskHandler {

packages/engine/src/system-task/http.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Description, Name, Output, Parameters, validateParameters } from '@letrun/core';
1+
import { Description, Icon, Name, Output, Parameters, validateParameters } from '@letrun/core';
22
import { TaskHandler, TaskHandlerInput } from '@letrun/common';
33
import Joi from 'joi';
44

@@ -72,6 +72,7 @@ const OutputSchema = Joi.any().description('The response data from the HTTP requ
7272

7373
@Name('http')
7474
@Description('Sends HTTP requests and processes responses')
75+
@Icon('https://raw.githubusercontent.com/sontx/letrun/main/icons/http.svg')
7576
@Parameters(Schema)
7677
@Output(OutputSchema)
7778
export class HttpTaskHandler implements TaskHandler {

packages/engine/src/system-task/if.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
countTasks,
33
Description,
4+
Icon,
45
isWorkflowTaskDefsEmpty,
56
Name,
67
Output,
@@ -81,6 +82,7 @@ const OutputSchema = Joi.boolean().description('The result of the expression');
8182

8283
@Name('if')
8384
@Description('Executes tasks based on conditions')
85+
@Icon('https://raw.githubusercontent.com/sontx/letrun/main/icons/if.svg')
8486
@Parameters(Schema)
8587
@Output(OutputSchema)
8688
export class IfTaskHandler implements TaskHandler {

packages/engine/src/system-task/iterate.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Description, Name, Output, Parameters, validateParameters } from '@letrun/core';
1+
import { Description, Icon, Name, Output, Parameters, validateParameters } from '@letrun/core';
22
import { RerunError, TaskDef, TaskHandler, TaskHandlerInput } from '@letrun/common';
33
import Joi from 'joi';
44
import { initNewIteration, validateLoopTask } from './loop-task';
@@ -26,6 +26,7 @@ const OutputSchema = Joi.object({
2626

2727
@Name('iterate')
2828
@Description('Loops through a list of items and performs tasks')
29+
@Icon('https://raw.githubusercontent.com/sontx/letrun/main/icons/iterate.svg')
2930
@Parameters(Schema)
3031
@Output(OutputSchema)
3132
export class IterateTaskHandler implements TaskHandler {

packages/engine/src/system-task/lambda.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Joi from 'joi';
22
import {
3-
Description,
3+
Description, Icon,
44
Name,
55
Output,
66
Parameters,
@@ -33,6 +33,7 @@ const OutputSchema = Joi.any().description('The result of the lambda expression.
3333

3434
@Name('lambda')
3535
@Description('Evaluates a lambda expression.')
36+
@Icon('https://raw.githubusercontent.com/sontx/letrun/main/icons/lambda.svg')
3637
@Parameters(Schema)
3738
@Output(OutputSchema)
3839
export class LambdaTaskHandler implements TaskHandler {

0 commit comments

Comments
 (0)