diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e710a67
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+node_modules/
+package.json
+package-lock.json
diff --git a/AI_prompt.txt b/AI_prompt.txt
index 5120027..2df5aab 100644
--- a/AI_prompt.txt
+++ b/AI_prompt.txt
@@ -18,12 +18,9 @@ Create a walkthrough for Julia service-A service sending a mix-content chat mess
-
I updated the following:
- NATSBridge.jl. Essentially I add NATS_connection keyword and new publish_message function to support the keyword.
-
Use them and ONLY them as ground truth.
-
Then update the following files accordingly:
- architecture.md
- implementation.md
@@ -39,11 +36,8 @@ All API should be semantically consistent and naming should be consistent across
Task: Update NATSBridge.js to reflect recent changes in NATSBridge.jl and docs
-
Context: NATSBridge.jl and docs has been updated.
-
Requirements:
-
Source of Truth: Treat the updated NATSBridge.jl and docs as the definitive source.
API Consistency: Ensure the Main Package API (e.g., smartsend(), publish_message()) uses consistent naming across all three supported languages.
Ecosystem Variance: Low-level native functions (e.g., NATS.connect(), JSON.read()) should follow the conventions of the specific language ecosystem and do not require cross-language consistency.
@@ -51,3 +45,59 @@ Ecosystem Variance: Low-level native functions (e.g., NATS.connect(), JSON.read(
+
+
+
+I'm expanding this Julia package (NATSBridge) into a cross-platform project by adding a JavaScript and Python/MicroPython implementation. To ensure accuracy, the Julia src directory will serve as the ground truth, as the documentation may be outdated.
+
+My goal is to maintain interface parity at the high-level API for a consistent user experience, while ensuring the low-level implementation adheres strictly to the idiomatic conventions of each respective language (e.g., multiple dispatch in Julia vs. asynchronous, prototype, or class-based patterns in JS and Python/MicroPython)
+
+Now, help me do the following:
+1) check architecture.md for any mistake.
+
+
+
+
+Help me expands this Julia package (NATSBridge) into a cross-platform project by adding a JavaScript and Python/MicroPython implementation. To ensure accuracy, NATSBridge.jl will serve as the ground truth, as the documentation may be outdated.
+
+My goal is to maintain interface parity at the high-level API for a consistent user experience, while ensuring the low-level implementation adheres strictly to the idiomatic conventions of each respective language (e.g., multiple dispatch in Julia vs. asynchronous, prototype, or class-based patterns in JS and Python/MicroPython)
+
+Now do the following:
+1) check docs to see if there is any mistake.
+
+
+
+
+
+I'm expanding this Julia package (NATSBridge) into a cross-platform project by adding
+a JavaScript, Python and MicroPython implementation.
+The following will serve as the ground truth:
+- test_julia_mix_payloads_sender.jl
+- NATSBridge.jl
+- test_julia_mix_payloads_receiver.jl
+- architecture.md
+
+My goal is to maintain interface parity at the high-level API for a consistent user experience,
+while ensuring the low-level implementation adheres strictly to the idiomatic conventions of each
+respective language (e.g., multiple dispatch in Julia vs. asynchronous, prototype, or class-based
+patterns in JS, Python and MicroPython)
+
+Now, help me do the following:
+1) Check whether natsbridge.js needs update or it already up to date.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/README.md b/README.md
index be3f1ce..1fdf508 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-# NATSBridge
+# NATSBridge - Cross-Platform Bi-Directional Data Bridge
-A high-performance, bi-directional data bridge for **Julia** applications using NATS (Core & JetStream), implementing the Claim-Check pattern for large payloads.
+A high-performance, bi-directional data bridge for **Julia, JavaScript, Python, and MicroPython** applications using NATS (Core & JetStream), implementing the Claim-Check pattern for large payloads.
[](https://opensource.org/licenses/MIT)
[](https://nats.io)
@@ -10,22 +10,21 @@ A high-performance, bi-directional data bridge for **Julia** applications using
## Table of Contents
- [Overview](#overview)
+- [Cross-Platform Support](#cross-platform-support)
- [Features](#features)
-- [Architecture](#architecture)
-- [Installation](#installation)
- [Quick Start](#quick-start)
- [API Reference](#api-reference)
- [Payload Types](#payload-types)
-- [Transport Strategies](#transport-strategies)
-- [Examples](#examples)
+- [Cross-Platform Examples](#cross-platform-examples)
- [Testing](#testing)
+- [Documentation](#documentation)
- [License](#license)
---
## Overview
-NATSBridge enables seamless communication for Julia applications through NATS, with intelligent transport selection based on payload size:
+NATSBridge enables seamless communication across multiple platforms through NATS, with intelligent transport selection based on payload size:
| Transport | Payload Size | Method |
|-----------|--------------|--------|
@@ -36,14 +35,39 @@ NATSBridge enables seamless communication for Julia applications through NATS, w
- **Chat Applications**: Text, images, audio, video in a single message
- **File Transfer**: Efficient transfer of large files using claim-check pattern
-- **Streaming Data**: Sensor data, telemetry, and analytics pipelines
+- **IoT/Embedded**: Sensor data, telemetry, and analytics pipelines (MicroPython)
+- **Cross-Platform Communication**: Interoperability between Julia, JavaScript, Python, and MicroPython systems
+---
+
+## Cross-Platform Support
+
+| Platform | Implementation | Features |
+|----------|----------------|----------|
+| **Julia** | [`src/NATSBridge.jl`](src/NATSBridge.jl) | Full feature set, Arrow IPC, multiple dispatch |
+| **JavaScript** | [`src/natsbridge.js`](src/natsbridge.js) | Node.js & browser, async/await |
+| **Python** | [`src/natsbridge.py`](src/natsbridge.py) | Desktop Python, asyncio, type hints |
+| **MicroPython** | [`src/natsbridge_mpy.py`](src/natsbridge_mpy.py) | Memory-constrained, synchronous API |
+
+### Platform Comparison
+
+| Feature | Julia | JavaScript | Python | MicroPython |
+|---------|-------|------------|--------|-------------|
+| Multiple Dispatch | ✅ Native | ❌ | ❌ | ❌ |
+| Async/Await | ❌ | ✅ Native | ✅ Native | ⚠️ (uasyncio) |
+| Type Safety | ✅ Strong | ⚠️ (TypeScript) | ✅ (Type hints) | ❌ |
+| Arrow IPC | ✅ Native | ✅ | ✅ | ❌ |
+| Direct Transport | ✅ | ✅ | ✅ | ✅ |
+| Link Transport | ✅ | ✅ | ✅ | ⚠️ (Limited) |
+| Handler Functions | ✅ | ✅ | ✅ | ✅ |
+| Cross-Platform API | ✅ | ✅ | ✅ | ✅ |
---
## Features
-- ✅ **Bi-directional messaging** for Julia applications
+- ✅ **Cross-platform messaging** for Julia, JavaScript, Python, and MicroPython applications
+- ✅ **Bi-directional messaging** with request-reply patterns
- ✅ **Multi-payload support** - send multiple payloads with different types in one message
- ✅ **Automatic transport selection** - direct vs link based on payload size
- ✅ **Claim-Check pattern** for payloads > 1MB
@@ -51,100 +75,7 @@ NATSBridge enables seamless communication for Julia applications through NATS, w
- ✅ **Exponential backoff** for reliable file server downloads
- ✅ **Correlation ID tracking** for message tracing
- ✅ **Reply-to support** for request-response patterns
-- ✅ **JetStream support** for message replay and durability
-
-
----
-
-## Architecture
-
-### System Components
-
-```mermaid
-flowchart TB
- subgraph Sender["Julia Application (Sender)"]
- SenderApp[App Code]
- NATSBridge_Send[NATSBridge]
- NATS_Client[NATS.jl]
- end
-
- subgraph Receiver["Julia Application (Receiver)"]
- ReceiverApp[App Code]
- NATSBridge_Recv[NATSBridge]
- NATS_Client_Recv[NATS.jl]
- end
-
- subgraph Infrastructure["Infrastructure"]
- NATS[NATS Server
Message Broker]
- FileServer[HTTP File Server
Upload/Download]
- end
-
- SenderApp --> NATSBridge_Send
- NATSBridge_Send --> NATS_Client
- NATS_Client --> NATS
-
- NATS --> NATS_Client_Recv
- NATS_Client_Recv --> NATSBridge_Recv
- NATSBridge_Recv --> ReceiverApp
-
- NATSBridge_Send -.->|HTTP POST upload| FileServer
- FileServer -.->|HTTP GET download| NATSBridge_Recv
-
- style SenderApp fill:#e8f5e9
- style ReceiverApp fill:#e8f5e9
- style NATS fill:#fff3e0
- style FileServer fill:#f3e5f5
-```
-
-### Key Components
-
-| Component | Description |
-|-----------|-------------|
-| **Julia Application** | Sender and receiver applications using the NATSBridge module |
-| **NATS Server** | Message broker for transporting message envelopes |
-| **HTTP File Server** | Independent HTTP server for large payload storage (e.g., Plik) |
-
-### Message Flow
-
-1. **Sender** creates a message envelope with payloads using `smartsend()`
-2. **NATSBridge** serializes and encodes each payload based on type
-3. **Transport Decision**:
- - **Direct** (< 1MB): Payload encoded as Base64, published to NATS
- - **Link** (≥ 1MB): Payload uploaded to HTTP file server, URL published to NATS
-4. **NATS** routes message envelope to subscribers
-5. **Receiver** receives message via NATS subscription callback
-6. **NATSBridge** processes envelope:
- - Decodes Base64 payloads from NATS message
- - Fetches URLs from file server with exponential backoff
-7. **Receiver** deserializes payloads based on their type
-
-### File Server Handler Abstraction
-
-The system uses handler functions to abstract file server operations:
-
-| Handler | Purpose |
-|---------|---------|
-| `plik_oneshot_upload()` | Uploads payload bytes to file server, returns URL |
-| `_fetch_with_backoff()` | Downloads data from URL with exponential backoff retry |
-
-This abstraction allows support for different file server implementations (Plik, AWS S3, custom HTTP server).
-
----
-
-## Installation
-
-### Prerequisites
-
-- **NATS Server** (v2.10+ recommended)
-- **HTTP File Server** (optional, for payloads > 1MB)
-
-### Julia
-
-```julia
-using Pkg
-Pkg.add("NATS")
-Pkg.add("https://git.yiem.cc/ton/NATSBridge")
-```
+- ✅ **Handler function abstraction** - pluggable file server implementations (Plik, AWS S3, custom)
---
@@ -173,54 +104,72 @@ python3 -m http.server 8080 --directory /tmp/fileserver
```julia
using NATSBridge
-# Send a text message
data = [("message", "Hello World", "text")]
-env, env_json_str = NATSBridge.smartsend("/chat/room1", data; broker_url="nats://localhost:4222")
+env, env_json_str = smartsend("/chat/room1", data, broker_url="nats://localhost:4222")
println("Message sent!")
```
-### Step 4: Receive Messages
+#### JavaScript
-#### Julia
+```javascript
+const NATSBridge = require('./src/natsbridge.js');
-```julia
-using NATS, NATSBridge
+const data = [["message", "Hello World", "text"]];
+const [env, env_json_str] = await NATSBridge.smartsend(
+ "/chat/room1",
+ data,
+ { broker_url: "nats://localhost:4222" }
+);
+console.log("Message sent!");
+```
-# Configuration
-const SUBJECT = "/chat/room1"
-const NATS_URL = "nats://localhost:4222"
+#### Python
-# Helper: Log with correlation ID
-function log_trace(message)
- timestamp = Dates.now()
- println("[$timestamp] $message")
-end
+```python
+from natsbridge import smartsend
-# Receiver: Listen for messages - msg comes from the callback
-function test_receive()
- conn = NATS.connect(NATS_URL)
- NATS.subscribe(conn, SUBJECT) do msg
- log_trace("Received message on $(msg.subject)")
-
- # Receive and process message
- env, env_json_str = NATSBridge.smartreceive(msg, fileserverDownloadHandler)
- for (dataname, data, type) in env["payloads"]
- println("Received $dataname: $data")
- end
- end
-
- # Keep listening for 120 seconds
- sleep(120)
- NATS.drain(conn)
-end
-
-test_receive()
+data = [("message", "Hello World", "text")]
+env, env_json_str = await smartsend(
+ "/chat/room1",
+ data,
+ broker_url="nats://localhost:4222"
+)
+print("Message sent!")
```
---
## API Reference
+### Unified API Standard
+
+All platforms use the same input/output format for payloads:
+
+**Input format for smartsend:**
+```
+[(dataname1, data1, type1), (dataname2, data2, type2), ...]
+```
+
+**Output format for smartreceive:**
+```
+{
+ "correlation_id": "...",
+ "msg_id": "...",
+ "timestamp": "...",
+ "send_to": "...",
+ "msg_purpose": "...",
+ "sender_name": "...",
+ "sender_id": "...",
+ "receiver_name": "...",
+ "receiver_id": "...",
+ "reply_to": "...",
+ "reply_to_msg_id": "...",
+ "broker_url": "...",
+ "metadata": {...},
+ "payloads": [(dataname1, data1, type1), (dataname2, data2, type2), ...]
+}
+```
+
### smartsend
Sends data either directly via NATS or via a fileserver URL, depending on payload size.
@@ -231,27 +180,96 @@ Sends data either directly via NATS or via a fileserver URL, depending on payloa
using NATSBridge
env, env_json_str = NATSBridge.smartsend(
- subject, # NATS subject
- data::AbstractArray{Tuple{String, Any, String}}; # List of (dataname, data, type)
+ subject::String,
+ data::AbstractArray{Tuple{String, Any, String}};
broker_url::String = "nats://localhost:4222",
fileserver_url = "http://localhost:8080",
fileserver_upload_handler::Function = plik_oneshot_upload,
size_threshold::Int = 1_000_000,
- correlation_id::String = string(uuid4()), # Correlation ID for tracing (auto-generated UUID)
+ correlation_id::String = string(uuid4()),
msg_purpose::String = "chat",
sender_name::String = "NATSBridge",
receiver_name::String = "",
receiver_id::String = "",
reply_to::String = "",
reply_to_msg_id::String = "",
- is_publish::Bool = true, # Whether to automatically publish to NATS
- NATS_connection::Union{NATS.Connection, Nothing} = nothing, # Pre-existing NATS connection (optional, saves connection overhead)
- msg_id::String = string(uuid4()), # Message ID (auto-generated UUID)
- sender_id::String = string(uuid4()) # Sender ID (auto-generated UUID)
+ is_publish::Bool = true,
+ NATS_connection::Union{NATS.Connection, Nothing} = nothing,
+ msg_id::String = string(uuid4()),
+ sender_id::String = string(uuid4())
)
# Returns: ::Tuple{msg_envelope_v1, String}
-# - env: msg_envelope_v1 object with all envelope metadata and payloads
-# - env_json_str: JSON string representation of the envelope for publishing
+```
+
+#### JavaScript
+
+```javascript
+const NATSBridge = require('natsbridge');
+
+const [env, env_json_str] = await NATSBridge.smartsend(
+ subject,
+ data, // Array of [dataname, data, type] tuples
+ {
+ broker_url: 'nats://localhost:4222',
+ fileserver_url: 'http://localhost:8080',
+ fileserver_upload_handler: NATSBridge.plikOneshotUpload,
+ size_threshold: 1_000_000,
+ correlation_id: uuidv4(),
+ msg_purpose: 'chat',
+ sender_name: 'NATSBridge',
+ receiver_name: '',
+ receiver_id: '',
+ reply_to: '',
+ reply_to_msg_id: '',
+ is_publish: true,
+ nats_connection: null,
+ msg_id: uuidv4(),
+ sender_id: uuidv4()
+ }
+);
+// Returns: Promise<[env, env_json_str]>
+```
+
+#### Python
+
+```python
+from natsbridge import NATSBridge
+
+env, env_json_str = await NATSBridge.smartsend(
+ subject: str,
+ data: List[Tuple[str, Any, str]],
+ broker_url: str = "nats://localhost:4222",
+ fileserver_url: str = "http://localhost:8080",
+ fileserver_upload_handler: Callable = plik_oneshot_upload,
+ size_threshold: int = 1_000_000,
+ correlation_id: str = None,
+ msg_purpose: str = "chat",
+ sender_name: str = "NATSBridge",
+ receiver_name: str = "",
+ receiver_id: str = "",
+ reply_to: str = "",
+ reply_to_msg_id: str = "",
+ is_publish: bool = True,
+ nats_connection: Any = None,
+ msg_id: str = None,
+ sender_id: str = None
+)
+# Returns: Tuple[Dict, str]
+```
+
+#### MicroPython
+
+```python
+from natsbridge import NATSBridge
+
+# Limited to direct transport (< 100KB threshold)
+env, env_json_str = NATSBridge.smartsend(
+ subject,
+ data, # List of (dataname, data, type) tuples
+ broker_url="nats://localhost:4222",
+ size_threshold=100000 # Lower threshold for memory constraints
+)
+# Returns: Tuple[Dict, str]
```
### smartreceive
@@ -263,7 +281,6 @@ Receives and processes messages from NATS, handling both direct and link transpo
```julia
using NATSBridge
-# Note: msg is a NATS.Msg object passed from the subscription callback
env = NATSBridge.smartreceive(
msg::NATS.Msg;
fileserver_download_handler::Function = _fetch_with_backoff,
@@ -271,85 +288,75 @@ env = NATSBridge.smartreceive(
base_delay::Int = 100,
max_delay::Int = 5000
)
-# Returns: ::JSON.Object{String, Any} - key-value structure resemble msg_envelope_v1
+# Returns: ::JSON.Object{String, Any}
```
-### publish_message
+#### JavaScript
-Publish a message to a NATS subject. This function is available in Julia with two overloads:
+```javascript
+const env = await NATSBridge.smartreceive(
+ msg,
+ {
+ fileserver_download_handler: NATSBridge.fetchWithBackoff,
+ max_retries: 5,
+ base_delay: 100,
+ max_delay: 5000
+ }
+);
+// Returns: Promise
+```
-#### Julia
+#### Python
-**Using broker URL (creates new connection):**
-```julia
-using NATSBridge, NATS
-
-# Publish with URL - creates a new connection
-NATSBridge.publish_message(
- "nats://localhost:4222", # broker_url
- "/chat/room1", # subject
- "{\"correlation_id\":\"abc123\"}", # message
- "abc123" # correlation_id
+```python
+env = await NATSBridge.smartreceive(
+ msg,
+ fileserver_download_handler=fetch_with_backoff,
+ max_retries=5,
+ base_delay=100,
+ max_delay=5000
)
+# Returns: Dict with "payloads" key
```
-**Using pre-existing connection (saves connection overhead):**
-```julia
-using NATSBridge, NATS
+#### MicroPython
-# Create connection once and reuse
-conn = NATS.connect("nats://localhost:4222")
-NATSBridge.publish_message(conn, "/chat/room1", "{\"correlation_id\":\"abc123\"}", "abc123")
-# Connection is automatically drained after publish
+```python
+env = NATSBridge.smartreceive(
+ msg,
+ fileserver_download_handler=_sync_fileserver_download,
+ max_retries=3,
+ base_delay=100,
+ max_delay=1000
+)
+# Returns: Dict with "payloads" key
```
---
## Payload Types
-| Type | Description | Serialization |
-|------|-------------|---------------|
-| `text` | Plain text strings | UTF-8 bytes |
-| `dictionary` | JSON-serializable dictionaries | JSON |
-| `table` | Tabular data (DataFrames, arrays) | Apache Arrow IPC |
-| `image` | Image data (PNG, JPG) | Raw bytes |
-| `audio` | Audio data (WAV, MP3) | Raw bytes |
-| `video` | Video data (MP4, AVI) | Raw bytes |
-| `binary` | Generic binary data | Raw bytes |
+| Type | Julia | JavaScript | Python | MicroPython | Description |
+|------|-------|------------|--------|-------------|-------------|
+| `text` | `String` | `string` | `str` | `str` | Plain text strings |
+| `dictionary` | `Dict`, `NamedTuple` | `Object`, `Array` | `dict`, `list` | `dict` | JSON-serializable dictionaries |
+| `arrowtable` | `DataFrame`, `Arrow.Table` | `Array