@anarlabs/crosspulse 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AnarEsgerzade
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,535 @@
1
+ # Crosspulse
2
+
3
+ **Seamless Python ↔ JavaScript Bridge** - Bidirectional, fully synchronized cross-language communication library.
4
+
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![Python 3.7+](https://img.shields.io/badge/python-3.7+-blue.svg)](https://www.python.org/downloads/)
7
+ [![Node 12+](https://img.shields.io/badge/node-12+-green.svg)](https://nodejs.org/)
8
+
9
+ > Break down language barriers and let Python and JavaScript talk to each other like old friends.
10
+
11
+ ---
12
+
13
+ ## ✨ Features
14
+
15
+ - ✅ **Bidirectional Communication**: JS → PY and PY → JS
16
+ - ✅ **Synchronous Calls**: Full Promise/await support
17
+ - ✅ **Event-Based Architecture**: Register, listen, and call methods
18
+ - ✅ **Error Handling**: Exception handling in both languages
19
+ - ✅ **Type Safe**: JSON serialization with validation
20
+ - ✅ **Simple API**: Just 3 core methods: `register()`, `listen()`, `call()`
21
+ - ✅ **Zero Dependencies**: No external packages required
22
+ - ✅ **Lightweight**: Minimal overhead, maximum performance
23
+
24
+ ---
25
+
26
+ ## 🎯 Why Crosspulse?
27
+
28
+ Ever wanted to combine Python's data processing power with JavaScript's UI capabilities? Or run ML models in Python while displaying results in Node.js? Crosspulse makes it effortless.
29
+
30
+ ```javascript
31
+ // JavaScript
32
+ const result = await bridge.call("train_model", data);
33
+ console.log("Accuracy:", result.accuracy);
34
+ ```
35
+
36
+ ```python
37
+ # Python (automatically responds)
38
+ bridge.register("train_model", train_ml_model)
39
+ ```
40
+
41
+ That's it. No REST APIs, no HTTP servers, no complexity.
42
+
43
+ ---
44
+
45
+ ## 📦 Installation
46
+
47
+ Simply copy the files to your project:
48
+
49
+ ```bash
50
+ crosspulse.py
51
+ crosspulse.js
52
+ ```
53
+
54
+ **Requirements:**
55
+ - Python 3.7+
56
+ - Node.js 12+
57
+
58
+ ---
59
+
60
+ ## 🚀 Quick Start
61
+
62
+ ### Mode 1: JavaScript → Python
63
+
64
+ Call Python functions from JavaScript.
65
+
66
+ **JavaScript side:**
67
+ ```javascript
68
+ const Crosspulse = require('./crosspulse');
69
+
70
+ async function main() {
71
+ const bridge = new Crosspulse("connect");
72
+ await bridge.connect("./crosspulse.py");
73
+
74
+ // Call Python function
75
+ const result = await bridge.call("py_add", 10, 20);
76
+ console.log(result); // 30
77
+
78
+ bridge.disconnect();
79
+ }
80
+
81
+ main();
82
+ ```
83
+
84
+ **Python side:**
85
+ ```python
86
+ from crosspulse import Crosspulse
87
+
88
+ bridge = Crosspulse(mode="listen")
89
+
90
+ # Register method
91
+ bridge.register("py_add", lambda a, b: a + b)
92
+
93
+ # Start listening
94
+ bridge.listen()
95
+ ```
96
+
97
+ **Run:**
98
+ ```bash
99
+ node app.js
100
+ ```
101
+
102
+ ---
103
+
104
+ ### Mode 2: Python → JavaScript
105
+
106
+ Call JavaScript functions from Python.
107
+
108
+ **Python side:**
109
+ ```python
110
+ from crosspulse import Crosspulse
111
+
112
+ bridge = Crosspulse(mode="connect")
113
+ bridge.connect("./crosspulse.js")
114
+
115
+ # Call JavaScript function
116
+ result = bridge.call("js_multiply", 100, 50)
117
+ print(result) # 5000
118
+
119
+ bridge.disconnect()
120
+ ```
121
+
122
+ **JavaScript side:**
123
+ ```javascript
124
+ const Crosspulse = require('./crosspulse');
125
+
126
+ const bridge = new Crosspulse("listen");
127
+
128
+ // Register method
129
+ bridge.register("js_multiply", (a, b) => a * b);
130
+
131
+ // Start listening
132
+ bridge.listen();
133
+ ```
134
+
135
+ **Run:**
136
+ ```bash
137
+ python3 main.py
138
+ ```
139
+
140
+ ---
141
+
142
+ ### Mode 3: Bidirectional Communication
143
+
144
+ Both languages can call each other simultaneously!
145
+
146
+ **Python side:**
147
+ ```python
148
+ bridge = Crosspulse(mode="connect")
149
+
150
+ # Register our methods (JS can call these)
151
+ bridge.register("py_square", lambda x: x ** 2)
152
+ bridge.register("py_reverse", lambda s: s[::-1])
153
+
154
+ bridge.connect("./app.js")
155
+
156
+ # Call JS methods
157
+ result = bridge.call("js_capitalize", "hello world")
158
+ print(result) # "HELLO WORLD"
159
+
160
+ # JS can simultaneously call py_square() or py_reverse()
161
+ ```
162
+
163
+ **JavaScript side:**
164
+ ```javascript
165
+ const bridge = new Crosspulse("listen");
166
+
167
+ // Register our methods (Python can call these)
168
+ bridge.register("js_capitalize", (str) => str.toUpperCase());
169
+ bridge.register("js_length", (str) => str.length);
170
+
171
+ bridge.listen();
172
+
173
+ // Python can simultaneously call our methods
174
+ // We automatically respond to incoming calls
175
+ ```
176
+
177
+ ---
178
+
179
+ ## 📖 API Reference
180
+
181
+ ### Python
182
+
183
+ ```python
184
+ from crosspulse import Crosspulse
185
+
186
+ # Create instance
187
+ bridge = Crosspulse(mode="listen") # Listen mode
188
+ bridge = Crosspulse(mode="connect") # Connect mode
189
+
190
+ # Register method
191
+ bridge.register("method_name", callback_function)
192
+
193
+ # Listen for calls (listen mode)
194
+ bridge.listen()
195
+
196
+ # Connect to target (connect mode)
197
+ bridge.connect("target_script.js")
198
+
199
+ # Call remote method
200
+ result = bridge.call("method_name", arg1, arg2)
201
+
202
+ # Disconnect
203
+ bridge.disconnect()
204
+ ```
205
+
206
+ ### JavaScript
207
+
208
+ ```javascript
209
+ const Crosspulse = require('./crosspulse');
210
+
211
+ // Create instance
212
+ const bridge = new Crosspulse("listen"); // Listen mode
213
+ const bridge = new Crosspulse("connect"); // Connect mode
214
+
215
+ // Register method
216
+ bridge.register("method_name", (arg1, arg2) => {
217
+ return result;
218
+ });
219
+
220
+ // Listen for calls (listen mode)
221
+ bridge.listen();
222
+
223
+ // Connect to target (connect mode)
224
+ await bridge.connect("./target_script.py");
225
+
226
+ // Call remote method
227
+ const result = await bridge.call("method_name", arg1, arg2);
228
+
229
+ // Disconnect
230
+ bridge.disconnect();
231
+ ```
232
+
233
+ ---
234
+
235
+ ## 🎯 Real-World Examples
236
+
237
+ ### Example 1: Data Processing Pipeline
238
+
239
+ ```python
240
+ # data_processor.py
241
+ import pandas as pd
242
+ from crosspulse import Crosspulse
243
+
244
+ bridge = Crosspulse("connect")
245
+ bridge.connect("./visualizer.js")
246
+
247
+ # Process data in Python
248
+ df = pd.read_csv("sales_data.csv")
249
+ insights = analyze_sales(df)
250
+
251
+ # Visualize in JavaScript
252
+ chart = bridge.call("create_chart", insights.to_dict())
253
+ print(f"Chart created: {chart}")
254
+ ```
255
+
256
+ ```javascript
257
+ // visualizer.js
258
+ const bridge = new Crosspulse("listen");
259
+
260
+ bridge.register("create_chart", (data) => {
261
+ // Use Chart.js, D3.js, or any JS library
262
+ const chart = generateChart(data);
263
+ return chart.id;
264
+ });
265
+
266
+ bridge.listen();
267
+ ```
268
+
269
+ ### Example 2: Machine Learning UI
270
+
271
+ ```javascript
272
+ // ml_interface.js
273
+ const bridge = new Crosspulse("connect");
274
+
275
+ async function trainModel(dataset) {
276
+ await bridge.connect("./ml_model.py");
277
+
278
+ const progress = await bridge.call("train", dataset);
279
+ console.log("Training progress:", progress);
280
+
281
+ const predictions = await bridge.call("predict", testData);
282
+ displayResults(predictions);
283
+ }
284
+ ```
285
+
286
+ ```python
287
+ # ml_model.py
288
+ from sklearn.ensemble import RandomForestClassifier
289
+
290
+ bridge = Crosspulse("listen")
291
+
292
+ model = RandomForestClassifier()
293
+
294
+ def train_model(data):
295
+ X, y = prepare_data(data)
296
+ model.fit(X, y)
297
+ return {"status": "trained", "accuracy": model.score(X, y)}
298
+
299
+ bridge.register("train", train_model)
300
+ bridge.listen()
301
+ ```
302
+
303
+ ### Example 3: Web Scraping + Frontend
304
+
305
+ ```python
306
+ # scraper.py
307
+ from crosspulse import Crosspulse
308
+ import requests
309
+ from bs4 import BeautifulSoup
310
+
311
+ bridge = Crosspulse("connect")
312
+
313
+ def scrape_news():
314
+ # Scrape with Python
315
+ data = scrape_website()
316
+
317
+ # Send to JavaScript for display
318
+ bridge.call("update_ui", data)
319
+
320
+ bridge.connect("./server.js")
321
+ scrape_news()
322
+ ```
323
+
324
+ ### Example 4: Desktop App (Electron + Python)
325
+
326
+ ```javascript
327
+ // electron_main.js
328
+ const bridge = new Crosspulse("connect");
329
+
330
+ ipcMain.on("process-image", async (event, imagePath) => {
331
+ await bridge.connect("./image_processor.py");
332
+
333
+ const processed = await bridge.call("enhance_image", imagePath);
334
+ event.reply("image-ready", processed);
335
+ });
336
+ ```
337
+
338
+ ---
339
+
340
+ ## 🔧 Advanced Usage
341
+
342
+ ### Error Handling
343
+
344
+ ```javascript
345
+ try {
346
+ const result = await bridge.call("risky_operation", data);
347
+ console.log("Success:", result);
348
+ } catch (error) {
349
+ console.error("Python error:", error.message);
350
+ }
351
+ ```
352
+
353
+ ```python
354
+ try:
355
+ result = bridge.call("risky_operation", data)
356
+ print(f"Success: {result}")
357
+ except Exception as e:
358
+ print(f"JavaScript error: {e}")
359
+ ```
360
+
361
+ ### Multiple Arguments & Complex Data
362
+
363
+ ```javascript
364
+ // JavaScript
365
+ const result = await bridge.call("process_user", {
366
+ name: "John",
367
+ age: 30,
368
+ tags: ["developer", "python", "javascript"]
369
+ });
370
+ ```
371
+
372
+ ```python
373
+ # Python
374
+ def process_user(user_data):
375
+ return {
376
+ "id": generate_id(),
377
+ "name": user_data["name"],
378
+ "processed": True
379
+ }
380
+
381
+ bridge.register("process_user", process_user)
382
+ ```
383
+
384
+ ### Async Operations
385
+
386
+ ```python
387
+ # Python
388
+ import time
389
+
390
+ def long_running_task(duration):
391
+ time.sleep(duration)
392
+ return "Task completed"
393
+
394
+ bridge.register("long_task", long_running_task)
395
+ ```
396
+
397
+ ```javascript
398
+ // JavaScript
399
+ const result = await bridge.call("long_task", 5);
400
+ console.log(result); // "Task completed" (after 5 seconds)
401
+ ```
402
+
403
+ ---
404
+
405
+ ## 🎨 Use Cases
406
+
407
+ | Use Case | Python Side | JavaScript Side |
408
+ |----------|-------------|-----------------|
409
+ | **Web Scraping** | BeautifulSoup, Scrapy | Display in React/Vue |
410
+ | **Machine Learning** | TensorFlow, PyTorch | Real-time UI updates |
411
+ | **Data Analysis** | Pandas, NumPy | Chart.js, D3.js |
412
+ | **Image Processing** | OpenCV, Pillow | Canvas, WebGL |
413
+ | **File Processing** | Parse Excel/PDF | Electron file picker |
414
+ | **API Gateway** | Flask/FastAPI alternative | Frontend communication |
415
+ | **Desktop Apps** | Backend logic | Electron UI |
416
+ | **Automation** | Selenium, automation | Control panel |
417
+
418
+ ---
419
+
420
+ ## ⚡ Performance
421
+
422
+ - **Latency**: ~5-10ms per call (local)
423
+ - **Throughput**: 1000+ calls/second
424
+ - **Memory**: Minimal overhead (<5MB)
425
+ - **Scalability**: Single process pair
426
+
427
+ For high-throughput scenarios, consider batching calls or using WebSocket alternatives.
428
+
429
+ ---
430
+
431
+ ## 🛡️ Security Notes
432
+
433
+ - Crosspulse uses STDIN/STDOUT for IPC
434
+ - Only use with trusted code
435
+ - Validate all incoming data
436
+ - Don't expose to untrusted networks
437
+ - Consider sandboxing for production
438
+
439
+ ---
440
+
441
+ ## 🐛 Troubleshooting
442
+
443
+ ### "Method not found" error
444
+ ```python
445
+ # Make sure method is registered before listening
446
+ bridge.register("my_method", my_function)
447
+ bridge.listen() # Must be after register
448
+ ```
449
+
450
+ ### Connection timeout
451
+ ```javascript
452
+ // Ensure Python script is running
453
+ await bridge.connect("./script.py");
454
+ // Python should be in listen mode
455
+ ```
456
+
457
+ ### JSON serialization errors
458
+ ```python
459
+ # Only use JSON-serializable types
460
+ # ✅ str, int, float, list, dict, bool, None
461
+ # ❌ Custom objects, functions, file handles
462
+ ```
463
+
464
+ ---
465
+
466
+ ## 🤝 Contributing
467
+
468
+ Contributions are welcome! Here's how:
469
+
470
+ ```bash
471
+ git clone https://github.com/yourusername/crosspulse.git
472
+ cd crosspulse
473
+ ```
474
+
475
+ **Areas to contribute:**
476
+ - TypeScript definitions
477
+ - More examples
478
+ - Performance improvements
479
+ - Documentation
480
+ - Bug fixes
481
+
482
+ ---
483
+
484
+ ## 📄 License
485
+
486
+ MIT License - Use it however you want!
487
+
488
+ ```
489
+ MIT License
490
+
491
+ Copyright (c) 2026 AnarEsgerzade
492
+
493
+ Permission is hereby granted, free of charge, to any person obtaining a copy
494
+ of this software and associated documentation files (the "Software"), to deal
495
+ in the Software without restriction, including without limitation the rights
496
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
497
+ copies of the Software, and to permit persons to whom the Software is
498
+ furnished to do so, subject to the following conditions:
499
+
500
+ The above copyright notice and this permission notice shall be included in all
501
+ copies or substantial portions of the Software.
502
+
503
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
504
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
505
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
506
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
507
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
508
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
509
+ SOFTWARE.
510
+ ```
511
+
512
+ ---
513
+
514
+
515
+
516
+ ## 🌟 Show Your Support
517
+
518
+ If Crosspulse helps your project, give it a ⭐️ on GitHub!
519
+
520
+ ---
521
+
522
+ ## 📞 Support
523
+
524
+ - **Issues**: [GitHub Issues](https://github.com/AnarDevStudio/crosspulse/issues)
525
+ - **Discussions**: [GitHub Discussions](https://github.com/AnarDevStudio/crosspulse/discussions)
526
+ - **Email**: anardevstudio@gmail.com
527
+
528
+ ---
529
+
530
+
531
+ **Built with ❤️ by developers who believe languages should work together, not apart.**
532
+
533
+ **Crosspulse** - Where Python meets JavaScript. 🚀
534
+
535
+ **Make by AnarEsgerzade🌷**
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@anarlabs/crosspulse",
3
+ "version": "1.0.1",
4
+ "description": "Call Python from Node.js and Node.js from Python easily with Crosspulse’s lightweight bridge.",
5
+ "main": "crosspulse.js",
6
+ "directories": {
7
+ "example": "example"
8
+ },
9
+ "scripts": {
10
+ "test": "echo \"No tests yet\" && exit 0"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/AnarDevStudio/Crosspulse.git"
15
+ },
16
+ "keywords": [
17
+ "nodejs",
18
+ "javascript",
19
+ "python",
20
+ "events",
21
+ "ipc",
22
+ "stdout",
23
+ "stdin",
24
+ "interop",
25
+ "bridge",
26
+ "event-driven",
27
+ "cross-language",
28
+ "python-javascript"
29
+ ],
30
+ "author": "AnarDevStudio",
31
+ "license": "MIT",
32
+ "bugs": {
33
+ "url": "https://github.com/AnarDevStudio/Crosspulse/issues"
34
+ },
35
+ "homepage": "https://github.com/AnarDevStudio/Crosspulse#readme"
36
+ }
@@ -0,0 +1,204 @@
1
+ // Copyright (c) 2026 Crosspulse
2
+
3
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ // of this software and associated documentation files (the "Software"), to deal
5
+ // in the Software without restriction, including without limitation the rights
6
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ // copies of the Software.
8
+
9
+ const { spawn } = require("child_process");
10
+ const path = require("path");
11
+
12
+ class Crosspulse {
13
+ /**
14
+ * Crosspulse - JavaScript ↔ Python Bridge
15
+ * Bidirectional communication: both listening and calling
16
+ */
17
+
18
+ constructor(mode = "connect") {
19
+ /**
20
+ * mode:
21
+ * "connect" = connect to Python and call its methods
22
+ * "listen" = listen for method calls coming from Python
23
+ */
24
+ this.mode = mode;
25
+ this.handlers = new Map();
26
+ this.process = null;
27
+ this.buffer = "";
28
+ this.callbacks = new Map();
29
+ this.requestId = 0;
30
+ }
31
+
32
+ async connect(pythonFile) {
33
+ /**
34
+ * Connect to a Python script
35
+ */
36
+ if (this.mode !== "connect") {
37
+ throw new Error("Crosspulse must be in 'connect' mode");
38
+ }
39
+
40
+ return new Promise((resolve, reject) => {
41
+ const pyPath = path.resolve(__dirname, pythonFile);
42
+ this.process = spawn("python3", [pyPath]);
43
+
44
+ this.process.stdout.on("data", (data) => {
45
+ this.buffer += data.toString();
46
+
47
+ let lines = this.buffer.split("\n");
48
+ this.buffer = lines.pop() || "";
49
+
50
+ for (let line of lines) {
51
+ if (!line.trim()) continue;
52
+
53
+ try {
54
+ const response = JSON.parse(line);
55
+
56
+ // Response to a method call made to Python
57
+ if (response.id !== undefined && this.callbacks.has(response.id)) {
58
+ const callback = this.callbacks.get(response.id);
59
+ this.callbacks.delete(response.id);
60
+
61
+ if (response.success) {
62
+ callback.resolve(response.result);
63
+ } else {
64
+ callback.reject(new Error(response.error));
65
+ }
66
+ }
67
+
68
+ // Method call coming from Python
69
+ else if (response.method) {
70
+ this._handleIncomingCall(response);
71
+ }
72
+
73
+ } catch (err) {
74
+ console.error("JSON parse error:", err);
75
+ }
76
+ }
77
+ });
78
+
79
+ this.process.stderr.on("data", (data) => {
80
+ console.error("Python stderr:", data.toString());
81
+ });
82
+
83
+ this.process.on("close", (code) => {
84
+ if (code !== 0) {
85
+ reject(new Error(`Python process exited with code ${code}`));
86
+ }
87
+ });
88
+
89
+ this.process.on("error", (err) => {
90
+ reject(err);
91
+ });
92
+
93
+ // Process is ready
94
+ setTimeout(() => resolve(this), 100);
95
+ });
96
+ }
97
+
98
+ call(method, ...args) {
99
+ /**
100
+ * Call a method defined in Python
101
+ */
102
+ return new Promise((resolve, reject) => {
103
+ if (!this.process) {
104
+ return reject(new Error("Not connected. Call connect() first."));
105
+ }
106
+
107
+ const id = this.requestId++;
108
+ this.callbacks.set(id, { resolve, reject });
109
+
110
+ const request = {
111
+ id,
112
+ method,
113
+ args,
114
+ kwargs: {}
115
+ };
116
+
117
+ this.process.stdin.write(JSON.stringify(request) + "\n");
118
+ });
119
+ }
120
+
121
+ disconnect() {
122
+ /**
123
+ * Close the connection
124
+ */
125
+ if (this.process) {
126
+ this.process.kill();
127
+ this.process = null;
128
+ }
129
+ }
130
+
131
+ // ==================== LISTENER MODE ====================
132
+
133
+ register(methodName, callback) {
134
+ /**
135
+ * Register a method that can be called from Python
136
+ */
137
+ this.handlers.set(methodName, callback);
138
+ return this;
139
+ }
140
+
141
+ listen() {
142
+ /**
143
+ * Listen for incoming method calls from Python (via stdin)
144
+ */
145
+ if (this.mode !== "listen") {
146
+ throw new Error("Crosspulse must be in 'listen' mode");
147
+ }
148
+
149
+ process.stdin.setEncoding('utf8');
150
+
151
+ process.stdin.on('data', (data) => {
152
+ this.buffer += data.toString();
153
+
154
+ let lines = this.buffer.split("\n");
155
+ this.buffer = lines.pop() || "";
156
+
157
+ for (let line of lines) {
158
+ if (!line.trim()) continue;
159
+
160
+ try {
161
+ const request = JSON.parse(line);
162
+ this._handleIncomingCall(request);
163
+ } catch (err) {
164
+ console.error("JSON parse error:", err);
165
+ }
166
+ }
167
+ });
168
+
169
+ process.stdin.on('end', () => {
170
+ process.exit(0);
171
+ });
172
+ }
173
+
174
+ _handleIncomingCall(request) {
175
+ /**
176
+ * Handle an incoming method call
177
+ */
178
+ const method = request.method;
179
+ const args = request.args || [];
180
+ const id = request.id;
181
+
182
+ let response;
183
+
184
+ if (this.handlers.has(method)) {
185
+ try {
186
+ const result = this.handlers.get(method)(...args);
187
+ response = { id, success: true, result };
188
+ } catch (err) {
189
+ response = { id, success: false, error: err.message };
190
+ }
191
+ } else {
192
+ response = { id, success: false, error: `Method not found: ${method}` };
193
+ }
194
+
195
+ // Send the response back
196
+ if (this.mode === "connect" && this.process) {
197
+ this.process.stdin.write(JSON.stringify(response) + "\n");
198
+ } else if (this.mode === "listen") {
199
+ console.log(JSON.stringify(response));
200
+ }
201
+ }
202
+ }
203
+
204
+ module.exports = Crosspulse;