@abyss-project/console 1.0.29 → 1.0.31
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/expressions/functions/array.d.ts +2 -0
- package/dist/expressions/functions/array.js +252 -0
- package/dist/expressions/functions/crypto.d.ts +2 -0
- package/dist/expressions/functions/crypto.js +101 -0
- package/dist/expressions/functions/datetime.d.ts +2 -0
- package/dist/expressions/functions/datetime.js +256 -0
- package/dist/expressions/functions/index.d.ts +7 -0
- package/dist/expressions/functions/index.js +46 -0
- package/dist/expressions/functions/math.d.ts +2 -0
- package/dist/expressions/functions/math.js +174 -0
- package/dist/expressions/functions/string.d.ts +2 -0
- package/dist/expressions/functions/string.js +301 -0
- package/dist/expressions/functions/utility.d.ts +2 -0
- package/dist/expressions/functions/utility.js +230 -0
- package/dist/expressions/helpers.d.ts +26 -0
- package/dist/expressions/helpers.js +132 -0
- package/dist/expressions/index.d.ts +5 -0
- package/dist/expressions/index.js +16 -0
- package/dist/expressions/mapper.d.ts +9 -0
- package/dist/expressions/mapper.js +88 -0
- package/dist/expressions/parser.d.ts +3 -0
- package/dist/expressions/parser.js +97 -0
- package/dist/expressions/pipes/array-pipes.d.ts +2 -0
- package/dist/expressions/pipes/array-pipes.js +248 -0
- package/dist/expressions/pipes/index.d.ts +8 -0
- package/dist/expressions/pipes/index.js +40 -0
- package/dist/expressions/pipes/object-pipes.d.ts +2 -0
- package/dist/expressions/pipes/object-pipes.js +243 -0
- package/dist/expressions/pipes/string-pipes.d.ts +9 -0
- package/dist/expressions/pipes/string-pipes.js +178 -0
- package/dist/expressions/resolver.d.ts +12 -0
- package/dist/expressions/resolver.js +88 -0
- package/dist/expressions/types.d.ts +36 -0
- package/dist/expressions/types.js +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -1
- package/dist/utils/webhook-trigger.utils.js +10 -6
- package/dist/workflow-expressions/functions/array.d.ts +2 -0
- package/dist/workflow-expressions/functions/array.js +252 -0
- package/dist/workflow-expressions/functions/crypto.d.ts +2 -0
- package/dist/workflow-expressions/functions/crypto.js +101 -0
- package/dist/workflow-expressions/functions/datetime.d.ts +2 -0
- package/dist/workflow-expressions/functions/datetime.js +256 -0
- package/dist/workflow-expressions/functions/index.d.ts +7 -0
- package/dist/workflow-expressions/functions/index.js +46 -0
- package/dist/workflow-expressions/functions/math.d.ts +2 -0
- package/dist/workflow-expressions/functions/math.js +174 -0
- package/dist/workflow-expressions/functions/string.d.ts +2 -0
- package/dist/workflow-expressions/functions/string.js +301 -0
- package/dist/workflow-expressions/functions/utility.d.ts +2 -0
- package/dist/workflow-expressions/functions/utility.js +230 -0
- package/dist/workflow-expressions/helpers.d.ts +71 -0
- package/dist/workflow-expressions/helpers.js +262 -0
- package/dist/workflow-expressions/index.d.ts +16 -0
- package/dist/workflow-expressions/index.js +66 -0
- package/dist/workflow-expressions/parser.d.ts +8 -0
- package/dist/workflow-expressions/parser.js +456 -0
- package/dist/workflow-expressions/pipes/array-pipes.d.ts +2 -0
- package/dist/workflow-expressions/pipes/array-pipes.js +248 -0
- package/dist/workflow-expressions/pipes/index.d.ts +8 -0
- package/dist/workflow-expressions/pipes/index.js +40 -0
- package/dist/workflow-expressions/pipes/object-pipes.d.ts +2 -0
- package/dist/workflow-expressions/pipes/object-pipes.js +243 -0
- package/dist/workflow-expressions/pipes/string-pipes.d.ts +9 -0
- package/dist/workflow-expressions/pipes/string-pipes.js +178 -0
- package/dist/workflow-expressions/resolver.d.ts +8 -0
- package/dist/workflow-expressions/resolver.js +260 -0
- package/dist/workflow-expressions/types.d.ts +141 -0
- package/dist/workflow-expressions/types.js +33 -0
- package/package.json +2 -1
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.tokenizeTemplate = exports.parseExpression = exports.parsePathSegments = exports.detectDataSource = void 0;
|
|
4
|
+
const EXPRESSION_PATTERN = /\{\{(.+?)\}\}/g;
|
|
5
|
+
const FUNCTION_PATTERN = /^(?:fn\.)?(\w+)\((.*)\)$/s;
|
|
6
|
+
const PIPE_PATTERN = /\s*\|\s*(\w+)(?:\(([^)]*)\))?/g;
|
|
7
|
+
const DATA_SOURCE_PREFIXES = {
|
|
8
|
+
trigger: 'trigger',
|
|
9
|
+
triggerData: 'trigger',
|
|
10
|
+
steps: 'steps',
|
|
11
|
+
variables: 'variables',
|
|
12
|
+
secret: 'secret',
|
|
13
|
+
ipAddress: 'ipAddress',
|
|
14
|
+
domain: 'domain',
|
|
15
|
+
abyss: 'abyss',
|
|
16
|
+
app: 'app',
|
|
17
|
+
project: 'project',
|
|
18
|
+
env: 'env',
|
|
19
|
+
fn: 'fn',
|
|
20
|
+
};
|
|
21
|
+
function detectDataSource(path) {
|
|
22
|
+
const firstDot = path.indexOf('.');
|
|
23
|
+
const firstBracket = path.indexOf('[');
|
|
24
|
+
let prefix;
|
|
25
|
+
if (firstDot === -1 && firstBracket === -1) {
|
|
26
|
+
prefix = path;
|
|
27
|
+
}
|
|
28
|
+
else if (firstDot === -1) {
|
|
29
|
+
prefix = path.substring(0, firstBracket);
|
|
30
|
+
}
|
|
31
|
+
else if (firstBracket === -1) {
|
|
32
|
+
prefix = path.substring(0, firstDot);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
prefix = path.substring(0, Math.min(firstDot, firstBracket));
|
|
36
|
+
}
|
|
37
|
+
return DATA_SOURCE_PREFIXES[prefix] || null;
|
|
38
|
+
}
|
|
39
|
+
exports.detectDataSource = detectDataSource;
|
|
40
|
+
function parsePathSegments(path) {
|
|
41
|
+
const segments = [];
|
|
42
|
+
let current = '';
|
|
43
|
+
let inBracket = false;
|
|
44
|
+
let bracketContent = '';
|
|
45
|
+
for (let i = 0; i < path.length; i++) {
|
|
46
|
+
const char = path[i];
|
|
47
|
+
if (char === '[') {
|
|
48
|
+
if (current) {
|
|
49
|
+
segments.push(current);
|
|
50
|
+
current = '';
|
|
51
|
+
}
|
|
52
|
+
inBracket = true;
|
|
53
|
+
bracketContent = '';
|
|
54
|
+
}
|
|
55
|
+
else if (char === ']' && inBracket) {
|
|
56
|
+
const cleaned = bracketContent.replace(/^["']|["']$/g, '');
|
|
57
|
+
segments.push(cleaned);
|
|
58
|
+
inBracket = false;
|
|
59
|
+
bracketContent = '';
|
|
60
|
+
}
|
|
61
|
+
else if (inBracket) {
|
|
62
|
+
bracketContent += char;
|
|
63
|
+
}
|
|
64
|
+
else if (char === '.') {
|
|
65
|
+
if (current) {
|
|
66
|
+
segments.push(current);
|
|
67
|
+
current = '';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
current += char;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (current) {
|
|
75
|
+
segments.push(current);
|
|
76
|
+
}
|
|
77
|
+
return segments;
|
|
78
|
+
}
|
|
79
|
+
exports.parsePathSegments = parsePathSegments;
|
|
80
|
+
function parseExpression(expression) {
|
|
81
|
+
const trimmed = expression.trim();
|
|
82
|
+
if (!trimmed) {
|
|
83
|
+
return {
|
|
84
|
+
type: 'literal',
|
|
85
|
+
literalType: 'string',
|
|
86
|
+
literalValue: '',
|
|
87
|
+
isValid: false,
|
|
88
|
+
error: 'Empty expression',
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
try {
|
|
92
|
+
return parseExpressionAST(trimmed);
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
return {
|
|
96
|
+
type: 'literal',
|
|
97
|
+
literalType: 'string',
|
|
98
|
+
literalValue: '',
|
|
99
|
+
isValid: false,
|
|
100
|
+
error: error instanceof Error ? error.message : 'Parse error',
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.parseExpression = parseExpression;
|
|
105
|
+
function parseExpressionAST(expr) {
|
|
106
|
+
const trimmed = expr.trim();
|
|
107
|
+
const ternary = findTernaryOperator(trimmed);
|
|
108
|
+
if (ternary) {
|
|
109
|
+
return {
|
|
110
|
+
type: 'ternary',
|
|
111
|
+
condition: parseExpressionAST(ternary.condition),
|
|
112
|
+
consequent: parseExpressionAST(ternary.consequent),
|
|
113
|
+
alternate: parseExpressionAST(ternary.alternate),
|
|
114
|
+
isValid: true,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const binary = findBinaryOperator(trimmed);
|
|
118
|
+
if (binary) {
|
|
119
|
+
return {
|
|
120
|
+
type: 'binary',
|
|
121
|
+
operator: binary.operator,
|
|
122
|
+
left: parseExpressionAST(binary.left),
|
|
123
|
+
right: parseExpressionAST(binary.right),
|
|
124
|
+
isValid: true,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
return parsePrimary(trimmed);
|
|
128
|
+
}
|
|
129
|
+
function parsePrimary(expr) {
|
|
130
|
+
const trimmed = expr.trim();
|
|
131
|
+
if (trimmed.startsWith('!') && !trimmed.startsWith('!=')) {
|
|
132
|
+
return {
|
|
133
|
+
type: 'unary',
|
|
134
|
+
operator: '!',
|
|
135
|
+
operand: parsePrimary(trimmed.substring(1)),
|
|
136
|
+
isValid: true,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
if (trimmed.startsWith('(') && trimmed.endsWith(')')) {
|
|
140
|
+
const inner = trimmed.substring(1, trimmed.length - 1);
|
|
141
|
+
return {
|
|
142
|
+
type: 'group',
|
|
143
|
+
expression: parseExpressionAST(inner),
|
|
144
|
+
isValid: true,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
if ((trimmed.startsWith('"') && trimmed.endsWith('"')) ||
|
|
148
|
+
(trimmed.startsWith("'") && trimmed.endsWith("'"))) {
|
|
149
|
+
return {
|
|
150
|
+
type: 'literal',
|
|
151
|
+
literalType: 'string',
|
|
152
|
+
literalValue: trimmed.slice(1, -1),
|
|
153
|
+
isValid: true,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
if (/^-?\d+(\.\d+)?$/.test(trimmed)) {
|
|
157
|
+
return {
|
|
158
|
+
type: 'literal',
|
|
159
|
+
literalType: 'number',
|
|
160
|
+
literalValue: parseFloat(trimmed),
|
|
161
|
+
isValid: true,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
if (trimmed === 'true' || trimmed === 'false') {
|
|
165
|
+
return {
|
|
166
|
+
type: 'literal',
|
|
167
|
+
literalType: 'boolean',
|
|
168
|
+
literalValue: trimmed === 'true',
|
|
169
|
+
isValid: true,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
if (trimmed === 'null') {
|
|
173
|
+
return {
|
|
174
|
+
type: 'literal',
|
|
175
|
+
literalType: 'null',
|
|
176
|
+
literalValue: null,
|
|
177
|
+
isValid: true,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
const funcMatch = trimmed.match(FUNCTION_PATTERN);
|
|
181
|
+
if (funcMatch) {
|
|
182
|
+
const [, funcName, argsStr] = funcMatch;
|
|
183
|
+
return {
|
|
184
|
+
type: 'function',
|
|
185
|
+
isFunction: true,
|
|
186
|
+
functionName: funcName,
|
|
187
|
+
functionArgs: parseArgs(argsStr),
|
|
188
|
+
isValid: true,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
const pipeIndex = findFirstPipeIndex(trimmed);
|
|
192
|
+
if (pipeIndex !== -1) {
|
|
193
|
+
const pathPart = trimmed.substring(0, pipeIndex).trim();
|
|
194
|
+
const pipesPart = trimmed.substring(pipeIndex);
|
|
195
|
+
const operations = parsePipeOperations(pipesPart);
|
|
196
|
+
const source = detectDataSource(pathPart);
|
|
197
|
+
return {
|
|
198
|
+
type: 'path',
|
|
199
|
+
path: pathPart,
|
|
200
|
+
source,
|
|
201
|
+
operations,
|
|
202
|
+
isValid: true,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
const source = detectDataSource(trimmed);
|
|
206
|
+
return {
|
|
207
|
+
type: 'path',
|
|
208
|
+
path: trimmed,
|
|
209
|
+
source,
|
|
210
|
+
isValid: true,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
const OPERATOR_PRECEDENCE_MAP = {
|
|
214
|
+
'||': 1,
|
|
215
|
+
'&&': 2,
|
|
216
|
+
'==': 3,
|
|
217
|
+
'!=': 3,
|
|
218
|
+
'<': 4,
|
|
219
|
+
'>': 4,
|
|
220
|
+
'<=': 4,
|
|
221
|
+
'>=': 4,
|
|
222
|
+
'+': 5,
|
|
223
|
+
'-': 5,
|
|
224
|
+
'*': 6,
|
|
225
|
+
'/': 6,
|
|
226
|
+
'%': 6,
|
|
227
|
+
'**': 7,
|
|
228
|
+
};
|
|
229
|
+
function findTernaryOperator(expr) {
|
|
230
|
+
let depth = 0;
|
|
231
|
+
let questionIdx = -1;
|
|
232
|
+
let colonIdx = -1;
|
|
233
|
+
for (let i = 0; i < expr.length; i++) {
|
|
234
|
+
const char = expr[i];
|
|
235
|
+
if (char === '(' || char === '[' || char === '{') {
|
|
236
|
+
depth++;
|
|
237
|
+
}
|
|
238
|
+
if (char === ')' || char === ']' || char === '}') {
|
|
239
|
+
depth--;
|
|
240
|
+
}
|
|
241
|
+
if (depth === 0) {
|
|
242
|
+
if (char === '?' && questionIdx === -1) {
|
|
243
|
+
questionIdx = i;
|
|
244
|
+
}
|
|
245
|
+
else if (char === ':' && questionIdx !== -1 && colonIdx === -1) {
|
|
246
|
+
colonIdx = i;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (questionIdx !== -1 && colonIdx !== -1) {
|
|
251
|
+
return {
|
|
252
|
+
condition: expr.substring(0, questionIdx).trim(),
|
|
253
|
+
consequent: expr.substring(questionIdx + 1, colonIdx).trim(),
|
|
254
|
+
alternate: expr.substring(colonIdx + 1).trim(),
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
function findBinaryOperator(expr) {
|
|
260
|
+
const operators = [
|
|
261
|
+
'||',
|
|
262
|
+
'&&',
|
|
263
|
+
'===',
|
|
264
|
+
'!==',
|
|
265
|
+
'==',
|
|
266
|
+
'!=',
|
|
267
|
+
'>=',
|
|
268
|
+
'<=',
|
|
269
|
+
'>',
|
|
270
|
+
'<',
|
|
271
|
+
'**',
|
|
272
|
+
'+',
|
|
273
|
+
'-',
|
|
274
|
+
'*',
|
|
275
|
+
'/',
|
|
276
|
+
'%',
|
|
277
|
+
];
|
|
278
|
+
let depth = 0;
|
|
279
|
+
let inString = false;
|
|
280
|
+
let stringChar = '';
|
|
281
|
+
let bestOp = null;
|
|
282
|
+
for (let i = 0; i < expr.length; i++) {
|
|
283
|
+
const char = expr[i];
|
|
284
|
+
if ((char === '"' || char === "'") && (i === 0 || expr[i - 1] !== '\\')) {
|
|
285
|
+
if (!inString) {
|
|
286
|
+
inString = true;
|
|
287
|
+
stringChar = char;
|
|
288
|
+
}
|
|
289
|
+
else if (char === stringChar) {
|
|
290
|
+
inString = false;
|
|
291
|
+
}
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
if (inString) {
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
if (char === '(' || char === '[' || char === '{')
|
|
298
|
+
depth++;
|
|
299
|
+
if (char === ')' || char === ']' || char === '}')
|
|
300
|
+
depth--;
|
|
301
|
+
if (depth !== 0)
|
|
302
|
+
continue;
|
|
303
|
+
for (const op of operators) {
|
|
304
|
+
if (expr.substring(i, i + op.length) === op) {
|
|
305
|
+
if (i === 0)
|
|
306
|
+
continue;
|
|
307
|
+
const precedence = OPERATOR_PRECEDENCE_MAP[op] || 0;
|
|
308
|
+
if (!bestOp ||
|
|
309
|
+
precedence < bestOp.precedence ||
|
|
310
|
+
(precedence === bestOp.precedence && i > bestOp.index)) {
|
|
311
|
+
bestOp = { operator: op, index: i, precedence };
|
|
312
|
+
}
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
if (bestOp && bestOp.index > 0) {
|
|
318
|
+
return {
|
|
319
|
+
operator: bestOp.operator,
|
|
320
|
+
left: expr.substring(0, bestOp.index).trim(),
|
|
321
|
+
right: expr.substring(bestOp.index + bestOp.operator.length).trim(),
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
return null;
|
|
325
|
+
}
|
|
326
|
+
function findFirstPipeIndex(str) {
|
|
327
|
+
let depth = 0;
|
|
328
|
+
let inString = false;
|
|
329
|
+
let stringChar = '';
|
|
330
|
+
for (let i = 0; i < str.length; i++) {
|
|
331
|
+
const char = str[i];
|
|
332
|
+
const prevChar = i > 0 ? str[i - 1] : '';
|
|
333
|
+
if ((char === '"' || char === "'") && prevChar !== '\\') {
|
|
334
|
+
if (!inString) {
|
|
335
|
+
inString = true;
|
|
336
|
+
stringChar = char;
|
|
337
|
+
}
|
|
338
|
+
else if (char === stringChar) {
|
|
339
|
+
inString = false;
|
|
340
|
+
}
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
if (inString)
|
|
344
|
+
continue;
|
|
345
|
+
if (char === '(' || char === '[' || char === '{')
|
|
346
|
+
depth++;
|
|
347
|
+
if (char === ')' || char === ']' || char === '}')
|
|
348
|
+
depth--;
|
|
349
|
+
if (char === '|' && depth === 0 && str[i + 1] !== '|') {
|
|
350
|
+
return i;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return -1;
|
|
354
|
+
}
|
|
355
|
+
function parseArgs(argsString) {
|
|
356
|
+
if (!argsString.trim()) {
|
|
357
|
+
return [];
|
|
358
|
+
}
|
|
359
|
+
const args = [];
|
|
360
|
+
let current = '';
|
|
361
|
+
let depth = 0;
|
|
362
|
+
let inString = false;
|
|
363
|
+
let stringChar = '';
|
|
364
|
+
for (let i = 0; i < argsString.length; i++) {
|
|
365
|
+
const char = argsString[i];
|
|
366
|
+
const prevChar = i > 0 ? argsString[i - 1] : '';
|
|
367
|
+
if ((char === '"' || char === "'") && prevChar !== '\\') {
|
|
368
|
+
if (!inString) {
|
|
369
|
+
inString = true;
|
|
370
|
+
stringChar = char;
|
|
371
|
+
}
|
|
372
|
+
else if (char === stringChar) {
|
|
373
|
+
inString = false;
|
|
374
|
+
}
|
|
375
|
+
current += char;
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
if (inString) {
|
|
379
|
+
current += char;
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
if (char === '(' || char === '[' || char === '{') {
|
|
383
|
+
depth++;
|
|
384
|
+
current += char;
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
if (char === ')' || char === ']' || char === '}') {
|
|
388
|
+
depth--;
|
|
389
|
+
current += char;
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
if (char === ',' && depth === 0) {
|
|
393
|
+
args.push(parseArgValue(current.trim()));
|
|
394
|
+
current = '';
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
current += char;
|
|
398
|
+
}
|
|
399
|
+
if (current.trim()) {
|
|
400
|
+
args.push(parseArgValue(current.trim()));
|
|
401
|
+
}
|
|
402
|
+
return args;
|
|
403
|
+
}
|
|
404
|
+
function parseArgValue(value) {
|
|
405
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
406
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
407
|
+
return value.slice(1, -1);
|
|
408
|
+
}
|
|
409
|
+
if (value === 'true')
|
|
410
|
+
return true;
|
|
411
|
+
if (value === 'false')
|
|
412
|
+
return false;
|
|
413
|
+
if (value === 'null')
|
|
414
|
+
return null;
|
|
415
|
+
if (/^-?\d+(\.\d+)?$/.test(value))
|
|
416
|
+
return parseFloat(value);
|
|
417
|
+
return value;
|
|
418
|
+
}
|
|
419
|
+
function parsePipeOperations(pipesStr) {
|
|
420
|
+
const operations = [];
|
|
421
|
+
const pipePattern = /\s*\|\s*(\w+)(?:\(([^)]*)\))?/g;
|
|
422
|
+
let match;
|
|
423
|
+
while ((match = pipePattern.exec(pipesStr)) !== null) {
|
|
424
|
+
const [, name, argsStr] = match;
|
|
425
|
+
const args = argsStr ? parseArgs(argsStr) : [];
|
|
426
|
+
operations.push({ name, args });
|
|
427
|
+
}
|
|
428
|
+
return operations;
|
|
429
|
+
}
|
|
430
|
+
function tokenizeTemplate(template) {
|
|
431
|
+
const tokens = [];
|
|
432
|
+
let lastIndex = 0;
|
|
433
|
+
const regex = new RegExp(EXPRESSION_PATTERN);
|
|
434
|
+
let match;
|
|
435
|
+
while ((match = regex.exec(template)) !== null) {
|
|
436
|
+
if (match.index > lastIndex) {
|
|
437
|
+
tokens.push({
|
|
438
|
+
type: 'text',
|
|
439
|
+
value: template.substring(lastIndex, match.index),
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
tokens.push({
|
|
443
|
+
type: 'expression',
|
|
444
|
+
value: match[1],
|
|
445
|
+
});
|
|
446
|
+
lastIndex = match.index + match[0].length;
|
|
447
|
+
}
|
|
448
|
+
if (lastIndex < template.length) {
|
|
449
|
+
tokens.push({
|
|
450
|
+
type: 'text',
|
|
451
|
+
value: template.substring(lastIndex),
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
return tokens;
|
|
455
|
+
}
|
|
456
|
+
exports.tokenizeTemplate = tokenizeTemplate;
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.arrayPipes = void 0;
|
|
4
|
+
exports.arrayPipes = {
|
|
5
|
+
first: {
|
|
6
|
+
name: 'first',
|
|
7
|
+
description: 'Gets the first element',
|
|
8
|
+
category: 'array',
|
|
9
|
+
signature: 'first',
|
|
10
|
+
examples: ['{{trigger.items | first}}'],
|
|
11
|
+
execute: (value) => {
|
|
12
|
+
if (Array.isArray(value) && value.length > 0) {
|
|
13
|
+
return value[0];
|
|
14
|
+
}
|
|
15
|
+
return undefined;
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
last: {
|
|
19
|
+
name: 'last',
|
|
20
|
+
description: 'Gets the last element',
|
|
21
|
+
category: 'array',
|
|
22
|
+
signature: 'last',
|
|
23
|
+
examples: ['{{trigger.items | last}}'],
|
|
24
|
+
execute: (value) => {
|
|
25
|
+
if (Array.isArray(value) && value.length > 0) {
|
|
26
|
+
return value[value.length - 1];
|
|
27
|
+
}
|
|
28
|
+
return undefined;
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
length: {
|
|
32
|
+
name: 'length',
|
|
33
|
+
description: 'Returns the length',
|
|
34
|
+
category: 'array',
|
|
35
|
+
signature: 'length',
|
|
36
|
+
examples: ['{{trigger.items | length}}'],
|
|
37
|
+
execute: (value) => {
|
|
38
|
+
if (Array.isArray(value)) {
|
|
39
|
+
return value.length;
|
|
40
|
+
}
|
|
41
|
+
if (typeof value === 'string') {
|
|
42
|
+
return value.length;
|
|
43
|
+
}
|
|
44
|
+
return 0;
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
join: {
|
|
48
|
+
name: 'join',
|
|
49
|
+
description: 'Joins array elements',
|
|
50
|
+
category: 'array',
|
|
51
|
+
signature: 'join(separator?)',
|
|
52
|
+
examples: ['{{trigger.tags | join(", ")}}'],
|
|
53
|
+
execute: (value, separator) => {
|
|
54
|
+
if (!Array.isArray(value)) {
|
|
55
|
+
return '';
|
|
56
|
+
}
|
|
57
|
+
return value.join(separator !== undefined ? String(separator) : ',');
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
slice: {
|
|
61
|
+
name: 'slice',
|
|
62
|
+
description: 'Extracts a section',
|
|
63
|
+
category: 'array',
|
|
64
|
+
signature: 'slice(start, end?)',
|
|
65
|
+
examples: ['{{trigger.items | slice(0, 3)}}'],
|
|
66
|
+
execute: (value, start, end) => {
|
|
67
|
+
if (!Array.isArray(value)) {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
return value.slice(Number(start), end !== undefined ? Number(end) : undefined);
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
reverse: {
|
|
74
|
+
name: 'reverse',
|
|
75
|
+
description: 'Reverses the order',
|
|
76
|
+
category: 'array',
|
|
77
|
+
signature: 'reverse',
|
|
78
|
+
examples: ['{{trigger.items | reverse}}'],
|
|
79
|
+
execute: (value) => {
|
|
80
|
+
if (!Array.isArray(value)) {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
return [...value].reverse();
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
sort: {
|
|
87
|
+
name: 'sort',
|
|
88
|
+
description: 'Sorts the array',
|
|
89
|
+
category: 'array',
|
|
90
|
+
signature: 'sort',
|
|
91
|
+
examples: ['{{trigger.numbers | sort}}'],
|
|
92
|
+
execute: (value) => {
|
|
93
|
+
if (!Array.isArray(value)) {
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
return [...value].sort();
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
unique: {
|
|
100
|
+
name: 'unique',
|
|
101
|
+
description: 'Returns unique elements',
|
|
102
|
+
category: 'array',
|
|
103
|
+
signature: 'unique',
|
|
104
|
+
examples: ['{{trigger.tags | unique}}'],
|
|
105
|
+
execute: (value) => {
|
|
106
|
+
if (!Array.isArray(value)) {
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
return Array.from(new Set(value));
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
flatten: {
|
|
113
|
+
name: 'flatten',
|
|
114
|
+
description: 'Flattens nested arrays',
|
|
115
|
+
category: 'array',
|
|
116
|
+
signature: 'flatten',
|
|
117
|
+
examples: ['{{trigger.nested | flatten}}'],
|
|
118
|
+
execute: (value) => {
|
|
119
|
+
if (!Array.isArray(value)) {
|
|
120
|
+
return [];
|
|
121
|
+
}
|
|
122
|
+
return value.flat();
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
compact: {
|
|
126
|
+
name: 'compact',
|
|
127
|
+
description: 'Removes falsy values',
|
|
128
|
+
category: 'array',
|
|
129
|
+
signature: 'compact',
|
|
130
|
+
examples: ['{{trigger.items | compact}}'],
|
|
131
|
+
execute: (value) => {
|
|
132
|
+
if (!Array.isArray(value)) {
|
|
133
|
+
return [];
|
|
134
|
+
}
|
|
135
|
+
return value.filter(Boolean);
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
sum: {
|
|
139
|
+
name: 'sum',
|
|
140
|
+
description: 'Sums numeric values',
|
|
141
|
+
category: 'array',
|
|
142
|
+
signature: 'sum',
|
|
143
|
+
examples: ['{{trigger.numbers | sum}}'],
|
|
144
|
+
execute: (value) => {
|
|
145
|
+
if (!Array.isArray(value)) {
|
|
146
|
+
return 0;
|
|
147
|
+
}
|
|
148
|
+
return value.reduce((acc, val) => acc + Number(val), 0);
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
avg: {
|
|
152
|
+
name: 'avg',
|
|
153
|
+
description: 'Calculates average',
|
|
154
|
+
category: 'array',
|
|
155
|
+
signature: 'avg',
|
|
156
|
+
examples: ['{{trigger.scores | avg}}'],
|
|
157
|
+
execute: (value) => {
|
|
158
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
159
|
+
return 0;
|
|
160
|
+
}
|
|
161
|
+
const sum = value.reduce((acc, val) => acc + Number(val), 0);
|
|
162
|
+
return sum / value.length;
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
min: {
|
|
166
|
+
name: 'min',
|
|
167
|
+
description: 'Returns minimum value',
|
|
168
|
+
category: 'array',
|
|
169
|
+
signature: 'min',
|
|
170
|
+
examples: ['{{trigger.numbers | min}}'],
|
|
171
|
+
execute: (value) => {
|
|
172
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
return Math.min(...value.map(Number));
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
max: {
|
|
179
|
+
name: 'max',
|
|
180
|
+
description: 'Returns maximum value',
|
|
181
|
+
category: 'array',
|
|
182
|
+
signature: 'max',
|
|
183
|
+
examples: ['{{trigger.numbers | max}}'],
|
|
184
|
+
execute: (value) => {
|
|
185
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
186
|
+
return undefined;
|
|
187
|
+
}
|
|
188
|
+
return Math.max(...value.map(Number));
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
map: {
|
|
192
|
+
name: 'map',
|
|
193
|
+
description: 'Maps over array elements',
|
|
194
|
+
category: 'array',
|
|
195
|
+
signature: 'map(property)',
|
|
196
|
+
examples: ['{{trigger.users | map("name")}}'],
|
|
197
|
+
execute: (value, property) => {
|
|
198
|
+
if (!Array.isArray(value)) {
|
|
199
|
+
return [];
|
|
200
|
+
}
|
|
201
|
+
const prop = String(property);
|
|
202
|
+
return value.map((item) => {
|
|
203
|
+
if (item && typeof item === 'object') {
|
|
204
|
+
return item[prop];
|
|
205
|
+
}
|
|
206
|
+
return undefined;
|
|
207
|
+
});
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
filter: {
|
|
211
|
+
name: 'filter',
|
|
212
|
+
description: 'Filters array elements by property',
|
|
213
|
+
category: 'array',
|
|
214
|
+
signature: 'filter(property, value)',
|
|
215
|
+
examples: ['{{trigger.users | filter("active", true)}}'],
|
|
216
|
+
execute: (value, property, filterValue) => {
|
|
217
|
+
if (!Array.isArray(value)) {
|
|
218
|
+
return [];
|
|
219
|
+
}
|
|
220
|
+
const prop = String(property);
|
|
221
|
+
return value.filter((item) => {
|
|
222
|
+
if (item && typeof item === 'object') {
|
|
223
|
+
return item[prop] === filterValue;
|
|
224
|
+
}
|
|
225
|
+
return false;
|
|
226
|
+
});
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
pluck: {
|
|
230
|
+
name: 'pluck',
|
|
231
|
+
description: 'Extracts property from each object',
|
|
232
|
+
category: 'array',
|
|
233
|
+
signature: 'pluck(property)',
|
|
234
|
+
examples: ['{{trigger.users | pluck("email")}}'],
|
|
235
|
+
execute: (value, property) => {
|
|
236
|
+
if (!Array.isArray(value)) {
|
|
237
|
+
return [];
|
|
238
|
+
}
|
|
239
|
+
const prop = String(property);
|
|
240
|
+
return value.map((item) => {
|
|
241
|
+
if (item && typeof item === 'object') {
|
|
242
|
+
return item[prop];
|
|
243
|
+
}
|
|
244
|
+
return undefined;
|
|
245
|
+
});
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PipeDefinition } from './string-pipes';
|
|
2
|
+
import type { OperationCategory } from '../types';
|
|
3
|
+
export declare const PIPE_OPERATIONS: Record<string, PipeDefinition>;
|
|
4
|
+
export declare function executePipeOperation(name: string, value: unknown, args: unknown[]): unknown;
|
|
5
|
+
export declare function getPipesByCategory(category: OperationCategory): Record<string, PipeDefinition>;
|
|
6
|
+
export declare function getPipeNames(): string[];
|
|
7
|
+
export declare function hasPipe(name: string): boolean;
|
|
8
|
+
export declare function getPipe(name: string): PipeDefinition | undefined;
|