update
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
# Specification: natsClient_JS
|
||||
|
||||
The technical contract for the module's exports. Each item carries an `SP-XXX` ID and traces to a
|
||||
Requirement (FR/NFR) and Solution Design decision (SD).
|
||||
|
||||
## 1. Module Exports
|
||||
|
||||
- `connectionStatus` — Svelte writable store of `{ state, message }`.
|
||||
- `setConfig(cfg)` — inject config (broker/fileserver URLs).
|
||||
- `getNats(opts)` — establish the shared connection.
|
||||
- `subscribe(subject, onMessage)` — subscribe and decode.
|
||||
- `publish(subject, payload, opts)` — publish.
|
||||
- `closeNats()` — close and cleanup.
|
||||
- `connectNATS(brokerUrl, cfg)` — connect using a broker URL or config.
|
||||
- `request(subject, payload, opts)` — request/reply.
|
||||
- `reply(subject, handler, opts)` — reply handler.
|
||||
- `sendMsghandlerRequest(subject, functioncall, args, config)` — msghandler request.
|
||||
|
||||
## 2. API Contract
|
||||
|
||||
### SP-001: getNats(opts)
|
||||
|
||||
```
|
||||
getNats(opts?: { servers?: string }) => Promise<connection>
|
||||
```
|
||||
- URL resolution precedence: `opts.servers` → `import.meta.env.VITE_NATS_URL` →
|
||||
`config.nats_server_info.url` → `wss://natsws.yiem.cc`.
|
||||
- Emits `connecting` then `connected` on `connectionStatus`.
|
||||
- Returns the NATS connection object.
|
||||
- Throws on connection failure.
|
||||
**Traceability**: FR-001, FR-007, SD-001, SD-002, SD-004
|
||||
|
||||
### SP-002: subscribe(subject, onMessage)
|
||||
|
||||
```
|
||||
subscribe(subject: string, onMessage: (parsed) => void) => Promise<{ unsubscribe(): Promise<void> }>
|
||||
```
|
||||
- Auto-connects via `getNats` if not connected.
|
||||
- Decodes each message with `StringCodec`, then `JSON.parse`, falling back to `{ text }`.
|
||||
- Registers the subscription in the `Map` registry for cleanup (SD-005).
|
||||
**Traceability**: FR-002, SD-003, SD-005
|
||||
|
||||
### SP-003: publish(subject, payload, opts)
|
||||
|
||||
```
|
||||
publish(subject: string, payload: object | string = {}, opts?: object) => Promise<void>
|
||||
```
|
||||
- Auto-connects via `getNats` if not connected.
|
||||
- String payloads are sent verbatim; other payloads are `JSON.stringify`ed.
|
||||
**Traceability**: FR-003, SD-001, SD-003
|
||||
|
||||
### SP-004: request(subject, payload, opts)
|
||||
|
||||
```
|
||||
request(subject: string, payload: object | string, opts?: { timeout?: number }) => Promise<object>
|
||||
```
|
||||
- Sends a request with `nc.request`, encoding non-strings via `JSON.stringify`.
|
||||
- Decodes the reply (`JSON.parse`, else `{ text }`).
|
||||
**Traceability**: FR-004, SD-003
|
||||
|
||||
### SP-005: reply(subject, handler, opts)
|
||||
|
||||
```
|
||||
reply(subject: string, handler: (parsed, msg) => object | string, opts?: object)
|
||||
=> Promise<{ unsubscribe(): Promise<void> }>
|
||||
```
|
||||
- Invokes `handler(parsed, msg)` and publishes the returned value on `m.subject`.
|
||||
**Traceability**: FR-005, SD-005
|
||||
|
||||
### SP-006: sendMsghandlerRequest(subject, functioncall, args, config)
|
||||
|
||||
```
|
||||
sendMsghandlerRequest(subject: string, functioncall: string, args: object, config: object)
|
||||
=> Promise<object>
|
||||
```
|
||||
- Packs `[[db_request, { functioncall, args }, "dictionary"]]` via `msghandlerCSR.smartpack`.
|
||||
- Sends a request, unpacks via `msghandlerCSR.smartunpack`.
|
||||
- Returns the `jsontable`/`dictionary` `data`; throws if `type === "text"`.
|
||||
**Traceability**: FR-006, SD-006
|
||||
|
||||
### SP-007: closeNats()
|
||||
|
||||
```
|
||||
closeNats() => Promise<void>
|
||||
```
|
||||
- Unsubscribes every tracked subscription, clears reconnect timers, closes the connection.
|
||||
**Traceability**: FR-008, NFR-501, SD-005
|
||||
|
||||
### SP-008: connectionStatus store
|
||||
|
||||
```
|
||||
connectionStatus: Writable<{ state: "connecting" | "connected" | "disconnected" | "error", message: string }>
|
||||
```
|
||||
**Traceability**: FR-007, NFR-201, SD-004
|
||||
|
||||
## 3. Payload Format
|
||||
|
||||
All payloads are JSON text encoded via `StringCodec`:
|
||||
- Publish/request: `JSON.stringify(payload)` for objects; string sent verbatim.
|
||||
- Decode: `JSON.parse(text)`, fallback `{ text }`.
|
||||
|
||||
## 4. Msghandler Envelope Format
|
||||
|
||||
### SP-010: Request envelope
|
||||
|
||||
Built by `msghandlerCSR.smartpack(subject, [["db_request", { functioncall, args }, "dictionary"]], { broker_url, fileserver_url })`.
|
||||
|
||||
### SP-011: Response envelope
|
||||
|
||||
Returned by `msghandlerCSR.smartunpack`; `.payloads` is an array of `[dataname, data, type]`.
|
||||
`sendMsghandlerRequest` returns `data` when `type` is `jsontable` or `dictionary`, and throws when
|
||||
`type === "text"`.
|
||||
|
||||
## 5. Error Codes
|
||||
|
||||
| Condition | Behavior | Traceability |
|
||||
|-----------|----------|--------------|
|
||||
| `type === "text"` in msghandler reply | `throw new Error(data)` | FR-006, SP-011 |
|
||||
| `getNats` fails | sets `error` status, throws | FR-001, SP-001 |
|
||||
| No `jsontable`/`dictionary` payload | `throw new Error('No valid response found')` | FR-006 |
|
||||
Reference in New Issue
Block a user