@fnet/cli 0.3.15 → 0.4.1
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/fnet/index.js +9 -9
- package/dist/fnode/{index.hd9ty41n.js → index.937tt8st.js} +1 -1
- package/dist/fnode/index.js +1 -1
- package/package.json +1 -1
- package/template/fnet/node/src/default/blocks/assign.js.njk +10 -48
- package/template/fnet/node/src/default/blocks/call.js.njk +110 -156
- package/template/fnet/node/src/default/blocks/for.js.njk +59 -95
- package/template/fnet/node/src/default/blocks/form.js.njk +21 -59
- package/template/fnet/node/src/default/blocks/http.js.njk +125 -147
- package/template/fnet/node/src/default/blocks/modules.js.njk +10 -52
- package/template/fnet/node/src/default/blocks/new.js.njk +40 -85
- package/template/fnet/node/src/default/blocks/next.js.njk +10 -32
- package/template/fnet/node/src/default/blocks/output.js.njk +10 -48
- package/template/fnet/node/src/default/blocks/parallel.js.njk +60 -106
- package/template/fnet/node/src/default/blocks/pipeline.js.njk +100 -137
- package/template/fnet/node/src/default/blocks/raise.js.njk +9 -25
- package/template/fnet/node/src/default/blocks/retry.js.njk +63 -87
- package/template/fnet/node/src/default/blocks/return.js.njk +13 -25
- package/template/fnet/node/src/default/blocks/schedule.js.njk +56 -73
- package/template/fnet/node/src/default/blocks/signal.js.njk +10 -32
- package/template/fnet/node/src/default/blocks/steps.js.njk +32 -55
- package/template/fnet/node/src/default/blocks/switch.js.njk +37 -74
- package/template/fnet/node/src/default/blocks/tryexcept.js.njk +58 -52
- package/template/fnet/node/src/default/blocks/wait.js.njk +10 -30
- package/template/fnet/node/src/default/macros/block-body-header.js.njk +1 -1
- package/template/fnet/node/src/default/macros/block-next.js.njk +0 -1
- package/template/fnet/node/src/default/types/block.js.njk +133 -0
- package/template/fnet/node/src/default/workflow.js.njk +1 -1
|
@@ -1,87 +1,42 @@
|
|
|
1
|
-
{%
|
|
2
|
-
|
|
3
|
-
{%
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
{% set assign=true %}
|
|
2
|
+
{% set signal=true %}
|
|
3
|
+
{% set resolve=true %}
|
|
4
|
+
{% set result=true %}
|
|
5
|
+
|
|
6
|
+
{% import "src/default/types/block.js.njk" as block with context %}
|
|
7
|
+
|
|
8
|
+
{% call block.header() %}
|
|
9
|
+
{% include "src/default/macros/block-library-header.js.njk" %}
|
|
10
|
+
{% endcall %}
|
|
11
|
+
|
|
12
|
+
{% call block.definition() %}
|
|
13
|
+
|
|
14
|
+
{# NEW: Check if 'new' keyword is present for constructor call #}
|
|
15
|
+
{% if context.transform.new !== undefined %}
|
|
16
|
+
{# Constructor instantiation with 'new' keyword #}
|
|
17
|
+
{% if context.lib.type==='atom' and context.lib.atom.protocol!=='use:' %}
|
|
18
|
+
const LibClass=LIBRARY;
|
|
19
|
+
{% elseif context.lib.atom.protocol==='use:' %}
|
|
20
|
+
{# For use:e:: protocol, call value is the class name (e.g., use:e::Map → Map) #}
|
|
21
|
+
const LibClass={{context.transform.import}};
|
|
22
|
+
if(!LibClass) throw new Error('[use] Couldnt find class.');
|
|
23
|
+
{% else %}
|
|
24
|
+
throw new Error('Cannot instantiate: unsupported lib type.');
|
|
25
|
+
{% endif %}
|
|
26
|
+
|
|
27
|
+
{# Create instance with constructor args #}
|
|
28
|
+
{% if context.transform.new %}
|
|
29
|
+
const constructorArgs = {{ context.transform.new | safe }};
|
|
30
|
+
const instance = Array.isArray(constructorArgs) ? new LibClass(...constructorArgs) : new LibClass(constructorArgs);
|
|
31
|
+
{% else %}
|
|
32
|
+
const instance = new LibClass();
|
|
33
|
+
{% endif %}
|
|
34
|
+
|
|
35
|
+
{% endif %}
|
|
36
|
+
|
|
37
|
+
const result = instance;
|
|
12
38
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
{% include "src/default/macros/block-entry-args.js.njk" %}
|
|
16
|
-
|
|
17
|
-
return new Promise(async (resolve,reject)=>{
|
|
18
|
-
|
|
19
|
-
try{
|
|
20
|
-
{% include "src/default/macros/block-run-header.js.njk" %}
|
|
21
|
-
|
|
22
|
-
{% include "src/default/macros/page.js.njk" %}
|
|
23
|
-
|
|
24
|
-
{% include "src/default/macros/block-modules.js.njk" %}
|
|
25
|
-
|
|
26
|
-
{% if context.next and context.transform.wait==='next' %}
|
|
27
|
-
flow.waitForNext({
|
|
28
|
-
key:'{{indexKey}}',
|
|
29
|
-
next: async () => {
|
|
30
|
-
{% include "src/default/macros/block-next.js.njk" %}
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
{% endif %}
|
|
34
|
-
|
|
35
|
-
{# NEW: Check if 'new' keyword is present for constructor call #}
|
|
36
|
-
{% if context.transform.new !== undefined %}
|
|
37
|
-
{# Constructor instantiation with 'new' keyword #}
|
|
38
|
-
{% if context.lib.type==='atom' and context.lib.atom.protocol!=='use:' %}
|
|
39
|
-
const LibClass=LIBRARY;
|
|
40
|
-
{% elseif context.lib.atom.protocol==='use:' %}
|
|
41
|
-
{# For use:e:: protocol, call value is the class name (e.g., use:e::Map → Map) #}
|
|
42
|
-
const LibClass={{context.transform.import}};
|
|
43
|
-
if(!LibClass) throw new Error('[use] Couldnt find class.');
|
|
44
|
-
{% else %}
|
|
45
|
-
throw new Error('Cannot instantiate: unsupported lib type.');
|
|
46
|
-
{% endif %}
|
|
47
|
-
|
|
48
|
-
{# Create instance with constructor args #}
|
|
49
|
-
{% if context.transform.new %}
|
|
50
|
-
const constructorArgs = {{ context.transform.new | safe }};
|
|
51
|
-
const instance = Array.isArray(constructorArgs) ? new LibClass(...constructorArgs) : new LibClass(constructorArgs);
|
|
52
|
-
{% else %}
|
|
53
|
-
const instance = new LibClass();
|
|
54
|
-
{% endif %}
|
|
55
|
-
|
|
56
|
-
{% endif %}
|
|
57
|
-
|
|
58
|
-
const result = instance;
|
|
59
|
-
|
|
60
|
-
{% for assign in context.transform.result %}
|
|
61
|
-
flow.set({{assign.key | safe}},{{assign.value | safe}});
|
|
62
|
-
{% endfor%}
|
|
63
|
-
|
|
64
|
-
{% include "src/default/macros/block-assign.js.njk" %}
|
|
65
|
-
|
|
66
|
-
{% include "src/default/macros/block-signal.js.njk" %}
|
|
67
|
-
|
|
68
|
-
{% if context.transform.return %}
|
|
69
|
-
resolve({type:'return',value: {{context.transform.return | safe}}});
|
|
70
|
-
{% elseif context.next and context.transform.wait!=='next'%}
|
|
71
|
-
{% include "src/default/macros/block-next.js.njk" %}
|
|
72
|
-
{% elseif not context.next%}
|
|
73
|
-
resolve();
|
|
74
|
-
{% endif %}
|
|
75
|
-
|
|
76
|
-
{% include "src/default/macros/block-run-footer.js.njk" %}
|
|
77
|
-
}
|
|
78
|
-
catch(error){
|
|
79
|
-
onError? onError(error) : reject(error);
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
Object.freeze(this);
|
|
85
|
-
}
|
|
39
|
+
{% endcall %}
|
|
86
40
|
|
|
87
|
-
{%
|
|
41
|
+
{% call block.footer()%}
|
|
42
|
+
{% endcall %}
|
|
@@ -1,37 +1,15 @@
|
|
|
1
|
-
{%
|
|
1
|
+
{% set assign=true %}
|
|
2
|
+
{% set signal=true %}
|
|
3
|
+
{% set resolve=true %}
|
|
2
4
|
|
|
3
|
-
{%
|
|
5
|
+
{% import "src/default/types/block.js.njk" as block with context %}
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
{% include "src/default/macros/block-body-header.js.njk" %}
|
|
7
|
+
{% call block.header() %}
|
|
8
|
+
{% endcall %}
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
{% include "src/default/macros/block-entry-args.js.njk" %}
|
|
10
|
+
{% call block.definition() %}
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
{% include "src/default/macros/block-run-header.js.njk" %}
|
|
15
|
-
|
|
16
|
-
{% include "src/default/macros/page.js.njk" %}
|
|
17
|
-
|
|
18
|
-
{% include "src/default/macros/block-assign.js.njk" %}
|
|
12
|
+
{% endcall %}
|
|
19
13
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
{% if context.transform.return %}
|
|
23
|
-
resolve({type:'return',value: {{context.transform.return | safe}}});
|
|
24
|
-
{% elseif context.next %}
|
|
25
|
-
{% include "src/default/macros/block-next.js.njk" %}
|
|
26
|
-
{% else %}
|
|
27
|
-
resolve();
|
|
28
|
-
{% endif %}
|
|
29
|
-
|
|
30
|
-
{% include "src/default/macros/block-run-footer.js.njk" %}
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
Object.freeze(this);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
{% include "src/default/macros/block-footer.js.njk" %}
|
|
14
|
+
{% call block.footer()%}
|
|
15
|
+
{% endcall %}
|
|
@@ -1,53 +1,15 @@
|
|
|
1
|
-
{%
|
|
1
|
+
{% set assign=true %}
|
|
2
|
+
{% set signal=true %}
|
|
3
|
+
{% set resolve=true %}
|
|
2
4
|
|
|
3
|
-
{%
|
|
5
|
+
{% import "src/default/types/block.js.njk" as block with context %}
|
|
4
6
|
|
|
5
|
-
{%
|
|
7
|
+
{% call block.header() %}
|
|
8
|
+
{% endcall %}
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
{% call block.definition() %}
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
{% endcall %}
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
{% include "src/default/macros/block-entry-args.js.njk" %}
|
|
14
|
-
|
|
15
|
-
return new Promise(async (resolve,reject)=>{
|
|
16
|
-
|
|
17
|
-
{% include "src/default/macros/block-run-header.js.njk" %}
|
|
18
|
-
|
|
19
|
-
{% include "src/default/macros/page.js.njk" %}
|
|
20
|
-
|
|
21
|
-
{% include "src/default/macros/block-modules.js.njk" %}
|
|
22
|
-
|
|
23
|
-
{% if context.next and context.transform.wait==='next' %}
|
|
24
|
-
flow.waitForNext({
|
|
25
|
-
key:'{{indexKey}}',
|
|
26
|
-
next: async () => {
|
|
27
|
-
{% include "src/default/macros/block-next.js.njk" %}
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
{% endif %}
|
|
31
|
-
|
|
32
|
-
{% for assign in context.transform.assign %}
|
|
33
|
-
flow.set({{assign.key | safe}},{{assign.value | safe}});
|
|
34
|
-
{% endfor%}
|
|
35
|
-
|
|
36
|
-
{% include "src/default/macros/block-signal.js.njk" %}
|
|
37
|
-
|
|
38
|
-
{% if context.transform.return %}
|
|
39
|
-
resolve({type:'return',value: {{context.transform.return | safe}}});
|
|
40
|
-
{% elseif context.next and context.transform.wait!=='next'%}
|
|
41
|
-
{% include "src/default/macros/block-next.js.njk" %}
|
|
42
|
-
{% elseif not context.next%}
|
|
43
|
-
resolve();
|
|
44
|
-
{% endif %}
|
|
45
|
-
|
|
46
|
-
{% include "src/default/macros/block-run-footer.js.njk" %}
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
Object.freeze(this);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
{% include "src/default/macros/block-footer.js.njk" %}
|
|
14
|
+
{% call block.footer()%}
|
|
15
|
+
{% endcall %}
|
|
@@ -1,110 +1,64 @@
|
|
|
1
|
-
{%
|
|
2
|
-
|
|
3
|
-
{%
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
{
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
{
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
{% for child in childs %}
|
|
34
|
-
{% if child.definition.dynamic %}
|
|
35
|
-
// PARALLEL CHILD: {{child.indexKey}}
|
|
36
|
-
const { default: {{child.codeKey}} } = await import("./{{child.codeKey}}.js");
|
|
37
|
-
{% endif %}
|
|
38
|
-
|
|
39
|
-
promises.push((async () => {
|
|
40
|
-
const current = new {{child.codeKey}}({ parent: _this, engine, flow, caller: c, onError, error });
|
|
41
|
-
|
|
42
|
-
{% if workflow.parent.context.atom.doc.features.print_runners %}
|
|
43
|
-
console.log(new Date().toLocaleString(), ' * ', _this.constructor.IndexKey, ' -> ', current.constructor.IndexKey);
|
|
44
|
-
{% endif %}
|
|
45
|
-
|
|
46
|
-
const nextBlock = Array.isArray(args)
|
|
47
|
-
? await current.run.apply(current, args)
|
|
48
|
-
: await current.run.call(current, args);
|
|
49
|
-
|
|
50
|
-
return nextBlock;
|
|
51
|
-
})());
|
|
52
|
-
{% endfor %}
|
|
53
|
-
|
|
54
|
-
// Execute based on strategy
|
|
55
|
-
{% set strategy = context.transform.strategy | default('all') %}
|
|
56
|
-
let results;
|
|
57
|
-
|
|
58
|
-
try {
|
|
59
|
-
{% if strategy == 'race' %}
|
|
60
|
-
// Promise.race - first to complete wins
|
|
61
|
-
results = [await Promise.race(promises)];
|
|
62
|
-
{% elif strategy == 'any' %}
|
|
63
|
-
// Promise.any - first successful wins
|
|
64
|
-
results = [await Promise.any(promises)];
|
|
65
|
-
{% elif strategy == 'allsettled' %}
|
|
66
|
-
// Promise.allSettled - all complete, collect results
|
|
67
|
-
const settled = await Promise.allSettled(promises);
|
|
68
|
-
results = settled.map(r => r.status === 'fulfilled' ? r.value : null);
|
|
69
|
-
{% else %}
|
|
70
|
-
// Promise.all - all must succeed (default)
|
|
71
|
-
results = await Promise.all(promises);
|
|
72
|
-
{% endif %}
|
|
73
|
-
} catch (err) {
|
|
74
|
-
if (onError) {
|
|
75
|
-
return onError(err);
|
|
76
|
-
}
|
|
77
|
-
throw err;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Check if any child returned or jumped
|
|
81
|
-
for (const result of results) {
|
|
82
|
-
if (result?.type === 'return') {
|
|
83
|
-
return resolve(result);
|
|
84
|
-
}
|
|
85
|
-
if (result?.type === 'block') {
|
|
86
|
-
return resolve(result);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
{% include "src/default/macros/block-assign.js.njk" %}
|
|
91
|
-
|
|
92
|
-
{% include "src/default/macros/block-signal.js.njk" %}
|
|
93
|
-
|
|
94
|
-
{% if context.transform.return %}
|
|
95
|
-
resolve({ type: 'return', value: {{context.transform.return | safe}} });
|
|
96
|
-
{% elseif context.next %}
|
|
97
|
-
{% include "src/default/macros/block-next.js.njk" %}
|
|
98
|
-
{% else %}
|
|
99
|
-
resolve();
|
|
1
|
+
{% set assign=true %}
|
|
2
|
+
{% set signal=true %}
|
|
3
|
+
{% set resolve=true %}
|
|
4
|
+
{% set result=true %}
|
|
5
|
+
|
|
6
|
+
{% import "src/default/types/block.js.njk" as block with context %}
|
|
7
|
+
|
|
8
|
+
{% call block.header() %}
|
|
9
|
+
{% for child in childs %}
|
|
10
|
+
{% if not child.definition.dynamic %}
|
|
11
|
+
// PARALLEL CHILD: {{child.indexKey}}
|
|
12
|
+
import {{child.codeKey}} from "./{{child.codeKey}}.js";
|
|
13
|
+
{% endif %}
|
|
14
|
+
{% endfor %}
|
|
15
|
+
{% endcall %}
|
|
16
|
+
|
|
17
|
+
{% call block.definition() %}
|
|
18
|
+
// PARALLEL EXECUTION
|
|
19
|
+
const promises = [];
|
|
20
|
+
|
|
21
|
+
{% for child in childs %}
|
|
22
|
+
{% if child.definition.dynamic %}
|
|
23
|
+
// PARALLEL CHILD: {{child.indexKey}}
|
|
24
|
+
const { default: {{child.codeKey}} } = await import("./{{child.codeKey}}.js");
|
|
25
|
+
{% endif %}
|
|
26
|
+
|
|
27
|
+
promises.push((async () => {
|
|
28
|
+
const current = new {{child.codeKey}}({ parent: _this, engine, flow, caller: c, error });
|
|
29
|
+
|
|
30
|
+
{% if workflow.parent.context.atom.doc.features.print_runners %}
|
|
31
|
+
console.log(new Date().toLocaleString(), ' * ', _this.constructor.IndexKey, ' -> ', current.constructor.IndexKey);
|
|
100
32
|
{% endif %}
|
|
101
33
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
34
|
+
const nextBlock = Array.isArray(args)
|
|
35
|
+
? await current.run.apply(current, args)
|
|
36
|
+
: await current.run.call(current, args);
|
|
37
|
+
|
|
38
|
+
return nextBlock;
|
|
39
|
+
})());
|
|
40
|
+
{% endfor %}
|
|
41
|
+
|
|
42
|
+
// Execute based on strategy
|
|
43
|
+
{% set strategy = context.transform.strategy | default('all') %}
|
|
44
|
+
let result;
|
|
45
|
+
|
|
46
|
+
{% if strategy == 'race' %}
|
|
47
|
+
// Promise.race - first to complete wins
|
|
48
|
+
result = [await Promise.race(promises)];
|
|
49
|
+
{% elif strategy == 'any' %}
|
|
50
|
+
// Promise.any - first successful wins
|
|
51
|
+
result = [await Promise.any(promises)];
|
|
52
|
+
{% elif strategy == 'allsettled' %}
|
|
53
|
+
// Promise.allSettled - all complete, collect results
|
|
54
|
+
const settled = await Promise.allSettled(promises);
|
|
55
|
+
result = settled.map(r => r.status === 'fulfilled' ? r.value : null);
|
|
56
|
+
{% else %}
|
|
57
|
+
// Promise.all - all must succeed (default)
|
|
58
|
+
result = await Promise.all(promises);
|
|
59
|
+
{% endif %}
|
|
108
60
|
|
|
109
|
-
{%
|
|
61
|
+
{% endcall %}
|
|
110
62
|
|
|
63
|
+
{% call block.footer()%}
|
|
64
|
+
{% endcall %}
|
|
@@ -1,146 +1,109 @@
|
|
|
1
|
-
{%
|
|
1
|
+
{% set assign=true %}
|
|
2
|
+
{% set signal=true %}
|
|
3
|
+
{% set resolve=true %}
|
|
4
|
+
{% set result=true %}
|
|
5
|
+
|
|
6
|
+
{% import "src/default/types/block.js.njk" as block with context %}
|
|
7
|
+
|
|
8
|
+
{% call block.header() %}
|
|
9
|
+
{% endcall %}
|
|
10
|
+
|
|
11
|
+
{% call block.definition() %}
|
|
12
|
+
// PIPELINE EXECUTION
|
|
13
|
+
const { spawn } = await import('child_process');
|
|
14
|
+
|
|
15
|
+
const pipelineBinary = '{{ context.transform.binaryName }}';
|
|
16
|
+
{% if context.transform.args %}
|
|
17
|
+
const pipelineArgs = {{ context.transform.args | safe }};
|
|
18
|
+
{% else %}
|
|
19
|
+
const pipelineArgs = [];
|
|
20
|
+
{% endif %}
|
|
21
|
+
|
|
22
|
+
{% if context.transform.input %}
|
|
23
|
+
const pipelineInput = {{ context.transform.input | safe }};
|
|
24
|
+
{% else %}
|
|
25
|
+
const pipelineInput = null;
|
|
26
|
+
{% endif %}
|
|
27
|
+
|
|
28
|
+
const pipelineFormat = '{{ context.transform.format }}';
|
|
29
|
+
|
|
30
|
+
{% if context.transform.env %}
|
|
31
|
+
const pipelineEnv = {{ context.transform.env | safe }};
|
|
32
|
+
{% else %}
|
|
33
|
+
const pipelineEnv = {};
|
|
34
|
+
{% endif %}
|
|
35
|
+
|
|
36
|
+
{% if context.transform.cwd %}
|
|
37
|
+
const pipelineCwd = {{ context.transform.cwd | safe }};
|
|
38
|
+
{% else %}
|
|
39
|
+
const pipelineCwd = undefined;
|
|
40
|
+
{% endif %}
|
|
41
|
+
|
|
42
|
+
const result = await new Promise((pipelineResolve, pipelineReject) => {
|
|
43
|
+
const spawnOptions = {
|
|
44
|
+
env: { ...process.env, ...pipelineEnv },
|
|
45
|
+
stdio: ['pipe', 'pipe', 'pipe'] // stdin, stdout, stderr as pipes (don't inherit parent)
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
if (pipelineCwd) {
|
|
49
|
+
spawnOptions.cwd = pipelineCwd;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const proc = spawn(pipelineBinary, pipelineArgs, spawnOptions);
|
|
53
|
+
|
|
54
|
+
let stdout = '';
|
|
55
|
+
let stderr = '';
|
|
56
|
+
|
|
57
|
+
proc.stdout.on('data', (data) => {
|
|
58
|
+
stdout += data.toString();
|
|
59
|
+
});
|
|
2
60
|
|
|
3
|
-
|
|
61
|
+
proc.stderr.on('data', (data) => {
|
|
62
|
+
stderr += data.toString();
|
|
63
|
+
});
|
|
4
64
|
|
|
5
|
-
|
|
65
|
+
proc.on('error', (error) => {
|
|
66
|
+
pipelineReject(new Error(`Failed to execute pipeline '${pipelineBinary}': ${error.message}`));
|
|
67
|
+
});
|
|
6
68
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
this.run= function (){
|
|
12
|
-
|
|
13
|
-
{% include "src/default/macros/block-entry-args.js.njk" %}
|
|
14
|
-
|
|
15
|
-
return new Promise(async (resolve,reject)=>{
|
|
16
|
-
|
|
17
|
-
try{
|
|
18
|
-
{% include "src/default/macros/block-run-header.js.njk" %}
|
|
19
|
-
|
|
20
|
-
{% include "src/default/macros/page.js.njk" %}
|
|
21
|
-
|
|
22
|
-
{% include "src/default/macros/block-modules.js.njk" %}
|
|
23
|
-
|
|
24
|
-
// PIPELINE EXECUTION
|
|
25
|
-
const { spawn } = await import('child_process');
|
|
26
|
-
|
|
27
|
-
const pipelineBinary = '{{ context.binaryName }}';
|
|
28
|
-
{% if context.transform.args %}
|
|
29
|
-
const pipelineArgs = {{ context.transform.args | safe }};
|
|
30
|
-
{% else %}
|
|
31
|
-
const pipelineArgs = [];
|
|
32
|
-
{% endif %}
|
|
33
|
-
|
|
34
|
-
{% if context.transform.input %}
|
|
35
|
-
const pipelineInput = {{ context.transform.input | safe }};
|
|
36
|
-
{% else %}
|
|
37
|
-
const pipelineInput = null;
|
|
38
|
-
{% endif %}
|
|
39
|
-
|
|
40
|
-
const pipelineFormat = '{{ context.format }}';
|
|
41
|
-
|
|
42
|
-
{% if context.transform.env %}
|
|
43
|
-
const pipelineEnv = {{ context.transform.env | safe }};
|
|
44
|
-
{% else %}
|
|
45
|
-
const pipelineEnv = {};
|
|
46
|
-
{% endif %}
|
|
47
|
-
|
|
48
|
-
{% if context.transform.cwd %}
|
|
49
|
-
const pipelineCwd = {{ context.transform.cwd | safe }};
|
|
50
|
-
{% else %}
|
|
51
|
-
const pipelineCwd = undefined;
|
|
52
|
-
{% endif %}
|
|
53
|
-
|
|
54
|
-
const result = await new Promise((pipelineResolve, pipelineReject) => {
|
|
55
|
-
const spawnOptions = {
|
|
56
|
-
env: { ...process.env, ...pipelineEnv },
|
|
57
|
-
stdio: ['pipe', 'pipe', 'pipe'] // stdin, stdout, stderr as pipes (don't inherit parent)
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
if (pipelineCwd) {
|
|
61
|
-
spawnOptions.cwd = pipelineCwd;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const proc = spawn(pipelineBinary, pipelineArgs, spawnOptions);
|
|
65
|
-
|
|
66
|
-
let stdout = '';
|
|
67
|
-
let stderr = '';
|
|
68
|
-
|
|
69
|
-
proc.stdout.on('data', (data) => {
|
|
70
|
-
stdout += data.toString();
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
proc.stderr.on('data', (data) => {
|
|
74
|
-
stderr += data.toString();
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
proc.on('error', (error) => {
|
|
78
|
-
pipelineReject(new Error(`Failed to execute pipeline '${pipelineBinary}': ${error.message}`));
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
proc.on('close', (code) => {
|
|
82
|
-
if (code !== 0) {
|
|
83
|
-
pipelineReject(new Error(`Pipeline '${pipelineBinary}' exited with code ${code}: ${stderr}`));
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Parse output based on format
|
|
88
|
-
if (pipelineFormat === 'text') {
|
|
89
|
-
// Text format: return as-is
|
|
90
|
-
pipelineResolve(stdout.trim());
|
|
91
|
-
} else {
|
|
92
|
-
// JSON format (default): parse
|
|
93
|
-
try {
|
|
94
|
-
const result = JSON.parse(stdout.trim());
|
|
95
|
-
pipelineResolve(result);
|
|
96
|
-
} catch (error) {
|
|
97
|
-
pipelineReject(new Error(`Failed to parse pipeline output as JSON: ${error.message}`));
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
// Write input based on type (auto-detect)
|
|
103
|
-
if (pipelineInput !== null && pipelineInput !== undefined) {
|
|
104
|
-
if (typeof pipelineInput === 'object') {
|
|
105
|
-
// Object/Array → JSON
|
|
106
|
-
proc.stdin.write(JSON.stringify(pipelineInput) + '\n');
|
|
107
|
-
} else if (typeof pipelineInput === 'string') {
|
|
108
|
-
// String → as-is (text)
|
|
109
|
-
proc.stdin.write(pipelineInput + '\n');
|
|
110
|
-
} else {
|
|
111
|
-
// Other types → JSON
|
|
112
|
-
proc.stdin.write(JSON.stringify(pipelineInput) + '\n');
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
proc.stdin.end();
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
{% if context.transform.result %}
|
|
119
|
-
flow.set('{{ context.transform.result }}', result);
|
|
120
|
-
{% endif %}
|
|
121
|
-
|
|
122
|
-
{% include "src/default/macros/block-assign.js.njk" %}
|
|
123
|
-
|
|
124
|
-
{% include "src/default/macros/block-signal.js.njk" %}
|
|
125
|
-
|
|
126
|
-
{% if context.transform.return %}
|
|
127
|
-
resolve({type:'return',value: {{context.transform.return | safe}}});
|
|
128
|
-
{% elseif context.next %}
|
|
129
|
-
{% include "src/default/macros/block-next.js.njk" %}
|
|
130
|
-
{% else %}
|
|
131
|
-
resolve();
|
|
132
|
-
{% endif %}
|
|
133
|
-
|
|
134
|
-
{% include "src/default/macros/block-run-footer.js.njk" %}
|
|
69
|
+
proc.on('close', (code) => {
|
|
70
|
+
if (code !== 0) {
|
|
71
|
+
pipelineReject(new Error(`Pipeline '${pipelineBinary}' exited with code ${code}: ${stderr}`));
|
|
72
|
+
return;
|
|
135
73
|
}
|
|
136
|
-
|
|
137
|
-
|
|
74
|
+
|
|
75
|
+
// Parse output based on format
|
|
76
|
+
if (pipelineFormat === 'text') {
|
|
77
|
+
// Text format: return as-is
|
|
78
|
+
pipelineResolve(stdout.trim());
|
|
79
|
+
} else {
|
|
80
|
+
// JSON format (default): parse
|
|
81
|
+
try {
|
|
82
|
+
const result = JSON.parse(stdout.trim());
|
|
83
|
+
pipelineResolve(result);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
pipelineReject(new Error(`Failed to parse pipeline output as JSON: ${error.message}`));
|
|
86
|
+
}
|
|
138
87
|
}
|
|
139
88
|
});
|
|
140
|
-
}
|
|
141
89
|
|
|
142
|
-
|
|
143
|
-
|
|
90
|
+
// Write input based on type (auto-detect)
|
|
91
|
+
if (pipelineInput !== null && pipelineInput !== undefined) {
|
|
92
|
+
if (typeof pipelineInput === 'object') {
|
|
93
|
+
// Object/Array → JSON
|
|
94
|
+
proc.stdin.write(JSON.stringify(pipelineInput) + '\n');
|
|
95
|
+
} else if (typeof pipelineInput === 'string') {
|
|
96
|
+
// String → as-is (text)
|
|
97
|
+
proc.stdin.write(pipelineInput + '\n');
|
|
98
|
+
} else {
|
|
99
|
+
// Other types → JSON
|
|
100
|
+
proc.stdin.write(JSON.stringify(pipelineInput) + '\n');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
proc.stdin.end();
|
|
104
|
+
});
|
|
144
105
|
|
|
145
|
-
{%
|
|
106
|
+
{% endcall %}
|
|
146
107
|
|
|
108
|
+
{% call block.footer()%}
|
|
109
|
+
{% endcall %}
|