@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.
Files changed (184) hide show
  1. package/dist/fbin/index.js +15 -0
  2. package/dist/fnet/index.0jcm9pn5.js +1 -0
  3. package/dist/fnet/index.2084z2ed.js +2 -0
  4. package/dist/fnet/index.33f1ggpr.js +1 -0
  5. package/dist/fnet/index.3exge2js.js +1 -0
  6. package/dist/fnet/index.3kfx538h.js +1 -0
  7. package/dist/fnet/index.490y87nc.js +1 -0
  8. package/dist/fnet/index.4g9yezkq.js +1 -0
  9. package/dist/fnet/index.4jkat7r4.js +1 -0
  10. package/dist/fnet/index.7crx8ky1.js +1 -0
  11. package/dist/fnet/index.7vw06nrn.js +1 -0
  12. package/dist/fnet/index.9567fa9x.js +1 -0
  13. package/dist/fnet/index.gh75wt1m.js +1 -0
  14. package/dist/fnet/index.hzsfswvp.js +1 -0
  15. package/dist/fnet/index.jgpc3grc.js +1 -0
  16. package/dist/fnet/index.js +20 -0
  17. package/dist/fnet/index.p0zb7e1b.js +1 -0
  18. package/dist/fnet/index.r19p3bpa.js +2 -0
  19. package/dist/fnet/index.r82rtnmz.js +1 -0
  20. package/dist/fnet/index.s662t98v.js +1 -0
  21. package/dist/fnet/index.w74dpnpn.js +1 -0
  22. package/dist/fnet/index.xeaw5xa9.js +1 -0
  23. package/dist/fnet/index.zm4kesg6.js +1 -0
  24. package/dist/fnode/index.05n3mvs9.js +2 -0
  25. package/dist/fnode/index.2hc9tbyx.js +1 -0
  26. package/dist/fnode/index.2pnjg6dc.js +1 -0
  27. package/dist/fnode/index.9qgtmxq3.js +2 -0
  28. package/dist/fnode/index.b1q7y05p.js +1 -0
  29. package/dist/fnode/index.bhapgrs7.js +1 -0
  30. package/dist/fnode/index.cvxrf34y.js +2 -0
  31. package/dist/fnode/index.dp9wyahp.js +1 -0
  32. package/dist/fnode/index.eqxmcpdc.js +1 -0
  33. package/dist/fnode/index.f2tb0x3t.js +1 -0
  34. package/dist/fnode/index.fbzv6wwf.js +1 -0
  35. package/dist/fnode/index.gazd9raq.js +1 -0
  36. package/dist/fnode/index.hv4s25f0.js +3 -0
  37. package/dist/fnode/index.j5z7dtsx.js +1 -0
  38. package/dist/fnode/index.js +10 -0
  39. package/dist/fnode/index.kb4e4bxf.js +1 -0
  40. package/dist/fnode/index.qn0schqp.js +1 -0
  41. package/dist/fnode/index.rht29phd.js +1 -0
  42. package/dist/fnode/index.rzsfmek6.js +3 -0
  43. package/dist/fnode/index.s0nk6cv8.js +4 -0
  44. package/dist/fnode/index.s66v6wt4.js +1 -0
  45. package/dist/fnode/index.sv7v0y60.js +1 -0
  46. package/dist/fnode/index.tgkhgnrp.js +1 -0
  47. package/dist/fnode/index.vq706f75.js +1 -0
  48. package/dist/fnode/index.y8pvdcny.js +1 -0
  49. package/dist/fnode/index.z4vz93ww.js +1 -0
  50. package/dist/frun/index.js +2 -0
  51. package/dist/fservice/index.js +19 -0
  52. package/dist/fservice/index.q01yvaz0.js +2 -0
  53. package/package.json +74 -57
  54. package/readme.md +298 -0
  55. package/template/fnet/core/assert.js +6 -0
  56. package/template/fnet/core/message.js +3 -0
  57. package/template/fnet/core/object.js +47 -0
  58. package/template/fnet/core/sleep.js +5 -0
  59. package/template/fnet/node/.gitignore.njk +9 -0
  60. package/template/fnet/node/build.js.njk +153 -0
  61. package/template/fnet/node/package.json.njk +121 -0
  62. package/template/fnet/node/readme.md.njk +21 -0
  63. package/template/fnet/node/rollup.config.mjs.njk +498 -0
  64. package/template/fnet/node/src/app/index.html.njk +67 -0
  65. package/template/fnet/node/src/app/index.js.njk +36 -0
  66. package/template/fnet/node/src/cli/index.js.njk +9 -0
  67. package/template/fnet/node/src/cli/index.js.v1.njk +318 -0
  68. package/template/fnet/node/src/cli/v2/core/args-parser.njk +10 -0
  69. package/template/fnet/node/src/cli/v2/core/imports.njk +31 -0
  70. package/template/fnet/node/src/cli/v2/core/run-wrapper.njk +25 -0
  71. package/template/fnet/node/src/cli/v2/index.js.njk +184 -0
  72. package/template/fnet/node/src/cli/v2/modes/default/extend.njk +11 -0
  73. package/template/fnet/node/src/cli/v2/modes/default/standard.njk +20 -0
  74. package/template/fnet/node/src/cli/v2/modes/http/builtin.njk +66 -0
  75. package/template/fnet/node/src/cli/v2/modes/http/imports.njk +9 -0
  76. package/template/fnet/node/src/cli/v2/modes/http/index.njk +12 -0
  77. package/template/fnet/node/src/cli/v2/modes/mcp/imports.njk +33 -0
  78. package/template/fnet/node/src/cli/v2/modes/mcp/index.njk +30 -0
  79. package/template/fnet/node/src/cli/v2/modes/mcp/server-setup.njk +15 -0
  80. package/template/fnet/node/src/cli/v2/modes/mcp/tool-handlers.njk +46 -0
  81. package/template/fnet/node/src/cli/v2/modes/mcp/transport-http.njk +222 -0
  82. package/template/fnet/node/src/cli/v2/modes/mcp/transport-stdio.njk +9 -0
  83. package/template/fnet/node/src/cli/v2/modes/pipeline/imports.njk +9 -0
  84. package/template/fnet/node/src/cli/v2/modes/pipeline/index.njk +113 -0
  85. package/template/fnet/node/src/cli/v2/modes/webhook/imports.njk +9 -0
  86. package/template/fnet/node/src/cli/v2/modes/webhook/index.njk +127 -0
  87. package/template/fnet/node/src/cli/v2/modes/websocket/imports.njk +15 -0
  88. package/template/fnet/node/src/cli/v2/modes/websocket/index.njk +104 -0
  89. package/template/fnet/node/src/default/blocks/assign.js.njk +15 -0
  90. package/template/fnet/node/src/default/blocks/call.js.njk +110 -0
  91. package/template/fnet/node/src/default/blocks/for.js.njk +71 -0
  92. package/template/fnet/node/src/default/blocks/form.js.njk +31 -0
  93. package/template/fnet/node/src/default/blocks/http.js.njk +135 -0
  94. package/template/fnet/node/src/default/blocks/modules.js.njk +15 -0
  95. package/template/fnet/node/src/default/blocks/new.js.njk +42 -0
  96. package/template/fnet/node/src/default/blocks/next.js.njk +15 -0
  97. package/template/fnet/node/src/default/blocks/output.js.njk +15 -0
  98. package/template/fnet/node/src/default/blocks/parallel.js.njk +64 -0
  99. package/template/fnet/node/src/default/blocks/pipeline.js.njk +109 -0
  100. package/template/fnet/node/src/default/blocks/raise.js.njk +15 -0
  101. package/template/fnet/node/src/default/blocks/retry.js.njk +70 -0
  102. package/template/fnet/node/src/default/blocks/return.js.njk +21 -0
  103. package/template/fnet/node/src/default/blocks/schedule.js.njk +66 -0
  104. package/template/fnet/node/src/default/blocks/signal.js.njk +15 -0
  105. package/template/fnet/node/src/default/blocks/steps.js.njk +47 -0
  106. package/template/fnet/node/src/default/blocks/switch.js.njk +49 -0
  107. package/template/fnet/node/src/default/blocks/tryexcept.js.njk +80 -0
  108. package/template/fnet/node/src/default/blocks/wait.js.njk +14 -0
  109. package/template/fnet/node/src/default/engine.js.njk +79 -0
  110. package/template/fnet/node/src/default/input.args.js.njk +125 -0
  111. package/template/fnet/node/src/default/macros/block-assign.js.njk +3 -0
  112. package/template/fnet/node/src/default/macros/block-body-header.js.njk +7 -0
  113. package/template/fnet/node/src/default/macros/block-entry-args.js.njk +2 -0
  114. package/template/fnet/node/src/default/macros/block-footer.js.njk +3 -0
  115. package/template/fnet/node/src/default/macros/block-header.js.njk +11 -0
  116. package/template/fnet/node/src/default/macros/block-library-header.js.njk +43 -0
  117. package/template/fnet/node/src/default/macros/block-modules-header.js.njk +8 -0
  118. package/template/fnet/node/src/default/macros/block-modules.js.njk +29 -0
  119. package/template/fnet/node/src/default/macros/block-next-header.js.njk +6 -0
  120. package/template/fnet/node/src/default/macros/block-next.js.njk +21 -0
  121. package/template/fnet/node/src/default/macros/block-run-footer.js.njk +7 -0
  122. package/template/fnet/node/src/default/macros/block-run-form.js.njk +32 -0
  123. package/template/fnet/node/src/default/macros/block-run-header.js.njk +43 -0
  124. package/template/fnet/node/src/default/macros/block-signal.js.njk +3 -0
  125. package/template/fnet/node/src/default/macros/page.js.njk +8 -0
  126. package/template/fnet/node/src/default/types/block.js.njk +133 -0
  127. package/template/fnet/node/src/default/workflow.js.njk +125 -0
  128. package/template/fnet/node/tsconfig.json.njk +16 -0
  129. package/template/fnet/project/.gitignore.njk +7 -0
  130. package/template/fnet/project/.vscode/launch.json.njk +41 -0
  131. package/template/fnet/project/.vscode/tasks.json.njk +46 -0
  132. package/template/fnet/project/fnet/flows.yaml.njk +4 -0
  133. package/template/fnet/project/fnet/targets.yaml.njk +7 -0
  134. package/template/fnet/project/fnet.yaml.njk +3 -0
  135. package/template/fnode/node/.gitignore.njk +9 -0
  136. package/template/fnode/node/build.js.njk +149 -0
  137. package/template/fnode/node/package.json.njk +121 -0
  138. package/template/fnode/node/readme.md.njk +21 -0
  139. package/template/fnode/node/rollup.config.mjs.njk +498 -0
  140. package/template/fnode/node/src/app/index-js-with-react-host.njk +50 -0
  141. package/template/fnode/node/src/app/index-js-without-react-host.njk +23 -0
  142. package/template/fnode/node/src/app/index.html.njk +67 -0
  143. package/template/fnode/node/src/app/index.js.njk +9 -0
  144. package/template/fnode/node/src/cli/index.js.njk +9 -0
  145. package/template/fnode/node/src/cli/index.js.v1.njk +464 -0
  146. package/template/fnode/node/src/cli/v2/core/args-parser.njk +10 -0
  147. package/template/fnode/node/src/cli/v2/core/imports.njk +29 -0
  148. package/template/fnode/node/src/cli/v2/core/run-wrapper.njk +25 -0
  149. package/template/fnode/node/src/cli/v2/index.js.njk +184 -0
  150. package/template/fnode/node/src/cli/v2/modes/default/extend.njk +11 -0
  151. package/template/fnode/node/src/cli/v2/modes/default/standard.njk +19 -0
  152. package/template/fnode/node/src/cli/v2/modes/http/builtin.njk +61 -0
  153. package/template/fnode/node/src/cli/v2/modes/http/imports.njk +9 -0
  154. package/template/fnode/node/src/cli/v2/modes/http/index.njk +12 -0
  155. package/template/fnode/node/src/cli/v2/modes/mcp/imports.njk +33 -0
  156. package/template/fnode/node/src/cli/v2/modes/mcp/index.njk +30 -0
  157. package/template/fnode/node/src/cli/v2/modes/mcp/server-setup.njk +15 -0
  158. package/template/fnode/node/src/cli/v2/modes/mcp/tool-handlers.njk +41 -0
  159. package/template/fnode/node/src/cli/v2/modes/mcp/transport-http.njk +212 -0
  160. package/template/fnode/node/src/cli/v2/modes/mcp/transport-stdio.njk +9 -0
  161. package/template/fnode/node/src/cli/v2/modes/pipeline/imports.njk +9 -0
  162. package/template/fnode/node/src/cli/v2/modes/pipeline/index.njk +103 -0
  163. package/template/fnode/node/src/cli/v2/modes/webhook/imports.njk +9 -0
  164. package/template/fnode/node/src/cli/v2/modes/webhook/index.njk +122 -0
  165. package/template/fnode/node/src/cli/v2/modes/websocket/imports.njk +15 -0
  166. package/template/fnode/node/src/cli/v2/modes/websocket/index.njk +99 -0
  167. package/template/fnode/node/src/default/engine.js.njk +17 -0
  168. package/template/fnode/node/src/default/input.args.js.njk +126 -0
  169. package/template/fnode/node/tsconfig.json.njk +16 -0
  170. package/template/fnode/project/.gitignore.njk +11 -0
  171. package/template/fnode/project/.vscode/launch.json.njk +78 -0
  172. package/template/fnode/project/.vscode/tasks.json.njk +46 -0
  173. package/template/fnode/project/fnet/targets.yaml.njk +25 -0
  174. package/template/fnode/project/fnode.yaml.njk +12 -0
  175. package/template/fnode/python/.gitignore.njk +7 -0
  176. package/template/fnode/python/package.json.njk +4 -0
  177. package/template/fnode/python/pyproject.toml.njk +3 -0
  178. package/template/fnode/python/readme.md.njk +12 -0
  179. package/template/fnode/python/setup.py.njk +19 -0
  180. package/template/fnode/python/src/cli/index.py.njk +25 -0
  181. package/template/schemas/to-npm.yaml +14 -0
  182. package/dist/builder/lib-cli.js +0 -2
  183. package/dist/builder/wf-cli.js +0 -2
  184. 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,11 @@
1
+ .DS_Store
2
+ .workspace
3
+ .fnet
4
+ .out
5
+ .package
6
+ .npmrc
7
+ .vscode
8
+ {% if runtime === 'node' %}
9
+ {% elif runtime === 'python' %}
10
+ __pycache__
11
+ {% endif %}
@@ -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 %}
@@ -0,0 +1,12 @@
1
+ name: {{name}}
2
+
3
+ {% if runtime === 'node' %}
4
+ features:
5
+ s::runtime.type: node
6
+ {% elif runtime === 'python' %}
7
+ features:
8
+ s::runtime.type: python
9
+ {% elif runtime === 'bun' %}
10
+ features:
11
+ s::runtime.type: bun
12
+ {% endif %}