@fnet/cli 0.4.25 → 0.5.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/dist/fbin/index.js +15 -0
- package/dist/fnet/index.0jcm9pn5.js +1 -0
- package/dist/fnet/index.2084z2ed.js +2 -0
- package/dist/fnet/index.33f1ggpr.js +1 -0
- package/dist/fnet/index.3exge2js.js +1 -0
- package/dist/fnet/index.3kfx538h.js +1 -0
- package/dist/fnet/index.490y87nc.js +1 -0
- package/dist/fnet/index.4g9yezkq.js +1 -0
- package/dist/fnet/index.4jkat7r4.js +1 -0
- package/dist/fnet/index.7crx8ky1.js +1 -0
- package/dist/fnet/index.7vw06nrn.js +1 -0
- package/dist/fnet/index.9567fa9x.js +1 -0
- package/dist/fnet/index.gh75wt1m.js +1 -0
- package/dist/fnet/index.hzsfswvp.js +1 -0
- package/dist/fnet/index.jgpc3grc.js +1 -0
- package/dist/fnet/index.js +20 -0
- package/dist/fnet/index.p0zb7e1b.js +1 -0
- package/dist/fnet/index.r19p3bpa.js +2 -0
- package/dist/fnet/index.r82rtnmz.js +1 -0
- package/dist/fnet/index.s662t98v.js +1 -0
- package/dist/fnet/index.w74dpnpn.js +1 -0
- package/dist/fnet/index.xeaw5xa9.js +1 -0
- package/dist/fnet/index.zm4kesg6.js +1 -0
- package/dist/fnode/index.05n3mvs9.js +2 -0
- package/dist/fnode/index.2hc9tbyx.js +1 -0
- package/dist/fnode/index.2pnjg6dc.js +1 -0
- package/dist/fnode/index.9qgtmxq3.js +2 -0
- package/dist/fnode/index.b1q7y05p.js +1 -0
- package/dist/fnode/index.bhapgrs7.js +1 -0
- package/dist/fnode/index.cvxrf34y.js +2 -0
- package/dist/fnode/index.dp9wyahp.js +1 -0
- package/dist/fnode/index.eqxmcpdc.js +1 -0
- package/dist/fnode/index.f2tb0x3t.js +1 -0
- package/dist/fnode/index.fbzv6wwf.js +1 -0
- package/dist/fnode/index.gazd9raq.js +1 -0
- package/dist/fnode/index.hv4s25f0.js +3 -0
- package/dist/fnode/index.j5z7dtsx.js +1 -0
- package/dist/fnode/index.js +10 -0
- package/dist/fnode/index.kb4e4bxf.js +1 -0
- package/dist/fnode/index.qn0schqp.js +1 -0
- package/dist/fnode/index.rht29phd.js +1 -0
- package/dist/fnode/index.rzsfmek6.js +3 -0
- package/dist/fnode/index.s0nk6cv8.js +4 -0
- package/dist/fnode/index.s66v6wt4.js +1 -0
- package/dist/fnode/index.sv7v0y60.js +1 -0
- package/dist/fnode/index.tgkhgnrp.js +1 -0
- package/dist/fnode/index.vq706f75.js +1 -0
- package/dist/fnode/index.y8pvdcny.js +1 -0
- package/dist/fnode/index.z4vz93ww.js +1 -0
- package/dist/frun/index.js +2 -0
- package/dist/fservice/index.js +19 -0
- package/dist/fservice/index.q01yvaz0.js +2 -0
- package/package.json +74 -57
- package/readme.md +298 -0
- package/template/fnet/core/assert.js +6 -0
- package/template/fnet/core/message.js +3 -0
- package/template/fnet/core/object.js +47 -0
- package/template/fnet/core/sleep.js +5 -0
- package/template/fnet/node/.gitignore.njk +9 -0
- package/template/fnet/node/build.js.njk +153 -0
- package/template/fnet/node/package.json.njk +121 -0
- package/template/fnet/node/readme.md.njk +21 -0
- package/template/fnet/node/rollup.config.mjs.njk +498 -0
- package/template/fnet/node/src/app/index.html.njk +67 -0
- package/template/fnet/node/src/app/index.js.njk +36 -0
- package/template/fnet/node/src/cli/index.js.njk +9 -0
- package/template/fnet/node/src/cli/index.js.v1.njk +318 -0
- package/template/fnet/node/src/cli/v2/core/args-parser.njk +10 -0
- package/template/fnet/node/src/cli/v2/core/imports.njk +31 -0
- package/template/fnet/node/src/cli/v2/core/run-wrapper.njk +25 -0
- package/template/fnet/node/src/cli/v2/index.js.njk +184 -0
- package/template/fnet/node/src/cli/v2/modes/default/extend.njk +11 -0
- package/template/fnet/node/src/cli/v2/modes/default/standard.njk +20 -0
- package/template/fnet/node/src/cli/v2/modes/http/builtin.njk +66 -0
- package/template/fnet/node/src/cli/v2/modes/http/imports.njk +9 -0
- package/template/fnet/node/src/cli/v2/modes/http/index.njk +12 -0
- package/template/fnet/node/src/cli/v2/modes/mcp/imports.njk +33 -0
- package/template/fnet/node/src/cli/v2/modes/mcp/index.njk +30 -0
- package/template/fnet/node/src/cli/v2/modes/mcp/server-setup.njk +15 -0
- package/template/fnet/node/src/cli/v2/modes/mcp/tool-handlers.njk +46 -0
- package/template/fnet/node/src/cli/v2/modes/mcp/transport-http.njk +222 -0
- package/template/fnet/node/src/cli/v2/modes/mcp/transport-stdio.njk +9 -0
- package/template/fnet/node/src/cli/v2/modes/pipeline/imports.njk +9 -0
- package/template/fnet/node/src/cli/v2/modes/pipeline/index.njk +113 -0
- package/template/fnet/node/src/cli/v2/modes/webhook/imports.njk +9 -0
- package/template/fnet/node/src/cli/v2/modes/webhook/index.njk +127 -0
- package/template/fnet/node/src/cli/v2/modes/websocket/imports.njk +15 -0
- package/template/fnet/node/src/cli/v2/modes/websocket/index.njk +104 -0
- package/template/fnet/node/src/default/blocks/assign.js.njk +15 -0
- package/template/fnet/node/src/default/blocks/call.js.njk +110 -0
- package/template/fnet/node/src/default/blocks/for.js.njk +71 -0
- package/template/fnet/node/src/default/blocks/form.js.njk +31 -0
- package/template/fnet/node/src/default/blocks/http.js.njk +135 -0
- package/template/fnet/node/src/default/blocks/modules.js.njk +15 -0
- package/template/fnet/node/src/default/blocks/new.js.njk +42 -0
- package/template/fnet/node/src/default/blocks/next.js.njk +15 -0
- package/template/fnet/node/src/default/blocks/output.js.njk +15 -0
- package/template/fnet/node/src/default/blocks/parallel.js.njk +64 -0
- package/template/fnet/node/src/default/blocks/pipeline.js.njk +109 -0
- package/template/fnet/node/src/default/blocks/raise.js.njk +15 -0
- package/template/fnet/node/src/default/blocks/retry.js.njk +70 -0
- package/template/fnet/node/src/default/blocks/return.js.njk +21 -0
- package/template/fnet/node/src/default/blocks/schedule.js.njk +66 -0
- package/template/fnet/node/src/default/blocks/signal.js.njk +15 -0
- package/template/fnet/node/src/default/blocks/steps.js.njk +47 -0
- package/template/fnet/node/src/default/blocks/switch.js.njk +49 -0
- package/template/fnet/node/src/default/blocks/tryexcept.js.njk +80 -0
- package/template/fnet/node/src/default/blocks/wait.js.njk +14 -0
- package/template/fnet/node/src/default/engine.js.njk +79 -0
- package/template/fnet/node/src/default/input.args.js.njk +125 -0
- package/template/fnet/node/src/default/macros/block-assign.js.njk +3 -0
- package/template/fnet/node/src/default/macros/block-body-header.js.njk +7 -0
- package/template/fnet/node/src/default/macros/block-entry-args.js.njk +2 -0
- package/template/fnet/node/src/default/macros/block-footer.js.njk +3 -0
- package/template/fnet/node/src/default/macros/block-header.js.njk +11 -0
- package/template/fnet/node/src/default/macros/block-library-header.js.njk +43 -0
- package/template/fnet/node/src/default/macros/block-modules-header.js.njk +8 -0
- package/template/fnet/node/src/default/macros/block-modules.js.njk +29 -0
- package/template/fnet/node/src/default/macros/block-next-header.js.njk +6 -0
- package/template/fnet/node/src/default/macros/block-next.js.njk +21 -0
- package/template/fnet/node/src/default/macros/block-run-footer.js.njk +7 -0
- package/template/fnet/node/src/default/macros/block-run-form.js.njk +32 -0
- package/template/fnet/node/src/default/macros/block-run-header.js.njk +43 -0
- package/template/fnet/node/src/default/macros/block-signal.js.njk +3 -0
- package/template/fnet/node/src/default/macros/page.js.njk +8 -0
- package/template/fnet/node/src/default/types/block.js.njk +133 -0
- package/template/fnet/node/src/default/workflow.js.njk +125 -0
- package/template/fnet/node/tsconfig.json.njk +16 -0
- package/template/fnet/project/.gitignore.njk +7 -0
- package/template/fnet/project/.vscode/launch.json.njk +41 -0
- package/template/fnet/project/.vscode/tasks.json.njk +46 -0
- package/template/fnet/project/fnet/flows.yaml.njk +4 -0
- package/template/fnet/project/fnet/targets.yaml.njk +7 -0
- package/template/fnet/project/fnet.yaml.njk +3 -0
- package/template/fnode/node/.gitignore.njk +9 -0
- package/template/fnode/node/build.js.njk +149 -0
- package/template/fnode/node/package.json.njk +121 -0
- package/template/fnode/node/readme.md.njk +21 -0
- package/template/fnode/node/rollup.config.mjs.njk +498 -0
- package/template/fnode/node/src/app/index-js-with-react-host.njk +50 -0
- package/template/fnode/node/src/app/index-js-without-react-host.njk +23 -0
- package/template/fnode/node/src/app/index.html.njk +67 -0
- package/template/fnode/node/src/app/index.js.njk +9 -0
- package/template/fnode/node/src/cli/index.js.njk +9 -0
- package/template/fnode/node/src/cli/index.js.v1.njk +464 -0
- package/template/fnode/node/src/cli/v2/core/args-parser.njk +10 -0
- package/template/fnode/node/src/cli/v2/core/imports.njk +29 -0
- package/template/fnode/node/src/cli/v2/core/run-wrapper.njk +25 -0
- package/template/fnode/node/src/cli/v2/index.js.njk +184 -0
- package/template/fnode/node/src/cli/v2/modes/default/extend.njk +11 -0
- package/template/fnode/node/src/cli/v2/modes/default/standard.njk +19 -0
- package/template/fnode/node/src/cli/v2/modes/http/builtin.njk +61 -0
- package/template/fnode/node/src/cli/v2/modes/http/imports.njk +9 -0
- package/template/fnode/node/src/cli/v2/modes/http/index.njk +12 -0
- package/template/fnode/node/src/cli/v2/modes/mcp/imports.njk +33 -0
- package/template/fnode/node/src/cli/v2/modes/mcp/index.njk +30 -0
- package/template/fnode/node/src/cli/v2/modes/mcp/server-setup.njk +15 -0
- package/template/fnode/node/src/cli/v2/modes/mcp/tool-handlers.njk +41 -0
- package/template/fnode/node/src/cli/v2/modes/mcp/transport-http.njk +212 -0
- package/template/fnode/node/src/cli/v2/modes/mcp/transport-stdio.njk +9 -0
- package/template/fnode/node/src/cli/v2/modes/pipeline/imports.njk +9 -0
- package/template/fnode/node/src/cli/v2/modes/pipeline/index.njk +103 -0
- package/template/fnode/node/src/cli/v2/modes/webhook/imports.njk +9 -0
- package/template/fnode/node/src/cli/v2/modes/webhook/index.njk +122 -0
- package/template/fnode/node/src/cli/v2/modes/websocket/imports.njk +15 -0
- package/template/fnode/node/src/cli/v2/modes/websocket/index.njk +99 -0
- package/template/fnode/node/src/default/engine.js.njk +17 -0
- package/template/fnode/node/src/default/input.args.js.njk +126 -0
- package/template/fnode/node/tsconfig.json.njk +16 -0
- package/template/fnode/project/.gitignore.njk +11 -0
- package/template/fnode/project/.vscode/launch.json.njk +78 -0
- package/template/fnode/project/.vscode/tasks.json.njk +46 -0
- package/template/fnode/project/fnet/targets.yaml.njk +25 -0
- package/template/fnode/project/fnode.yaml.njk +12 -0
- package/template/fnode/python/.gitignore.njk +7 -0
- package/template/fnode/python/package.json.njk +4 -0
- package/template/fnode/python/pyproject.toml.njk +3 -0
- package/template/fnode/python/readme.md.njk +12 -0
- package/template/fnode/python/setup.py.njk +19 -0
- package/template/fnode/python/src/cli/index.py.njk +25 -0
- package/template/schemas/to-npm.yaml +14 -0
- package/dist/builder/lib-cli.js +0 -2
- package/dist/builder/wf-cli.js +0 -2
- package/dist/index.js +0 -2
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
{# ============================================================================
|
|
2
|
+
PIPELINE MODE - MAIN
|
|
3
|
+
============================================================================
|
|
4
|
+
Unix pipeline integration via stdin/stdout
|
|
5
|
+
Supports line-by-line processing and full input mode
|
|
6
|
+
============================================================================ #}
|
|
7
|
+
|
|
8
|
+
if (cliMode === 'pipeline') {
|
|
9
|
+
// Pipeline mode code
|
|
10
|
+
const pipelineMode = args['pipeline-mode'] || args.pipeline_mode || 'lines';
|
|
11
|
+
const pipelineFormat = args['pipeline-format'] || args.pipeline_format || 'json';
|
|
12
|
+
|
|
13
|
+
if (pipelineMode === 'lines') {
|
|
14
|
+
// Line-by-line processing (default)
|
|
15
|
+
{% if atom.doc.features.project.format==='esm' %}
|
|
16
|
+
const readline = await import('readline');
|
|
17
|
+
{% elif atom.doc.features.project.format==='cjs' %}
|
|
18
|
+
const readline = require('readline');
|
|
19
|
+
{% endif %}
|
|
20
|
+
const rl = readline.createInterface({
|
|
21
|
+
input: process.stdin,
|
|
22
|
+
output: process.stdout,
|
|
23
|
+
terminal: false
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
rl.on('line', async (line) => {
|
|
27
|
+
try {
|
|
28
|
+
// Parse input based on format
|
|
29
|
+
let input;
|
|
30
|
+
if (pipelineFormat === 'json') {
|
|
31
|
+
input = JSON.parse(line);
|
|
32
|
+
} else {
|
|
33
|
+
input = { data: line };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Validate input
|
|
37
|
+
// TODO: Add schema validation if needed
|
|
38
|
+
|
|
39
|
+
// Process with Core
|
|
40
|
+
const result = await Node(input);
|
|
41
|
+
|
|
42
|
+
// Output result
|
|
43
|
+
if (pipelineFormat === 'json') {
|
|
44
|
+
console.log(JSON.stringify(result));
|
|
45
|
+
} else {
|
|
46
|
+
console.log(result);
|
|
47
|
+
}
|
|
48
|
+
} catch (error) {
|
|
49
|
+
console.error(`Error processing line: ${error.message}`);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
rl.on('close', () => {
|
|
54
|
+
process.exit(0);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
} else if (pipelineMode === 'full') {
|
|
58
|
+
// Full input processing
|
|
59
|
+
let inputData = '';
|
|
60
|
+
|
|
61
|
+
process.stdin.on('data', (chunk) => {
|
|
62
|
+
inputData += chunk;
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
process.stdin.on('end', async () => {
|
|
66
|
+
try {
|
|
67
|
+
// Parse input based on format
|
|
68
|
+
let input;
|
|
69
|
+
if (pipelineFormat === 'json') {
|
|
70
|
+
input = JSON.parse(inputData);
|
|
71
|
+
} else {
|
|
72
|
+
input = { data: inputData };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Validate input
|
|
76
|
+
// TODO: Add schema validation if needed
|
|
77
|
+
|
|
78
|
+
// Process with Core
|
|
79
|
+
const result = await Node(input);
|
|
80
|
+
|
|
81
|
+
// Output result
|
|
82
|
+
if (pipelineFormat === 'json') {
|
|
83
|
+
console.log(JSON.stringify(result, null, 2));
|
|
84
|
+
} else {
|
|
85
|
+
console.log(result);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
process.exit(0);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
console.error(`Error processing input: ${error.message}`);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
} else {
|
|
96
|
+
console.error(`Unknown pipeline mode: ${pipelineMode}`);
|
|
97
|
+
console.error(`Supported modes: lines, full`);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{# ============================================================================
|
|
2
|
+
WEBHOOK MODE - IMPORTS
|
|
3
|
+
============================================================================
|
|
4
|
+
No mode-specific imports needed
|
|
5
|
+
http and crypto modules are imported in shared imports section
|
|
6
|
+
============================================================================ #}
|
|
7
|
+
|
|
8
|
+
{# http and crypto modules imported in shared section #}
|
|
9
|
+
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
{# ============================================================================
|
|
2
|
+
WEBHOOK MODE - IMPLEMENTATION
|
|
3
|
+
============================================================================
|
|
4
|
+
Event-driven HTTP webhook server with HMAC signature verification
|
|
5
|
+
============================================================================ #}
|
|
6
|
+
|
|
7
|
+
if (cliMode === 'webhook') {
|
|
8
|
+
const port = args['cli-port'] || args.cli_port || 3000;
|
|
9
|
+
const webhookPath = args['webhook-path'] || args.webhook_path || '/webhook';
|
|
10
|
+
const webhookSecret = args['webhook-secret'] || args.webhook_secret || process.env.WEBHOOK_SECRET;
|
|
11
|
+
const signatureHeader = args['webhook-signature-header'] || args.webhook_signature_header || 'x-hub-signature-256';
|
|
12
|
+
|
|
13
|
+
const server = http.createServer(async (req, res) => {
|
|
14
|
+
// CORS headers
|
|
15
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
16
|
+
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
|
|
17
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, ' + signatureHeader);
|
|
18
|
+
|
|
19
|
+
// Handle OPTIONS preflight
|
|
20
|
+
if (req.method === 'OPTIONS') {
|
|
21
|
+
res.writeHead(200);
|
|
22
|
+
res.end();
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Only accept POST requests
|
|
27
|
+
if (req.method !== 'POST') {
|
|
28
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
29
|
+
res.end(JSON.stringify({ error: 'Method not allowed. Use POST.' }));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Only accept webhook path
|
|
34
|
+
if (req.url !== webhookPath) {
|
|
35
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
36
|
+
res.end(JSON.stringify({ error: 'Not found. Use ' + webhookPath }));
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Read request body
|
|
41
|
+
let body = '';
|
|
42
|
+
req.on('data', chunk => {
|
|
43
|
+
body += chunk.toString();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
req.on('end', async () => {
|
|
47
|
+
try {
|
|
48
|
+
// Verify signature if secret is provided
|
|
49
|
+
if (webhookSecret) {
|
|
50
|
+
const signature = req.headers[signatureHeader.toLowerCase()];
|
|
51
|
+
|
|
52
|
+
if (!signature) {
|
|
53
|
+
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
54
|
+
res.end(JSON.stringify({ error: 'Missing signature header: ' + signatureHeader }));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Calculate expected signature (HMAC-SHA256)
|
|
59
|
+
const hmac = crypto.createHmac('sha256', webhookSecret);
|
|
60
|
+
hmac.update(body);
|
|
61
|
+
const expectedSignature = 'sha256=' + hmac.digest('hex');
|
|
62
|
+
|
|
63
|
+
// Compare signatures (timing-safe)
|
|
64
|
+
const signatureBuffer = Buffer.from(signature);
|
|
65
|
+
const expectedBuffer = Buffer.from(expectedSignature);
|
|
66
|
+
|
|
67
|
+
if (signatureBuffer.length !== expectedBuffer.length ||
|
|
68
|
+
!crypto.timingSafeEqual(signatureBuffer, expectedBuffer)) {
|
|
69
|
+
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
70
|
+
res.end(JSON.stringify({ error: 'Invalid signature' }));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Parse JSON payload
|
|
76
|
+
let payload;
|
|
77
|
+
try {
|
|
78
|
+
payload = JSON.parse(body);
|
|
79
|
+
} catch (e) {
|
|
80
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
81
|
+
res.end(JSON.stringify({ error: 'Invalid JSON payload' }));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Process webhook with Core
|
|
86
|
+
const result = await Node(payload);
|
|
87
|
+
|
|
88
|
+
// Send response
|
|
89
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
90
|
+
res.end(JSON.stringify(result));
|
|
91
|
+
|
|
92
|
+
} catch (error) {
|
|
93
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
94
|
+
res.end(JSON.stringify({
|
|
95
|
+
error: error.message,
|
|
96
|
+
type: 'processing_error'
|
|
97
|
+
}));
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
req.on('error', (error) => {
|
|
102
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
103
|
+
res.end(JSON.stringify({
|
|
104
|
+
error: error.message,
|
|
105
|
+
type: 'request_error'
|
|
106
|
+
}));
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
server.listen(port, () => {
|
|
111
|
+
console.log(`Webhook server started on port ${port}`);
|
|
112
|
+
console.log(`Webhook endpoint: ${webhookPath}`);
|
|
113
|
+
if (webhookSecret) {
|
|
114
|
+
console.log(`Signature verification: enabled (header: ${signatureHeader})`);
|
|
115
|
+
} else {
|
|
116
|
+
console.log(`Signature verification: disabled (no secret provided)`);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{# ============================================================================
|
|
2
|
+
WEBSOCKET MODE - IMPORTS
|
|
3
|
+
============================================================================
|
|
4
|
+
WebSocket server dependencies using 'ws' library
|
|
5
|
+
Supports both ESM and CJS formats
|
|
6
|
+
============================================================================ #}
|
|
7
|
+
|
|
8
|
+
{% if atom.doc.features.project.format==='esm' %}
|
|
9
|
+
// Using ws library for WebSocket mode
|
|
10
|
+
import { WebSocketServer } from 'ws';
|
|
11
|
+
{% elif atom.doc.features.project.format==='cjs' %}
|
|
12
|
+
// Using ws library for WebSocket mode
|
|
13
|
+
const { WebSocketServer } = require('ws');
|
|
14
|
+
{% endif %}
|
|
15
|
+
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
{# ============================================================================
|
|
2
|
+
WEBSOCKET MODE - MAIN
|
|
3
|
+
============================================================================
|
|
4
|
+
WebSocket server for real-time bidirectional communication
|
|
5
|
+
Supports connection handling, message processing, and heartbeat
|
|
6
|
+
============================================================================ #}
|
|
7
|
+
|
|
8
|
+
if (cliMode === 'websocket') {
|
|
9
|
+
// WebSocket mode code
|
|
10
|
+
const port = args['cli-port'] || args.cli_port || 3000;
|
|
11
|
+
const heartbeat = args['ws-heartbeat'] || args.ws_heartbeat || 30000; // 30 seconds default
|
|
12
|
+
|
|
13
|
+
const wss = new WebSocketServer({ port });
|
|
14
|
+
|
|
15
|
+
// Store active connections
|
|
16
|
+
const clients = new Set();
|
|
17
|
+
|
|
18
|
+
wss.on('connection', (ws) => {
|
|
19
|
+
console.log('WebSocket client connected');
|
|
20
|
+
clients.add(ws);
|
|
21
|
+
|
|
22
|
+
// Set up heartbeat
|
|
23
|
+
ws.isAlive = true;
|
|
24
|
+
ws.on('pong', () => {
|
|
25
|
+
ws.isAlive = true;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Handle incoming messages
|
|
29
|
+
ws.on('message', async (data) => {
|
|
30
|
+
try {
|
|
31
|
+
// Parse message
|
|
32
|
+
const message = data.toString();
|
|
33
|
+
let input;
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
input = JSON.parse(message);
|
|
37
|
+
} catch (e) {
|
|
38
|
+
// If not JSON, wrap in object
|
|
39
|
+
input = { data: message };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Validate input
|
|
43
|
+
// TODO: Add schema validation if needed
|
|
44
|
+
|
|
45
|
+
// Process with Core
|
|
46
|
+
const result = await Node(input);
|
|
47
|
+
|
|
48
|
+
// Send response back to client
|
|
49
|
+
ws.send(JSON.stringify(result));
|
|
50
|
+
|
|
51
|
+
} catch (error) {
|
|
52
|
+
// Send error to client
|
|
53
|
+
ws.send(JSON.stringify({
|
|
54
|
+
error: error.message,
|
|
55
|
+
type: 'processing_error'
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Handle client disconnect
|
|
61
|
+
ws.on('close', () => {
|
|
62
|
+
console.log('WebSocket client disconnected');
|
|
63
|
+
clients.delete(ws);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Handle errors
|
|
67
|
+
ws.on('error', (error) => {
|
|
68
|
+
console.error('WebSocket error:', error.message);
|
|
69
|
+
clients.delete(ws);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Heartbeat interval
|
|
74
|
+
if (heartbeat > 0) {
|
|
75
|
+
const interval = setInterval(() => {
|
|
76
|
+
wss.clients.forEach((ws) => {
|
|
77
|
+
if (ws.isAlive === false) {
|
|
78
|
+
console.log('Terminating inactive client');
|
|
79
|
+
return ws.terminate();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
ws.isAlive = false;
|
|
83
|
+
ws.ping();
|
|
84
|
+
});
|
|
85
|
+
}, heartbeat);
|
|
86
|
+
|
|
87
|
+
wss.on('close', () => {
|
|
88
|
+
clearInterval(interval);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
console.log(`WebSocket server started on port ${port}`);
|
|
93
|
+
if (heartbeat > 0) {
|
|
94
|
+
console.log(`Heartbeat interval: ${heartbeat}ms`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{% if atom.doc.features.project.format === 'esm' %}
|
|
2
|
+
{% if atom.relativePath %}
|
|
3
|
+
export * from "{{atom.relativePath}}";
|
|
4
|
+
export { default } from "{{atom.relativePath}}";
|
|
5
|
+
{% else %}
|
|
6
|
+
export * from "../libs/{{atom.id or atom.doc.name}}";
|
|
7
|
+
export { default } from "../libs/{{atom.id or atom.doc.name}}";
|
|
8
|
+
{% endif %}
|
|
9
|
+
{% elif atom.doc.features.project.format === 'cjs' %}
|
|
10
|
+
{% if atom.relativePath %}
|
|
11
|
+
const moduleExports = require("{{atom.relativePath}}");
|
|
12
|
+
module.exports = { ...moduleExports, default: moduleExports.default || moduleExports };
|
|
13
|
+
{% else %}
|
|
14
|
+
const moduleExports = require("../libs/{{atom.id or atom.doc.name}}");
|
|
15
|
+
module.exports = { ...moduleExports, default: moduleExports.default || moduleExports };
|
|
16
|
+
{% endif %}
|
|
17
|
+
{% endif %}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
{% if atom.doc.features.project.format === 'esm' %}
|
|
2
|
+
import fnetArgs,{argsParser} from '@fnet/args';
|
|
3
|
+
import validate,{schema as inputSchema} from "./validate_input";
|
|
4
|
+
|
|
5
|
+
{% elif atom.doc.features.project.format === 'cjs' %}
|
|
6
|
+
const {default:fnetArgs,argsParser} = require('@fnet/args');
|
|
7
|
+
const validate,{schema as inputSchema} = require("./validate_input");
|
|
8
|
+
{% endif %}
|
|
9
|
+
|
|
10
|
+
{% if atom.doc.features.cli.fargs and atom.doc.features.cli.fargs?.enabled !== false %}
|
|
11
|
+
|
|
12
|
+
const get_fargs = (argv) => {
|
|
13
|
+
const fargsIndex = argv.indexOf('--fargs');
|
|
14
|
+
if (fargsIndex !== -1 && argv[fargsIndex + 1]) return argv[fargsIndex + 1];
|
|
15
|
+
{% if atom.doc.features.cli.fargs.default %}
|
|
16
|
+
else return "{{atom.doc.features.cli.fargs.default}}";
|
|
17
|
+
{% endif %}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const get_ftags = (argv) => {
|
|
21
|
+
const ftags = [];
|
|
22
|
+
for (let i = 0; i < argv.length; i++) {
|
|
23
|
+
if (argv[i] === '--ftag' && argv[i + 1]) {
|
|
24
|
+
ftags.push(argv[i + 1]);
|
|
25
|
+
i++;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
{% if atom.doc.features.cli.fargs.tags %}
|
|
30
|
+
return ftags.length > 0 ? ftags : {{atom.doc.features.cli.fargs.tags | dump | safe}};
|
|
31
|
+
{% else %}
|
|
32
|
+
return ftags.length > 0 ? ftags : undefined;
|
|
33
|
+
{% endif %}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
{% endif %}
|
|
37
|
+
|
|
38
|
+
{% if atom.doc.features.project.format === 'esm' %}
|
|
39
|
+
|
|
40
|
+
export default async () => {
|
|
41
|
+
|
|
42
|
+
let schema = inputSchema;
|
|
43
|
+
let initial;
|
|
44
|
+
|
|
45
|
+
{% if atom.doc.features.cli.fargs and atom.doc.features.cli.fargs?.enabled !== false %}
|
|
46
|
+
const fargs = get_fargs(process.argv.slice(2));
|
|
47
|
+
const ftags = get_ftags(process.argv.slice(2));
|
|
48
|
+
|
|
49
|
+
if (fargs) {
|
|
50
|
+
const { default: fnetConfig } = await import("@fnet/config");
|
|
51
|
+
const config = await fnetConfig({ name: fargs, tags: ftags });
|
|
52
|
+
if (config?.data) {
|
|
53
|
+
initial=config.data;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
{% endif %}
|
|
57
|
+
|
|
58
|
+
const packageCallback = async () => {
|
|
59
|
+
const { default: url } = await import("node:url");
|
|
60
|
+
const { default: path } = await import("node:path");
|
|
61
|
+
const { default: fs } = await import("node:fs");
|
|
62
|
+
let currentDir = path.dirname(url.fileURLToPath(import.meta.url));
|
|
63
|
+
let firstPackageJson = path.join(currentDir, "package.json");
|
|
64
|
+
while (currentDir !== path.parse(currentDir).root && !fs.existsSync(firstPackageJson)) {
|
|
65
|
+
currentDir = path.dirname(currentDir);
|
|
66
|
+
firstPackageJson = path.join(currentDir, "package.json");
|
|
67
|
+
}
|
|
68
|
+
if (!fs.existsSync(firstPackageJson)) return {
|
|
69
|
+
name: "Unknown",
|
|
70
|
+
version: "Unknown"
|
|
71
|
+
}
|
|
72
|
+
else return await JSON.parse(fs.readFileSync(firstPackageJson, "utf8"));
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
return await fnetArgs({schema,initial,validate,packageCallback});
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export { argsParser };
|
|
79
|
+
|
|
80
|
+
{% elif atom.doc.features.project.format === 'cjs' %}
|
|
81
|
+
|
|
82
|
+
module.exports = async () => {
|
|
83
|
+
|
|
84
|
+
let schema = inputSchema;
|
|
85
|
+
let initial;
|
|
86
|
+
|
|
87
|
+
{% if atom.doc.features.cli.fargs and atom.doc.features.cli.fargs?.enabled !== false %}
|
|
88
|
+
const fargs = get_fargs(process.argv.slice(2));
|
|
89
|
+
const ftags = get_ftags(process.argv.slice(2));
|
|
90
|
+
|
|
91
|
+
if (fargs) {
|
|
92
|
+
const { default: fnetConfig } = await import("@fnet/config");
|
|
93
|
+
const config = await fnetConfig({ name: fargs, tags: ftags });
|
|
94
|
+
if (config?.data) {
|
|
95
|
+
initial=config.data;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
{% endif %}
|
|
99
|
+
|
|
100
|
+
const packageCallback = async () => {
|
|
101
|
+
const path = require("node:path");
|
|
102
|
+
const fs = require("node:fs");
|
|
103
|
+
|
|
104
|
+
let currentDir = __dirname;
|
|
105
|
+
let firstPackageJson = path.join(currentDir, "package.json");
|
|
106
|
+
|
|
107
|
+
while (currentDir !== path.parse(currentDir).root && !fs.existsSync(firstPackageJson)) {
|
|
108
|
+
currentDir = path.dirname(currentDir);
|
|
109
|
+
firstPackageJson = path.join(currentDir, "package.json");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (!fs.existsSync(firstPackageJson)) {
|
|
113
|
+
return {
|
|
114
|
+
name: "Unknown",
|
|
115
|
+
version: "Unknown"
|
|
116
|
+
};
|
|
117
|
+
} else {
|
|
118
|
+
return JSON.parse(fs.readFileSync(firstPackageJson, "utf8"));
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
return await fnetArgs({schema,initial,validate,packageCallback});
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
module.exports.argsParser = argsParser;
|
|
126
|
+
{% endif %}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"include": [
|
|
3
|
+
"src/**/*.js"
|
|
4
|
+
],
|
|
5
|
+
"compilerOptions": {
|
|
6
|
+
"outDir": "./types",
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"allowJs": true,
|
|
9
|
+
"emitDeclarationOnly": true,
|
|
10
|
+
"target": "es5",
|
|
11
|
+
"strict": true,
|
|
12
|
+
"forceConsistentCasingInFileNames": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"jsx": "react-jsx"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{% if runtime==='node' %}
|
|
2
|
+
{
|
|
3
|
+
// Use IntelliSense to learn about possible attributes.
|
|
4
|
+
// Hover to view descriptions of existing attributes.
|
|
5
|
+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
6
|
+
"version": "0.2.0",
|
|
7
|
+
"configurations": [
|
|
8
|
+
{
|
|
9
|
+
"name": "debug-fnode-cli",
|
|
10
|
+
"type": "node",
|
|
11
|
+
"request": "launch",
|
|
12
|
+
"skipFiles": [
|
|
13
|
+
"<node_internals>/**"
|
|
14
|
+
],
|
|
15
|
+
"program": "${workspaceFolder}/.workspace/dist/cli/esm/index.js",
|
|
16
|
+
"cwd": "${workspaceFolder}/.workspace",
|
|
17
|
+
"preLaunchTask": "fnode-watch",
|
|
18
|
+
"console": "integratedTerminal"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "debug-fnode-app",
|
|
22
|
+
"type": "chrome",
|
|
23
|
+
"request": "launch",
|
|
24
|
+
"url": "http://localhost:3000/dist/app/esm/",
|
|
25
|
+
"webRoot": "${workspaceFolder}/.workspace",
|
|
26
|
+
"preLaunchTask": "fnode-watch",
|
|
27
|
+
// "userDataDir": false,
|
|
28
|
+
// "runtimeArgs": [
|
|
29
|
+
// "--profile-directory=<profile-name>",
|
|
30
|
+
// ]
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
// "compounds": [
|
|
34
|
+
// {
|
|
35
|
+
// "name": "debug-fnode-all",
|
|
36
|
+
// "configurations": [
|
|
37
|
+
// "debug-fnode-cli",
|
|
38
|
+
// "debug-fnode-app"
|
|
39
|
+
// ]
|
|
40
|
+
// }
|
|
41
|
+
// ]
|
|
42
|
+
}
|
|
43
|
+
{% elif runtime==='python' %}
|
|
44
|
+
{
|
|
45
|
+
// Use IntelliSense to learn about possible attributes.
|
|
46
|
+
// Hover to view descriptions of existing attributes.
|
|
47
|
+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
48
|
+
"version": "0.2.0",
|
|
49
|
+
"configurations": [
|
|
50
|
+
{
|
|
51
|
+
"name": "debug-fnode-cli",
|
|
52
|
+
"type": "debugpy",
|
|
53
|
+
"request": "launch",
|
|
54
|
+
"program": "${workspaceFolder}/.workspace/src/cli/index.py",
|
|
55
|
+
"console": "integratedTerminal",
|
|
56
|
+
"cwd": "${workspaceFolder}/.workspace",
|
|
57
|
+
"env": {
|
|
58
|
+
"PYTHONPATH": "${workspaceFolder}/.workspace/src"
|
|
59
|
+
},
|
|
60
|
+
{% if platform ==='win32' %}
|
|
61
|
+
"python": "${workspaceFolder}/.workspace/.conda/python.exe",
|
|
62
|
+
{% else %}
|
|
63
|
+
"python":"${workspaceFolder}/.workspace/.conda/bin/python",
|
|
64
|
+
{% endif %}
|
|
65
|
+
"args": []
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
{% else %}
|
|
70
|
+
{
|
|
71
|
+
// Use IntelliSense to learn about possible attributes.
|
|
72
|
+
// Hover to view descriptions of existing attributes.
|
|
73
|
+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
74
|
+
"version": "0.2.0",
|
|
75
|
+
"configurations": [
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
{% endif %}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "2.0.0",
|
|
3
|
+
"tasks": [
|
|
4
|
+
{
|
|
5
|
+
"label": "fnode-build",
|
|
6
|
+
"type": "shell",
|
|
7
|
+
"command": "fnode build",
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"label": "fnode-watch",
|
|
11
|
+
"type": "shell",
|
|
12
|
+
"command": "fnode watch",
|
|
13
|
+
"isBackground": true
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"label": "fnode-deploy",
|
|
17
|
+
"type": "shell",
|
|
18
|
+
"command": "fnode deploy",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"label": "fnode-cli",
|
|
22
|
+
"type": "shell",
|
|
23
|
+
"command": "fnode cli",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"label": "fnode-app",
|
|
27
|
+
"type": "shell",
|
|
28
|
+
"command": "fnode app",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"label": "fnode-project-update",
|
|
32
|
+
"type": "shell",
|
|
33
|
+
"command": "fnode project -u",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"label": "fnode-npm-update",
|
|
37
|
+
"type": "shell",
|
|
38
|
+
"command": "fnode npm update",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"label": "fnode-npm-outdated",
|
|
42
|
+
"type": "shell",
|
|
43
|
+
"command": "fnode npm outdated",
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{% if runtime ==='node' %}
|
|
2
|
+
npm-default:
|
|
3
|
+
type: npm
|
|
4
|
+
enabled: false
|
|
5
|
+
version: "{{npm.version or "0.1.0"}}"
|
|
6
|
+
params:
|
|
7
|
+
# bin: some-bin-name
|
|
8
|
+
name: "{{npm.name or "@fnet/"+name}}"
|
|
9
|
+
{% elif runtime==='bun' %}
|
|
10
|
+
npm-default:
|
|
11
|
+
type: npm
|
|
12
|
+
enabled: false
|
|
13
|
+
version: "{{npm.version or "0.1.0"}}"
|
|
14
|
+
params:
|
|
15
|
+
# bin: some-bin-name
|
|
16
|
+
name: "{{npm.name or "@fnet/"+name}}"
|
|
17
|
+
{% elif runtime==='python' %}
|
|
18
|
+
pypi-default:
|
|
19
|
+
type: pypi
|
|
20
|
+
enabled: false
|
|
21
|
+
version: "{{pip.version or "0.1.0"}}"
|
|
22
|
+
params:
|
|
23
|
+
# bin: some-bin-name
|
|
24
|
+
name: "{{pip.name or "@fnet/"+name}}"
|
|
25
|
+
{% endif %}
|