testblocks 0.1.0
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/LICENSE +21 -0
- package/README.md +333 -0
- package/dist/cli/executor.d.ts +32 -0
- package/dist/cli/executor.js +517 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +411 -0
- package/dist/cli/reporters.d.ts +62 -0
- package/dist/cli/reporters.js +451 -0
- package/dist/client/assets/index-4hbFPUhP.js +2087 -0
- package/dist/client/assets/index-4hbFPUhP.js.map +1 -0
- package/dist/client/assets/index-Dnk1ti7l.css +1 -0
- package/dist/client/index.html +25 -0
- package/dist/core/blocks/api.d.ts +2 -0
- package/dist/core/blocks/api.js +610 -0
- package/dist/core/blocks/data-driven.d.ts +2 -0
- package/dist/core/blocks/data-driven.js +245 -0
- package/dist/core/blocks/index.d.ts +15 -0
- package/dist/core/blocks/index.js +71 -0
- package/dist/core/blocks/lifecycle.d.ts +2 -0
- package/dist/core/blocks/lifecycle.js +199 -0
- package/dist/core/blocks/logic.d.ts +2 -0
- package/dist/core/blocks/logic.js +357 -0
- package/dist/core/blocks/playwright.d.ts +2 -0
- package/dist/core/blocks/playwright.js +764 -0
- package/dist/core/blocks/procedures.d.ts +5 -0
- package/dist/core/blocks/procedures.js +321 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.js +44 -0
- package/dist/core/plugins.d.ts +66 -0
- package/dist/core/plugins.js +118 -0
- package/dist/core/types.d.ts +153 -0
- package/dist/core/types.js +2 -0
- package/dist/server/codegenManager.d.ts +54 -0
- package/dist/server/codegenManager.js +259 -0
- package/dist/server/codegenParser.d.ts +17 -0
- package/dist/server/codegenParser.js +598 -0
- package/dist/server/executor.d.ts +37 -0
- package/dist/server/executor.js +672 -0
- package/dist/server/globals.d.ts +85 -0
- package/dist/server/globals.js +273 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.js +361 -0
- package/dist/server/plugins.d.ts +55 -0
- package/dist/server/plugins.js +206 -0
- package/package.json +103 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { BlockDefinition, ProcedureDefinition } from '../types';
|
|
2
|
+
export declare function registerProcedure(name: string, procedure: ProcedureDefinition): void;
|
|
3
|
+
export declare function getProcedure(name: string): ProcedureDefinition | undefined;
|
|
4
|
+
export declare function clearProcedures(): void;
|
|
5
|
+
export declare const procedureBlocks: BlockDefinition[];
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.procedureBlocks = void 0;
|
|
4
|
+
exports.registerProcedure = registerProcedure;
|
|
5
|
+
exports.getProcedure = getProcedure;
|
|
6
|
+
exports.clearProcedures = clearProcedures;
|
|
7
|
+
// Procedure registry for runtime
|
|
8
|
+
const procedureRegistry = new Map();
|
|
9
|
+
function registerProcedure(name, procedure) {
|
|
10
|
+
procedureRegistry.set(name, procedure);
|
|
11
|
+
}
|
|
12
|
+
function getProcedure(name) {
|
|
13
|
+
return procedureRegistry.get(name);
|
|
14
|
+
}
|
|
15
|
+
function clearProcedures() {
|
|
16
|
+
procedureRegistry.clear();
|
|
17
|
+
}
|
|
18
|
+
// Procedure Blocks - Custom Reusable Actions
|
|
19
|
+
exports.procedureBlocks = [
|
|
20
|
+
// Define a procedure (function)
|
|
21
|
+
{
|
|
22
|
+
type: 'procedure_define',
|
|
23
|
+
category: 'Procedures',
|
|
24
|
+
color: '#9C27B0',
|
|
25
|
+
tooltip: 'Define a reusable procedure with parameters',
|
|
26
|
+
inputs: [
|
|
27
|
+
{ name: 'NAME', type: 'field', fieldType: 'text', required: true },
|
|
28
|
+
{ name: 'DESCRIPTION', type: 'field', fieldType: 'text', default: '' },
|
|
29
|
+
{ name: 'PARAMS', type: 'field', fieldType: 'text', default: '' }, // comma-separated: "username, password, timeout"
|
|
30
|
+
{ name: 'DO', type: 'statement' },
|
|
31
|
+
],
|
|
32
|
+
execute: async (params, context) => {
|
|
33
|
+
const name = params.NAME;
|
|
34
|
+
const description = params.DESCRIPTION;
|
|
35
|
+
const paramsStr = params.PARAMS;
|
|
36
|
+
// Parse parameters
|
|
37
|
+
const procedureParams = paramsStr
|
|
38
|
+
.split(',')
|
|
39
|
+
.map(p => p.trim())
|
|
40
|
+
.filter(p => p)
|
|
41
|
+
.map(p => {
|
|
42
|
+
// Support type annotations: "username:string", "count:number"
|
|
43
|
+
const [paramName, paramType] = p.split(':').map(s => s.trim());
|
|
44
|
+
return {
|
|
45
|
+
name: paramName,
|
|
46
|
+
type: paramType || 'any',
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
// Register the procedure
|
|
50
|
+
const procedure = {
|
|
51
|
+
name,
|
|
52
|
+
description,
|
|
53
|
+
params: procedureParams,
|
|
54
|
+
steps: [], // Steps will be extracted by the executor
|
|
55
|
+
};
|
|
56
|
+
registerProcedure(name, procedure);
|
|
57
|
+
if (context.procedures) {
|
|
58
|
+
context.procedures.set(name, procedure);
|
|
59
|
+
}
|
|
60
|
+
context.logger.debug(`Defined procedure: ${name}(${procedureParams.map(p => p.name).join(', ')})`);
|
|
61
|
+
return { procedureDefine: true, name, procedure };
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
// Call a procedure
|
|
65
|
+
{
|
|
66
|
+
type: 'procedure_call',
|
|
67
|
+
category: 'Procedures',
|
|
68
|
+
color: '#9C27B0',
|
|
69
|
+
tooltip: 'Call a defined procedure',
|
|
70
|
+
inputs: [
|
|
71
|
+
{ name: 'NAME', type: 'field', fieldType: 'text', required: true },
|
|
72
|
+
{ name: 'ARGS', type: 'field', fieldType: 'text', default: '' }, // JSON object or comma-separated values
|
|
73
|
+
],
|
|
74
|
+
previousStatement: true,
|
|
75
|
+
nextStatement: true,
|
|
76
|
+
execute: async (params, context) => {
|
|
77
|
+
const name = params.NAME;
|
|
78
|
+
const argsStr = resolveVariables(params.ARGS, context);
|
|
79
|
+
// Look up procedure
|
|
80
|
+
const procedure = context.procedures?.get(name) || getProcedure(name);
|
|
81
|
+
if (!procedure) {
|
|
82
|
+
throw new Error(`Procedure not found: ${name}`);
|
|
83
|
+
}
|
|
84
|
+
// Parse arguments
|
|
85
|
+
let args = {};
|
|
86
|
+
if (argsStr.trim()) {
|
|
87
|
+
try {
|
|
88
|
+
// Try JSON format first: {"username": "test", "password": "123"}
|
|
89
|
+
args = JSON.parse(argsStr);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// Fall back to comma-separated values matching parameter order
|
|
93
|
+
const values = argsStr.split(',').map(v => {
|
|
94
|
+
const trimmed = v.trim();
|
|
95
|
+
try {
|
|
96
|
+
return JSON.parse(trimmed);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return trimmed;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
if (procedure.params) {
|
|
103
|
+
procedure.params.forEach((param, index) => {
|
|
104
|
+
if (index < values.length) {
|
|
105
|
+
args[param.name] = values[index];
|
|
106
|
+
}
|
|
107
|
+
else if (param.default !== undefined) {
|
|
108
|
+
args[param.name] = param.default;
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
context.logger.info(`Calling procedure: ${name}`);
|
|
115
|
+
return { procedureCall: true, name, args, procedure };
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
// Call procedure with return value
|
|
119
|
+
{
|
|
120
|
+
type: 'procedure_call_with_return',
|
|
121
|
+
category: 'Procedures',
|
|
122
|
+
color: '#9C27B0',
|
|
123
|
+
tooltip: 'Call a procedure and get return value',
|
|
124
|
+
inputs: [
|
|
125
|
+
{ name: 'NAME', type: 'field', fieldType: 'text', required: true },
|
|
126
|
+
{ name: 'ARGS', type: 'field', fieldType: 'text', default: '' },
|
|
127
|
+
],
|
|
128
|
+
output: { type: ['String', 'Number', 'Boolean', 'Object', 'Array'] },
|
|
129
|
+
execute: async (params, context) => {
|
|
130
|
+
const name = params.NAME;
|
|
131
|
+
const argsStr = resolveVariables(params.ARGS, context);
|
|
132
|
+
const procedure = context.procedures?.get(name) || getProcedure(name);
|
|
133
|
+
if (!procedure) {
|
|
134
|
+
throw new Error(`Procedure not found: ${name}`);
|
|
135
|
+
}
|
|
136
|
+
let args = {};
|
|
137
|
+
if (argsStr.trim()) {
|
|
138
|
+
try {
|
|
139
|
+
args = JSON.parse(argsStr);
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
const values = argsStr.split(',').map(v => v.trim());
|
|
143
|
+
if (procedure.params) {
|
|
144
|
+
procedure.params.forEach((param, index) => {
|
|
145
|
+
if (index < values.length) {
|
|
146
|
+
args[param.name] = values[index];
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return { procedureCall: true, name, args, procedure, expectReturn: true };
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
// Return from procedure
|
|
156
|
+
{
|
|
157
|
+
type: 'procedure_return',
|
|
158
|
+
category: 'Procedures',
|
|
159
|
+
color: '#9C27B0',
|
|
160
|
+
tooltip: 'Return a value from a procedure',
|
|
161
|
+
inputs: [
|
|
162
|
+
{ name: 'VALUE', type: 'value' },
|
|
163
|
+
],
|
|
164
|
+
previousStatement: true,
|
|
165
|
+
execute: async (params, _context) => {
|
|
166
|
+
const value = params.VALUE;
|
|
167
|
+
return { procedureReturn: true, value };
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
// Get procedure parameter
|
|
171
|
+
{
|
|
172
|
+
type: 'procedure_get_param',
|
|
173
|
+
category: 'Procedures',
|
|
174
|
+
color: '#9C27B0',
|
|
175
|
+
tooltip: 'Get a procedure parameter value',
|
|
176
|
+
inputs: [
|
|
177
|
+
{ name: 'NAME', type: 'field', fieldType: 'text', required: true },
|
|
178
|
+
],
|
|
179
|
+
output: { type: ['String', 'Number', 'Boolean', 'Object', 'Array'] },
|
|
180
|
+
execute: async (params, context) => {
|
|
181
|
+
const name = params.NAME;
|
|
182
|
+
// Parameters are stored in variables with a prefix
|
|
183
|
+
const value = context.variables.get(`__param_${name}`);
|
|
184
|
+
if (value === undefined) {
|
|
185
|
+
// Check regular variables as fallback
|
|
186
|
+
return context.variables.get(name);
|
|
187
|
+
}
|
|
188
|
+
return value;
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
// Define inline procedure (lambda-style)
|
|
192
|
+
{
|
|
193
|
+
type: 'procedure_inline',
|
|
194
|
+
category: 'Procedures',
|
|
195
|
+
color: '#9C27B0',
|
|
196
|
+
tooltip: 'Define and immediately use an inline procedure',
|
|
197
|
+
inputs: [
|
|
198
|
+
{ name: 'PARAMS', type: 'field', fieldType: 'text', default: '' },
|
|
199
|
+
{ name: 'DO', type: 'statement' },
|
|
200
|
+
],
|
|
201
|
+
output: { type: 'Procedure' },
|
|
202
|
+
execute: async (params, _context) => {
|
|
203
|
+
return {
|
|
204
|
+
inlineProcedure: true,
|
|
205
|
+
params: params.PARAMS.split(',').map(p => p.trim()).filter(p => p),
|
|
206
|
+
statement: 'DO',
|
|
207
|
+
};
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
// Apply/Map procedure to array
|
|
211
|
+
{
|
|
212
|
+
type: 'procedure_map',
|
|
213
|
+
category: 'Procedures',
|
|
214
|
+
color: '#9C27B0',
|
|
215
|
+
tooltip: 'Apply a procedure to each item in an array',
|
|
216
|
+
inputs: [
|
|
217
|
+
{ name: 'ARRAY', type: 'value', check: 'Array', required: true },
|
|
218
|
+
{ name: 'PROCEDURE', type: 'field', fieldType: 'text', required: true },
|
|
219
|
+
{ name: 'ITEM_PARAM', type: 'field', fieldType: 'text', default: 'item' },
|
|
220
|
+
],
|
|
221
|
+
output: { type: 'Array' },
|
|
222
|
+
execute: async (params, _context) => {
|
|
223
|
+
const array = params.ARRAY;
|
|
224
|
+
const procedureName = params.PROCEDURE;
|
|
225
|
+
const itemParam = params.ITEM_PARAM;
|
|
226
|
+
return {
|
|
227
|
+
procedureMap: true,
|
|
228
|
+
array,
|
|
229
|
+
procedureName,
|
|
230
|
+
itemParam,
|
|
231
|
+
};
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
// Common action blocks - frequently used patterns
|
|
235
|
+
// Login procedure template
|
|
236
|
+
{
|
|
237
|
+
type: 'procedure_login',
|
|
238
|
+
category: 'Procedures',
|
|
239
|
+
color: '#AB47BC',
|
|
240
|
+
tooltip: 'Common login action with username and password',
|
|
241
|
+
inputs: [
|
|
242
|
+
{ name: 'USERNAME_SELECTOR', type: 'field', fieldType: 'text', default: '#username' },
|
|
243
|
+
{ name: 'PASSWORD_SELECTOR', type: 'field', fieldType: 'text', default: '#password' },
|
|
244
|
+
{ name: 'SUBMIT_SELECTOR', type: 'field', fieldType: 'text', default: 'button[type="submit"]' },
|
|
245
|
+
{ name: 'USERNAME', type: 'value', check: 'String', required: true },
|
|
246
|
+
{ name: 'PASSWORD', type: 'value', check: 'String', required: true },
|
|
247
|
+
],
|
|
248
|
+
previousStatement: true,
|
|
249
|
+
nextStatement: true,
|
|
250
|
+
execute: async (params, _context) => {
|
|
251
|
+
// This is a compound action that expands to multiple steps
|
|
252
|
+
return {
|
|
253
|
+
compoundAction: 'login',
|
|
254
|
+
steps: [
|
|
255
|
+
{ type: 'web_fill', params: { SELECTOR: params.USERNAME_SELECTOR, VALUE: params.USERNAME } },
|
|
256
|
+
{ type: 'web_fill', params: { SELECTOR: params.PASSWORD_SELECTOR, VALUE: params.PASSWORD } },
|
|
257
|
+
{ type: 'web_click', params: { SELECTOR: params.SUBMIT_SELECTOR } },
|
|
258
|
+
],
|
|
259
|
+
};
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
// Wait for element and click
|
|
263
|
+
{
|
|
264
|
+
type: 'procedure_wait_and_click',
|
|
265
|
+
category: 'Procedures',
|
|
266
|
+
color: '#AB47BC',
|
|
267
|
+
tooltip: 'Wait for element to be visible then click',
|
|
268
|
+
inputs: [
|
|
269
|
+
{ name: 'SELECTOR', type: 'field', fieldType: 'text', required: true },
|
|
270
|
+
{ name: 'TIMEOUT', type: 'field', fieldType: 'number', default: 30000 },
|
|
271
|
+
],
|
|
272
|
+
previousStatement: true,
|
|
273
|
+
nextStatement: true,
|
|
274
|
+
execute: async (params, _context) => {
|
|
275
|
+
return {
|
|
276
|
+
compoundAction: 'waitAndClick',
|
|
277
|
+
steps: [
|
|
278
|
+
{ type: 'web_wait_for_element', params: { SELECTOR: params.SELECTOR, STATE: 'visible', TIMEOUT: params.TIMEOUT } },
|
|
279
|
+
{ type: 'web_click', params: { SELECTOR: params.SELECTOR } },
|
|
280
|
+
],
|
|
281
|
+
};
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
// Fill form fields from object
|
|
285
|
+
{
|
|
286
|
+
type: 'procedure_fill_form',
|
|
287
|
+
category: 'Procedures',
|
|
288
|
+
color: '#AB47BC',
|
|
289
|
+
tooltip: 'Fill multiple form fields from a data object',
|
|
290
|
+
inputs: [
|
|
291
|
+
{ name: 'FIELDS', type: 'value', check: 'Object', required: true },
|
|
292
|
+
],
|
|
293
|
+
previousStatement: true,
|
|
294
|
+
nextStatement: true,
|
|
295
|
+
execute: async (params, _context) => {
|
|
296
|
+
const fields = params.FIELDS;
|
|
297
|
+
const steps = Object.entries(fields).map(([selector, value]) => ({
|
|
298
|
+
type: 'web_fill',
|
|
299
|
+
params: { SELECTOR: selector, VALUE: value },
|
|
300
|
+
}));
|
|
301
|
+
return { compoundAction: 'fillForm', steps };
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
];
|
|
305
|
+
// Helper function
|
|
306
|
+
function resolveVariables(text, context) {
|
|
307
|
+
return text.replace(/\$\{(\w+)\}/g, (_, varName) => {
|
|
308
|
+
// Check param prefix first
|
|
309
|
+
const paramValue = context.variables.get(`__param_${varName}`);
|
|
310
|
+
if (paramValue !== undefined) {
|
|
311
|
+
return String(paramValue);
|
|
312
|
+
}
|
|
313
|
+
// Then check current data
|
|
314
|
+
if (context.currentData?.values[varName] !== undefined) {
|
|
315
|
+
return String(context.currentData.values[varName]);
|
|
316
|
+
}
|
|
317
|
+
// Then regular variables
|
|
318
|
+
const value = context.variables.get(varName);
|
|
319
|
+
return value !== undefined ? String(value) : '';
|
|
320
|
+
});
|
|
321
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export * from './types';
|
|
2
|
+
export * from './blocks';
|
|
3
|
+
export * from './plugins';
|
|
4
|
+
export { builtInBlocks, blockRegistry, registerBlock, registerBlocks, getBlock, getAllBlocks, getBlocksByCategory, getCategories, } from './blocks';
|
|
5
|
+
export { registerPlugin, getPlugin, getAllPlugins, getAllPluginBlocks, unregisterPlugin, createPlugin, createBlock, createActionBlock, createValueBlock, createAssertionBlock, } from './plugins';
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.createAssertionBlock = exports.createValueBlock = exports.createActionBlock = exports.createBlock = exports.createPlugin = exports.unregisterPlugin = exports.getAllPluginBlocks = exports.getAllPlugins = exports.getPlugin = exports.registerPlugin = exports.getCategories = exports.getBlocksByCategory = exports.getAllBlocks = exports.getBlock = exports.registerBlocks = exports.registerBlock = exports.blockRegistry = exports.builtInBlocks = void 0;
|
|
18
|
+
// Types
|
|
19
|
+
__exportStar(require("./types"), exports);
|
|
20
|
+
// Blocks
|
|
21
|
+
__exportStar(require("./blocks"), exports);
|
|
22
|
+
// Plugins
|
|
23
|
+
__exportStar(require("./plugins"), exports);
|
|
24
|
+
// Re-export specific items for convenience
|
|
25
|
+
var blocks_1 = require("./blocks");
|
|
26
|
+
Object.defineProperty(exports, "builtInBlocks", { enumerable: true, get: function () { return blocks_1.builtInBlocks; } });
|
|
27
|
+
Object.defineProperty(exports, "blockRegistry", { enumerable: true, get: function () { return blocks_1.blockRegistry; } });
|
|
28
|
+
Object.defineProperty(exports, "registerBlock", { enumerable: true, get: function () { return blocks_1.registerBlock; } });
|
|
29
|
+
Object.defineProperty(exports, "registerBlocks", { enumerable: true, get: function () { return blocks_1.registerBlocks; } });
|
|
30
|
+
Object.defineProperty(exports, "getBlock", { enumerable: true, get: function () { return blocks_1.getBlock; } });
|
|
31
|
+
Object.defineProperty(exports, "getAllBlocks", { enumerable: true, get: function () { return blocks_1.getAllBlocks; } });
|
|
32
|
+
Object.defineProperty(exports, "getBlocksByCategory", { enumerable: true, get: function () { return blocks_1.getBlocksByCategory; } });
|
|
33
|
+
Object.defineProperty(exports, "getCategories", { enumerable: true, get: function () { return blocks_1.getCategories; } });
|
|
34
|
+
var plugins_1 = require("./plugins");
|
|
35
|
+
Object.defineProperty(exports, "registerPlugin", { enumerable: true, get: function () { return plugins_1.registerPlugin; } });
|
|
36
|
+
Object.defineProperty(exports, "getPlugin", { enumerable: true, get: function () { return plugins_1.getPlugin; } });
|
|
37
|
+
Object.defineProperty(exports, "getAllPlugins", { enumerable: true, get: function () { return plugins_1.getAllPlugins; } });
|
|
38
|
+
Object.defineProperty(exports, "getAllPluginBlocks", { enumerable: true, get: function () { return plugins_1.getAllPluginBlocks; } });
|
|
39
|
+
Object.defineProperty(exports, "unregisterPlugin", { enumerable: true, get: function () { return plugins_1.unregisterPlugin; } });
|
|
40
|
+
Object.defineProperty(exports, "createPlugin", { enumerable: true, get: function () { return plugins_1.createPlugin; } });
|
|
41
|
+
Object.defineProperty(exports, "createBlock", { enumerable: true, get: function () { return plugins_1.createBlock; } });
|
|
42
|
+
Object.defineProperty(exports, "createActionBlock", { enumerable: true, get: function () { return plugins_1.createActionBlock; } });
|
|
43
|
+
Object.defineProperty(exports, "createValueBlock", { enumerable: true, get: function () { return plugins_1.createValueBlock; } });
|
|
44
|
+
Object.defineProperty(exports, "createAssertionBlock", { enumerable: true, get: function () { return plugins_1.createAssertionBlock; } });
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Plugin, BlockDefinition, ExecutionContext } from './types';
|
|
2
|
+
export declare function registerPlugin(plugin: Plugin): void;
|
|
3
|
+
export declare function getPlugin(name: string): Plugin | undefined;
|
|
4
|
+
export declare function getAllPlugins(): Plugin[];
|
|
5
|
+
export declare function getAllPluginBlocks(): BlockDefinition[];
|
|
6
|
+
export declare function unregisterPlugin(name: string): boolean;
|
|
7
|
+
export declare function createPlugin(config: {
|
|
8
|
+
name: string;
|
|
9
|
+
version: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
blocks?: BlockDefinition[];
|
|
12
|
+
hooks?: Plugin['hooks'];
|
|
13
|
+
}): Plugin;
|
|
14
|
+
export declare function createBlock(config: {
|
|
15
|
+
type: string;
|
|
16
|
+
category: string;
|
|
17
|
+
color?: string;
|
|
18
|
+
tooltip?: string;
|
|
19
|
+
helpUrl?: string;
|
|
20
|
+
inputs: BlockDefinition['inputs'];
|
|
21
|
+
output?: BlockDefinition['output'];
|
|
22
|
+
previousStatement?: boolean;
|
|
23
|
+
nextStatement?: boolean;
|
|
24
|
+
execute: BlockDefinition['execute'];
|
|
25
|
+
}): BlockDefinition;
|
|
26
|
+
/**
|
|
27
|
+
* Create an action block - executes an action, can be chained with other blocks
|
|
28
|
+
* Has previous/next statements, no output value
|
|
29
|
+
*/
|
|
30
|
+
export declare function createActionBlock(config: {
|
|
31
|
+
type: string;
|
|
32
|
+
category: string;
|
|
33
|
+
color?: string;
|
|
34
|
+
tooltip?: string;
|
|
35
|
+
inputs: BlockDefinition['inputs'];
|
|
36
|
+
execute: (params: Record<string, unknown>, context: ExecutionContext) => Promise<unknown>;
|
|
37
|
+
}): BlockDefinition;
|
|
38
|
+
/**
|
|
39
|
+
* Create a value block - returns a value that can be used as input to other blocks
|
|
40
|
+
* Has output, no previous/next statements
|
|
41
|
+
*/
|
|
42
|
+
export declare function createValueBlock(config: {
|
|
43
|
+
type: string;
|
|
44
|
+
category: string;
|
|
45
|
+
color?: string;
|
|
46
|
+
tooltip?: string;
|
|
47
|
+
inputs: BlockDefinition['inputs'];
|
|
48
|
+
outputType: string | string[];
|
|
49
|
+
execute: (params: Record<string, unknown>, context: ExecutionContext) => Promise<unknown>;
|
|
50
|
+
}): BlockDefinition;
|
|
51
|
+
/**
|
|
52
|
+
* Create an assertion block - validates a condition
|
|
53
|
+
* Throws an error if assertion fails
|
|
54
|
+
*/
|
|
55
|
+
export declare function createAssertionBlock(config: {
|
|
56
|
+
type: string;
|
|
57
|
+
category?: string;
|
|
58
|
+
color?: string;
|
|
59
|
+
tooltip?: string;
|
|
60
|
+
inputs: BlockDefinition['inputs'];
|
|
61
|
+
assert: (params: Record<string, unknown>, context: ExecutionContext) => Promise<{
|
|
62
|
+
pass: boolean;
|
|
63
|
+
message?: string;
|
|
64
|
+
}>;
|
|
65
|
+
}): BlockDefinition;
|
|
66
|
+
export type { Plugin, BlockDefinition, ExecutionContext };
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerPlugin = registerPlugin;
|
|
4
|
+
exports.getPlugin = getPlugin;
|
|
5
|
+
exports.getAllPlugins = getAllPlugins;
|
|
6
|
+
exports.getAllPluginBlocks = getAllPluginBlocks;
|
|
7
|
+
exports.unregisterPlugin = unregisterPlugin;
|
|
8
|
+
exports.createPlugin = createPlugin;
|
|
9
|
+
exports.createBlock = createBlock;
|
|
10
|
+
exports.createActionBlock = createActionBlock;
|
|
11
|
+
exports.createValueBlock = createValueBlock;
|
|
12
|
+
exports.createAssertionBlock = createAssertionBlock;
|
|
13
|
+
const blocks_1 = require("./blocks");
|
|
14
|
+
// Plugin registry
|
|
15
|
+
const pluginRegistry = new Map();
|
|
16
|
+
// Register a plugin
|
|
17
|
+
function registerPlugin(plugin) {
|
|
18
|
+
if (pluginRegistry.has(plugin.name)) {
|
|
19
|
+
console.warn(`Plugin "${plugin.name}" is already registered. Overwriting...`);
|
|
20
|
+
}
|
|
21
|
+
pluginRegistry.set(plugin.name, plugin);
|
|
22
|
+
// Register the plugin's blocks
|
|
23
|
+
if (plugin.blocks && plugin.blocks.length > 0) {
|
|
24
|
+
(0, blocks_1.registerBlocks)(plugin.blocks);
|
|
25
|
+
}
|
|
26
|
+
console.log(`Plugin registered: ${plugin.name} v${plugin.version}`);
|
|
27
|
+
}
|
|
28
|
+
// Get a registered plugin
|
|
29
|
+
function getPlugin(name) {
|
|
30
|
+
return pluginRegistry.get(name);
|
|
31
|
+
}
|
|
32
|
+
// Get all registered plugins
|
|
33
|
+
function getAllPlugins() {
|
|
34
|
+
return Array.from(pluginRegistry.values());
|
|
35
|
+
}
|
|
36
|
+
// Get all plugin blocks
|
|
37
|
+
function getAllPluginBlocks() {
|
|
38
|
+
const blocks = [];
|
|
39
|
+
for (const plugin of pluginRegistry.values()) {
|
|
40
|
+
blocks.push(...plugin.blocks);
|
|
41
|
+
}
|
|
42
|
+
return blocks;
|
|
43
|
+
}
|
|
44
|
+
// Unregister a plugin
|
|
45
|
+
function unregisterPlugin(name) {
|
|
46
|
+
return pluginRegistry.delete(name);
|
|
47
|
+
}
|
|
48
|
+
// Create a plugin helper
|
|
49
|
+
function createPlugin(config) {
|
|
50
|
+
return {
|
|
51
|
+
name: config.name,
|
|
52
|
+
version: config.version,
|
|
53
|
+
description: config.description,
|
|
54
|
+
blocks: config.blocks || [],
|
|
55
|
+
hooks: config.hooks,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
// Helper to create a custom block easily
|
|
59
|
+
function createBlock(config) {
|
|
60
|
+
return {
|
|
61
|
+
type: config.type,
|
|
62
|
+
category: config.category,
|
|
63
|
+
color: config.color || '#607D8B',
|
|
64
|
+
tooltip: config.tooltip,
|
|
65
|
+
helpUrl: config.helpUrl,
|
|
66
|
+
inputs: config.inputs,
|
|
67
|
+
output: config.output,
|
|
68
|
+
previousStatement: config.previousStatement,
|
|
69
|
+
nextStatement: config.nextStatement,
|
|
70
|
+
execute: config.execute,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Create an action block - executes an action, can be chained with other blocks
|
|
75
|
+
* Has previous/next statements, no output value
|
|
76
|
+
*/
|
|
77
|
+
function createActionBlock(config) {
|
|
78
|
+
return createBlock({
|
|
79
|
+
...config,
|
|
80
|
+
previousStatement: true,
|
|
81
|
+
nextStatement: true,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Create a value block - returns a value that can be used as input to other blocks
|
|
86
|
+
* Has output, no previous/next statements
|
|
87
|
+
*/
|
|
88
|
+
function createValueBlock(config) {
|
|
89
|
+
return createBlock({
|
|
90
|
+
...config,
|
|
91
|
+
output: { type: config.outputType },
|
|
92
|
+
previousStatement: false,
|
|
93
|
+
nextStatement: false,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Create an assertion block - validates a condition
|
|
98
|
+
* Throws an error if assertion fails
|
|
99
|
+
*/
|
|
100
|
+
function createAssertionBlock(config) {
|
|
101
|
+
return createBlock({
|
|
102
|
+
type: config.type,
|
|
103
|
+
category: config.category || 'Assertions',
|
|
104
|
+
color: config.color || '#E91E63',
|
|
105
|
+
tooltip: config.tooltip,
|
|
106
|
+
inputs: config.inputs,
|
|
107
|
+
previousStatement: true,
|
|
108
|
+
nextStatement: true,
|
|
109
|
+
execute: async (params, context) => {
|
|
110
|
+
const result = await config.assert(params, context);
|
|
111
|
+
if (!result.pass) {
|
|
112
|
+
throw new Error(result.message || `Assertion failed: ${config.type}`);
|
|
113
|
+
}
|
|
114
|
+
context.logger.info(`✓ ${config.tooltip || config.type}`);
|
|
115
|
+
return result;
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
}
|