mstate-cli 0.4.2 → 0.4.4
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/.prettierrc +5 -5
- package/Readme.md +39 -39
- package/dist/index.js +50 -50
- package/package.json +46 -46
- package/rollup.config.mjs +34 -34
- package/src/common/constant.ts +19 -19
- package/src/common/enum.ts +30 -26
- package/src/common/helpers.ts +85 -58
- package/src/common/utils.ts +67 -67
- package/src/handlers/action.handler.ts +94 -94
- package/src/handlers/company.handler.ts +226 -202
- package/src/handlers/environment.handler.ts +77 -77
- package/src/handlers/help.handler.ts +122 -81
- package/src/handlers/mobioffice.handler.ts +43 -43
- package/src/handlers/workflow.handler.ts +207 -171
- package/src/index.ts +94 -85
- package/src/interface.d.ts +43 -43
- package/tsconfig.json +18 -18
@@ -1,171 +1,207 @@
|
|
1
|
-
import * as fs from 'fs';
|
2
|
-
import path from 'path';
|
3
|
-
import { MSTATE_URL } from '../common/constant';
|
4
|
-
import { customLog, getSecretKey } from '../common/utils';
|
5
|
-
import { getValueFromArgs } from '../common/helpers';
|
6
|
-
import { Variables } from 'src/common/enum';
|
7
|
-
|
8
|
-
class WorkflowHandler {
|
9
|
-
constructor() {}
|
10
|
-
|
11
|
-
private async addNewWorkflow(workflowPath: string, file: string) {
|
12
|
-
try {
|
13
|
-
const secretKey = getSecretKey();
|
14
|
-
|
15
|
-
if (!file) {
|
16
|
-
customLog.changeAndThrow(`Parameter file is required`);
|
17
|
-
return;
|
18
|
-
}
|
19
|
-
|
20
|
-
if (!secretKey) {
|
21
|
-
customLog.changeAndThrow(`Parameter secret is required`);
|
22
|
-
return;
|
23
|
-
}
|
24
|
-
|
25
|
-
const filePath = path.resolve(file);
|
26
|
-
const workflowJSON = fs.readFileSync(filePath, 'utf8');
|
27
|
-
|
28
|
-
let query = '';
|
29
|
-
if (workflowPath) {
|
30
|
-
query += `path=${workflowPath}`;
|
31
|
-
}
|
32
|
-
|
33
|
-
if (query.length) {
|
34
|
-
query = '?' + query;
|
35
|
-
}
|
36
|
-
|
37
|
-
const url = `${MSTATE_URL}/workflow/config/new${query}`;
|
38
|
-
const responseJSON = await fetch(url, {
|
39
|
-
method: 'POST',
|
40
|
-
headers: {
|
41
|
-
'secret-key': secretKey,
|
42
|
-
'Content-Type': 'application/json',
|
43
|
-
},
|
44
|
-
body: workflowJSON,
|
45
|
-
});
|
46
|
-
|
47
|
-
const response = await responseJSON.json();
|
48
|
-
if (response?.errors) {
|
49
|
-
customLog.changeAndThrow(
|
50
|
-
'Invalid Parameters for Workflow: ',
|
51
|
-
...response?.errors,
|
52
|
-
);
|
53
|
-
} else {
|
54
|
-
customLog.success('Workflow Added successfully', response?.data);
|
55
|
-
}
|
56
|
-
} catch (error: any) {
|
57
|
-
customLog.changeAndThrow(error.message);
|
58
|
-
}
|
59
|
-
}
|
60
|
-
|
61
|
-
async updateWorkflowToDB() {
|
62
|
-
const workflowName = getValueFromArgs(Variables.WORKFLOW, true);
|
63
|
-
const secretKey = getSecretKey();
|
64
|
-
|
65
|
-
const folderPath = path.resolve(workflowName);
|
66
|
-
const filePath = path.join(folderPath, 'workflow.json');
|
67
|
-
|
68
|
-
const workflowJSON = fs.readFileSync(filePath, 'utf8');
|
69
|
-
|
70
|
-
let query = `?workflow=${workflowName}`;
|
71
|
-
|
72
|
-
const url = `${MSTATE_URL}/workflow/config${query}`;
|
73
|
-
const responseJSON = await fetch(url, {
|
74
|
-
method: 'PUT',
|
75
|
-
headers: {
|
76
|
-
'secret-key': secretKey,
|
77
|
-
'Content-Type': 'application/json',
|
78
|
-
},
|
79
|
-
body: workflowJSON,
|
80
|
-
});
|
81
|
-
|
82
|
-
const response = await responseJSON.json();
|
83
|
-
if (response?.errors) {
|
84
|
-
customLog.changeAndThrow(
|
85
|
-
'Invalid Parameters for Server: ',
|
86
|
-
...response?.errors,
|
87
|
-
);
|
88
|
-
} else {
|
89
|
-
customLog.success('Workflow Uploaded successfully \n', response?.data);
|
90
|
-
}
|
91
|
-
|
92
|
-
return response;
|
93
|
-
}
|
94
|
-
|
95
|
-
async
|
96
|
-
const workflowName = getValueFromArgs(Variables.WORKFLOW, true);
|
97
|
-
const
|
98
|
-
|
99
|
-
|
100
|
-
const
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
1
|
+
import * as fs from 'fs';
|
2
|
+
import path from 'path';
|
3
|
+
import { MSTATE_URL } from '../common/constant';
|
4
|
+
import { customLog, getSecretKey } from '../common/utils';
|
5
|
+
import { getValueFromArgs, sortJSON } from '../common/helpers';
|
6
|
+
import { Variables } from 'src/common/enum';
|
7
|
+
|
8
|
+
class WorkflowHandler {
|
9
|
+
constructor() {}
|
10
|
+
|
11
|
+
private async addNewWorkflow(workflowPath: string, file: string) {
|
12
|
+
try {
|
13
|
+
const secretKey = getSecretKey();
|
14
|
+
|
15
|
+
if (!file) {
|
16
|
+
customLog.changeAndThrow(`Parameter file is required`);
|
17
|
+
return;
|
18
|
+
}
|
19
|
+
|
20
|
+
if (!secretKey) {
|
21
|
+
customLog.changeAndThrow(`Parameter secret is required`);
|
22
|
+
return;
|
23
|
+
}
|
24
|
+
|
25
|
+
const filePath = path.resolve(file);
|
26
|
+
const workflowJSON = fs.readFileSync(filePath, 'utf8');
|
27
|
+
|
28
|
+
let query = '';
|
29
|
+
if (workflowPath) {
|
30
|
+
query += `path=${workflowPath}`;
|
31
|
+
}
|
32
|
+
|
33
|
+
if (query.length) {
|
34
|
+
query = '?' + query;
|
35
|
+
}
|
36
|
+
|
37
|
+
const url = `${MSTATE_URL}/workflow/config/new${query}`;
|
38
|
+
const responseJSON = await fetch(url, {
|
39
|
+
method: 'POST',
|
40
|
+
headers: {
|
41
|
+
'secret-key': secretKey,
|
42
|
+
'Content-Type': 'application/json',
|
43
|
+
},
|
44
|
+
body: workflowJSON,
|
45
|
+
});
|
46
|
+
|
47
|
+
const response = await responseJSON.json();
|
48
|
+
if (response?.errors) {
|
49
|
+
customLog.changeAndThrow(
|
50
|
+
'Invalid Parameters for Workflow: ',
|
51
|
+
...response?.errors,
|
52
|
+
);
|
53
|
+
} else {
|
54
|
+
customLog.success('Workflow Added successfully', response?.data);
|
55
|
+
}
|
56
|
+
} catch (error: any) {
|
57
|
+
customLog.changeAndThrow(error.message);
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
async updateWorkflowToDB() {
|
62
|
+
const workflowName = getValueFromArgs(Variables.WORKFLOW, true);
|
63
|
+
const secretKey = getSecretKey();
|
64
|
+
|
65
|
+
const folderPath = path.resolve(workflowName);
|
66
|
+
const filePath = path.join(folderPath, 'workflow.json');
|
67
|
+
|
68
|
+
const workflowJSON = fs.readFileSync(filePath, 'utf8');
|
69
|
+
|
70
|
+
let query = `?workflow=${workflowName}`;
|
71
|
+
|
72
|
+
const url = `${MSTATE_URL}/workflow/config${query}`;
|
73
|
+
const responseJSON = await fetch(url, {
|
74
|
+
method: 'PUT',
|
75
|
+
headers: {
|
76
|
+
'secret-key': secretKey,
|
77
|
+
'Content-Type': 'application/json',
|
78
|
+
},
|
79
|
+
body: workflowJSON,
|
80
|
+
});
|
81
|
+
|
82
|
+
const response = await responseJSON.json();
|
83
|
+
if (response?.errors) {
|
84
|
+
customLog.changeAndThrow(
|
85
|
+
'Invalid Parameters for Server: ',
|
86
|
+
...response?.errors,
|
87
|
+
);
|
88
|
+
} else {
|
89
|
+
customLog.success('Workflow Uploaded successfully \n', response?.data);
|
90
|
+
}
|
91
|
+
|
92
|
+
return response;
|
93
|
+
}
|
94
|
+
|
95
|
+
async updateWorkflowProperty() {
|
96
|
+
const workflowName = getValueFromArgs(Variables.WORKFLOW, true);
|
97
|
+
const visibility =
|
98
|
+
getValueFromArgs(Variables.VISIBILITY, false) || 'private';
|
99
|
+
|
100
|
+
const secretKey = getSecretKey();
|
101
|
+
|
102
|
+
let query = `?workflow=${workflowName}`;
|
103
|
+
const url = `${MSTATE_URL}/workflow/property${query}`;
|
104
|
+
const responseJSON = await fetch(url, {
|
105
|
+
method: 'PUT',
|
106
|
+
headers: {
|
107
|
+
'secret-key': secretKey,
|
108
|
+
'Content-Type': 'application/json',
|
109
|
+
},
|
110
|
+
body: JSON.stringify({
|
111
|
+
type: visibility,
|
112
|
+
}),
|
113
|
+
});
|
114
|
+
|
115
|
+
const response = await responseJSON.json();
|
116
|
+
if (response?.errors) {
|
117
|
+
customLog.changeAndThrow(
|
118
|
+
'Invalid Parameters for Server: ',
|
119
|
+
...response?.errors,
|
120
|
+
);
|
121
|
+
} else {
|
122
|
+
customLog.success('Workflow Updated successfully \n');
|
123
|
+
}
|
124
|
+
|
125
|
+
return response;
|
126
|
+
}
|
127
|
+
|
128
|
+
async cloneWorkflow() {
|
129
|
+
const workflowName = getValueFromArgs(Variables.WORKFLOW, true);
|
130
|
+
const secretKey = getSecretKey();
|
131
|
+
|
132
|
+
const url = `${MSTATE_URL}/workflow/config/?workflow=${workflowName}&hasNickName=${true}`;
|
133
|
+
const responseJSON = await fetch(url, {
|
134
|
+
method: 'GET',
|
135
|
+
headers: {
|
136
|
+
'Content-Type': 'application/json',
|
137
|
+
'secret-key': secretKey,
|
138
|
+
},
|
139
|
+
});
|
140
|
+
|
141
|
+
const response = await responseJSON.json();
|
142
|
+
if (response?.errors) {
|
143
|
+
customLog.changeAndThrow(
|
144
|
+
'Invalid Parameters for Workflow: ',
|
145
|
+
...response?.errors,
|
146
|
+
);
|
147
|
+
} else {
|
148
|
+
const workflowConfig = sortJSON(response?.data);
|
149
|
+
if (workflowConfig) {
|
150
|
+
delete workflowConfig?.id;
|
151
|
+
}
|
152
|
+
|
153
|
+
const folderPath = path.resolve(workflowName);
|
154
|
+
fs.mkdirSync(folderPath, { recursive: true });
|
155
|
+
|
156
|
+
const filePath = path.join(folderPath, 'workflow.json');
|
157
|
+
fs.writeFileSync(filePath, JSON.stringify(workflowConfig, null, 2));
|
158
|
+
|
159
|
+
customLog.success(`Workflow cloned successfully`);
|
160
|
+
}
|
161
|
+
}
|
162
|
+
|
163
|
+
async copyWorkflow() {
|
164
|
+
try {
|
165
|
+
const workflowName = getValueFromArgs(Variables.WORKFLOW, true);
|
166
|
+
|
167
|
+
let path = '';
|
168
|
+
let file = '';
|
169
|
+
|
170
|
+
const workflowPath = ('/' + workflowName).replace(/\/([^\/]*)$/, '');
|
171
|
+
if (workflowPath) {
|
172
|
+
path = workflowPath.slice(1, workflowPath.length);
|
173
|
+
}
|
174
|
+
file = workflowName + '/workflow.json';
|
175
|
+
|
176
|
+
await this.addNewWorkflow(path, file);
|
177
|
+
} catch (error: any) {
|
178
|
+
customLog.changeAndThrow(error.message);
|
179
|
+
}
|
180
|
+
}
|
181
|
+
|
182
|
+
async resetCache() {
|
183
|
+
const workflowName = getValueFromArgs(Variables.WORKFLOW, true);
|
184
|
+
const secretKey = getSecretKey();
|
185
|
+
|
186
|
+
const url = `${MSTATE_URL}/cache/reset/?workflow=${workflowName}`;
|
187
|
+
const responseJSON = await fetch(url, {
|
188
|
+
method: 'DELETE',
|
189
|
+
headers: {
|
190
|
+
'Content-Type': 'application/json',
|
191
|
+
'secret-key': secretKey,
|
192
|
+
},
|
193
|
+
});
|
194
|
+
|
195
|
+
const response = await responseJSON.json();
|
196
|
+
if (response?.errors) {
|
197
|
+
customLog.changeAndThrow(
|
198
|
+
'Invalid Parameters for Workflow: ',
|
199
|
+
...response?.errors,
|
200
|
+
);
|
201
|
+
} else {
|
202
|
+
customLog.success(`Workflow updated successfully`);
|
203
|
+
}
|
204
|
+
}
|
205
|
+
}
|
206
|
+
|
207
|
+
export const workflowHandler = new WorkflowHandler();
|
package/src/index.ts
CHANGED
@@ -1,85 +1,94 @@
|
|
1
|
-
#!/usr/bin/env node
|
2
|
-
|
3
|
-
import packageJSON from '../package.json';
|
4
|
-
|
5
|
-
import { actionHandler } from './handlers/action.handler';
|
6
|
-
import { workflowHandler } from './handlers/workflow.handler';
|
7
|
-
import { CmdAction } from './common/enum';
|
8
|
-
import { mobiofficeHandler } from './handlers/mobioffice.handler';
|
9
|
-
import { customLog } from './common/utils';
|
10
|
-
import { hasFlag } from './common/helpers';
|
11
|
-
import { environmentHandler } from './handlers/environment.handler';
|
12
|
-
import { companyHandler } from './handlers/company.handler';
|
13
|
-
import { argv } from 'process';
|
14
|
-
import { helpHandler } from './handlers/help.handler';
|
15
|
-
|
16
|
-
const [action] = argv.slice(2);
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
await
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
await
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
break;
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
);
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
1
|
+
#!/usr/bin/env node
|
2
|
+
|
3
|
+
import packageJSON from '../package.json';
|
4
|
+
|
5
|
+
import { actionHandler } from './handlers/action.handler';
|
6
|
+
import { workflowHandler } from './handlers/workflow.handler';
|
7
|
+
import { CmdAction } from './common/enum';
|
8
|
+
import { mobiofficeHandler } from './handlers/mobioffice.handler';
|
9
|
+
import { customLog } from './common/utils';
|
10
|
+
import { hasFlag } from './common/helpers';
|
11
|
+
import { environmentHandler } from './handlers/environment.handler';
|
12
|
+
import { companyHandler } from './handlers/company.handler';
|
13
|
+
import { argv } from 'process';
|
14
|
+
import { helpHandler } from './handlers/help.handler';
|
15
|
+
|
16
|
+
const [action] = argv.slice(2);
|
17
|
+
|
18
|
+
(async function () {
|
19
|
+
// helpHandler.setWorkflowPath(action as CmdAction);
|
20
|
+
|
21
|
+
switch (action as CmdAction) {
|
22
|
+
case CmdAction.VERSION:
|
23
|
+
case CmdAction.VERSION_FLAG:
|
24
|
+
console.log(`v${packageJSON.version}`);
|
25
|
+
break;
|
26
|
+
|
27
|
+
case CmdAction.LINK:
|
28
|
+
case CmdAction.UNLINK:
|
29
|
+
await mobiofficeHandler.linkToMobioffice(
|
30
|
+
action as CmdAction.LINK | CmdAction.UNLINK,
|
31
|
+
);
|
32
|
+
break;
|
33
|
+
|
34
|
+
case CmdAction.PERMISSION:
|
35
|
+
if (hasFlag('-d')) await companyHandler.revokePermission();
|
36
|
+
else await companyHandler.addToken();
|
37
|
+
break;
|
38
|
+
|
39
|
+
case CmdAction.SET:
|
40
|
+
companyHandler.handleUpdateSavedSecretKey();
|
41
|
+
break;
|
42
|
+
|
43
|
+
case CmdAction.ADD_USER:
|
44
|
+
await companyHandler.addUser();
|
45
|
+
break;
|
46
|
+
|
47
|
+
case CmdAction.INFO:
|
48
|
+
companyHandler.logInfo();
|
49
|
+
break;
|
50
|
+
|
51
|
+
case CmdAction.LOGIN:
|
52
|
+
await companyHandler.handleLogin();
|
53
|
+
break;
|
54
|
+
|
55
|
+
case CmdAction.CLONE:
|
56
|
+
await workflowHandler.cloneWorkflow();
|
57
|
+
await actionHandler.cloneActions();
|
58
|
+
await environmentHandler.cloneEnvironments();
|
59
|
+
// helpHandler.createInfoFiles();
|
60
|
+
break;
|
61
|
+
case CmdAction.ADD:
|
62
|
+
await workflowHandler.copyWorkflow();
|
63
|
+
case CmdAction.PUSH:
|
64
|
+
await workflowHandler.updateWorkflowToDB();
|
65
|
+
await actionHandler.saveToDB();
|
66
|
+
await environmentHandler.saveToDB();
|
67
|
+
await workflowHandler.resetCache();
|
68
|
+
break;
|
69
|
+
|
70
|
+
case CmdAction.CHANGE:
|
71
|
+
await workflowHandler.updateWorkflowProperty();
|
72
|
+
break;
|
73
|
+
|
74
|
+
case CmdAction.HELP:
|
75
|
+
case CmdAction.HELP_FLAG:
|
76
|
+
helpHandler.logCommandInfo();
|
77
|
+
break;
|
78
|
+
|
79
|
+
default:
|
80
|
+
customLog.error(
|
81
|
+
`${action ? 'Invalid' : 'Missing'} command: ${action ?? ''}`,
|
82
|
+
);
|
83
|
+
console.log(
|
84
|
+
`\t\t use 'mstate <command>? ${CmdAction.HELP_FLAG}, ${CmdAction.HELP}' for getting allowed action`,
|
85
|
+
);
|
86
|
+
}
|
87
|
+
})()
|
88
|
+
.then()
|
89
|
+
.catch((error: any) => {
|
90
|
+
if (hasFlag(CmdAction.HELP) || hasFlag(CmdAction.HELP_FLAG)) {
|
91
|
+
helpHandler.logActionInfo(action as CmdAction);
|
92
|
+
} else customLog.error(error.message);
|
93
|
+
});
|
94
|
+
console.log('');
|
package/src/interface.d.ts
CHANGED
@@ -1,43 +1,43 @@
|
|
1
|
-
interface WorkflowConfig {
|
2
|
-
name: string;
|
3
|
-
states: State[];
|
4
|
-
}
|
5
|
-
|
6
|
-
interface State {
|
7
|
-
name: string;
|
8
|
-
actions: Action[];
|
9
|
-
}
|
10
|
-
|
11
|
-
interface Action {
|
12
|
-
name: string;
|
13
|
-
when?: string;
|
14
|
-
on: {
|
15
|
-
[key: string]: {
|
16
|
-
name: string;
|
17
|
-
type: 'ACTION' | 'STATE';
|
18
|
-
};
|
19
|
-
done: {
|
20
|
-
name: string;
|
21
|
-
type: 'ACTION' | 'STATE';
|
22
|
-
};
|
23
|
-
error: {
|
24
|
-
name: string;
|
25
|
-
type: 'ACTION' | 'STATE';
|
26
|
-
};
|
27
|
-
};
|
28
|
-
}
|
29
|
-
|
30
|
-
interface ActionConfig {
|
31
|
-
name: string;
|
32
|
-
version: string;
|
33
|
-
meta?: unknown;
|
34
|
-
type: 'MANUAL' | 'AUTO' | 'CHAINED';
|
35
|
-
steps: Step[];
|
36
|
-
completionWebhook?: string;
|
37
|
-
}
|
38
|
-
|
39
|
-
interface Step {
|
40
|
-
id: string;
|
41
|
-
module: string;
|
42
|
-
config: unknown;
|
43
|
-
}
|
1
|
+
interface WorkflowConfig {
|
2
|
+
name: string;
|
3
|
+
states: State[];
|
4
|
+
}
|
5
|
+
|
6
|
+
interface State {
|
7
|
+
name: string;
|
8
|
+
actions: Action[];
|
9
|
+
}
|
10
|
+
|
11
|
+
interface Action {
|
12
|
+
name: string;
|
13
|
+
when?: string;
|
14
|
+
on: {
|
15
|
+
[key: string]: {
|
16
|
+
name: string;
|
17
|
+
type: 'ACTION' | 'STATE';
|
18
|
+
};
|
19
|
+
done: {
|
20
|
+
name: string;
|
21
|
+
type: 'ACTION' | 'STATE';
|
22
|
+
};
|
23
|
+
error: {
|
24
|
+
name: string;
|
25
|
+
type: 'ACTION' | 'STATE';
|
26
|
+
};
|
27
|
+
};
|
28
|
+
}
|
29
|
+
|
30
|
+
interface ActionConfig {
|
31
|
+
name: string;
|
32
|
+
version: string;
|
33
|
+
meta?: unknown;
|
34
|
+
type: 'MANUAL' | 'AUTO' | 'CHAINED';
|
35
|
+
steps: Step[];
|
36
|
+
completionWebhook?: string;
|
37
|
+
}
|
38
|
+
|
39
|
+
interface Step {
|
40
|
+
id: string;
|
41
|
+
module: string;
|
42
|
+
config: unknown;
|
43
|
+
}
|