@synergenius/flow-weaver 0.21.20 → 0.21.22
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/api/generate-in-place.js +4 -10
- package/dist/api/generate.js +5 -20
- package/dist/api/inline-runtime.d.ts +0 -8
- package/dist/api/inline-runtime.js +17 -113
- package/dist/cli/flow-weaver.mjs +93 -188
- package/dist/generated-version.d.ts +1 -1
- package/dist/generated-version.js +1 -1
- package/dist/generator/code-utils.d.ts +1 -0
- package/dist/generator/code-utils.js +20 -17
- package/dist/generator/scope-function-generator.js +19 -9
- package/dist/generator/unified.js +43 -35
- package/package.json +1 -1
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* - Function body (between markers)
|
|
9
9
|
*/
|
|
10
10
|
import { bodyGenerator } from '../body-generator.js';
|
|
11
|
-
import { generateInlineRuntime
|
|
11
|
+
import { generateInlineRuntime } from './inline-runtime.js';
|
|
12
12
|
import { isExecutePort, isSuccessPort, isFailurePort, isControlFlowPort } from '../constants.js';
|
|
13
13
|
import { generateJSDocPortTag, assignPortOrders, generateNodeInstanceTag, } from '../annotation-generator.js';
|
|
14
14
|
import { shouldWorkflowBeAsync } from '../generator/async-detection.js';
|
|
@@ -112,9 +112,11 @@ export function generateInPlace(sourceCode, ast, options = {}) {
|
|
|
112
112
|
}
|
|
113
113
|
// Step 5: Detect async from node composition + source signature
|
|
114
114
|
// If any node is async, force async (even if source isn't marked async)
|
|
115
|
+
// In dev mode (!production), always force async so the debugger can pause execution
|
|
116
|
+
// at breakpoints (sendStatusChangedEvent must be awaited).
|
|
115
117
|
const nodesRequireAsync = shouldWorkflowBeAsync(ast, ast.nodeTypes);
|
|
116
118
|
const sourceIsAsync = detectFunctionIsAsync(result, ast.functionName);
|
|
117
|
-
const forceAsync = nodesRequireAsync;
|
|
119
|
+
const forceAsync = nodesRequireAsync || !production;
|
|
118
120
|
const isAsync = forceAsync || sourceIsAsync;
|
|
119
121
|
// Add async keyword to source if nodes or debug hooks require it
|
|
120
122
|
const asyncSigResult = ensureAsyncKeyword(result, ast.functionName, forceAsync);
|
|
@@ -158,19 +160,11 @@ function generateRuntimeSection(functionName, production, moduleFormat = 'esm',
|
|
|
158
160
|
lines.push(`import type { TDebugger } from '${externalRuntimePath}';`);
|
|
159
161
|
// Declare __flowWeaverDebugger__ so body code can reference it
|
|
160
162
|
lines.push('declare const __flowWeaverDebugger__: TDebugger | undefined;');
|
|
161
|
-
// Include inline debug client (createFlowWeaverDebugClient is not exported from runtime)
|
|
162
|
-
lines.push('');
|
|
163
|
-
lines.push(generateInlineDebugClient(moduleFormat));
|
|
164
163
|
}
|
|
165
164
|
}
|
|
166
165
|
else {
|
|
167
166
|
// Inline runtime: embed all types and classes directly
|
|
168
167
|
lines.push(generateInlineRuntime(production));
|
|
169
|
-
// Add debug client (dev mode only)
|
|
170
|
-
if (!production) {
|
|
171
|
-
lines.push('');
|
|
172
|
-
lines.push(generateInlineDebugClient(moduleFormat));
|
|
173
|
-
}
|
|
174
168
|
}
|
|
175
169
|
return lines.join('\n');
|
|
176
170
|
}
|
package/dist/api/generate.js
CHANGED
|
@@ -3,7 +3,7 @@ import { extractExitPorts, extractStartPorts, hasBranching } from '../ast/workfl
|
|
|
3
3
|
import { isExecutePort } from '../constants.js';
|
|
4
4
|
import { mapToTypeScript } from '../type-mappings.js';
|
|
5
5
|
import { SourceMapGenerator } from 'source-map';
|
|
6
|
-
import { generateInlineRuntime,
|
|
6
|
+
import { generateInlineRuntime, stripTypeScript } from './inline-runtime.js';
|
|
7
7
|
import { validateWorkflowAsync } from '../generator/async-detection.js';
|
|
8
8
|
import { extractTypeDeclarationsFromFile } from './extract-types.js';
|
|
9
9
|
import * as path from 'node:path';
|
|
@@ -100,13 +100,6 @@ export function generateCode(ast, options) {
|
|
|
100
100
|
? `const { TDebugger } = require('${externalRuntimePath}');`
|
|
101
101
|
: `import type { TDebugger } from '${externalRuntimePath}';`);
|
|
102
102
|
addLine();
|
|
103
|
-
// Include inline debug client (createFlowWeaverDebugClient is not exported from runtime)
|
|
104
|
-
const inlineDebugClient = generateInlineDebugClient(moduleFormat);
|
|
105
|
-
const debugClientLines = inlineDebugClient.split('\n');
|
|
106
|
-
debugClientLines.forEach((line) => {
|
|
107
|
-
lines.push(line);
|
|
108
|
-
addLine();
|
|
109
|
-
});
|
|
110
103
|
}
|
|
111
104
|
lines.push('');
|
|
112
105
|
addLine();
|
|
@@ -121,15 +114,6 @@ export function generateCode(ast, options) {
|
|
|
121
114
|
});
|
|
122
115
|
lines.push('');
|
|
123
116
|
addLine();
|
|
124
|
-
// Include inline debug client (dev mode only)
|
|
125
|
-
if (!production) {
|
|
126
|
-
const inlineDebugClient = generateInlineDebugClient(moduleFormat);
|
|
127
|
-
const debugClientLines = inlineDebugClient.split('\n');
|
|
128
|
-
debugClientLines.forEach((line) => {
|
|
129
|
-
lines.push(line);
|
|
130
|
-
addLine();
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
117
|
}
|
|
134
118
|
// Extract and include type declarations from source file (interfaces, type aliases)
|
|
135
119
|
if (ast.sourceFile) {
|
|
@@ -374,7 +358,8 @@ export function generateCode(ast, options) {
|
|
|
374
358
|
}
|
|
375
359
|
}
|
|
376
360
|
// Generate conditional async keyword and export keyword based on module format
|
|
377
|
-
|
|
361
|
+
// In dev mode, always async so the debugger can pause at breakpoints
|
|
362
|
+
const asyncKeyword = (shouldBeAsync || !production) ? 'async ' : '';
|
|
378
363
|
const exportKeyword = generateFunctionExportKeyword(moduleFormat);
|
|
379
364
|
lines.push(`${exportKeyword}${asyncKeyword}function ${ast.functionName}(`);
|
|
380
365
|
addLine();
|
|
@@ -488,8 +473,8 @@ function generateWorkflowFunction(workflow, production, allWorkflows, generatedW
|
|
|
488
473
|
// Generate function signature
|
|
489
474
|
const startPorts = extractStartPorts(workflow);
|
|
490
475
|
const exitPorts = extractExitPorts(workflow);
|
|
491
|
-
const
|
|
492
|
-
lines.push(`${
|
|
476
|
+
const asyncKeyword2 = (shouldBeAsync || !production) ? 'async ' : '';
|
|
477
|
+
lines.push(`${asyncKeyword2}function ${workflow.functionName}(`);
|
|
493
478
|
// STEP Port Architecture: execute is first parameter
|
|
494
479
|
lines.push(` execute: boolean = true,`);
|
|
495
480
|
// Collect param names and types for destructuring
|
|
@@ -18,14 +18,6 @@ export declare function stripTypeScript(code: string): string;
|
|
|
18
18
|
*/
|
|
19
19
|
export declare function generateInlineRuntime(production: boolean, exportClasses?: boolean, outputFormat?: TOutputFormat): string;
|
|
20
20
|
import type { TModuleFormat } from '../ast/types.js';
|
|
21
|
-
/**
|
|
22
|
-
* Generates inline WebSocket debug client for auto-detection from env var
|
|
23
|
-
* Only included in development mode builds
|
|
24
|
-
*
|
|
25
|
-
* @param moduleFormat - The module format to use for imports ('esm' or 'cjs')
|
|
26
|
-
* @param outputFormat - Output format: 'typescript' (default) or 'javascript' (strips types)
|
|
27
|
-
*/
|
|
28
|
-
export declare function generateInlineDebugClient(moduleFormat?: TModuleFormat, outputFormat?: TOutputFormat): string;
|
|
29
21
|
/**
|
|
30
22
|
* Generates a standalone runtime module file for multi-workflow bundles.
|
|
31
23
|
* This exports all runtime types and classes so individual workflow files can import them.
|
|
@@ -100,7 +100,7 @@ export function generateInlineRuntime(production, exportClasses = false, outputF
|
|
|
100
100
|
lines.push(' | TWorkflowCompletedEvent;');
|
|
101
101
|
lines.push('');
|
|
102
102
|
lines.push(`${exportKeyword}type TDebugger = {`);
|
|
103
|
-
lines.push(' sendEvent: (event: TEvent) => void
|
|
103
|
+
lines.push(' sendEvent: (event: TEvent) => void | Promise<void>;');
|
|
104
104
|
lines.push(' innerFlowInvocation: boolean;');
|
|
105
105
|
lines.push(' sessionId?: string;');
|
|
106
106
|
lines.push('};');
|
|
@@ -303,12 +303,13 @@ export function generateInlineRuntime(production, exportClasses = false, outputF
|
|
|
303
303
|
lines.push(' }');
|
|
304
304
|
lines.push('');
|
|
305
305
|
// createScope
|
|
306
|
-
lines.push(' createScope(_parentNodeName: string, _parentIndex: number, _scopeName: string, cleanScope: boolean = false): GeneratedExecutionContext {');
|
|
306
|
+
lines.push(' createScope(_parentNodeName: string, _parentIndex: number, _scopeName: string, cleanScope: boolean = false, isAsyncOverride?: boolean): GeneratedExecutionContext {');
|
|
307
|
+
lines.push(' const effectiveIsAsync = isAsyncOverride !== undefined ? isAsyncOverride : this.isAsync;');
|
|
307
308
|
if (production) {
|
|
308
|
-
lines.push(' const scopedContext = new GeneratedExecutionContext(
|
|
309
|
+
lines.push(' const scopedContext = new GeneratedExecutionContext(effectiveIsAsync, this.abortSignal);');
|
|
309
310
|
}
|
|
310
311
|
else {
|
|
311
|
-
lines.push(' const scopedContext = new GeneratedExecutionContext(
|
|
312
|
+
lines.push(' const scopedContext = new GeneratedExecutionContext(effectiveIsAsync, this.flowWeaverDebugger, this.abortSignal);');
|
|
312
313
|
}
|
|
313
314
|
lines.push(' // For per-port function scopes (cleanScope=true), start with empty variables');
|
|
314
315
|
lines.push(' // For node-level scopes (cleanScope=false), inherit parent variables');
|
|
@@ -371,16 +372,16 @@ export function generateInlineRuntime(production, exportClasses = false, outputF
|
|
|
371
372
|
lines.push('');
|
|
372
373
|
// Debug event methods (only in development mode)
|
|
373
374
|
if (!production) {
|
|
374
|
-
lines.push(' sendStatusChangedEvent(args: {');
|
|
375
|
+
lines.push(' async sendStatusChangedEvent(args: {');
|
|
375
376
|
lines.push(' nodeTypeName: string;');
|
|
376
377
|
lines.push(' id: string;');
|
|
377
378
|
lines.push(' scope?: string;');
|
|
378
379
|
lines.push(' side?: "start" | "exit";');
|
|
379
380
|
lines.push(' executionIndex: number;');
|
|
380
381
|
lines.push(' status: TStatusType;');
|
|
381
|
-
lines.push(' }): void {');
|
|
382
|
+
lines.push(' }): Promise<void> {');
|
|
382
383
|
lines.push(' if (this.flowWeaverDebugger) {');
|
|
383
|
-
lines.push(' this.flowWeaverDebugger.sendEvent({');
|
|
384
|
+
lines.push(' await this.flowWeaverDebugger.sendEvent({');
|
|
384
385
|
lines.push(' type: "STATUS_CHANGED",');
|
|
385
386
|
lines.push(' ...args,');
|
|
386
387
|
lines.push(' innerFlowInvocation: this.flowWeaverDebugger.innerFlowInvocation,');
|
|
@@ -388,12 +389,12 @@ export function generateInlineRuntime(production, exportClasses = false, outputF
|
|
|
388
389
|
lines.push(' }');
|
|
389
390
|
lines.push(' }');
|
|
390
391
|
lines.push('');
|
|
391
|
-
lines.push(' private sendVariableSetEvent(args: {');
|
|
392
|
+
lines.push(' private async sendVariableSetEvent(args: {');
|
|
392
393
|
lines.push(' identifier: TVariableIdentification;');
|
|
393
394
|
lines.push(' value: unknown;');
|
|
394
|
-
lines.push(' }): void {');
|
|
395
|
+
lines.push(' }): Promise<void> {');
|
|
395
396
|
lines.push(' if (this.flowWeaverDebugger) {');
|
|
396
|
-
lines.push(' this.flowWeaverDebugger.sendEvent({');
|
|
397
|
+
lines.push(' await this.flowWeaverDebugger.sendEvent({');
|
|
397
398
|
lines.push(' type: "VARIABLE_SET",');
|
|
398
399
|
lines.push(' ...args,');
|
|
399
400
|
lines.push(' innerFlowInvocation: this.flowWeaverDebugger.innerFlowInvocation,');
|
|
@@ -401,16 +402,16 @@ export function generateInlineRuntime(production, exportClasses = false, outputF
|
|
|
401
402
|
lines.push(' }');
|
|
402
403
|
lines.push(' }');
|
|
403
404
|
lines.push('');
|
|
404
|
-
lines.push(' sendLogErrorEvent(args: {');
|
|
405
|
+
lines.push(' async sendLogErrorEvent(args: {');
|
|
405
406
|
lines.push(' nodeTypeName: string;');
|
|
406
407
|
lines.push(' id: string;');
|
|
407
408
|
lines.push(' scope?: string;');
|
|
408
409
|
lines.push(' side?: "start" | "exit";');
|
|
409
410
|
lines.push(' executionIndex: number;');
|
|
410
411
|
lines.push(' error: string;');
|
|
411
|
-
lines.push(' }): void {');
|
|
412
|
+
lines.push(' }): Promise<void> {');
|
|
412
413
|
lines.push(' if (this.flowWeaverDebugger) {');
|
|
413
|
-
lines.push(' this.flowWeaverDebugger.sendEvent({');
|
|
414
|
+
lines.push(' await this.flowWeaverDebugger.sendEvent({');
|
|
414
415
|
lines.push(' type: "LOG_ERROR",');
|
|
415
416
|
lines.push(' ...args,');
|
|
416
417
|
lines.push(' innerFlowInvocation: this.flowWeaverDebugger.innerFlowInvocation,');
|
|
@@ -418,13 +419,13 @@ export function generateInlineRuntime(production, exportClasses = false, outputF
|
|
|
418
419
|
lines.push(' }');
|
|
419
420
|
lines.push(' }');
|
|
420
421
|
lines.push('');
|
|
421
|
-
lines.push(' sendWorkflowCompletedEvent(args: {');
|
|
422
|
+
lines.push(' async sendWorkflowCompletedEvent(args: {');
|
|
422
423
|
lines.push(' executionIndex: number;');
|
|
423
424
|
lines.push(' status: "SUCCEEDED" | "FAILED" | "CANCELLED";');
|
|
424
425
|
lines.push(' result?: unknown;');
|
|
425
|
-
lines.push(' }): void {');
|
|
426
|
+
lines.push(' }): Promise<void> {');
|
|
426
427
|
lines.push(' if (this.flowWeaverDebugger) {');
|
|
427
|
-
lines.push(' this.flowWeaverDebugger.sendEvent({');
|
|
428
|
+
lines.push(' await this.flowWeaverDebugger.sendEvent({');
|
|
428
429
|
lines.push(' type: "WORKFLOW_COMPLETED",');
|
|
429
430
|
lines.push(' ...args,');
|
|
430
431
|
lines.push(' innerFlowInvocation: this.flowWeaverDebugger.innerFlowInvocation,');
|
|
@@ -490,92 +491,6 @@ export function generateInlineRuntime(production, exportClasses = false, outputF
|
|
|
490
491
|
}
|
|
491
492
|
return output;
|
|
492
493
|
}
|
|
493
|
-
/**
|
|
494
|
-
* Generates inline WebSocket debug client for auto-detection from env var
|
|
495
|
-
* Only included in development mode builds
|
|
496
|
-
*
|
|
497
|
-
* @param moduleFormat - The module format to use for imports ('esm' or 'cjs')
|
|
498
|
-
* @param outputFormat - Output format: 'typescript' (default) or 'javascript' (strips types)
|
|
499
|
-
*/
|
|
500
|
-
export function generateInlineDebugClient(moduleFormat = 'esm', outputFormat = 'typescript') {
|
|
501
|
-
const lines = [];
|
|
502
|
-
lines.push('// ============================================================================');
|
|
503
|
-
lines.push('// Inline Debug Client (auto-created from FLOW_WEAVER_DEBUG env var)');
|
|
504
|
-
lines.push('// ============================================================================');
|
|
505
|
-
lines.push('');
|
|
506
|
-
lines.push('/* eslint-disable @typescript-eslint/no-explicit-any, no-console */');
|
|
507
|
-
lines.push('function createFlowWeaverDebugClient(url: string, workflowExportName: string): any {');
|
|
508
|
-
lines.push(' let ws: any = null;');
|
|
509
|
-
lines.push(' let connected = false;');
|
|
510
|
-
lines.push(' let queue: string[] = [];');
|
|
511
|
-
lines.push(' const sessionId = Math.random().toString(36).substring(2, 15);');
|
|
512
|
-
lines.push('');
|
|
513
|
-
lines.push(' const connect = async () => {');
|
|
514
|
-
lines.push(' try {');
|
|
515
|
-
lines.push(" // Node.js environment - dynamically load 'ws' package");
|
|
516
|
-
// Generate format-appropriate import for 'ws' package
|
|
517
|
-
if (moduleFormat === 'cjs') {
|
|
518
|
-
// CommonJS: use require() directly
|
|
519
|
-
lines.push(" const wsModule = require('ws');");
|
|
520
|
-
}
|
|
521
|
-
else {
|
|
522
|
-
// ESM: use dynamic import
|
|
523
|
-
lines.push(" const wsModule = await import('ws');");
|
|
524
|
-
}
|
|
525
|
-
lines.push(' const WS: any = wsModule.default || wsModule;');
|
|
526
|
-
lines.push(' ws = new WS(url);');
|
|
527
|
-
lines.push('');
|
|
528
|
-
lines.push(" ws.on('open', () => {");
|
|
529
|
-
lines.push(' connected = true;');
|
|
530
|
-
lines.push(' // Send connect message');
|
|
531
|
-
lines.push(' ws.send(JSON.stringify({');
|
|
532
|
-
lines.push(" type: 'connect',");
|
|
533
|
-
lines.push(' sessionId,');
|
|
534
|
-
lines.push(' workflowExportName,');
|
|
535
|
-
lines.push(' clientInfo: {');
|
|
536
|
-
lines.push(' platform: process.platform,');
|
|
537
|
-
lines.push(' nodeVersion: process.version,');
|
|
538
|
-
lines.push(' pid: process.pid');
|
|
539
|
-
lines.push(' }');
|
|
540
|
-
lines.push(' }));');
|
|
541
|
-
lines.push('');
|
|
542
|
-
lines.push(' // Flush queued events');
|
|
543
|
-
lines.push(' while (queue.length > 0) {');
|
|
544
|
-
lines.push(' const msg = queue.shift();');
|
|
545
|
-
lines.push(' if (ws.readyState === 1) ws.send(msg);');
|
|
546
|
-
lines.push(' }');
|
|
547
|
-
lines.push(' });');
|
|
548
|
-
lines.push('');
|
|
549
|
-
lines.push(" ws.on('error', () => { connected = false; });");
|
|
550
|
-
lines.push(" ws.on('close', () => { connected = false; });");
|
|
551
|
-
lines.push(' } catch (err: unknown) {');
|
|
552
|
-
lines.push(" // Silently fail if 'ws' package not available");
|
|
553
|
-
lines.push(" console.warn('[Flow Weaver] Debug client failed to connect:', err instanceof Error ? err.message : String(err));");
|
|
554
|
-
lines.push(' }');
|
|
555
|
-
lines.push(' };');
|
|
556
|
-
lines.push('');
|
|
557
|
-
lines.push(' return {');
|
|
558
|
-
lines.push(' sendEvent: (event: unknown) => {');
|
|
559
|
-
lines.push(" const message = JSON.stringify({ type: 'event', sessionId, event });");
|
|
560
|
-
lines.push(' if (!ws) connect().catch(() => {});');
|
|
561
|
-
lines.push(' if (connected && ws.readyState === 1) {');
|
|
562
|
-
lines.push(' ws.send(message);');
|
|
563
|
-
lines.push(' } else {');
|
|
564
|
-
lines.push(' queue.push(message);');
|
|
565
|
-
lines.push(' }');
|
|
566
|
-
lines.push(' },');
|
|
567
|
-
lines.push(' innerFlowInvocation: false,');
|
|
568
|
-
lines.push(' sessionId');
|
|
569
|
-
lines.push(' };');
|
|
570
|
-
lines.push('}');
|
|
571
|
-
lines.push('/* eslint-enable @typescript-eslint/no-explicit-any, no-console */');
|
|
572
|
-
lines.push('');
|
|
573
|
-
const output = lines.join('\n');
|
|
574
|
-
if (outputFormat === 'javascript') {
|
|
575
|
-
return stripTypeScript(output);
|
|
576
|
-
}
|
|
577
|
-
return output;
|
|
578
|
-
}
|
|
579
494
|
/**
|
|
580
495
|
* Generates a standalone runtime module file for multi-workflow bundles.
|
|
581
496
|
* This exports all runtime types and classes so individual workflow files can import them.
|
|
@@ -595,14 +510,6 @@ export function generateStandaloneRuntimeModule(production, moduleFormat = 'esm'
|
|
|
595
510
|
const inlineRuntime = generateInlineRuntime(production, true);
|
|
596
511
|
lines.push(inlineRuntime);
|
|
597
512
|
lines.push('');
|
|
598
|
-
// Include debug client in development mode
|
|
599
|
-
if (!production) {
|
|
600
|
-
const debugClient = generateInlineDebugClient(moduleFormat);
|
|
601
|
-
// Add export to the createFlowWeaverDebugClient function
|
|
602
|
-
const exportedDebugClient = debugClient.replace('function createFlowWeaverDebugClient', 'export function createFlowWeaverDebugClient');
|
|
603
|
-
lines.push(exportedDebugClient);
|
|
604
|
-
lines.push('');
|
|
605
|
-
}
|
|
606
513
|
if (moduleFormat === 'cjs') {
|
|
607
514
|
// CommonJS exports
|
|
608
515
|
lines.push('// ============================================================================');
|
|
@@ -610,9 +517,6 @@ export function generateStandaloneRuntimeModule(production, moduleFormat = 'esm'
|
|
|
610
517
|
lines.push('// ============================================================================');
|
|
611
518
|
lines.push('');
|
|
612
519
|
const exports = ['GeneratedExecutionContext', 'CancellationError'];
|
|
613
|
-
if (!production) {
|
|
614
|
-
exports.push('createFlowWeaverDebugClient', 'TDebugger');
|
|
615
|
-
}
|
|
616
520
|
lines.push(`module.exports = { ${exports.join(', ')} };`);
|
|
617
521
|
}
|
|
618
522
|
// For ESM, exports are added via 'export' keyword in the generated code
|