@adminide-stack/form-builder-core 5.1.4-alpha.81 → 6.0.1-alpha.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 +30 -21
- package/lib/index.js +1 -1
- package/lib/inngest/generateFunctionCode.d.ts +1 -0
- package/lib/inngest/generateFunctionCode.d.ts.map +1 -1
- package/lib/inngest/generateFunctionCode.js +72 -3
- package/lib/inngest/generateFunctionCode.js.map +1 -1
- package/package.json +2 -2
- package/CHANGELOG.md +0 -56
- package/rollup.config.mjs +0 -33
- package/src/index.ts +0 -5
- package/src/inngest/MONACO_INTEGRATION_EXAMPLE.md +0 -406
- package/src/inngest/README_AUTOCOMPLETE.md +0 -380
- package/src/inngest/generateFunctionCode.ts +0 -151
- package/src/inngest/interfaces/index.ts +0 -1
- package/src/inngest/interfaces/types.ts +0 -63
- package/src/inngest/monacoAutocompleteIntegration.ts +0 -432
- package/src/inngest/stepGenerator.ts +0 -538
- package/src/utils/json.ts +0 -50
- package/tsconfig.json +0 -14
|
@@ -1,538 +0,0 @@
|
|
|
1
|
-
import type { InngestStep, ExtractedFunction } from './interfaces/types';
|
|
2
|
-
|
|
3
|
-
// Re-export for convenience
|
|
4
|
-
export type { ExtractedFunction } from './interfaces/types';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Step function generation utilities for unified code generation
|
|
8
|
-
* Used by both browser editor and server execution
|
|
9
|
-
*
|
|
10
|
-
* Integrates with js-autocomplete-extension for intelligent code completion
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Get scope context for code completion in step functions
|
|
15
|
-
* Returns available variables and their types for autocomplete
|
|
16
|
-
*/
|
|
17
|
-
export function getStepCompletionScope(): string[] {
|
|
18
|
-
return [
|
|
19
|
-
'step',
|
|
20
|
-
'event',
|
|
21
|
-
'run',
|
|
22
|
-
'sleep',
|
|
23
|
-
'sendEvent',
|
|
24
|
-
'waitForEvent',
|
|
25
|
-
'Promise',
|
|
26
|
-
'console',
|
|
27
|
-
'Date',
|
|
28
|
-
'JSON',
|
|
29
|
-
'Array',
|
|
30
|
-
'Object',
|
|
31
|
-
];
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Get type definitions for step function context
|
|
36
|
-
* Used by Monaco editor for enhanced IntelliSense
|
|
37
|
-
*/
|
|
38
|
-
export function getStepTypeDefinitions(): string {
|
|
39
|
-
return `
|
|
40
|
-
// Inngest Step API
|
|
41
|
-
declare const step: {
|
|
42
|
-
run<T>(id: string, fn: (event: any, step: any) => Promise<T> | T): Promise<T>;
|
|
43
|
-
sendEvent(id: string, input: { name: string; data?: any }): Promise<void>;
|
|
44
|
-
waitForEvent<T = any>(id: string, opts: { event: string; timeout?: string | number }): Promise<T>;
|
|
45
|
-
sleep(id: string, ms: string | number): Promise<void>;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
// Event context
|
|
49
|
-
declare const event: {
|
|
50
|
-
data: any;
|
|
51
|
-
id: string;
|
|
52
|
-
name: string;
|
|
53
|
-
ts: number;
|
|
54
|
-
user?: any;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// Common utilities available in step functions
|
|
58
|
-
declare const console: {
|
|
59
|
-
log(...args: any[]): void;
|
|
60
|
-
error(...args: any[]): void;
|
|
61
|
-
warn(...args: any[]): void;
|
|
62
|
-
info(...args: any[]): void;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
// Promise and async utilities
|
|
66
|
-
declare class Promise<T> {
|
|
67
|
-
then<TResult>(onfulfilled?: (value: T) => TResult | Promise<TResult>): Promise<TResult>;
|
|
68
|
-
catch<TResult>(onrejected?: (reason: any) => TResult | Promise<TResult>): Promise<TResult>;
|
|
69
|
-
finally(onfinally?: () => void): Promise<T>;
|
|
70
|
-
static all<T>(promises: Promise<T>[]): Promise<T[]>;
|
|
71
|
-
static race<T>(promises: Promise<T>[]): Promise<T>;
|
|
72
|
-
static resolve<T>(value: T): Promise<T>;
|
|
73
|
-
static reject(reason?: any): Promise<never>;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Date utilities
|
|
77
|
-
declare class Date {
|
|
78
|
-
constructor();
|
|
79
|
-
constructor(value: number | string);
|
|
80
|
-
toISOString(): string;
|
|
81
|
-
getTime(): number;
|
|
82
|
-
static now(): number;
|
|
83
|
-
}
|
|
84
|
-
`;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Get autocomplete suggestions for a specific step type
|
|
89
|
-
* Returns context-specific completions based on step type
|
|
90
|
-
*/
|
|
91
|
-
export function getStepTypeCompletions(stepType: string): Array<{ name: string; snippet: string; doc: string }> {
|
|
92
|
-
const completions: Record<string, Array<{ name: string; snippet: string; doc: string }>> = {
|
|
93
|
-
sleep: [
|
|
94
|
-
{
|
|
95
|
-
name: 'step.sleep',
|
|
96
|
-
snippet: "await step.sleep('${1:step-id}', '${2:5s}');",
|
|
97
|
-
doc: 'Sleep for a specified duration. Accepts time strings like "5s", "1m", "1h"',
|
|
98
|
-
},
|
|
99
|
-
],
|
|
100
|
-
sendEvent: [
|
|
101
|
-
{
|
|
102
|
-
name: 'step.sendEvent',
|
|
103
|
-
snippet: `await step.sendEvent('\${1:step-id}', {
|
|
104
|
-
name: '\${2:event.name}',
|
|
105
|
-
data: {
|
|
106
|
-
\${3:key}: \${4:value}
|
|
107
|
-
}
|
|
108
|
-
});`,
|
|
109
|
-
doc: 'Send an event to trigger other workflows',
|
|
110
|
-
},
|
|
111
|
-
],
|
|
112
|
-
waitForEvent: [
|
|
113
|
-
{
|
|
114
|
-
name: 'step.waitForEvent',
|
|
115
|
-
snippet: `const \${1:result} = await step.waitForEvent('\${2:step-id}', {
|
|
116
|
-
event: '\${3:event.name}',
|
|
117
|
-
timeout: '\${4:60s}'
|
|
118
|
-
});`,
|
|
119
|
-
doc: 'Wait for a specific event before continuing',
|
|
120
|
-
},
|
|
121
|
-
],
|
|
122
|
-
run: [
|
|
123
|
-
{
|
|
124
|
-
name: 'step.run',
|
|
125
|
-
snippet: `const \${1:result} = await step.run('\${2:step-id}', async () => {
|
|
126
|
-
\${3:// Your logic here}
|
|
127
|
-
return { success: true };
|
|
128
|
-
});`,
|
|
129
|
-
doc: 'Run a unit of work with automatic retries and error handling',
|
|
130
|
-
},
|
|
131
|
-
],
|
|
132
|
-
parallel: [
|
|
133
|
-
{
|
|
134
|
-
name: 'Promise.all',
|
|
135
|
-
snippet: `const results = await Promise.all([
|
|
136
|
-
\${1:step.run('step-1', async () => { return 1; })},
|
|
137
|
-
\${2:step.run('step-2', async () => { return 2; })}
|
|
138
|
-
]);`,
|
|
139
|
-
doc: 'Execute multiple steps in parallel',
|
|
140
|
-
},
|
|
141
|
-
],
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
return completions[stepType] || completions.run;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Extract variable names from step code for completion context
|
|
149
|
-
* Returns all declared variables in the step function
|
|
150
|
-
*/
|
|
151
|
-
export function extractVariablesFromCode(code: string): string[] {
|
|
152
|
-
const variables: string[] = [];
|
|
153
|
-
|
|
154
|
-
// Match const/let/var declarations
|
|
155
|
-
const declRegex = /(?:const|let|var)\s+(\w+)/g;
|
|
156
|
-
let match;
|
|
157
|
-
|
|
158
|
-
while ((match = declRegex.exec(code)) !== null) {
|
|
159
|
-
variables.push(match[1]);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Match function parameters
|
|
163
|
-
const paramRegex = /(?:async\s+)?\(([^)]*)\)\s*=>/g;
|
|
164
|
-
while ((match = paramRegex.exec(code)) !== null) {
|
|
165
|
-
const params = match[1].split(',').map((p) => p.trim().split(/\s+/)[0]);
|
|
166
|
-
variables.push(...params.filter((p) => p && p !== ''));
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
return [...new Set(variables)]; // Remove duplicates
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Get completion context for a step at a specific position
|
|
174
|
-
* Used by Monaco editor to provide context-aware completions
|
|
175
|
-
*/
|
|
176
|
-
export interface CompletionContext {
|
|
177
|
-
scope: string[];
|
|
178
|
-
typeDefinitions: string;
|
|
179
|
-
snippets: Array<{ name: string; snippet: string; doc: string }>;
|
|
180
|
-
variables: string[];
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
export function getStepCompletionContext(step: InngestStep, code: string): CompletionContext {
|
|
184
|
-
const stepType = step.type || 'run';
|
|
185
|
-
|
|
186
|
-
return {
|
|
187
|
-
scope: getStepCompletionScope(),
|
|
188
|
-
typeDefinitions: getStepTypeDefinitions(),
|
|
189
|
-
snippets: getStepTypeCompletions(stepType),
|
|
190
|
-
variables: extractVariablesFromCode(code),
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Pass through code without any cleaning/validation
|
|
195
|
-
export function cleanStepCode(code: string): string {
|
|
196
|
-
return code;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// Extract step variable name from code
|
|
200
|
-
export function extractStepVarName(code: string): string | null {
|
|
201
|
-
const match = code.match(/const\s+(\w+)\s*=/);
|
|
202
|
-
return match ? match[1] : null;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// Generate default step function for different step types
|
|
206
|
-
export function generateDefaultStepFunction(stepVar: string, stepType: string): string {
|
|
207
|
-
switch (stepType) {
|
|
208
|
-
case 'sleep':
|
|
209
|
-
return `const ${stepVar} = async (event, step) => {
|
|
210
|
-
// Sleep for specified duration
|
|
211
|
-
const sleepResult = await step.sleep('${stepVar}', '5s');
|
|
212
|
-
|
|
213
|
-
console.log('Sleep completed:', sleepResult);
|
|
214
|
-
|
|
215
|
-
return { success: true, duration: '5s', result: sleepResult };
|
|
216
|
-
};`;
|
|
217
|
-
|
|
218
|
-
case 'sendEvent':
|
|
219
|
-
return `const ${stepVar} = async (event, step) => {
|
|
220
|
-
// Send an event to trigger other functions
|
|
221
|
-
const eventResult = await step.sendEvent('${stepVar}', {
|
|
222
|
-
name: 'my.custom.event',
|
|
223
|
-
data: {
|
|
224
|
-
source: '${stepVar}',
|
|
225
|
-
timestamp: new Date().toISOString(),
|
|
226
|
-
payload: event.data
|
|
227
|
-
}
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
console.log('Event sent:', eventResult);
|
|
231
|
-
|
|
232
|
-
return { success: true, eventSent: true, result: eventResult };
|
|
233
|
-
};`;
|
|
234
|
-
|
|
235
|
-
case 'waitForEvent':
|
|
236
|
-
return `const ${stepVar} = async (event, step) => {
|
|
237
|
-
// Wait for a specific event before continuing
|
|
238
|
-
const waitResult = await step.waitForEvent('${stepVar}', {
|
|
239
|
-
event: 'my.waited.event',
|
|
240
|
-
timeout: '60s'
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
console.log('Event received:', waitResult);
|
|
244
|
-
|
|
245
|
-
return { success: true, eventReceived: true, result: waitResult };
|
|
246
|
-
};`;
|
|
247
|
-
|
|
248
|
-
case 'retrieveData':
|
|
249
|
-
return `const ${stepVar} = async (event, step) => {
|
|
250
|
-
// Data retrieval implementation
|
|
251
|
-
const formData = event.data.formData || {};
|
|
252
|
-
|
|
253
|
-
// Process and retrieve data
|
|
254
|
-
const retrievedData = {
|
|
255
|
-
...formData,
|
|
256
|
-
processedAt: new Date().toISOString()
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
return { success: true, data: retrievedData };
|
|
260
|
-
};`;
|
|
261
|
-
|
|
262
|
-
case 'validateForm':
|
|
263
|
-
return `const ${stepVar} = async (event, step) => {
|
|
264
|
-
// Validate form data
|
|
265
|
-
const formData = event.data.formData || {};
|
|
266
|
-
const errors = [];
|
|
267
|
-
|
|
268
|
-
// Add validation logic here
|
|
269
|
-
if (!formData.email) {
|
|
270
|
-
errors.push('Email is required');
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
return {
|
|
274
|
-
success: errors.length === 0,
|
|
275
|
-
errors,
|
|
276
|
-
validated: errors.length === 0
|
|
277
|
-
};
|
|
278
|
-
};`;
|
|
279
|
-
|
|
280
|
-
case 'parallel':
|
|
281
|
-
return `const ${stepVar} = async (event, step) => {
|
|
282
|
-
// Execute parallel operations
|
|
283
|
-
const results = await Promise.all([
|
|
284
|
-
// Add parallel operations here
|
|
285
|
-
Promise.resolve({ task: 'task1', result: 'completed' }),
|
|
286
|
-
Promise.resolve({ task: 'task2', result: 'completed' })
|
|
287
|
-
]);
|
|
288
|
-
|
|
289
|
-
return { success: true, results };
|
|
290
|
-
};`;
|
|
291
|
-
|
|
292
|
-
default:
|
|
293
|
-
return `const ${stepVar} = async (event, step) => {
|
|
294
|
-
// Default step implementation
|
|
295
|
-
return { success: true };
|
|
296
|
-
};`;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// Generate a step function in editor format (const step_xxx = async (event, step) => {...})
|
|
301
|
-
export function generateStepFunction(
|
|
302
|
-
step: InngestStep | ExtractedFunction,
|
|
303
|
-
index: number,
|
|
304
|
-
): { code: string; varName: string } {
|
|
305
|
-
// Extract or generate step variable name
|
|
306
|
-
const varName =
|
|
307
|
-
extractStepVarName(step.code || '') ||
|
|
308
|
-
(step as ExtractedFunction).originalStepName ||
|
|
309
|
-
step.id ||
|
|
310
|
-
`step_${index}`;
|
|
311
|
-
|
|
312
|
-
// If step has code, use it; otherwise generate default
|
|
313
|
-
const code = step.code || generateDefaultStepFunction(varName, (step as InngestStep).type || 'run');
|
|
314
|
-
|
|
315
|
-
return { code: cleanStepCode(code), varName };
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// Extract function body from step function code
|
|
319
|
-
export function extractFunctionBody(code: string): string | null {
|
|
320
|
-
// Find the opening brace after the arrow or function keyword
|
|
321
|
-
const arrowIndex = code.indexOf('=>');
|
|
322
|
-
const functionIndex = code.indexOf('function');
|
|
323
|
-
|
|
324
|
-
let startIndex = -1;
|
|
325
|
-
|
|
326
|
-
if (arrowIndex !== -1) {
|
|
327
|
-
// Find opening brace after =>
|
|
328
|
-
const openBraceIndex = code.indexOf('{', arrowIndex);
|
|
329
|
-
if (openBraceIndex !== -1) {
|
|
330
|
-
startIndex = openBraceIndex + 1;
|
|
331
|
-
}
|
|
332
|
-
} else if (functionIndex !== -1) {
|
|
333
|
-
// Find opening brace after function declaration
|
|
334
|
-
const openBraceIndex = code.indexOf('{', functionIndex);
|
|
335
|
-
if (openBraceIndex !== -1) {
|
|
336
|
-
startIndex = openBraceIndex + 1;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
if (startIndex === -1) {
|
|
341
|
-
// FALLBACK: If we can't find function wrapper, return the whole code
|
|
342
|
-
console.warn('Could not extract function body, returning full code');
|
|
343
|
-
return code;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// Find the matching closing brace by counting braces
|
|
347
|
-
let braceCount = 1;
|
|
348
|
-
let endIndex = startIndex;
|
|
349
|
-
let inString = false;
|
|
350
|
-
let stringChar = '';
|
|
351
|
-
let inTemplate = false;
|
|
352
|
-
|
|
353
|
-
while (endIndex < code.length && braceCount > 0) {
|
|
354
|
-
const char = code[endIndex];
|
|
355
|
-
const prevChar = endIndex > 0 ? code[endIndex - 1] : '';
|
|
356
|
-
|
|
357
|
-
// Handle string literals
|
|
358
|
-
if ((char === '"' || char === "'") && prevChar !== '\\') {
|
|
359
|
-
if (!inString) {
|
|
360
|
-
inString = true;
|
|
361
|
-
stringChar = char;
|
|
362
|
-
} else if (char === stringChar) {
|
|
363
|
-
inString = false;
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
// Handle template literals
|
|
368
|
-
if (char === '`' && prevChar !== '\\') {
|
|
369
|
-
inTemplate = !inTemplate;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
// Only count braces outside of strings
|
|
373
|
-
if (!inString && !inTemplate) {
|
|
374
|
-
if (char === '{') {
|
|
375
|
-
braceCount++;
|
|
376
|
-
} else if (char === '}') {
|
|
377
|
-
braceCount--;
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
if (braceCount > 0) {
|
|
382
|
-
endIndex++;
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
if (braceCount === 0) {
|
|
387
|
-
return code.substring(startIndex, endIndex).trim();
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// FALLBACK: Return full code if brace matching fails
|
|
391
|
-
console.warn('Brace matching failed, returning full code');
|
|
392
|
-
return code;
|
|
393
|
-
}
|
|
394
|
-
// Transform a step function for execution inside Inngest wrapper
|
|
395
|
-
export function transformStepForExecution(
|
|
396
|
-
stepFunction: { code: string; varName: string },
|
|
397
|
-
stepType: string,
|
|
398
|
-
stepLabel: string,
|
|
399
|
-
): string {
|
|
400
|
-
const functionBody = extractFunctionBody(stepFunction.code);
|
|
401
|
-
if (!functionBody) {
|
|
402
|
-
return `// ${stepLabel}\nconst ${stepFunction.varName}_result = { success: false, error: 'Invalid function format' };`;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
const cleanedBody = cleanStepCode(functionBody);
|
|
406
|
-
|
|
407
|
-
// For these step types, execute the body directly (they contain step.* calls)
|
|
408
|
-
if (stepType === 'sleep' || stepType === 'sendEvent' || stepType === 'waitForEvent') {
|
|
409
|
-
// Transform the body to ensure result is captured
|
|
410
|
-
let transformedBody = cleanedBody;
|
|
411
|
-
|
|
412
|
-
// Replace step method calls to ensure result variable is created
|
|
413
|
-
transformedBody = transformedBody.replace(
|
|
414
|
-
/(const\s+\w+\s*=\s*)?await\s+step\.(sleep|sendEvent|waitForEvent)/g,
|
|
415
|
-
(match, constPart, method) => {
|
|
416
|
-
if (constPart) {
|
|
417
|
-
// Already has assignment, replace variable name
|
|
418
|
-
return `const ${stepFunction.varName}_result = await step.${method}`;
|
|
419
|
-
}
|
|
420
|
-
// No assignment, add one
|
|
421
|
-
return `const ${stepFunction.varName}_result = await step.${method}`;
|
|
422
|
-
},
|
|
423
|
-
);
|
|
424
|
-
|
|
425
|
-
// Find the original variable name from the step assignment
|
|
426
|
-
const originalVarMatch = transformedBody.match(/const\s+(\w+)\s*=\s*await\s+step\./);
|
|
427
|
-
let originalVarName = null;
|
|
428
|
-
|
|
429
|
-
// Also try to find variable from the original code before transformation
|
|
430
|
-
if (!originalVarMatch) {
|
|
431
|
-
const [, codeVarName] = cleanedBody.match(/const\s+(\w+)\s*=\s*await\s+step\./) || [];
|
|
432
|
-
if (codeVarName) {
|
|
433
|
-
originalVarName = codeVarName;
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
// Replace variable references (like eventResult, sleepResult, waitResult)
|
|
438
|
-
// Common patterns: eventResult, sleepResult, waitResult, or any variable used in console.log/return
|
|
439
|
-
if (originalVarName) {
|
|
440
|
-
// Replace all references to the original variable with the new result variable
|
|
441
|
-
const varPattern = new RegExp(`\\b${originalVarName}\\b`, 'g');
|
|
442
|
-
transformedBody = transformedBody.replace(varPattern, `${stepFunction.varName}_result`);
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// Also replace common result variable names that might not have been caught
|
|
446
|
-
transformedBody = transformedBody
|
|
447
|
-
.replace(/\beventResult\b/g, `${stepFunction.varName}_result`)
|
|
448
|
-
.replace(/\bsleepResult\b/g, `${stepFunction.varName}_result`)
|
|
449
|
-
.replace(/\bwaitResult\b/g, `${stepFunction.varName}_result`);
|
|
450
|
-
|
|
451
|
-
// Remove return statements (since we'll add our own unified return)
|
|
452
|
-
transformedBody = transformedBody
|
|
453
|
-
.split('\n')
|
|
454
|
-
.filter((line) => {
|
|
455
|
-
const trimmed = line.trim();
|
|
456
|
-
// Remove lines that start with 'return'
|
|
457
|
-
return !trimmed.match(/^return\s/);
|
|
458
|
-
})
|
|
459
|
-
.join('\n');
|
|
460
|
-
|
|
461
|
-
return `// ${stepLabel}\n ${transformedBody}`;
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
// For other step types, wrap in step.run()
|
|
465
|
-
return `// ${stepLabel}
|
|
466
|
-
const ${stepFunction.varName}_result = await step.run('${stepFunction.varName}', async (event, step) => {
|
|
467
|
-
${cleanedBody}
|
|
468
|
-
});`;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
// Generate complete Inngest function from step functions
|
|
472
|
-
export function generateInngestFunctionFromSteps(
|
|
473
|
-
stepFunctions: Array<{ code: string; varName: string; type?: string; label?: string }>,
|
|
474
|
-
): string {
|
|
475
|
-
// Transform each step for execution
|
|
476
|
-
const stepBlocks: string[] = [];
|
|
477
|
-
const resultVars: string[] = [];
|
|
478
|
-
|
|
479
|
-
stepFunctions.forEach((stepFunc, index) => {
|
|
480
|
-
const stepType = stepFunc.type || 'run';
|
|
481
|
-
const stepLabel = stepFunc.label || `Step ${index + 1}`;
|
|
482
|
-
|
|
483
|
-
const executionCode = transformStepForExecution(stepFunc, stepType, stepLabel);
|
|
484
|
-
stepBlocks.push(executionCode);
|
|
485
|
-
|
|
486
|
-
// Determine result variable name
|
|
487
|
-
if (executionCode.includes(`${stepFunc.varName}_result`)) {
|
|
488
|
-
resultVars.push(`${stepFunc.varName}_result`);
|
|
489
|
-
} else {
|
|
490
|
-
// For direct execution without result assignment
|
|
491
|
-
resultVars.push(stepFunc.varName);
|
|
492
|
-
}
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
// Generate function body without async wrapper
|
|
496
|
-
const code = `${stepBlocks.join('\n\n')}
|
|
497
|
-
|
|
498
|
-
return {
|
|
499
|
-
steps: ${stepFunctions.length},
|
|
500
|
-
results: {
|
|
501
|
-
${resultVars.map((v, i) => ` ${stepFunctions[i].varName}: ${v}`).join(',\n')}
|
|
502
|
-
}
|
|
503
|
-
};`;
|
|
504
|
-
|
|
505
|
-
return code;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
// Convert ExtractedFunction array to step functions and generate Inngest function
|
|
509
|
-
export function generateFromExtractedFunctions(extractedFunctions: ExtractedFunction[]): string {
|
|
510
|
-
if (extractedFunctions.length === 0) {
|
|
511
|
-
return 'return { success: false, error: "No functions to execute" };';
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
// For functions that are complete workflow steps (like step_416),
|
|
515
|
-
// just return the code body directly without extraction
|
|
516
|
-
const func = extractedFunctions[0];
|
|
517
|
-
|
|
518
|
-
// Check if this is a complete function (has async function signature)
|
|
519
|
-
if (func.code && func.code.includes('async function')) {
|
|
520
|
-
// Extract just the body, preserving all helper functions and logic
|
|
521
|
-
const bodyMatch = func.code.match(/async function[^{]*\{([\s\S]*)\}[\s]*$/);
|
|
522
|
-
if (bodyMatch) {
|
|
523
|
-
return bodyMatch[1].trim();
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
// Check if code has arrow function format: const x = async (event, step) => { ... }
|
|
528
|
-
if (func.code && func.code.includes('async') && func.code.includes('=>')) {
|
|
529
|
-
const arrowBodyMatch = func.code.match(/=>\s*\{([\s\S]*)\}[\s]*;?[\s]*$/);
|
|
530
|
-
if (arrowBodyMatch) {
|
|
531
|
-
return arrowBodyMatch[1].trim();
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
// Fallback: return the code as-is if we can't parse it
|
|
536
|
-
console.warn('Could not parse function format, returning code as-is');
|
|
537
|
-
return func.code || 'return { success: false, error: "No code available" };';
|
|
538
|
-
}
|
package/src/utils/json.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
export function flatten(obj: Record<string, unknown>, parentKey = '', res: Record<string, unknown> = {}) {
|
|
2
|
-
Object.entries(obj).forEach(([key, value]) => {
|
|
3
|
-
const newKey = parentKey ? `${parentKey}.${key}` : key;
|
|
4
|
-
|
|
5
|
-
if (Array.isArray(value)) {
|
|
6
|
-
value.forEach((item, index) => {
|
|
7
|
-
if (item !== null && typeof item === 'object') {
|
|
8
|
-
flatten(item, `${newKey}.${index}`, res);
|
|
9
|
-
} else {
|
|
10
|
-
res[`${newKey}.${index}`] = item;
|
|
11
|
-
}
|
|
12
|
-
});
|
|
13
|
-
} else if (value !== null && typeof value === 'object') {
|
|
14
|
-
flatten(value as Record<string, unknown>, newKey, res);
|
|
15
|
-
} else {
|
|
16
|
-
res[newKey] = value;
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
return res;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function unflatten(obj: Record<string, unknown>) {
|
|
24
|
-
const result = {};
|
|
25
|
-
if (!obj || typeof obj !== 'object') return result;
|
|
26
|
-
for (const [flatKey, value] of Object.entries(obj)) {
|
|
27
|
-
const keys = flatKey.split('.');
|
|
28
|
-
keys.reduce((acc, cur, i) => {
|
|
29
|
-
const isLast = i === keys.length - 1;
|
|
30
|
-
const nextKey = keys[i + 1];
|
|
31
|
-
const curIsIndex = !Number.isNaN(Number(cur));
|
|
32
|
-
const nextIsIndex = !Number.isNaN(Number(nextKey));
|
|
33
|
-
|
|
34
|
-
// If current key is numeric, treat parent as an array
|
|
35
|
-
if (curIsIndex) {
|
|
36
|
-
if (!Array.isArray(acc)) return [];
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (isLast) {
|
|
40
|
-
acc[cur] = value;
|
|
41
|
-
} else if (acc[cur] == null) {
|
|
42
|
-
acc[cur] = nextIsIndex ? [] : {};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return acc[cur];
|
|
46
|
-
}, result);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return result;
|
|
50
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "../../../tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"resolveJsonModule": true,
|
|
5
|
-
"rootDir": "./src",
|
|
6
|
-
"outDir": "lib",
|
|
7
|
-
"sourceMap": false,
|
|
8
|
-
"declarationDir": "lib",
|
|
9
|
-
"declaration": true,
|
|
10
|
-
"declarationMap": true,
|
|
11
|
-
"skipLibCheck": true
|
|
12
|
-
},
|
|
13
|
-
"include": ["src"]
|
|
14
|
-
}
|