diff --git a/CLAUDE.md b/CLAUDE.md
index 8c3d27d..167d4fe 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -1,10 +1,41 @@
# RobustMQ SDK — Project Guide
-## What this repo is
+## What is RobustMQ
-Multi-language client SDK for RobustMQ, a unified messaging broker that supports MQTT, Kafka,
-NATS, AMQP, and mq9 on a shared storage layer. This SDK focuses on **mq9** — the AI-native
-async communication protocol built on top of NATS.
+RobustMQ is a **unified messaging platform written in Rust** — one binary, one broker, zero external dependencies.
+It natively runs MQTT, Kafka, NATS, AMQP, and mq9 on a **shared pluggable storage layer**.
+
+Core architecture (3-tier, fully decoupled):
+- **Broker** (stateless compute): protocol parsing, TCP/TLS/WebSocket/WSS/QUIC
+- **Meta Service**: Raft-based cluster coordination, replaces ZooKeeper
+- **Storage Engine**: pluggable — Memory / RocksDB / File Segment, S3 tiering
+
+Key differentiators vs Kafka/NATS:
+- Multi-protocol on one deployment (no bridging, no data silos)
+- Compute-storage separation → scale independently in seconds (not hours)
+- Rust: no GC pauses, predictable latency
+- mq9: AI-native async mailbox protocol (see below)
+
+## What this SDK is
+
+Multi-language client SDK for RobustMQ. Currently implements **mq9** — more protocols (MQTT, Kafka, AMQP)
+will be added as RobustMQ matures.
+
+**Package naming strategy (Method A — single SDK per language):**
+Each language ships one package that grows to cover all protocols via sub-modules.
+Users install one package and import the protocol they need.
+
+| Language | Published package | mq9 import/usage |
+| ---------- | ---------------------------- | --------------------------------------------- |
+| Python | `robustmq` (PyPI) | `from robustmq.mq9 import Client` |
+| Go | `robustmq-sdk/go` (git tag) | `import "github.com/robustmq/robustmq-sdk/go/mq9"` |
+| JavaScript | `@robustmq/sdk` (npm) | `import { MQ9Client } from '@robustmq/sdk/mq9'` |
+| Java | `com.robustmq:robustmq` | `import com.robustmq.mq9.*` |
+| Rust | `robustmq` (crates.io) | `use robustmq::mq9::MQ9Client` |
+| C# | `RobustMQ` (NuGet) | `using RobustMQ.Mq9` |
+
+When new protocols are added (e.g. MQTT, Kafka), they live in sub-modules of the same package:
+`robustmq.mqtt`, `@robustmq/sdk/mqtt`, `com.robustmq.mqtt`, `robustmq::mqtt`, etc.
The owner does not intervene in implementation details. Claude makes all technical decisions
and drives the project forward autonomously.
@@ -13,29 +44,31 @@ and drives the project forward autonomously.
## Version management
-Source of truth: root `VERSION` file (currently `1.0.0`).
+Source of truth: root `VERSION` file (currently `0.3.5`).
When bumping the version, update `VERSION` and all 6 build files in one commit:
- Python: `python/pyproject.toml` + `python/robustmq/__init__.py`
- Rust: `rust/Cargo.toml`
-- Go: git tag only (e.g. `v1.0.0`) — no file to update
+- Go: git tag only (e.g. `v0.3.5`) — no file to update
- JavaScript: `javascript/package.json`
- Java: `java/pom.xml`
- C#: `csharp/RobustMQ.Mq9/RobustMQ.Mq9.csproj`
+Also update version references in `demo/`, `docs/`, and `README.md`.
+
---
## SDK implementation status
-| Language | Package/Import | Class | NATS lib | Status |
-| ---------- | ----------------- | ----------- | ------------ | -------------- |
-| Python | `robustmq.mq9` | `MQ9Client` | `nats-py` | Implemented |
-| Rust | `robustmq_mq9` | `MQ9Client` | `async-nats` | Scaffolded |
-| Go | `mq9` (pkg) | `MQ9Client` | `nats.go` | Scaffolded |
-| JavaScript | `@robustmq/mq9` | `MQ9Client` | `nats` v2 | Scaffolded |
-| Java | `com.robustmq.mq9` | `MQ9Client` | `jnats` | Scaffolded |
-| C# | `RobustMQ.Mq9` | `MQ9Client` | `NATS.Net` | Scaffolded |
+| Language | Package/Import | Class | NATS lib | Status |
+| ---------- | ----------------------- | ----------- | ------------ | -------------- |
+| Python | `robustmq.mq9` | `MQ9Client` | `nats-py` | Implemented |
+| Rust | `robustmq::mq9` | `MQ9Client` | `async-nats` | Scaffolded |
+| Go | `mq9` (pkg) | `MQ9Client` | `nats.go` | Scaffolded |
+| JavaScript | `@robustmq/sdk/mq9` | `MQ9Client` | `nats` v2 | Scaffolded |
+| Java | `com.robustmq.mq9` | `MQ9Client` | `jnats` | Scaffolded |
+| C# | `RobustMQ.Mq9` (ns) | `MQ9Client` | `NATS.Net` | Scaffolded |
Go constructor convention: `NewMQ9Client(...)` (struct, not class).
@@ -54,15 +87,23 @@ java/ # 🚧 Scaffolded only
csharp/ # 🚧 Scaffolded only
docs/
mq9-protocol.md # Authoritative protocol spec — read before implementing
-demo/ # End-to-end demo scripts, one per language
+demo/
+ demo-python/ # Standalone Python demo project
+ demo-go/ # Standalone Go demo project
+ demo-javascript/ # Standalone JavaScript demo project
+ demo-java/ # Standalone Java demo project (Maven)
+ demo-rust/ # Standalone Rust demo project
+ demo-csharp/ # Standalone C# demo project
```
---
## mq9 protocol
-mq9 gives AI agents a durable mailbox. Messages persist until TTL expires; senders and
-receivers do not need to be online simultaneously.
+mq9 is RobustMQ's AI-native async communication protocol. It gives AI agents a durable mailbox —
+messages persist until TTL expires; senders and receivers do not need to be online simultaneously.
+
+Built on top of NATS (transport layer), mq9 adds store-first semantics and priority queuing.
### Subject structure
@@ -137,7 +178,7 @@ Return types:
### All languages
- NATS client is the only required runtime dependency
-- Use `request/reply` for CREATE, LIST, DELETE, PUBLIC.LIST
+- Use `request/reply` for CREATE, LIST, DELETE
- Use plain `publish` for SEND (no reply needed)
- Raise a typed `MQ9Error` (with `.code: int`) on server error responses
- Tests mock the NATS connection — no live server required
@@ -182,15 +223,14 @@ Return types:
## Demo module
-Location: `demo/`
-One script per language, all running the same scenario:
+Location: `demo/`
+Each language has a standalone project that imports the published SDK v0.3.5.
+All demos run the same scenario:
1. Connect to `nats://localhost:4222`
2. Create a private mailbox (TTL 60s)
3. Send 3 messages (high / normal / low priority)
4. Subscribe and print received messages
-5. List mailbox, delete one message
-6. Create a public mailbox and discover it via PUBLIC.LIST
+5. List mailbox metadata, delete one message
+6. Create a public mailbox
7. Close connection
-
-Demo scripts are standalone — they import the SDK from the local source tree, not a published package.
diff --git a/README.md b/README.md
index 6558545..fb28efb 100644
--- a/README.md
+++ b/README.md
@@ -34,12 +34,12 @@ Full spec: [docs/mq9-protocol.md](docs/mq9-protocol.md)
| Language | Package | Version | Install |
|----------|---------|---------|---------|
-| Python | `robustmq-mq9` | 1.0.0 | `pip install robustmq-mq9` |
-| Go | `github.com/robustmq/robustmq-sdk/go` | v1.0.0 | `go get github.com/robustmq/robustmq-sdk/go` |
-| JavaScript | `@robustmq/mq9` | 1.0.0 | `npm install @robustmq/mq9` |
-| Java | `com.robustmq:robustmq-sdk` | 1.0.0 | Maven / Gradle (see below) |
-| Rust | `robustmq` | 1.0.0 | `cargo add robustmq` |
-| C# | `RobustMQ.Mq9` | 1.0.0 | `dotnet add package RobustMQ.Mq9` |
+| Python | `robustmq` | 0.3.5 | `pip install robustmq` |
+| Go | `github.com/robustmq/robustmq-sdk/go` | v0.3.5 | `go get github.com/robustmq/robustmq-sdk/go` |
+| JavaScript | `@robustmq/sdk` | 0.3.5 | `npm install @robustmq/sdk` |
+| Java | `com.robustmq:robustmq` | 0.3.5 | Maven / Gradle (see below) |
+| Rust | `robustmq` | 0.3.5 | `cargo add robustmq` |
+| C# | `RobustMQ` | 0.3.5 | `dotnet add package RobustMQ` |
---
@@ -47,12 +47,12 @@ Full spec: [docs/mq9-protocol.md](docs/mq9-protocol.md)
**Python**
```bash
-pip install robustmq-mq9
+pip install robustmq
```
```python
from robustmq.mq9 import Client, Priority
-async with Client("nats://localhost:4222") as client:
+async with Client("nats://demo.robustmq.com:4222") as client:
mailbox = await client.create(ttl=3600)
await client.send(mailbox.mail_id, b"hello", priority=Priority.NORMAL)
@@ -69,7 +69,7 @@ go get github.com/robustmq/robustmq-sdk/go
```go
import "github.com/robustmq/robustmq-sdk/go/mq9"
-c := mq9.NewMQ9Client("nats://localhost:4222")
+c := mq9.NewMQ9Client("nats://demo.robustmq.com:4222")
c.Connect()
mailbox, _ := c.Create(3600)
c.Send(mailbox.MailID, []byte("hello"), mq9.Normal)
@@ -77,12 +77,12 @@ c.Send(mailbox.MailID, []byte("hello"), mq9.Normal)
**JavaScript / TypeScript**
```bash
-npm install @robustmq/mq9
+npm install @robustmq/sdk
```
```typescript
-import { MQ9Client } from "@robustmq/mq9";
+import { MQ9Client } from "@robustmq/sdk/mq9";
-const client = new MQ9Client({ server: "nats://localhost:4222" });
+const client = new MQ9Client({ server: "nats://demo.robustmq.com:4222" });
await client.connect();
const mailbox = await client.create({ ttl: 3600 });
await client.send(mailbox.mailId, "hello", "normal");
@@ -92,14 +92,14 @@ await client.send(mailbox.mailId, "hello", "normal");
```xml
com.robustmq
- robustmq-sdk
- 1.0.0
+ robustmq
+ 0.3.5
```
```java
import com.robustmq.mq9.*;
-MQ9Client client = new MQ9Client("nats://localhost:4222");
+MQ9Client client = new MQ9Client("nats://demo.robustmq.com:4222");
client.connect();
Mailbox mailbox = client.create(3600).get();
client.send(mailbox.getMailId(), "hello".getBytes(), Priority.NORMAL).get();
@@ -107,31 +107,31 @@ client.send(mailbox.getMailId(), "hello".getBytes(), Priority.NORMAL).get();
**Java (Gradle)**
```groovy
-implementation 'com.robustmq:robustmq-sdk:1.0.0'
+implementation 'com.robustmq:robustmq:0.3.5'
```
**Rust**
```toml
[dependencies]
-robustmq = "1.0"
+robustmq = "0.3"
tokio = { version = "1", features = ["full"] }
```
```rust
use robustmq::mq9::{MQ9Client, Priority};
-let client = MQ9Client::connect("nats://localhost:4222").await?;
+let client = MQ9Client::connect("nats://demo.robustmq.com:4222").await?;
let mailbox = client.create(3600, false, "", "").await?;
client.send(&mailbox.mail_id, b"hello", Priority::Normal).await?;
```
**C#**
```bash
-dotnet add package RobustMQ.Mq9
+dotnet add package RobustMQ
```
```csharp
using RobustMQ.Mq9;
-await using var client = new MQ9Client("nats://localhost:4222");
+await using var client = new MQ9Client("nats://demo.robustmq.com:4222");
await client.ConnectAsync();
var mailbox = await client.CreateAsync(3600);
await client.SendAsync(mailbox.MailId, "hello"u8.ToArray(), Priority.Normal);
@@ -154,7 +154,7 @@ await client.SendAsync(mailbox.MailId, "hello"u8.ToArray(), Priority.Normal);
## Running the demo
-Each demo is a standalone project that connects to `nats://localhost:4222` and runs the same scenario:
+Each demo is a standalone project that connects to `nats://demo.robustmq.com:4222` and runs the same scenario:
1. Create a private mailbox (TTL 60s)
2. Send 3 messages (high / normal / low priority)
3. Subscribe and print received messages
@@ -200,7 +200,7 @@ demo/
demo-java/ # Java standalone demo project (Maven)
demo-rust/ # Rust standalone demo project
demo-csharp/ # C# standalone demo project
-VERSION # Canonical version (currently 1.0.0)
+VERSION # Canonical version (currently 0.3.5)
```
---
diff --git a/VERSION b/VERSION
index 3eefcb9..c2c0004 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.0
+0.3.5
diff --git a/csharp/RobustMQ.Mq9/MQ9Client.cs b/csharp/RobustMQ.Mq9/MQ9Client.cs
index 65ded5e..d2407f9 100644
--- a/csharp/RobustMQ.Mq9/MQ9Client.cs
+++ b/csharp/RobustMQ.Mq9/MQ9Client.cs
@@ -213,20 +213,19 @@ private static Mq9Message ParseMessageNode(string mailId, JsonNode node)
file sealed class SubscriptionHandle : IAsyncDisposable
{
- private readonly IDisposable _sub;
+ private readonly IAsyncDisposable _sub;
private readonly CancellationTokenSource _cts;
- public SubscriptionHandle(IDisposable sub, CancellationTokenSource cts)
+ public SubscriptionHandle(IAsyncDisposable sub, CancellationTokenSource cts)
{
_sub = sub;
_cts = cts;
}
- public ValueTask DisposeAsync()
+ public async ValueTask DisposeAsync()
{
_cts.Cancel();
- _sub.Dispose();
+ await _sub.DisposeAsync();
_cts.Dispose();
- return ValueTask.CompletedTask;
}
}
diff --git a/csharp/RobustMQ.Mq9/RobustMQ.Mq9.csproj b/csharp/RobustMQ.Mq9/RobustMQ.Mq9.csproj
index 4ae4626..1a6f203 100644
--- a/csharp/RobustMQ.Mq9/RobustMQ.Mq9.csproj
+++ b/csharp/RobustMQ.Mq9/RobustMQ.Mq9.csproj
@@ -4,10 +4,11 @@
net8.0
enable
enable
+ RobustMQ
RobustMQ.Mq9
- RobustMQ.Mq9
- 1.0.0
- RobustMQ C# SDK — mq9 AI-native async messaging
+ RobustMQ
+ 0.3.5
+ RobustMQ SDK — unified messaging for AI, IoT, and data pipelines
Apache-2.0
@@ -15,4 +16,10 @@
+
+
+ <_Parameter1>RobustMQ.Mq9.Tests
+
+
+
diff --git a/demo/demo-csharp/Program.cs b/demo/demo-csharp/Program.cs
index 7235b3b..7401715 100644
--- a/demo/demo-csharp/Program.cs
+++ b/demo/demo-csharp/Program.cs
@@ -1,5 +1,5 @@
/**
- * mq9 C# demo — connects to nats://localhost:4222 and runs the full scenario.
+ * mq9 C# demo — connects to nats://demo.robustmq.com:4222 and runs the full scenario.
*
* Run:
* cd demo/demo-csharp
@@ -9,7 +9,8 @@
using System.Text;
using RobustMQ.Mq9;
-await using var client = new MQ9Client("nats://localhost:4222");
+// demo.robustmq.com 是公共的 RobustMQ 服务,可用于验证功能和测试,也可修改为自己的服务地址。
+await using var client = new MQ9Client("nats://demo.robustmq.com:4222");
await client.ConnectAsync();
Console.WriteLine("[csharp] connected");
diff --git a/demo/demo-csharp/demo-csharp.csproj b/demo/demo-csharp/demo-csharp.csproj
index bc3f7b2..e61b430 100644
--- a/demo/demo-csharp/demo-csharp.csproj
+++ b/demo/demo-csharp/demo-csharp.csproj
@@ -8,7 +8,7 @@
-
+
diff --git a/demo/demo-go/main.go b/demo/demo-go/main.go
index 81b0926..575b831 100644
--- a/demo/demo-go/main.go
+++ b/demo/demo-go/main.go
@@ -1,4 +1,4 @@
-// mq9 Go demo — connects to nats://localhost:4222 and runs the full scenario.
+// mq9 Go demo — connects to nats://demo.robustmq.com:4222 and runs the full scenario.
//
// Run:
//
@@ -15,7 +15,8 @@ import (
)
func main() {
- c := mq9.NewMQ9Client("nats://localhost:4222")
+ // demo.robustmq.com 是公共的 RobustMQ 服务,可用于验证功能和测试,也可修改为自己的服务地址。
+ c := mq9.NewMQ9Client("nats://demo.robustmq.com:4222")
if err := c.Connect(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
diff --git a/demo/demo-java/pom.xml b/demo/demo-java/pom.xml
index d573c04..6da7d8a 100644
--- a/demo/demo-java/pom.xml
+++ b/demo/demo-java/pom.xml
@@ -7,7 +7,7 @@
io.robustmq.demo
demo-java
- 1.0.0
+ 0.3.5
jar
RobustMQ mq9 Java Demo
@@ -21,8 +21,8 @@
com.robustmq
- robustmq-sdk
- 1.0.0
+ robustmq
+ 0.3.5
diff --git a/demo/demo-java/src/main/java/com/robustmq/demo/Demo.java b/demo/demo-java/src/main/java/com/robustmq/demo/Demo.java
index f897b42..4f0d6b9 100644
--- a/demo/demo-java/src/main/java/com/robustmq/demo/Demo.java
+++ b/demo/demo-java/src/main/java/com/robustmq/demo/Demo.java
@@ -9,7 +9,7 @@
import java.util.concurrent.TimeUnit;
/**
- * mq9 Java demo — connects to nats://localhost:4222 and runs the full scenario.
+ * mq9 Java demo — connects to nats://demo.robustmq.com:4222 and runs the full scenario.
*
* Run:
* cd demo/demo-java
@@ -17,7 +17,8 @@
*/
public class Demo {
public static void main(String[] args) throws Exception {
- MQ9Client client = new MQ9Client("nats://localhost:4222");
+ // demo.robustmq.com 是公共的 RobustMQ 服务,可用于验证功能和测试,也可修改为自己的服务地址。
+ MQ9Client client = new MQ9Client("nats://demo.robustmq.com:4222");
client.connect();
System.out.println("[java] connected");
diff --git a/demo/demo-javascript/demo.js b/demo/demo-javascript/demo.js
index 0a48fd5..c82a8f9 100644
--- a/demo/demo-javascript/demo.js
+++ b/demo/demo-javascript/demo.js
@@ -1,5 +1,5 @@
/**
- * mq9 JavaScript demo — connects to nats://localhost:4222 and runs the full scenario.
+ * mq9 JavaScript demo — connects to nats://demo.robustmq.com:4222 and runs the full scenario.
*
* Run:
* cd demo/demo-javascript
@@ -7,10 +7,11 @@
* npm start
*/
-const { MQ9Client } = require("@robustmq/mq9");
+const { MQ9Client } = require("@robustmq/sdk/mq9");
async function main() {
- const client = new MQ9Client({ server: "nats://localhost:4222" });
+ // demo.robustmq.com 是公共的 RobustMQ 服务,可用于验证功能和测试,也可修改为自己的服务地址。
+ const client = new MQ9Client({ server: "nats://demo.robustmq.com:4222" });
await client.connect();
console.log("[js] connected");
diff --git a/demo/demo-javascript/package.json b/demo/demo-javascript/package.json
index 5d3e5be..1a620cd 100644
--- a/demo/demo-javascript/package.json
+++ b/demo/demo-javascript/package.json
@@ -8,6 +8,6 @@
"start": "node demo.js"
},
"dependencies": {
- "@robustmq/mq9": "1.0.0"
+ "@robustmq/sdk": "0.3.5"
}
}
diff --git a/demo/demo-python/demo.py b/demo/demo-python/demo.py
index 5d0995e..c050c78 100644
--- a/demo/demo-python/demo.py
+++ b/demo/demo-python/demo.py
@@ -1,5 +1,5 @@
"""
-mq9 Python demo — connects to nats://localhost:4222 and runs the full scenario.
+mq9 Python demo — connects to nats://demo.robustmq.com:4222 and runs the full scenario.
Run:
cd demo/demo-python
@@ -12,7 +12,8 @@
async def main() -> None:
- client = Client(server="nats://localhost:4222")
+ # demo.robustmq.com 是公共的 RobustMQ 服务,可用于验证功能和测试,也可修改为自己的服务地址。
+ client = Client(server="nats://demo.robustmq.com:4222")
await client.connect()
print("[python] connected")
diff --git a/demo/demo-python/pyproject.toml b/demo/demo-python/pyproject.toml
index 84e277a..3d39314 100644
--- a/demo/demo-python/pyproject.toml
+++ b/demo/demo-python/pyproject.toml
@@ -1,9 +1,9 @@
[project]
name = "demo-python"
-version = "1.0.0"
+version = "0.3.5"
requires-python = ">=3.10"
dependencies = [
- "robustmq-mq9==1.0.0",
+ "robustmq==0.3.5",
]
[build-system]
diff --git a/demo/demo-python/requirements.txt b/demo/demo-python/requirements.txt
index 20f1182..dc44c8e 100644
--- a/demo/demo-python/requirements.txt
+++ b/demo/demo-python/requirements.txt
@@ -1 +1 @@
-robustmq-mq9==1.0.0
+robustmq==0.3.5
diff --git a/demo/demo-rust/Cargo.toml b/demo/demo-rust/Cargo.toml
index 42c8cae..23a42e9 100644
--- a/demo/demo-rust/Cargo.toml
+++ b/demo/demo-rust/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "demo-rust"
-version = "1.0.0"
+version = "0.3.5"
edition = "2021"
[[bin]]
@@ -8,5 +8,5 @@ name = "demo"
path = "src/main.rs"
[dependencies]
-robustmq = { version = "1.0.0", features = ["mq9"] }
+robustmq = { version = "0.3.5", features = ["mq9"] }
tokio = { version = "1", features = ["full"] }
diff --git a/demo/demo-rust/src/main.rs b/demo/demo-rust/src/main.rs
index 04e7a1b..af662d0 100644
--- a/demo/demo-rust/src/main.rs
+++ b/demo/demo-rust/src/main.rs
@@ -1,4 +1,4 @@
-// mq9 Rust demo — connects to nats://localhost:4222 and runs the full scenario.
+// mq9 Rust demo — connects to nats://demo.robustmq.com:4222 and runs the full scenario.
//
// Run:
// cd demo/demo-rust
@@ -9,7 +9,8 @@ use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() -> Result<(), Box> {
- let client = MQ9Client::connect("nats://localhost:4222").await?;
+ // demo.robustmq.com 是公共的 RobustMQ 服务,可用于验证功能和测试,也可修改为自己的服务地址。
+ let client = MQ9Client::connect("nats://demo.robustmq.com:4222").await?;
println!("[rust] connected");
// 1. Create a private mailbox (TTL 60s)
diff --git a/docs/csharp.md b/docs/csharp.md
index 7d2eaa2..7efdae7 100644
--- a/docs/csharp.md
+++ b/docs/csharp.md
@@ -1,12 +1,12 @@
# C# SDK
-**Package:** `RobustMQ.Mq9`
+**Package:** `RobustMQ`
**Requires:** .NET 8+, `NATS.Net`
## Install
```bash
-dotnet add package RobustMQ.Mq9
+dotnet add package RobustMQ
```
## Quick start
@@ -14,7 +14,7 @@ dotnet add package RobustMQ.Mq9
```csharp
using RobustMQ.Mq9;
-await using var client = new MQ9Client("nats://localhost:4222");
+await using var client = new MQ9Client("nats://demo.robustmq.com:4222");
await client.ConnectAsync();
// Create mailbox
@@ -39,7 +39,7 @@ await client.DeleteAsync(mailbox.MailId, metas[0].MsgId);
## API
```csharp
-MQ9Client(string server = "nats://localhost:4222") // IAsyncDisposable
+MQ9Client(string server = "nats://demo.robustmq.com:4222") // IAsyncDisposable
Task ConnectAsync()
ValueTask DisposeAsync()
diff --git a/docs/go.md b/docs/go.md
index 4a2b1ab..34b01d0 100644
--- a/docs/go.md
+++ b/docs/go.md
@@ -21,7 +21,7 @@ import (
)
func main() {
- c := mq9.NewMQ9Client("nats://localhost:4222")
+ c := mq9.NewMQ9Client("nats://demo.robustmq.com:4222")
c.Connect()
defer c.Close()
diff --git a/docs/java.md b/docs/java.md
index eb7497d..d078547 100644
--- a/docs/java.md
+++ b/docs/java.md
@@ -8,8 +8,8 @@
```xml
com.robustmq
- robustmq-sdk
- 1.0.0
+ robustmq
+ 0.3.5
```
@@ -19,7 +19,7 @@
import com.robustmq.mq9.*;
import java.util.List;
-MQ9Client client = new MQ9Client("nats://localhost:4222");
+MQ9Client client = new MQ9Client("nats://demo.robustmq.com:4222");
client.connect();
// Create mailbox
diff --git a/docs/javascript.md b/docs/javascript.md
index 0e9e6fc..4679800 100644
--- a/docs/javascript.md
+++ b/docs/javascript.md
@@ -1,20 +1,20 @@
# JavaScript / TypeScript SDK
-**Package:** `@robustmq/mq9`
+**Package:** `@robustmq/sdk`
**Requires:** Node.js 18+, `nats` v2
## Install
```bash
-npm install @robustmq/mq9
+npm install @robustmq/sdk
```
## Quick start
```typescript
-import { MQ9Client } from "@robustmq/mq9";
+import { MQ9Client } from "@robustmq/sdk/mq9";
-const client = new MQ9Client({ server: "nats://localhost:4222" });
+const client = new MQ9Client({ server: "nats://demo.robustmq.com:4222" });
await client.connect();
// Create mailbox
diff --git a/docs/python.md b/docs/python.md
index 5a73191..0aab513 100644
--- a/docs/python.md
+++ b/docs/python.md
@@ -6,7 +6,7 @@
## Install
```bash
-pip install robustmq-mq9
+pip install robustmq
```
## Quick start
@@ -16,7 +16,7 @@ import asyncio
from robustmq.mq9 import Client, Priority
async def main():
- async with Client(server="nats://localhost:4222") as client:
+ async with Client(server="nats://demo.robustmq.com:4222") as client:
# Create mailbox
mailbox = await client.create(ttl=3600)
@@ -45,7 +45,7 @@ asyncio.run(main())
## API
```python
-Client(server="nats://localhost:4222", *, max_reconnect_attempts=10,
+Client(server="nats://demo.robustmq.com:4222", *, max_reconnect_attempts=10,
reconnect_time_wait=2.0, request_timeout=5.0)
await client.connect()
diff --git a/docs/rust.md b/docs/rust.md
index 9cf5238..97852c6 100644
--- a/docs/rust.md
+++ b/docs/rust.md
@@ -7,7 +7,7 @@
```toml
[dependencies]
-robustmq = "1.0"
+robustmq = "0.3"
tokio = { version = "1", features = ["full"] }
```
@@ -18,7 +18,7 @@ use robustmq::mq9::{MQ9Client, Priority};
#[tokio::main]
async fn main() -> Result<(), Box> {
- let client = MQ9Client::connect("nats://localhost:4222").await?;
+ let client = MQ9Client::connect("nats://demo.robustmq.com:4222").await?;
// Create mailbox
let mailbox = client.create(3600, false, "", "").await?;
diff --git a/java/checkstyle.xml b/java/checkstyle.xml
new file mode 100644
index 0000000..fe42e15
--- /dev/null
+++ b/java/checkstyle.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/java/pom.xml b/java/pom.xml
index 0a8ab66..461b4d0 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -6,12 +6,12 @@
4.0.0
com.robustmq
- robustmq-sdk
- 1.0.0
+ robustmq
+ 0.3.5
jar
RobustMQ Java SDK
- RobustMQ Java SDK — mq9 AI-native async messaging
+ RobustMQ Java SDK — unified messaging for AI, IoT, and data pipelines
https://github.com/robustmq/robustmq-sdk
@@ -99,6 +99,17 @@
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ 3.4.0
+
+ checkstyle.xml
+ true
+ true
+ warning
+
+
diff --git a/java/src/main/java/com/robustmq/mq9/MQ9Client.java b/java/src/main/java/com/robustmq/mq9/MQ9Client.java
index 55f1bad..2253c74 100644
--- a/java/src/main/java/com/robustmq/mq9/MQ9Client.java
+++ b/java/src/main/java/com/robustmq/mq9/MQ9Client.java
@@ -10,7 +10,6 @@
import io.nats.client.Options;
import java.io.IOException;
-import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Base64;
@@ -77,18 +76,18 @@ public void close() {
// ── Create ────────────────────────────────────────────────────────────────
- public CompletableFuture create(int ttl) {
+ public CompletableFuture create(int ttl) {
return createInternal(ttl, false, "", "");
}
- public CompletableFuture createPublic(int ttl, String name, String desc) {
+ public CompletableFuture createPublic(int ttl, String name, String desc) {
if (name == null || name.isEmpty()) {
return CompletableFuture.failedFuture(new MQ9Error("name is required when public=true"));
}
return createInternal(ttl, true, name, desc != null ? desc : "");
}
- private CompletableFuture createInternal(int ttl, boolean isPublic,
+ private CompletableFuture createInternal(int ttl, boolean isPublic,
String name, String desc) {
return CompletableFuture.supplyAsync(() -> {
ObjectNode req = mapper.createObjectNode();
@@ -100,7 +99,7 @@ private CompletableFuture createInternal(int ttl, boole
}
JsonNode resp = doRequest(MAILBOX_CREATE, req);
String mailId = resp.get("mail_id").asText();
- return new io.robustmq.mq9.Mailbox(mailId, isPublic, name, desc);
+ return new com.robustmq.mq9.Mailbox(mailId, isPublic, name, desc);
});
}
@@ -129,7 +128,7 @@ public CompletableFuture subscribe(String mailId, MessageHandler han
: PREFIX + ".MAILBOX.MSG." + mailId + ".*";
Dispatcher dispatcher = nc.createDispatcher((Message msg) -> {
- io.robustmq.mq9.Message m = parseIncoming(mailId, msg);
+ com.robustmq.mq9.Message m = parseIncoming(mailId, msg);
handler.onMessage(m);
});
@@ -201,7 +200,7 @@ private JsonNode doRequest(String subject, ObjectNode payload) {
}
}
- private io.robustmq.mq9.Message parseIncoming(String mailId, Message raw) {
+ private com.robustmq.mq9.Message parseIncoming(String mailId, Message raw) {
// Extract priority from subject last token
String subject = raw.getSubject();
String[] parts = subject.split("\\.");
@@ -218,14 +217,14 @@ private io.robustmq.mq9.Message parseIncoming(String mailId, Message raw) {
// fall through to raw payload
}
- return new io.robustmq.mq9.Message("", mailId, priority, raw.getData());
+ return new com.robustmq.mq9.Message("", mailId, priority, raw.getData());
}
- private io.robustmq.mq9.Message parseMessageNode(String mailId, JsonNode node) {
+ private com.robustmq.mq9.Message parseMessageNode(String mailId, JsonNode node) {
String msgId = node.path("msg_id").asText("");
Priority priority = Priority.fromString(node.path("priority").asText("normal"));
String rawPayload = node.path("payload").asText("");
byte[] payload = rawPayload.isEmpty() ? new byte[0] : Base64.getDecoder().decode(rawPayload);
- return new io.robustmq.mq9.Message(msgId, mailId, priority, payload);
+ return new com.robustmq.mq9.Message(msgId, mailId, priority, payload);
}
}
diff --git a/javascript/eslint.config.js b/javascript/eslint.config.js
new file mode 100644
index 0000000..aa57556
--- /dev/null
+++ b/javascript/eslint.config.js
@@ -0,0 +1,15 @@
+// @ts-check
+const tseslint = require("typescript-eslint");
+
+module.exports = tseslint.config(
+ ...tseslint.configs.recommended,
+ {
+ rules: {
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
+ },
+ },
+ {
+ ignores: ["dist/**", "node_modules/**"],
+ }
+);
diff --git a/javascript/package-lock.json b/javascript/package-lock.json
index 727620a..ba30e9a 100644
--- a/javascript/package-lock.json
+++ b/javascript/package-lock.json
@@ -1,12 +1,12 @@
{
- "name": "@robustmq/mq9",
- "version": "1.0.0",
+ "name": "@robustmq/sdk",
+ "version": "0.3.5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
- "name": "@robustmq/mq9",
- "version": "1.0.0",
+ "name": "@robustmq/sdk",
+ "version": "0.3.5",
"license": "Apache-2.0",
"dependencies": {
"nats": "^2.27.0"
@@ -14,9 +14,11 @@
"devDependencies": {
"@types/jest": "^30.0.0",
"@types/node": "^25.5.2",
+ "eslint": "^9.0.0",
"jest": "^30.3.0",
"ts-jest": "^29.0.0",
- "typescript": "^6.0.2"
+ "typescript": "^6.0.2",
+ "typescript-eslint": "^8.0.0"
}
},
"node_modules/@babel/code-frame": {
@@ -549,6 +551,270 @@
"tslib": "^2.4.0"
}
},
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
+ "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.2",
+ "resolved": "https://registry.npmmirror.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+ "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/config-array": {
+ "version": "0.21.2",
+ "resolved": "https://registry.npmmirror.com/@eslint/config-array/-/config-array-0.21.2.tgz",
+ "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.7",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.5"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/config-array/node_modules/brace-expansion": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.13.tgz",
+ "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/@eslint/config-array/node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmmirror.com/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
+ "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmmirror.com/@eslint/core/-/core-0.17.0.tgz",
+ "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-3.3.5.tgz",
+ "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.14.0",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.1",
+ "minimatch": "^3.1.5",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.13.tgz",
+ "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/js-yaml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "9.39.4",
+ "resolved": "https://registry.npmmirror.com/@eslint/js/-/js-9.39.4.tgz",
+ "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmmirror.com/@eslint/object-schema/-/object-schema-2.1.7.tgz",
+ "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmmirror.com/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
+ "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0",
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@humanfs/core": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmmirror.com/@humanfs/core/-/core-0.19.1.tgz",
+ "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.7",
+ "resolved": "https://registry.npmmirror.com/@humanfs/node/-/node-0.16.7.tgz",
+ "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/core": "^0.19.1",
+ "@humanwhocodes/retry": "^0.4.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmmirror.com/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -1104,6 +1370,13 @@
"@babel/types": "^7.28.2"
}
},
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/istanbul-lib-coverage": {
"version": "2.0.6",
"resolved": "https://registry.npmmirror.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
@@ -1142,6 +1415,13 @@
"pretty-format": "^30.0.0"
}
},
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/node": {
"version": "25.5.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.2.tgz",
@@ -1176,6 +1456,301 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "8.58.1",
+ "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.58.1.tgz",
+ "integrity": "sha512-eSkwoemjo76bdXl2MYqtxg51HNwUSkWfODUOQ3PaTLZGh9uIWWFZIjyjaJnex7wXDu+TRx+ATsnSxdN9YWfRTQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.12.2",
+ "@typescript-eslint/scope-manager": "8.58.1",
+ "@typescript-eslint/type-utils": "8.58.1",
+ "@typescript-eslint/utils": "8.58.1",
+ "@typescript-eslint/visitor-keys": "8.58.1",
+ "ignore": "^7.0.5",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^2.5.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.58.1",
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmmirror.com/ignore/-/ignore-7.0.5.tgz",
+ "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "8.58.1",
+ "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.58.1.tgz",
+ "integrity": "sha512-gGkiNMPqerb2cJSVcruigx9eHBlLG14fSdPdqMoOcBfh+vvn4iCq2C8MzUB89PrxOXk0y3GZ1yIWb9aOzL93bw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "8.58.1",
+ "@typescript-eslint/types": "8.58.1",
+ "@typescript-eslint/typescript-estree": "8.58.1",
+ "@typescript-eslint/visitor-keys": "8.58.1",
+ "debug": "^4.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/project-service": {
+ "version": "8.58.1",
+ "resolved": "https://registry.npmmirror.com/@typescript-eslint/project-service/-/project-service-8.58.1.tgz",
+ "integrity": "sha512-gfQ8fk6cxhtptek+/8ZIqw8YrRW5048Gug8Ts5IYcMLCw18iUgrZAEY/D7s4hkI0FxEfGakKuPK/XUMPzPxi5g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/tsconfig-utils": "^8.58.1",
+ "@typescript-eslint/types": "^8.58.1",
+ "debug": "^4.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.58.1",
+ "resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.58.1.tgz",
+ "integrity": "sha512-TPYUEqJK6avLcEjumWsIuTpuYODTTDAtoMdt8ZZa93uWMTX13Nb8L5leSje1NluammvU+oI3QRr5lLXPgihX3w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.58.1",
+ "@typescript-eslint/visitor-keys": "8.58.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/tsconfig-utils": {
+ "version": "8.58.1",
+ "resolved": "https://registry.npmmirror.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.1.tgz",
+ "integrity": "sha512-JAr2hOIct2Q+qk3G+8YFfqkqi7sC86uNryT+2i5HzMa2MPjw4qNFvtjnw1IiA1rP7QhNKVe21mSSLaSjwA1Olw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "8.58.1",
+ "resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.58.1.tgz",
+ "integrity": "sha512-HUFxvTJVroT+0rXVJC7eD5zol6ID+Sn5npVPWoFuHGg9Ncq5Q4EYstqR+UOqaNRFXi5TYkpXXkLhoCHe3G0+7w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.58.1",
+ "@typescript-eslint/typescript-estree": "8.58.1",
+ "@typescript-eslint/utils": "8.58.1",
+ "debug": "^4.4.3",
+ "ts-api-utils": "^2.5.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "8.58.1",
+ "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.58.1.tgz",
+ "integrity": "sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.58.1",
+ "resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.58.1.tgz",
+ "integrity": "sha512-w4w7WR7GHOjqqPnvAYbazq+Y5oS68b9CzasGtnd6jIeOIeKUzYzupGTB2T4LTPSv4d+WPeccbxuneTFHYgAAWg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/project-service": "8.58.1",
+ "@typescript-eslint/tsconfig-utils": "8.58.1",
+ "@typescript-eslint/types": "8.58.1",
+ "@typescript-eslint/visitor-keys": "8.58.1",
+ "debug": "^4.4.3",
+ "minimatch": "^10.2.2",
+ "semver": "^7.7.3",
+ "tinyglobby": "^0.2.15",
+ "ts-api-utils": "^2.5.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-4.0.4.tgz",
+ "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-5.0.5.tgz",
+ "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
+ "version": "10.2.5",
+ "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-10.2.5.tgz",
+ "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "brace-expansion": "^5.0.5"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
+ "version": "7.7.4",
+ "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.4.tgz",
+ "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "8.58.1",
+ "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.58.1.tgz",
+ "integrity": "sha512-Ln8R0tmWC7pTtLOzgJzYTXSCjJ9rDNHAqTaVONF4FEi2qwce8mD9iSOxOpLFFvWp/wBFlew0mjM1L1ihYWfBdQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.9.1",
+ "@typescript-eslint/scope-manager": "8.58.1",
+ "@typescript-eslint/types": "8.58.1",
+ "@typescript-eslint/typescript-estree": "8.58.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.58.1",
+ "resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.58.1.tgz",
+ "integrity": "sha512-y+vH7QE8ycjoa0bWciFg7OpFcipUuem1ujhrdLtq1gByKwfbC7bPeKsiny9e0urg93DqwGcHey+bGRKCnF1nZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.58.1",
+ "eslint-visitor-keys": "^5.0.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+ "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
"node_modules/@ungap/structured-clone": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
@@ -1452,6 +2027,46 @@
"win32"
]
},
+ "node_modules/acorn": {
+ "version": "8.16.0",
+ "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.16.0.tgz",
+ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.14.0",
+ "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.14.0.tgz",
+ "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
"node_modules/ansi-escapes": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
@@ -1983,6 +2598,13 @@
}
}
},
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/deepmerge": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
@@ -2054,17 +2676,211 @@
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=6"
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "9.39.4",
+ "resolved": "https://registry.npmmirror.com/eslint/-/eslint-9.39.4.tgz",
+ "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.8.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.21.2",
+ "@eslint/config-helpers": "^0.4.2",
+ "@eslint/core": "^0.17.0",
+ "@eslint/eslintrc": "^3.3.5",
+ "@eslint/js": "9.39.4",
+ "@eslint/plugin-kit": "^0.4.1",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "ajv": "^6.14.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.5",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/brace-expansion": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.13.tgz",
+ "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/eslint/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/eslint/node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/escape-string-regexp": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
- "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "node_modules/espree": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmmirror.com/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
"dev": true,
- "license": "MIT",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
+ },
"engines": {
- "node": ">=8"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
"node_modules/esprima": {
@@ -2081,6 +2897,52 @@
"node": ">=4"
}
},
+ "node_modules/esquery": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.7.0.tgz",
+ "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/execa": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
@@ -2133,6 +2995,13 @@
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -2140,6 +3009,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/fb-watchman": {
"version": "2.0.2",
"resolved": "https://registry.npmmirror.com/fb-watchman/-/fb-watchman-2.0.2.tgz",
@@ -2150,6 +3026,19 @@
"bser": "2.1.1"
}
},
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
"node_modules/find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmmirror.com/find-up/-/find-up-4.1.0.tgz",
@@ -2164,6 +3053,27 @@
"node": ">=8"
}
},
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.4.2.tgz",
+ "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
+ "dev": true,
+ "license": "ISC"
+ },
"node_modules/foreground-child": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
@@ -2281,6 +3191,32 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmmirror.com/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -2337,6 +3273,43 @@
"node": ">=10.17.0"
}
},
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/import-fresh/node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/import-local": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
@@ -2393,6 +3366,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
@@ -2413,6 +3396,19 @@
"node": ">=6"
}
},
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/is-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
@@ -3198,6 +4194,13 @@
"node": ">=6"
}
},
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/json-parse-even-better-errors": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
@@ -3205,6 +4208,20 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/json5": {
"version": "2.2.3",
"resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz",
@@ -3218,6 +4235,16 @@
"node": ">=6"
}
},
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
"node_modules/leven": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
@@ -3228,6 +4255,20 @@
"node": ">=6"
}
},
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@@ -3255,6 +4296,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz",
@@ -3488,6 +4536,24 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
"node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
@@ -3550,6 +4616,19 @@
"dev": true,
"license": "BlueOak-1.0.0"
},
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/parse-json": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
@@ -3666,6 +4745,16 @@
"node": ">=8"
}
},
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
"node_modules/pretty-format": {
"version": "30.3.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz",
@@ -3694,6 +4783,16 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/pure-rand": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz",
@@ -4106,6 +5205,54 @@
"node": "*"
}
},
+ "node_modules/tinyglobby": {
+ "version": "0.2.16",
+ "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.16.tgz",
+ "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/tinyglobby/node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tinyglobby/node_modules/picomatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/tmpl": {
"version": "1.0.5",
"resolved": "https://registry.npmmirror.com/tmpl/-/tmpl-1.0.5.tgz",
@@ -4113,6 +5260,19 @@
"dev": true,
"license": "BSD-3-Clause"
},
+ "node_modules/ts-api-utils": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
+ "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.12"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4"
+ }
+ },
"node_modules/ts-jest": {
"version": "29.4.9",
"resolved": "https://registry.npmmirror.com/ts-jest/-/ts-jest-29.4.9.tgz",
@@ -4206,6 +5366,19 @@
"integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==",
"license": "Unlicense"
},
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
"node_modules/type-detect": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
@@ -4243,6 +5416,30 @@
"node": ">=14.17"
}
},
+ "node_modules/typescript-eslint": {
+ "version": "8.58.1",
+ "resolved": "https://registry.npmmirror.com/typescript-eslint/-/typescript-eslint-8.58.1.tgz",
+ "integrity": "sha512-gf6/oHChByg9HJvhMO1iBexJh12AqqTfnuxscMDOVqfJW3htsdRJI/GfPpHTTcyeB8cSTUY2JcZmVgoyPqcrDg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/eslint-plugin": "8.58.1",
+ "@typescript-eslint/parser": "8.58.1",
+ "@typescript-eslint/typescript-estree": "8.58.1",
+ "@typescript-eslint/utils": "8.58.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
"node_modules/uglify-js": {
"version": "3.19.3",
"resolved": "https://registry.npmmirror.com/uglify-js/-/uglify-js-3.19.3.tgz",
@@ -4330,6 +5527,16 @@
"browserslist": ">= 4.21.0"
}
},
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
"node_modules/v8-to-istanbul": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
@@ -4371,6 +5578,16 @@
"node": ">= 8"
}
},
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/wordwrap": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/wordwrap/-/wordwrap-1.0.0.tgz",
diff --git a/javascript/package.json b/javascript/package.json
index 599336b..1ba77a1 100644
--- a/javascript/package.json
+++ b/javascript/package.json
@@ -1,9 +1,21 @@
{
- "name": "@robustmq/mq9",
- "version": "1.0.0",
- "description": "RobustMQ JavaScript/TypeScript SDK — mq9 AI-native async messaging",
+ "name": "@robustmq/sdk",
+ "version": "0.3.5",
+ "description": "RobustMQ JavaScript/TypeScript SDK",
"main": "dist/index.js",
"types": "dist/index.d.ts",
+ "exports": {
+ ".": {
+ "require": "./dist/index.js",
+ "import": "./dist/index.js",
+ "types": "./dist/index.d.ts"
+ },
+ "./mq9": {
+ "require": "./dist/mq9/client.js",
+ "import": "./dist/mq9/client.js",
+ "types": "./dist/mq9/client.d.ts"
+ }
+ },
"license": "Apache-2.0",
"scripts": {
"build": "tsc",
@@ -15,6 +27,8 @@
"devDependencies": {
"@types/jest": "^30.0.0",
"@types/node": "^25.5.2",
+ "eslint": "^9.0.0",
+ "typescript-eslint": "^8.0.0",
"jest": "^30.3.0",
"ts-jest": "^29.0.0",
"typescript": "^6.0.2"
diff --git a/javascript/src/mq9/client.test.ts b/javascript/src/mq9/client.test.ts
index 0da7124..1c67aa6 100644
--- a/javascript/src/mq9/client.test.ts
+++ b/javascript/src/mq9/client.test.ts
@@ -1,4 +1,10 @@
-import { MQ9Client, MQ9Error, NatsTransport, Mq9Message, MessageMeta, Priority } from "./client.js";
+import {
+ MQ9Client,
+ MQ9Error,
+ NatsTransport,
+ MessageMeta,
+ Priority,
+} from "./client.js";
// ---------------------------------------------------------------------------
// Mock transport
@@ -41,13 +47,15 @@ describe("create", () => {
expect(t.request).toHaveBeenCalledWith(
"$mq9.AI.MAILBOX.CREATE",
expect.any(Uint8Array),
- expect.anything()
+ expect.anything(),
);
});
test("public mailbox", async () => {
const t = mockTransport({
- request: jest.fn().mockResolvedValue(jsonReply({ mail_id: "task.queue" })),
+ request: jest
+ .fn()
+ .mockResolvedValue(jsonReply({ mail_id: "task.queue" })),
});
const client = clientWith(t);
const mb = await client.create({
@@ -61,7 +69,7 @@ describe("create", () => {
expect(mb.public).toBe(true);
const sentPayload = JSON.parse(
- Buffer.from((t.request as jest.Mock).mock.calls[0][1]).toString()
+ Buffer.from((t.request as jest.Mock).mock.calls[0][1]).toString(),
);
expect(sentPayload.public).toBe(true);
expect(sentPayload.name).toBe("task.queue");
@@ -70,15 +78,15 @@ describe("create", () => {
test("public without name throws MQ9Error", async () => {
const client = clientWith(mockTransport());
await expect(client.create({ ttl: 3600, public: true })).rejects.toThrow(
- MQ9Error
+ MQ9Error,
);
});
test("server error throws MQ9Error with code", async () => {
const t = mockTransport({
- request: jest.fn().mockResolvedValue(
- jsonReply({ error: "quota exceeded", code: 429 })
- ),
+ request: jest
+ .fn()
+ .mockResolvedValue(jsonReply({ error: "quota exceeded", code: 429 })),
});
const client = clientWith(t);
const err = await client.create({ ttl: 3600 }).catch((e) => e);
@@ -99,7 +107,7 @@ describe("send", () => {
expect(t.publish).toHaveBeenCalledWith(
"$mq9.AI.MAILBOX.MSG.m-001.normal",
- expect.any(Uint8Array)
+ expect.any(Uint8Array),
);
});
@@ -110,7 +118,7 @@ describe("send", () => {
expect(t.publish).toHaveBeenCalledWith(
"$mq9.AI.MAILBOX.MSG.m-001.high",
- expect.any(Uint8Array)
+ expect.any(Uint8Array),
);
});
@@ -129,7 +137,9 @@ describe("send", () => {
await client.send("m-001", { task: "summarize" });
const data = (t.publish as jest.Mock).mock.calls[0][1] as Uint8Array;
- expect(JSON.parse(Buffer.from(data).toString())).toEqual({ task: "summarize" });
+ expect(JSON.parse(Buffer.from(data).toString())).toEqual({
+ task: "summarize",
+ });
});
});
@@ -143,10 +153,8 @@ describe("list", () => {
request: jest.fn().mockResolvedValue(
jsonReply({
mail_id: "m-001",
- messages: [
- { msg_id: "x1", priority: "high", ts: 100 },
- ],
- })
+ messages: [{ msg_id: "x1", priority: "high", ts: 100 }],
+ }),
),
});
const client = clientWith(t);
@@ -160,15 +168,15 @@ describe("list", () => {
expect(t.request).toHaveBeenCalledWith(
"$mq9.AI.MAILBOX.LIST.m-001",
expect.any(Uint8Array),
- expect.anything()
+ expect.anything(),
);
});
test("returns empty array for empty mailbox", async () => {
const t = mockTransport({
- request: jest.fn().mockResolvedValue(
- jsonReply({ mail_id: "m-001", messages: [] })
- ),
+ request: jest
+ .fn()
+ .mockResolvedValue(jsonReply({ mail_id: "m-001", messages: [] })),
});
const client = clientWith(t);
const msgs = await client.list("m-001");
@@ -191,7 +199,7 @@ describe("delete", () => {
expect(t.request).toHaveBeenCalledWith(
"$mq9.AI.MAILBOX.DELETE.m-001.msg-42",
expect.any(Uint8Array),
- expect.anything()
+ expect.anything(),
);
});
});
diff --git a/javascript/src/mq9/client.ts b/javascript/src/mq9/client.ts
index 17c7991..b2ef5ba 100644
--- a/javascript/src/mq9/client.ts
+++ b/javascript/src/mq9/client.ts
@@ -2,11 +2,7 @@
* mq9 client — AI-native async Agent mailbox communication over NATS.
*/
-import {
- connect,
- NatsConnection,
- Subscription,
-} from "nats";
+import { connect, NatsConnection, Subscription } from "nats";
// ---------------------------------------------------------------------------
// Types
@@ -81,9 +77,14 @@ export interface NatsTransport {
request(
subject: string,
data: Uint8Array,
- opts?: { timeout?: number }
+ opts?: { timeout?: number },
): Promise<{ data: Uint8Array }>;
- subscribe(subject: string, opts?: { queue?: string }): AsyncIterable<{ subject: string; data: Uint8Array }> & { unsubscribe(): void };
+ subscribe(
+ subject: string,
+ opts?: { queue?: string },
+ ): AsyncIterable<{ subject: string; data: Uint8Array }> & {
+ unsubscribe(): void;
+ };
drain(): Promise;
}
@@ -148,7 +149,7 @@ export class MQ9Client {
async send(
mailId: string,
payload: Uint8Array | string | object,
- priority: Priority = "normal"
+ priority: Priority = "normal",
): Promise {
this.ensureConnected();
const subject = subjectMsg(mailId, priority);
@@ -161,7 +162,7 @@ export class MQ9Client {
async subscribe(
mailId: string,
callback: (msg: Mq9Message) => Promise,
- opts: SubscribeOptions = {}
+ opts: SubscribeOptions = {},
): Promise<{ unsubscribe(): void }> {
this.ensureConnected();
const priority = opts.priority ?? "*";
@@ -217,7 +218,7 @@ export class MQ9Client {
private async request(
subject: string,
- payload: object
+ payload: object,
): Promise> {
this.ensureConnected();
const data = encodePayload(payload);
@@ -230,9 +231,10 @@ export class MQ9Client {
const msg = err instanceof Error ? err.message : String(err);
throw new MQ9Error(`request failed: ${msg}`);
}
- const resp = JSON.parse(
- Buffer.from(reply.data).toString("utf8")
- ) as Record;
+ const resp = JSON.parse(Buffer.from(reply.data).toString("utf8")) as Record<
+ string,
+ unknown
+ >;
if (resp.error) {
throw new MQ9Error(resp.error as string, (resp.code as number) ?? 0);
}
@@ -254,7 +256,7 @@ class RealTransport implements NatsTransport {
async request(
subject: string,
data: Uint8Array,
- opts?: { timeout?: number }
+ opts?: { timeout?: number },
): Promise<{ data: Uint8Array }> {
const msg = await this.nc.request(subject, data, {
timeout: opts?.timeout ?? 5000,
@@ -264,7 +266,7 @@ class RealTransport implements NatsTransport {
subscribe(
subject: string,
- opts?: { queue?: string }
+ opts?: { queue?: string },
): AsyncIterable<{ subject: string; data: Uint8Array }> & {
unsubscribe(): void;
} {
@@ -299,16 +301,17 @@ function encodePayload(payload: Uint8Array | string | object): Uint8Array {
function parseIncoming(
mailId: string,
subject: string,
- data: Uint8Array
+ data: Uint8Array,
): Mq9Message {
const parts = subject.split(".");
const priorityStr = parts[parts.length - 1] ?? "normal";
const priority = toPriority(priorityStr);
try {
- const node = JSON.parse(
- Buffer.from(data).toString("utf8")
- ) as Record;
+ const node = JSON.parse(Buffer.from(data).toString("utf8")) as Record<
+ string,
+ unknown
+ >;
if (node.msg_id !== undefined) {
return parseMessageNode(mailId, node);
}
@@ -321,7 +324,7 @@ function parseIncoming(
function parseMessageNode(
mailId: string,
- node: Record
+ node: Record,
): Mq9Message {
const rawPayload = (node.payload as string) ?? "";
const payload = rawPayload
diff --git a/python/pyproject.toml b/python/pyproject.toml
index c3d0b28..8002a65 100644
--- a/python/pyproject.toml
+++ b/python/pyproject.toml
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
[project]
name = "robustmq"
-version = "1.0.0"
-description = "RobustMQ Python SDK — mq9 AI-native async messaging"
+version = "0.3.5"
+description = "RobustMQ Python SDK — unified messaging for AI, IoT, and data pipelines"
readme = "README.md"
license = { text = "Apache-2.0" }
requires-python = ">=3.10"
diff --git a/python/robustmq/__init__.py b/python/robustmq/__init__.py
index 6d388ec..9c47b8d 100644
--- a/python/robustmq/__init__.py
+++ b/python/robustmq/__init__.py
@@ -1,3 +1,3 @@
"""RobustMQ Python SDK."""
-__version__ = "1.0.0"
+__version__ = "0.3.5"
diff --git a/python/robustmq/mq9/client.py b/python/robustmq/mq9/client.py
index 4fee39f..11b7f06 100644
--- a/python/robustmq/mq9/client.py
+++ b/python/robustmq/mq9/client.py
@@ -6,7 +6,7 @@
import base64
import json
import logging
-from dataclasses import dataclass, field
+from dataclasses import dataclass
from enum import Enum
from typing import Any, Awaitable, Callable
@@ -225,7 +225,8 @@ async def subscribe(
if priority == "*":
subject = _MAILBOX_MSG.format(mail_id=mail_id, priority="*")
else:
- subject = _MAILBOX_MSG.format(mail_id=mail_id, priority=Priority(priority).value)
+ p = Priority(priority).value
+ subject = _MAILBOX_MSG.format(mail_id=mail_id, priority=p)
async def _handler(raw: Msg) -> None:
try:
@@ -275,13 +276,17 @@ async def delete(self, mail_id: str, msg_id: str) -> None:
def _ensure_connected(self) -> None:
if self._nc is None or self._nc.is_closed:
- raise RuntimeError("Client is not connected. Call await client.connect() first.")
+ raise RuntimeError(
+ "Client is not connected. Call await client.connect() first."
+ )
async def _request(self, subject: str, payload: dict[str, Any]) -> dict[str, Any]:
self._ensure_connected()
data = json.dumps(payload).encode()
try:
- reply = await self._nc.request(subject, data, timeout=self._request_timeout) # type: ignore[union-attr]
+ reply = await self._nc.request( # type: ignore[union-attr]
+ subject, data, timeout=self._request_timeout
+ )
except nats.errors.NoRespondersError as exc:
raise Mq9Error(f"No responders for subject: {subject}") from exc
except asyncio.TimeoutError as exc:
@@ -317,6 +322,7 @@ async def __aexit__(self, *_: Any) -> None:
# Module-level helpers
# ------------------------------------------------------------------
+
def _encode_payload(payload: bytes | str | dict[str, Any]) -> bytes:
if isinstance(payload, bytes):
return payload
@@ -349,7 +355,11 @@ def _parse_incoming(mail_id: str, raw: Msg) -> Message:
msg_id=envelope["msg_id"],
mail_id=mail_id,
priority=priority,
- payload=base64.b64decode(envelope.get("payload", "")) if envelope.get("payload") else raw.data,
+ payload=(
+ base64.b64decode(envelope["payload"])
+ if envelope.get("payload")
+ else raw.data
+ ),
)
except (json.JSONDecodeError, KeyError):
pass
diff --git a/python/tests/test_client.py b/python/tests/test_client.py
index 1bf827b..49ffaf9 100644
--- a/python/tests/test_client.py
+++ b/python/tests/test_client.py
@@ -21,6 +21,7 @@
# Helpers
# ---------------------------------------------------------------------------
+
def _make_reply(data: dict[str, Any]) -> MagicMock:
msg = MagicMock()
msg.data = json.dumps(data).encode()
@@ -47,10 +48,13 @@ async def _inject_nc(client: Client) -> AsyncMock:
# connect / close
# ---------------------------------------------------------------------------
+
@pytest.mark.asyncio
async def test_connect_and_close():
client = _make_client()
- with patch("robustmq.mq9.client.nats.connect", new_callable=AsyncMock) as mock_connect:
+ with patch(
+ "robustmq.mq9.client.nats.connect", new_callable=AsyncMock
+ ) as mock_connect:
nc = AsyncMock()
nc.is_closed = False
mock_connect.return_value = nc
@@ -66,7 +70,9 @@ async def test_connect_and_close():
@pytest.mark.asyncio
async def test_context_manager():
client = _make_client()
- with patch("robustmq.mq9.client.nats.connect", new_callable=AsyncMock) as mock_connect:
+ with patch(
+ "robustmq.mq9.client.nats.connect", new_callable=AsyncMock
+ ) as mock_connect:
nc = AsyncMock()
nc.is_closed = False
mock_connect.return_value = nc
@@ -80,6 +86,7 @@ async def test_context_manager():
# create
# ---------------------------------------------------------------------------
+
@pytest.mark.asyncio
async def test_create_private_mailbox():
client = _make_client()
@@ -105,7 +112,9 @@ async def test_create_public_mailbox():
nc = await _inject_nc(client)
nc.request = AsyncMock(return_value=_make_reply({"mail_id": "task.queue"}))
- mailbox = await client.create(ttl=86400, public=True, name="task.queue", desc="Task queue")
+ mailbox = await client.create(
+ ttl=86400, public=True, name="task.queue", desc="Task queue"
+ )
assert mailbox.mail_id == "task.queue"
assert mailbox.public is True
@@ -143,6 +152,7 @@ async def test_create_server_error():
# send
# ---------------------------------------------------------------------------
+
@pytest.mark.asyncio
async def test_send_bytes_normal_priority():
client = _make_client()
@@ -150,9 +160,7 @@ async def test_send_bytes_normal_priority():
await client.send("m-001", b"hello", priority=Priority.NORMAL)
- nc.publish.assert_awaited_once_with(
- "$mq9.AI.MAILBOX.MSG.m-001.normal", b"hello"
- )
+ nc.publish.assert_awaited_once_with("$mq9.AI.MAILBOX.MSG.m-001.normal", b"hello")
@pytest.mark.asyncio
@@ -191,6 +199,7 @@ async def test_send_invalid_priority():
# subscribe
# ---------------------------------------------------------------------------
+
@pytest.mark.asyncio
async def test_subscribe_all_priorities():
client = _make_client()
@@ -270,6 +279,7 @@ async def handler(msg: Message) -> None:
# list
# ---------------------------------------------------------------------------
+
@pytest.mark.asyncio
async def test_list_messages():
client = _make_client()
@@ -298,7 +308,9 @@ async def test_list_messages():
async def test_list_empty_mailbox():
client = _make_client()
nc = await _inject_nc(client)
- nc.request = AsyncMock(return_value=_make_reply({"mail_id": "m-001", "messages": []}))
+ nc.request = AsyncMock(
+ return_value=_make_reply({"mail_id": "m-001", "messages": []})
+ )
messages = await client.list("m-001")
assert messages == []
@@ -308,6 +320,7 @@ async def test_list_empty_mailbox():
# delete
# ---------------------------------------------------------------------------
+
@pytest.mark.asyncio
async def test_delete_message():
client = _make_client()
@@ -324,10 +337,9 @@ async def test_delete_message():
# Error handling
# ---------------------------------------------------------------------------
+
@pytest.mark.asyncio
async def test_request_timeout_raises_mq9_error():
- import nats.errors
-
client = _make_client()
nc = await _inject_nc(client)
nc.request = AsyncMock(side_effect=asyncio.TimeoutError())
@@ -360,6 +372,7 @@ async def test_not_connected_raises_runtime_error():
# _encode_payload helper
# ---------------------------------------------------------------------------
+
def test_encode_bytes():
assert _encode_payload(b"raw") == b"raw"
@@ -377,14 +390,17 @@ def test_encode_dict():
# _parse_incoming helper
# ---------------------------------------------------------------------------
+
def test_parse_incoming_with_envelope():
raw = MagicMock()
raw.subject = "$mq9.AI.MAILBOX.MSG.m-001.high"
- raw.data = json.dumps({
- "msg_id": "x9",
- "priority": "high",
- "payload": base64.b64encode(b"data").decode(),
- }).encode()
+ raw.data = json.dumps(
+ {
+ "msg_id": "x9",
+ "priority": "high",
+ "payload": base64.b64encode(b"data").decode(),
+ }
+ ).encode()
msg = _parse_incoming("m-001", raw)
assert msg.msg_id == "x9"
diff --git a/rust/Cargo.lock b/rust/Cargo.lock
index c9ddba9..d04e6d3 100644
--- a/rust/Cargo.lock
+++ b/rust/Cargo.lock
@@ -754,7 +754,7 @@ dependencies = [
[[package]]
name = "robustmq"
-version = "1.0.0"
+version = "0.3.5"
dependencies = [
"async-nats",
"bytes",
diff --git a/rust/Cargo.toml b/rust/Cargo.toml
index 21eb1a4..766e96c 100644
--- a/rust/Cargo.toml
+++ b/rust/Cargo.toml
@@ -1,8 +1,8 @@
[package]
name = "robustmq"
-version = "1.0.0"
+version = "0.3.5"
edition = "2021"
-description = "RobustMQ Rust SDK — mq9 AI-native async messaging"
+description = "RobustMQ Rust SDK — unified messaging for AI, IoT, and data pipelines"
license = "Apache-2.0"
[dependencies]
diff --git a/rust/examples/demo.rs b/rust/examples/demo.rs
index 72de952..51b77bf 100644
--- a/rust/examples/demo.rs
+++ b/rust/examples/demo.rs
@@ -18,9 +18,15 @@ async fn main() -> Result<(), Box> {
println!("[rust] private mailbox: {}", mailbox.mail_id);
// 2. Send 3 messages with different priorities
- client.send(&mailbox.mail_id, b"urgent task", Priority::High).await?;
- client.send(&mailbox.mail_id, b"normal task", Priority::Normal).await?;
- client.send(&mailbox.mail_id, b"background task", Priority::Low).await?;
+ client
+ .send(&mailbox.mail_id, b"urgent task", Priority::High)
+ .await?;
+ client
+ .send(&mailbox.mail_id, b"normal task", Priority::Normal)
+ .await?;
+ client
+ .send(&mailbox.mail_id, b"background task", Priority::Low)
+ .await?;
println!("[rust] sent 3 messages (high / normal / low)");
// 3. Subscribe and print received messages
@@ -44,7 +50,10 @@ async fn main() -> Result<(), Box> {
let metas = client.list(&mailbox.mail_id).await?;
println!("[rust] list: {} message(s) in mailbox", metas.len());
for m in &metas {
- println!(" msg_id={} priority={} ts={}", m.msg_id, m.priority, m.ts);
+ println!(
+ " msg_id={} priority={} ts={}",
+ m.msg_id, m.priority, m.ts
+ );
}
// 5. Delete first message
diff --git a/rust/src/mq9/mod.rs b/rust/src/mq9/mod.rs
index 04e9151..5a816e9 100644
--- a/rust/src/mq9/mod.rs
+++ b/rust/src/mq9/mod.rs
@@ -108,7 +108,7 @@ pub struct Message {
}
/// A raw incoming message from the transport (subject + payload bytes).
-pub(crate) struct RawMsg {
+pub struct RawMsg {
pub subject: String,
pub payload: Bytes,
}
@@ -189,10 +189,13 @@ impl NatsTransport for RealNats {
payload: Bytes,
) -> std::pin::Pin> + Send + 'a>> {
Box::pin(async move {
- self.0.publish(subject, payload).await.map_err(|e| MQ9Error {
- message: format!("publish failed: {e}"),
- code: 0,
- })
+ self.0
+ .publish(subject, payload)
+ .await
+ .map_err(|e| MQ9Error {
+ message: format!("publish failed: {e}"),
+ code: 0,
+ })
})
}
@@ -202,10 +205,14 @@ impl NatsTransport for RealNats {
payload: Bytes,
) -> std::pin::Pin> + Send + 'a>> {
Box::pin(async move {
- let reply = self.0.request(subject, payload).await.map_err(|e| MQ9Error {
- message: format!("request failed: {e}"),
- code: 0,
- })?;
+ let reply = self
+ .0
+ .request(subject, payload)
+ .await
+ .map_err(|e| MQ9Error {
+ message: format!("request failed: {e}"),
+ code: 0,
+ })?;
Ok(reply.payload)
})
}
@@ -217,10 +224,13 @@ impl NatsTransport for RealNats {
) -> std::pin::Pin> + Send + 'a>> {
Box::pin(async move {
let sub = if let Some(queue) = queue_group {
- self.0.queue_subscribe(subject, queue).await.map_err(|e| MQ9Error {
- message: format!("queue_subscribe failed: {e}"),
- code: 0,
- })?
+ self.0
+ .queue_subscribe(subject, queue)
+ .await
+ .map_err(|e| MQ9Error {
+ message: format!("queue_subscribe failed: {e}"),
+ code: 0,
+ })?
} else {
self.0.subscribe(subject).await.map_err(|e| MQ9Error {
message: format!("subscribe failed: {e}"),
@@ -390,11 +400,7 @@ impl MQ9Client {
let resp = self.do_request(&subject, &serde_json::json!({})).await?;
let metas = resp["messages"]
.as_array()
- .map(|arr| {
- arr.iter()
- .filter_map(|v| parse_message_meta(v))
- .collect()
- })
+ .map(|arr| arr.iter().filter_map(parse_message_meta).collect())
.unwrap_or_default();
Ok(metas)
}
@@ -482,7 +488,11 @@ fn parse_message_meta(v: &Value) -> Option {
let msg_id = v["msg_id"].as_str()?.to_string();
let priority = Priority::from_str_lossy(v["priority"].as_str().unwrap_or("normal"));
let ts = v["ts"].as_i64().unwrap_or(0);
- Some(MessageMeta { msg_id, priority, ts })
+ Some(MessageMeta {
+ msg_id,
+ priority,
+ ts,
+ })
}
// ---------------------------------------------------------------------------
@@ -577,7 +587,10 @@ mod tests {
fn push_ok(&self, body: serde_json::Value) {
let bytes = Bytes::from(serde_json::to_vec(&body).unwrap());
- self.responses.lock().unwrap().push_back(MockResponse::Ok(bytes));
+ self.responses
+ .lock()
+ .unwrap()
+ .push_back(MockResponse::Ok(bytes));
}
fn push_err(&self, message: &str, code: u32) {
@@ -614,7 +627,10 @@ mod tests {
subject: String,
payload: Bytes,
) -> std::pin::Pin> + Send + 'a>> {
- self.published.lock().unwrap().push((subject, payload.to_vec()));
+ self.published
+ .lock()
+ .unwrap()
+ .push((subject, payload.to_vec()));
Box::pin(async { Ok(()) })
}
@@ -623,7 +639,10 @@ mod tests {
subject: String,
payload: Bytes,
) -> std::pin::Pin> + Send + 'a>> {
- self.requested.lock().unwrap().push((subject, payload.to_vec()));
+ self.requested
+ .lock()
+ .unwrap()
+ .push((subject, payload.to_vec()));
let resp = self.responses.lock().unwrap().pop_front();
Box::pin(async move {
match resp {
@@ -633,7 +652,10 @@ mod tests {
let body = json!({ "error": message, "code": code });
Ok(Bytes::from(serde_json::to_vec(&body).unwrap()))
}
- None => Err(MQ9Error { message: "no mock response queued".into(), code: 0 }),
+ None => Err(MQ9Error {
+ message: "no mock response queued".into(),
+ code: 0,
+ }),
}
})
}
@@ -642,7 +664,8 @@ mod tests {
&'a self,
subject: String,
queue_group: Option,
- ) -> std::pin::Pin> + Send + 'a>> {
+ ) -> std::pin::Pin> + Send + 'a>>
+ {
self.subscribed.lock().unwrap().push((subject, queue_group));
// Drain the pre-loaded messages into a stream that yields them all then ends.
let messages: Vec = self.sub_messages.lock().unwrap().drain(..).collect();
@@ -703,7 +726,10 @@ mod tests {
mock.push_ok(json!({ "mail_id": "task.queue" }));
let client = make_client(mock);
- let mailbox = client.create(86400, true, "task.queue", "Task queue").await.unwrap();
+ let mailbox = client
+ .create(86400, true, "task.queue", "Task queue")
+ .await
+ .unwrap();
assert_eq!(mailbox.mail_id, "task.queue");
assert!(mailbox.public);
@@ -729,7 +755,10 @@ mod tests {
let arc = mock.clone();
let client = MQ9Client { transport: mock };
- client.create(86400, true, "task.queue", "Tasks").await.unwrap();
+ client
+ .create(86400, true, "task.queue", "Tasks")
+ .await
+ .unwrap();
let calls = arc.requested();
let body: serde_json::Value = serde_json::from_slice(&calls[0].1).unwrap();
@@ -762,7 +791,10 @@ mod tests {
let arc = mock.clone();
let client = MQ9Client { transport: mock };
- client.send("m-001", b"hello", Priority::Normal).await.unwrap();
+ client
+ .send("m-001", b"hello", Priority::Normal)
+ .await
+ .unwrap();
let calls = arc.published();
assert_eq!(calls.len(), 1);
@@ -776,7 +808,10 @@ mod tests {
let arc = mock.clone();
let client = MQ9Client { transport: mock };
- client.send("m-001", b"urgent", Priority::High).await.unwrap();
+ client
+ .send("m-001", b"urgent", Priority::High)
+ .await
+ .unwrap();
let calls = arc.published();
assert_eq!(calls[0].0, "$mq9.AI.MAILBOX.MSG.m-001.high");
@@ -801,7 +836,10 @@ mod tests {
let client = MQ9Client { transport: mock };
let payload = b"binary\x00data\xff";
- client.send("m-001", payload, Priority::Normal).await.unwrap();
+ client
+ .send("m-001", payload, Priority::Normal)
+ .await
+ .unwrap();
assert_eq!(&arc.published()[0].1, payload);
}
@@ -820,7 +858,10 @@ mod tests {
let arc = mock.clone();
let client = MQ9Client { transport: mock };
- let _sub = client.subscribe("m-001", |_msg| async {}, None, "").await.unwrap();
+ let _sub = client
+ .subscribe("m-001", |_msg| async {}, None, "")
+ .await
+ .unwrap();
let calls = arc.subscribed();
assert_eq!(calls.len(), 1);
@@ -912,8 +953,16 @@ mod tests {
let n = (b0 << 16) | (b1 << 8) | b2;
out.push(ALPHA[((n >> 18) & 63) as usize] as char);
out.push(ALPHA[((n >> 12) & 63) as usize] as char);
- out.push(if chunk.len() > 1 { ALPHA[((n >> 6) & 63) as usize] as char } else { '=' });
- out.push(if chunk.len() > 2 { ALPHA[(n & 63) as usize] as char } else { '=' });
+ out.push(if chunk.len() > 1 {
+ ALPHA[((n >> 6) & 63) as usize] as char
+ } else {
+ '='
+ });
+ out.push(if chunk.len() > 2 {
+ ALPHA[(n & 63) as usize] as char
+ } else {
+ '='
+ });
}
out
}
@@ -1016,7 +1065,10 @@ mod tests {
#[test]
fn test_mq9_error_display_with_code() {
- let err = MQ9Error { message: "quota exceeded".into(), code: 429 };
+ let err = MQ9Error {
+ message: "quota exceeded".into(),
+ code: 429,
+ };
let s = err.to_string();
assert!(s.contains("429"));
assert!(s.contains("quota exceeded"));
@@ -1024,14 +1076,20 @@ mod tests {
#[test]
fn test_mq9_error_display_no_code() {
- let err = MQ9Error { message: "connection failed".into(), code: 0 };
+ let err = MQ9Error {
+ message: "connection failed".into(),
+ code: 0,
+ };
let s = err.to_string();
assert!(s.contains("connection failed"));
}
#[test]
fn test_mq9_error_is_std_error() {
- let err: Box = Box::new(MQ9Error { message: "oops".into(), code: 500 });
+ let err: Box = Box::new(MQ9Error {
+ message: "oops".into(),
+ code: 500,
+ });
assert!(err.to_string().contains("oops"));
}