doover-js 0.5.3 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +146 -0
- package/dist/apis/_args.d.ts +16 -0
- package/dist/apis/_args.js +26 -0
- package/dist/apis/agents-api.d.ts +4 -1
- package/dist/apis/agents-api.js +139 -1
- package/dist/apis/aggregates-api.d.ts +23 -3
- package/dist/apis/aggregates-api.js +33 -4
- package/dist/apis/alarms-api.d.ts +30 -0
- package/dist/apis/alarms-api.js +51 -6
- package/dist/apis/channels-api.d.ts +40 -3
- package/dist/apis/channels-api.js +50 -5
- package/dist/apis/connections-api.d.ts +21 -5
- package/dist/apis/connections-api.js +26 -10
- package/dist/apis/messages-api.d.ts +54 -9
- package/dist/apis/messages-api.js +94 -12
- package/dist/apis/notifications-api.d.ts +52 -0
- package/dist/apis/notifications-api.js +99 -13
- package/dist/apis/permissions-api.d.ts +8 -0
- package/dist/apis/permissions-api.js +11 -2
- package/dist/apis/processors-api.d.ts +35 -0
- package/dist/apis/processors-api.js +64 -8
- package/dist/apis/users-api.d.ts +8 -0
- package/dist/apis/users-api.js +13 -0
- package/dist/client/capabilities.d.ts +10 -0
- package/dist/client/capabilities.js +43 -0
- package/dist/client/data-client.d.ts +104 -0
- package/dist/client/data-client.js +2 -0
- package/dist/client/doover-client.d.ts +31 -31
- package/dist/client/doover-client.js +58 -37
- package/dist/client/errors.d.ts +23 -0
- package/dist/client/errors.js +50 -0
- package/dist/client/local-agent-client.d.ts +65 -0
- package/dist/client/local-agent-client.js +222 -0
- package/dist/client/multiplex-client.d.ts +151 -0
- package/dist/client/multiplex-client.js +744 -0
- package/dist/client/multiplex-gateway.d.ts +49 -0
- package/dist/client/multiplex-gateway.js +114 -0
- package/dist/client/multiplex-merge.d.ts +12 -0
- package/dist/client/multiplex-merge.js +42 -0
- package/dist/client/provenance.d.ts +60 -0
- package/dist/client/provenance.js +113 -0
- package/dist/client/stats.d.ts +24 -0
- package/dist/client/stats.js +62 -0
- package/dist/client/status-tracker.d.ts +24 -0
- package/dist/client/status-tracker.js +90 -0
- package/dist/gateway/gateway-client.d.ts +23 -1
- package/dist/gateway/gateway-client.js +75 -6
- package/dist/http/rest-client.d.ts +5 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +22 -7
- package/dist/react/context.d.ts +9 -5
- package/dist/react/context.js +6 -2
- package/dist/react/index.d.ts +3 -0
- package/dist/react/index.js +3 -1
- package/dist/react/useChannelAggregate.d.ts +8 -1
- package/dist/react/useChannelAggregate.js +24 -6
- package/dist/react/useChannelMessage.d.ts +8 -1
- package/dist/react/useChannelMessage.js +17 -6
- package/dist/react/useChannelMessages.d.ts +8 -1
- package/dist/react/useChannelMessages.js +21 -7
- package/dist/react/useChannelSubscription.d.ts +6 -0
- package/dist/react/useChannelSubscription.js +8 -18
- package/dist/react/useClientStatus.d.ts +10 -0
- package/dist/react/useClientStatus.js +22 -0
- package/dist/react/useConnectionState.d.ts +5 -0
- package/dist/react/useConnectionState.js +5 -0
- package/dist/react/useMultiAgentAggregates.d.ts +8 -1
- package/dist/react/useMultiAgentAggregates.js +25 -21
- package/dist/react/useMultiAgentChannelMessages.d.ts +8 -1
- package/dist/react/useMultiAgentChannelMessages.js +23 -18
- package/dist/react/useSendMessage.d.ts +8 -1
- package/dist/react/useSendMessage.js +15 -2
- package/dist/react/useSendRpc.js +4 -1
- package/dist/react/useUpdateAggregate.d.ts +6 -0
- package/dist/react/useUpdateAggregate.js +20 -4
- package/dist/react/useUpdateMessage.d.ts +5 -0
- package/dist/react/useUpdateMessage.js +11 -2
- package/dist/rpc/errors.d.ts +10 -0
- package/dist/rpc/errors.js +23 -0
- package/dist/rpc/rpc-dispatcher.d.ts +28 -0
- package/dist/rpc/rpc-dispatcher.js +129 -0
- package/dist/test/api-args.test.d.ts +1 -0
- package/dist/test/api-args.test.js +48 -0
- package/dist/test/api-overloads.test.d.ts +9 -0
- package/dist/test/api-overloads.test.js +276 -0
- package/dist/test/capabilities.test.d.ts +1 -0
- package/dist/test/capabilities.test.js +27 -0
- package/dist/test/data-client-errors.test.d.ts +1 -0
- package/dist/test/data-client-errors.test.js +24 -0
- package/dist/test/data-client-shape.test.d.ts +1 -0
- package/dist/test/data-client-shape.test.js +28 -0
- package/dist/test/doover-client-dataclient.test.d.ts +1 -0
- package/dist/test/doover-client-dataclient.test.js +58 -0
- package/dist/test/doover-client-provenance.test.d.ts +1 -0
- package/dist/test/doover-client-provenance.test.js +32 -0
- package/dist/test/exports.test.d.ts +1 -0
- package/dist/test/exports.test.js +76 -0
- package/dist/test/gateway-provenance.test.d.ts +1 -0
- package/dist/test/gateway-provenance.test.js +29 -0
- package/dist/test/gateway-subscriptions.test.d.ts +1 -0
- package/dist/test/gateway-subscriptions.test.js +95 -0
- package/dist/test/local-agent-client.test.d.ts +1 -0
- package/dist/test/local-agent-client.test.js +202 -0
- package/dist/test/multiplex-capabilities.test.d.ts +1 -0
- package/dist/test/multiplex-capabilities.test.js +37 -0
- package/dist/test/multiplex-conflicts.test.d.ts +1 -0
- package/dist/test/multiplex-conflicts.test.js +35 -0
- package/dist/test/multiplex-gateway.test.d.ts +1 -0
- package/dist/test/multiplex-gateway.test.js +103 -0
- package/dist/test/multiplex-merge.test.d.ts +1 -0
- package/dist/test/multiplex-merge.test.js +19 -0
- package/dist/test/multiplex-noncore.test.d.ts +1 -0
- package/dist/test/multiplex-noncore.test.js +82 -0
- package/dist/test/multiplex-passthrough.test.d.ts +1 -0
- package/dist/test/multiplex-passthrough.test.js +35 -0
- package/dist/test/multiplex-reads.test.d.ts +1 -0
- package/dist/test/multiplex-reads.test.js +87 -0
- package/dist/test/multiplex-registry.test.d.ts +1 -0
- package/dist/test/multiplex-registry.test.js +81 -0
- package/dist/test/multiplex-routing.test.d.ts +1 -0
- package/dist/test/multiplex-routing.test.js +45 -0
- package/dist/test/multiplex-status.test.d.ts +1 -0
- package/dist/test/multiplex-status.test.js +63 -0
- package/dist/test/multiplex-writes.test.d.ts +1 -0
- package/dist/test/multiplex-writes.test.js +93 -0
- package/dist/test/provenance-regression.test.d.ts +1 -0
- package/dist/test/provenance-regression.test.js +45 -0
- package/dist/test/provenance-stamper.test.d.ts +1 -0
- package/dist/test/provenance-stamper.test.js +41 -0
- package/dist/test/provenance-type.test.d.ts +1 -0
- package/dist/test/provenance-type.test.js +15 -0
- package/dist/test/react-client-status.test.d.ts +1 -0
- package/dist/test/react-client-status.test.js +35 -0
- package/dist/test/react-dataclient.test.d.ts +1 -0
- package/dist/test/react-dataclient.test.js +28 -0
- package/dist/test/react-exports.test.d.ts +1 -0
- package/dist/test/react-exports.test.js +45 -0
- package/dist/test/react-sources-option.test.d.ts +1 -0
- package/dist/test/react-sources-option.test.js +41 -0
- package/dist/test/react.test.js +2 -2
- package/dist/test/rpc-dispatcher.test.d.ts +1 -0
- package/dist/test/rpc-dispatcher.test.js +190 -0
- package/dist/test/stats-rpc.test.d.ts +1 -0
- package/dist/test/stats-rpc.test.js +69 -0
- package/dist/test/status-tracker.test.d.ts +1 -0
- package/dist/test/status-tracker.test.js +85 -0
- package/dist/test/users-api.test.d.ts +1 -0
- package/dist/test/users-api.test.js +19 -0
- package/dist/types/common.d.ts +18 -1
- package/dist/types/openapi.d.ts +1 -0
- package/dist/types/provenance.d.ts +45 -0
- package/dist/types/provenance.js +2 -0
- package/dist/types/viewer.d.ts +3 -0
- package/dist/viewer/doover-data-provider.d.ts +30 -34
- package/dist/viewer/doover-data-provider.js +82 -316
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -122,8 +122,154 @@ const client = new DooverClient({
|
|
|
122
122
|
|
|
123
123
|
Reconnections automatically use the latest (potentially refreshed) token.
|
|
124
124
|
|
|
125
|
+
## Multi-source data (`DataClient`)
|
|
126
|
+
|
|
127
|
+
### The `DataClient` contract
|
|
128
|
+
|
|
129
|
+
`DooverClient` now implements the `DataClient` interface — the shared contract for every client type in this library. Any hook or provider that previously accepted a `DooverClient` now accepts any `DataClient`.
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
import type { DataClient } from "doover-js";
|
|
133
|
+
|
|
134
|
+
function useMyData(client: DataClient) {
|
|
135
|
+
return client.channels.listChannels("my-agent");
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Capability model
|
|
140
|
+
|
|
141
|
+
Each client advertises what it can do via `getCapabilities()` and the `supports(cap)` helper. Calling an unsupported method throws `UnsupportedCapabilityError`.
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
import { UnsupportedCapabilityError } from "doover-js";
|
|
145
|
+
|
|
146
|
+
if (client.supports("aggregates.write")) {
|
|
147
|
+
await client.aggregates.putAggregate(channelId, data);
|
|
148
|
+
} else {
|
|
149
|
+
console.warn("Client does not support aggregate writes");
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### `LocalAgentClient` — LAN / direct access
|
|
154
|
+
|
|
155
|
+
Connect directly to a local Doover agent without cloud auth:
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
import { LocalAgentClient } from "doover-js";
|
|
159
|
+
|
|
160
|
+
const local = new LocalAgentClient({
|
|
161
|
+
baseUrl: "http://192.168.0.7:49100",
|
|
162
|
+
sourceId: "local:192.168.0.7:49100", // stable id for cache keys
|
|
163
|
+
});
|
|
164
|
+
const channels = await local.channels.listChannels("my-agent");
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
`LocalAgentClient` exposes a narrowed capability set — reads for agents, channels, messages, aggregates, and the gateway are supported; cloud-only operations (alarms, notifications, permissions, etc.) are not.
|
|
168
|
+
|
|
169
|
+
### `MultiplexClient` — fan-out reads, routed writes
|
|
170
|
+
|
|
171
|
+
`MultiplexClient` manages a registry of named sources (cloud or local) and fans reads out across all active sources, merging the results. Writes are routed to the single source that owns the target agent.
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
import { MultiplexClient, LocalAgentClient, getDooverClient } from "doover-js";
|
|
175
|
+
|
|
176
|
+
const mux = new MultiplexClient({
|
|
177
|
+
factory: (d) =>
|
|
178
|
+
d.kind === "cloud"
|
|
179
|
+
? getDooverClient({ /* cloud config */ })
|
|
180
|
+
: new LocalAgentClient({ baseUrl: `http://${(d.params as any).host}:${(d.params as any).port}`, sourceId: d.id }),
|
|
181
|
+
register: [{ id: "cloud", kind: "cloud" }],
|
|
182
|
+
enable: ["cloud"],
|
|
183
|
+
});
|
|
184
|
+
mux.setActiveSources(["cloud", { id: "local:192.168.0.7:49100", kind: "local", params: { host: "192.168.0.7", port: 49100 } }]);
|
|
185
|
+
const channels = await mux.channels.listChannels("dev7"); // merged cloud + local
|
|
186
|
+
mux.on("conflict", (c) => console.warn("source disagreement", c));
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Use `getLastConflicts()` to inspect the most recent per-key disagreements between sources after a read.
|
|
190
|
+
|
|
191
|
+
### `__source` provenance
|
|
192
|
+
|
|
193
|
+
Every datum returned by any `DataClient` carries a `__source` field (type `SourceProvenance`) recording which client returned it, when, and via which transport.
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
const ch = await client.channels.getChannel("my-channel");
|
|
197
|
+
console.log(ch.__source?.client.id); // e.g. "cloud" or "local:192.168.0.7:49100"
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### React: hooks, `DooverProvider`, and `useClientStatus`
|
|
201
|
+
|
|
202
|
+
`DooverProvider` accepts any `DataClient`:
|
|
203
|
+
|
|
204
|
+
```tsx
|
|
205
|
+
import { DooverProvider } from "doover-js/react";
|
|
206
|
+
import { MultiplexClient } from "doover-js";
|
|
207
|
+
|
|
208
|
+
<DooverProvider client={mux}>
|
|
209
|
+
<App />
|
|
210
|
+
</DooverProvider>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
All data hooks gained an optional `sources?: string[]` prop that restricts fan-out to specific sources:
|
|
214
|
+
|
|
215
|
+
```tsx
|
|
216
|
+
const { data } = useChannelAggregate(channelId, { sources: ["local:192.168.0.7:49100"] });
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
The new `useClientStatus()` hook surfaces the connection status of every registered source:
|
|
220
|
+
|
|
221
|
+
```tsx
|
|
222
|
+
import { useClientStatus } from "doover-js/react";
|
|
223
|
+
|
|
224
|
+
const statuses = useClientStatus();
|
|
225
|
+
// statuses is DataClientStatus[] — one entry per registered source
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
`useConnectionState` is soft-deprecated in favour of `useClientStatus`. It still works and remains exported, but new code should prefer `useClientStatus`.
|
|
229
|
+
|
|
125
230
|
## Architecture
|
|
126
231
|
|
|
127
232
|
`DooverClient` builds one shared `DooverAuth` instance and injects it into `RestClient`, `DooverDataProvider`, and `GatewayClient`. Token refreshes propagate everywhere automatically.
|
|
128
233
|
|
|
129
234
|
`DooverDataProvider` preserves the older viewer-oriented interface. `DooverClient` exposes the broader API surface through subclients.
|
|
235
|
+
|
|
236
|
+
## 0.5.0-alpha.1
|
|
237
|
+
|
|
238
|
+
- **`DataClient` contract + capability model** — `DooverClient` now implements the `DataClient` interface. Every client type advertises its capability set; unsupported calls throw `UnsupportedCapabilityError`. `AmbiguousWriteError` is raised when a `MultiplexClient` write has more than one candidate source. (Additive, no breaking changes.)
|
|
239
|
+
- **`__source` provenance** — every datum carries a `__source: SourceProvenance` field recording which client returned it, when, and via which transport.
|
|
240
|
+
- **`LocalAgentClient`** — new client for direct LAN connections to a local Doover agent (no cloud auth required).
|
|
241
|
+
- **`MultiplexClient`** — new client that manages a registry of named sources, fans reads out across all active sources, merges results, and routes writes to the owning source.
|
|
242
|
+
- **React `sources` option** — all data hooks accept `sources?: string[]` to restrict fan-out to specific sources; query keys are source-dimensioned.
|
|
243
|
+
- **`useClientStatus()`** — new react hook that surfaces `DataClientStatus` for each registered source.
|
|
244
|
+
- **`useConnectionState` soft-deprecated** — still exported and working; prefer `useClientStatus` for new code.
|
|
245
|
+
|
|
246
|
+
## Migrating to 0.6.0
|
|
247
|
+
|
|
248
|
+
`DooverDataProvider` (`client.viewer`) is deprecated in 0.5.0 and removed in 0.6.0. The replacements are subclients on `DooverClient`:
|
|
249
|
+
|
|
250
|
+
| Viewer method | Replacement |
|
|
251
|
+
|---|---|
|
|
252
|
+
| `client.viewer.getMe()` | `client.users.getMe()` |
|
|
253
|
+
| `client.viewer.getAgents(opts)` | `client.agents.listAgents(opts)` |
|
|
254
|
+
| `client.viewer.getChannels(id, opts)` | `client.channels.listChannels(id, opts)` |
|
|
255
|
+
| `client.viewer.getChannel(id)` | `client.channels.getChannel(id)` |
|
|
256
|
+
| `client.viewer.createChannel(id, name, opts)` | `client.channels.putChannel(id, name, body)` |
|
|
257
|
+
| `client.viewer.archiveChannel(id)` | `client.channels.archiveChannel(id)` |
|
|
258
|
+
| `client.viewer.unarchiveChannel(id)` | `client.channels.unarchiveChannel(id)` |
|
|
259
|
+
| `client.viewer.subscribeToChannel(id, msg, agg, upd?)` | `client.gateway.subscribeToChannel(channel, { onMessage, onAggregate, onMessageUpdate })` — returns an unsubscribe fn |
|
|
260
|
+
| `client.viewer.unsubscribeFromChannel(id, cb)` | call the unsubscribe fn returned by `subscribeToChannel` |
|
|
261
|
+
| `client.viewer.getAggregate(id)` | `const ch = await client.channels.getChannel(id); ch.aggregate ?? client.aggregates.getAggregate(id)` |
|
|
262
|
+
| `client.viewer.updateAggregate(id, data, params)` | `client.aggregates.patchAggregate(id, data, params)` |
|
|
263
|
+
| `client.viewer.putAggregate(id, data, params)` | `client.aggregates.putAggregate(id, data, params)` |
|
|
264
|
+
| `client.viewer.getMessages(id, opts)` | `client.messages.listMessages(id, { ...opts, order: "asc" })` (omit `order` for raw newest-first server order) |
|
|
265
|
+
| `client.viewer.deleteMessage(id, msgId)` | `client.messages.deleteMessage(id, msgId)` |
|
|
266
|
+
| `client.viewer.sendMessage(id, data)` | `client.messages.postMessage(id, { data })` |
|
|
267
|
+
| `client.viewer.sendRPC(id, req, opts)` | `client.rpc.send(id, req, opts)` |
|
|
268
|
+
| `client.viewer.getChannelSubscriptions(id)` | `client.connections.getChannelSubscriptions(id)` |
|
|
269
|
+
| `client.viewer.getAgentConnections(id)` | `client.connections.getAgentConnections(id)` |
|
|
270
|
+
| `client.viewer.getIdentifierFromPath(p, s)` | `getIdentifierFromPath(p, s)` (free function — already exported) |
|
|
271
|
+
| `client.viewer.getAgentInfo(id)` | **dropped, no replacement** — was a synthesized stub with no network call |
|
|
272
|
+
|
|
273
|
+
`*Api` resource methods accept either positional arguments or a `ChannelIdentifier` / `{ agentId }` object on every call form.
|
|
274
|
+
|
|
275
|
+
`client.rpc.send` adds optional `signal: AbortSignal` and `timeoutMs: number` and rejects with `DooverRpcError` (with `.status` and `.request`) instead of the bare status string.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface ChannelIdentifierLike {
|
|
2
|
+
agentId: string;
|
|
3
|
+
channelName: string;
|
|
4
|
+
}
|
|
5
|
+
export interface AgentIdentifierLike {
|
|
6
|
+
agentId: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function resolveChannelArgs<TOptions>(args: unknown[]): {
|
|
9
|
+
agentId: string;
|
|
10
|
+
channelName: string;
|
|
11
|
+
options?: TOptions;
|
|
12
|
+
};
|
|
13
|
+
export declare function resolveAgentArgs<TOptions>(args: unknown[]): {
|
|
14
|
+
agentId: string;
|
|
15
|
+
options?: TOptions;
|
|
16
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveChannelArgs = resolveChannelArgs;
|
|
4
|
+
exports.resolveAgentArgs = resolveAgentArgs;
|
|
5
|
+
function resolveChannelArgs(args) {
|
|
6
|
+
if (typeof args[0] === "string") {
|
|
7
|
+
return {
|
|
8
|
+
agentId: args[0],
|
|
9
|
+
channelName: args[1],
|
|
10
|
+
options: args[2],
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
const id = args[0];
|
|
14
|
+
return {
|
|
15
|
+
agentId: id.agentId,
|
|
16
|
+
channelName: id.channelName,
|
|
17
|
+
options: args[1],
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function resolveAgentArgs(args) {
|
|
21
|
+
if (typeof args[0] === "string") {
|
|
22
|
+
return { agentId: args[0], options: args[1] };
|
|
23
|
+
}
|
|
24
|
+
const id = args[0];
|
|
25
|
+
return { agentId: id.agentId, options: args[1] };
|
|
26
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AgentAggregate, BatchMessagesResponse } from "../types/openapi";
|
|
2
|
+
import type { AgentsResponse, GetAgentsOptions } from "../types/viewer";
|
|
2
3
|
import type { RestClient } from "../http/rest-client";
|
|
3
4
|
export interface MultiAgentMessagesParams {
|
|
4
5
|
agent_id: string[];
|
|
@@ -28,7 +29,9 @@ export interface MultiAgentAggregatesParams {
|
|
|
28
29
|
}
|
|
29
30
|
export declare class AgentsApi {
|
|
30
31
|
private readonly rest;
|
|
31
|
-
|
|
32
|
+
private readonly controlApiUrl?;
|
|
33
|
+
constructor(rest: RestClient, controlApiUrl?: string | undefined);
|
|
34
|
+
listAgents(options?: GetAgentsOptions): Promise<AgentsResponse>;
|
|
32
35
|
getMultiAgentMessages(channelName: string, params: MultiAgentMessagesParams): Promise<BatchMessagesResponse>;
|
|
33
36
|
/**
|
|
34
37
|
* Batch-fetch aggregates for many agents. Auto-chunks `agent_id` so each
|
package/dist/apis/agents-api.js
CHANGED
|
@@ -2,9 +2,147 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AgentsApi = void 0;
|
|
4
4
|
const snowflake_1 = require("../utils/snowflake");
|
|
5
|
+
function isPlainObject(value) {
|
|
6
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
function buildUserDisplayName(rawUser) {
|
|
9
|
+
const source = isPlainObject(rawUser)
|
|
10
|
+
? rawUser
|
|
11
|
+
: {};
|
|
12
|
+
const firstName = typeof source.first_name === "string" ? source.first_name.trim() : "";
|
|
13
|
+
const lastName = typeof source.last_name === "string" ? source.last_name.trim() : "";
|
|
14
|
+
const fullName = `${firstName} ${lastName}`.trim();
|
|
15
|
+
if (fullName !== "") {
|
|
16
|
+
return fullName;
|
|
17
|
+
}
|
|
18
|
+
if (typeof source.username === "string" && source.username !== "") {
|
|
19
|
+
return source.username;
|
|
20
|
+
}
|
|
21
|
+
if (typeof source.email === "string" && source.email !== "") {
|
|
22
|
+
return source.email;
|
|
23
|
+
}
|
|
24
|
+
if (typeof source.id === "string" && source.id !== "") {
|
|
25
|
+
return source.id;
|
|
26
|
+
}
|
|
27
|
+
return String(source.id ?? "");
|
|
28
|
+
}
|
|
29
|
+
function coerceExtraConfig(value) {
|
|
30
|
+
return isPlainObject(value) ? value : {};
|
|
31
|
+
}
|
|
32
|
+
function normalizeAgentEntry(rawAgent) {
|
|
33
|
+
const source = isPlainObject(rawAgent)
|
|
34
|
+
? rawAgent
|
|
35
|
+
: {};
|
|
36
|
+
const fixedLocation = source.fixed_location;
|
|
37
|
+
const normalizedFixedLocation = isPlainObject(fixedLocation) &&
|
|
38
|
+
typeof fixedLocation.latitude === "number" &&
|
|
39
|
+
typeof fixedLocation.longitude === "number"
|
|
40
|
+
? {
|
|
41
|
+
latitude: fixedLocation.latitude,
|
|
42
|
+
longitude: fixedLocation.longitude,
|
|
43
|
+
}
|
|
44
|
+
: { latitude: 0, longitude: 0 };
|
|
45
|
+
const faIcon = typeof source.fa_icon === "string" && source.fa_icon.length > 0
|
|
46
|
+
? source.fa_icon
|
|
47
|
+
: "fa-solid fa-robot";
|
|
48
|
+
return {
|
|
49
|
+
...source,
|
|
50
|
+
id: typeof source.id === "string" ? source.id : String(source.id ?? ""),
|
|
51
|
+
organisation: typeof source.organisation === "string" ? source.organisation : "",
|
|
52
|
+
name: typeof source.name === "string" ? source.name : "",
|
|
53
|
+
display_name: typeof source.display_name === "string" ? source.display_name : "",
|
|
54
|
+
archived: typeof source.archived === "boolean" ? source.archived : false,
|
|
55
|
+
group: typeof source.group === "string" ? source.group : "",
|
|
56
|
+
fa_icon: faIcon,
|
|
57
|
+
type: source.type === "device" ||
|
|
58
|
+
source.type === "dashboard" ||
|
|
59
|
+
source.type === "organisation" ||
|
|
60
|
+
source.type === "user"
|
|
61
|
+
? source.type
|
|
62
|
+
: "device",
|
|
63
|
+
fixed_location: normalizedFixedLocation,
|
|
64
|
+
extra_config: coerceExtraConfig(source.extra_config),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function normalizeOrganisationEntry(rawOrganisation) {
|
|
68
|
+
const source = isPlainObject(rawOrganisation)
|
|
69
|
+
? rawOrganisation
|
|
70
|
+
: {};
|
|
71
|
+
const name = typeof source.name === "string" ? source.name : "";
|
|
72
|
+
const rootGroup = isPlainObject(source.root_group) ? source.root_group : null;
|
|
73
|
+
const groupName = rootGroup && typeof rootGroup.name === "string" ? rootGroup.name : "";
|
|
74
|
+
return {
|
|
75
|
+
id: typeof source.id === "string" ? source.id : String(source.id ?? ""),
|
|
76
|
+
organisation: name,
|
|
77
|
+
name,
|
|
78
|
+
display_name: name,
|
|
79
|
+
archived: typeof source.archived === "boolean" ? source.archived : false,
|
|
80
|
+
group: groupName,
|
|
81
|
+
fa_icon: "fa-solid fa-building",
|
|
82
|
+
type: "organisation",
|
|
83
|
+
fixed_location: { latitude: 0, longitude: 0 },
|
|
84
|
+
extra_config: coerceExtraConfig(source.extra_config),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function normalizeUserEntry(rawUser) {
|
|
88
|
+
const source = isPlainObject(rawUser)
|
|
89
|
+
? rawUser
|
|
90
|
+
: {};
|
|
91
|
+
const id = typeof source.id === "string" ? source.id : String(source.id ?? "");
|
|
92
|
+
const username = typeof source.username === "string" ? source.username : "";
|
|
93
|
+
const email = typeof source.email === "string" ? source.email : "";
|
|
94
|
+
const name = username !== "" ? username : email !== "" ? email : id;
|
|
95
|
+
return {
|
|
96
|
+
id,
|
|
97
|
+
organisation: "",
|
|
98
|
+
name,
|
|
99
|
+
display_name: buildUserDisplayName(source),
|
|
100
|
+
archived: false,
|
|
101
|
+
group: "",
|
|
102
|
+
fa_icon: "fa-solid fa-user",
|
|
103
|
+
type: "user",
|
|
104
|
+
fixed_location: { latitude: 0, longitude: 0 },
|
|
105
|
+
extra_config: coerceExtraConfig(source.custom_data),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
5
108
|
class AgentsApi {
|
|
6
|
-
constructor(rest) {
|
|
109
|
+
constructor(rest, controlApiUrl) {
|
|
7
110
|
this.rest = rest;
|
|
111
|
+
this.controlApiUrl = controlApiUrl;
|
|
112
|
+
}
|
|
113
|
+
async listAgents(options) {
|
|
114
|
+
const query = {};
|
|
115
|
+
if (options?.includeArchived)
|
|
116
|
+
query["include-archived"] = true;
|
|
117
|
+
if (options?.includeOrganisations)
|
|
118
|
+
query["include-organisations"] = true;
|
|
119
|
+
if (options?.includeUsers)
|
|
120
|
+
query["include-users"] = true;
|
|
121
|
+
const raw = await this.rest.request({
|
|
122
|
+
path: "/agents/",
|
|
123
|
+
baseUrl: this.controlApiUrl,
|
|
124
|
+
omitSharingHeader: true,
|
|
125
|
+
query: Object.keys(query).length > 0 ? query : undefined,
|
|
126
|
+
});
|
|
127
|
+
const rawAgents = Array.isArray(raw.agents) ? raw.agents : [];
|
|
128
|
+
const normalizedAgents = rawAgents.map(normalizeAgentEntry);
|
|
129
|
+
if (!options?.mergeIncludedAsAgents) {
|
|
130
|
+
return { ...raw, agents: normalizedAgents };
|
|
131
|
+
}
|
|
132
|
+
const merged = [...normalizedAgents];
|
|
133
|
+
if (options.includeOrganisations) {
|
|
134
|
+
const rawOrgs = Array.isArray(raw.organisations)
|
|
135
|
+
? raw.organisations
|
|
136
|
+
: [];
|
|
137
|
+
for (const org of rawOrgs)
|
|
138
|
+
merged.push(normalizeOrganisationEntry(org));
|
|
139
|
+
}
|
|
140
|
+
if (options.includeUsers) {
|
|
141
|
+
const rawUsers = Array.isArray(raw.users) ? raw.users : [];
|
|
142
|
+
for (const user of rawUsers)
|
|
143
|
+
merged.push(normalizeUserEntry(user));
|
|
144
|
+
}
|
|
145
|
+
return { ...raw, agents: merged, results: merged, count: merged.length };
|
|
8
146
|
}
|
|
9
147
|
async getMultiAgentMessages(channelName, params) {
|
|
10
148
|
const response = await this.rest.get(`/agents/channels/${channelName}/messages`, params);
|
|
@@ -8,8 +8,28 @@ export interface AggregateMutationParams {
|
|
|
8
8
|
export declare class AggregatesApi {
|
|
9
9
|
private readonly rest;
|
|
10
10
|
constructor(rest: RestClient);
|
|
11
|
-
getAggregate(agentId: string, channelName: string): Promise<Aggregate
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
getAggregate(agentId: string, channelName: string): Promise<Aggregate>;
|
|
12
|
+
getAggregate(identifier: {
|
|
13
|
+
agentId: string;
|
|
14
|
+
channelName: string;
|
|
15
|
+
}): Promise<Aggregate>;
|
|
16
|
+
private _getAggregate;
|
|
17
|
+
putAggregate(agentId: string, channelName: string, body: Record<string, unknown> | FormData, params?: AggregateMutationParams): Promise<Aggregate>;
|
|
18
|
+
putAggregate(identifier: {
|
|
19
|
+
agentId: string;
|
|
20
|
+
channelName: string;
|
|
21
|
+
}, body: Record<string, unknown> | FormData, params?: AggregateMutationParams): Promise<Aggregate>;
|
|
22
|
+
private _putAggregate;
|
|
23
|
+
patchAggregate(agentId: string, channelName: string, body: Record<string, unknown> | FormData, params?: AggregateMutationParams): Promise<Aggregate>;
|
|
24
|
+
patchAggregate(identifier: {
|
|
25
|
+
agentId: string;
|
|
26
|
+
channelName: string;
|
|
27
|
+
}, body: Record<string, unknown> | FormData, params?: AggregateMutationParams): Promise<Aggregate>;
|
|
28
|
+
private _patchAggregate;
|
|
14
29
|
getAggregateAttachment(agentId: string, channelName: string, attachmentId: string): Promise<Blob>;
|
|
30
|
+
getAggregateAttachment(identifier: {
|
|
31
|
+
agentId: string;
|
|
32
|
+
channelName: string;
|
|
33
|
+
}, attachmentId: string): Promise<Blob>;
|
|
34
|
+
private _getAggregateAttachment;
|
|
15
35
|
}
|
|
@@ -1,20 +1,49 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AggregatesApi = void 0;
|
|
4
|
+
const _args_1 = require("./_args");
|
|
4
5
|
class AggregatesApi {
|
|
5
6
|
constructor(rest) {
|
|
6
7
|
this.rest = rest;
|
|
7
8
|
}
|
|
8
|
-
getAggregate(
|
|
9
|
+
getAggregate(...args) {
|
|
10
|
+
const { agentId, channelName } = (0, _args_1.resolveChannelArgs)(args);
|
|
11
|
+
return this._getAggregate(agentId, channelName);
|
|
12
|
+
}
|
|
13
|
+
_getAggregate(agentId, channelName) {
|
|
9
14
|
return this.rest.get(`/agents/${agentId}/channels/${channelName}/aggregate`);
|
|
10
15
|
}
|
|
11
|
-
putAggregate(
|
|
16
|
+
putAggregate(...args) {
|
|
17
|
+
if (typeof args[0] === "string") {
|
|
18
|
+
const [agentId, channelName, body, params] = args;
|
|
19
|
+
return this._putAggregate(agentId, channelName, body, params);
|
|
20
|
+
}
|
|
21
|
+
const id = args[0];
|
|
22
|
+
return this._putAggregate(id.agentId, id.channelName, args[1], args[2]);
|
|
23
|
+
}
|
|
24
|
+
_putAggregate(agentId, channelName, body, params) {
|
|
12
25
|
return this.rest.put(`/agents/${agentId}/channels/${channelName}/aggregate`, body, params);
|
|
13
26
|
}
|
|
14
|
-
patchAggregate(
|
|
27
|
+
patchAggregate(...args) {
|
|
28
|
+
if (typeof args[0] === "string") {
|
|
29
|
+
const [agentId, channelName, body, params] = args;
|
|
30
|
+
return this._patchAggregate(agentId, channelName, body, params);
|
|
31
|
+
}
|
|
32
|
+
const id = args[0];
|
|
33
|
+
return this._patchAggregate(id.agentId, id.channelName, args[1], args[2]);
|
|
34
|
+
}
|
|
35
|
+
_patchAggregate(agentId, channelName, body, params) {
|
|
15
36
|
return this.rest.patch(`/agents/${agentId}/channels/${channelName}/aggregate`, body, params);
|
|
16
37
|
}
|
|
17
|
-
getAggregateAttachment(
|
|
38
|
+
getAggregateAttachment(...args) {
|
|
39
|
+
if (typeof args[0] === "string") {
|
|
40
|
+
const [agentId, channelName, attachmentId] = args;
|
|
41
|
+
return this._getAggregateAttachment(agentId, channelName, attachmentId);
|
|
42
|
+
}
|
|
43
|
+
const id = args[0];
|
|
44
|
+
return this._getAggregateAttachment(id.agentId, id.channelName, args[1]);
|
|
45
|
+
}
|
|
46
|
+
_getAggregateAttachment(agentId, channelName, attachmentId) {
|
|
18
47
|
return this.rest.get(`/agents/${agentId}/channels/${channelName}/aggregate/attachments/${attachmentId}`);
|
|
19
48
|
}
|
|
20
49
|
}
|
|
@@ -4,9 +4,39 @@ export declare class AlarmsApi {
|
|
|
4
4
|
private readonly rest;
|
|
5
5
|
constructor(rest: RestClient);
|
|
6
6
|
listAlarms(agentId: string, channelName: string): Promise<Alarm[]>;
|
|
7
|
+
listAlarms(identifier: {
|
|
8
|
+
agentId: string;
|
|
9
|
+
channelName: string;
|
|
10
|
+
}): Promise<Alarm[]>;
|
|
11
|
+
private _listAlarms;
|
|
7
12
|
createAlarm(agentId: string, channelName: string, body: CreateAlarmRequest): Promise<Alarm>;
|
|
13
|
+
createAlarm(identifier: {
|
|
14
|
+
agentId: string;
|
|
15
|
+
channelName: string;
|
|
16
|
+
}, body: CreateAlarmRequest): Promise<Alarm>;
|
|
17
|
+
private _createAlarm;
|
|
8
18
|
getAlarm(agentId: string, channelName: string, alarmId: string): Promise<Alarm>;
|
|
19
|
+
getAlarm(identifier: {
|
|
20
|
+
agentId: string;
|
|
21
|
+
channelName: string;
|
|
22
|
+
}, alarmId: string): Promise<Alarm>;
|
|
23
|
+
private _getAlarm;
|
|
9
24
|
putAlarm(agentId: string, channelName: string, alarmId: string, body: CreateAlarmRequest): Promise<Alarm>;
|
|
25
|
+
putAlarm(identifier: {
|
|
26
|
+
agentId: string;
|
|
27
|
+
channelName: string;
|
|
28
|
+
}, alarmId: string, body: CreateAlarmRequest): Promise<Alarm>;
|
|
29
|
+
private _putAlarm;
|
|
10
30
|
patchAlarm(agentId: string, channelName: string, alarmId: string, body: PatchAlarmRequest): Promise<Alarm>;
|
|
31
|
+
patchAlarm(identifier: {
|
|
32
|
+
agentId: string;
|
|
33
|
+
channelName: string;
|
|
34
|
+
}, alarmId: string, body: PatchAlarmRequest): Promise<Alarm>;
|
|
35
|
+
private _patchAlarm;
|
|
11
36
|
deleteAlarm(agentId: string, channelName: string, alarmId: string): Promise<unknown>;
|
|
37
|
+
deleteAlarm(identifier: {
|
|
38
|
+
agentId: string;
|
|
39
|
+
channelName: string;
|
|
40
|
+
}, alarmId: string): Promise<unknown>;
|
|
41
|
+
private _deleteAlarm;
|
|
12
42
|
}
|
package/dist/apis/alarms-api.js
CHANGED
|
@@ -1,26 +1,71 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AlarmsApi = void 0;
|
|
4
|
+
const _args_1 = require("./_args");
|
|
4
5
|
class AlarmsApi {
|
|
5
6
|
constructor(rest) {
|
|
6
7
|
this.rest = rest;
|
|
7
8
|
}
|
|
8
|
-
listAlarms(
|
|
9
|
+
listAlarms(...args) {
|
|
10
|
+
const { agentId, channelName } = (0, _args_1.resolveChannelArgs)(args);
|
|
11
|
+
return this._listAlarms(agentId, channelName);
|
|
12
|
+
}
|
|
13
|
+
_listAlarms(agentId, channelName) {
|
|
9
14
|
return this.rest.get(`/agents/${agentId}/channels/${channelName}/alarms`);
|
|
10
15
|
}
|
|
11
|
-
createAlarm(
|
|
16
|
+
createAlarm(...args) {
|
|
17
|
+
if (typeof args[0] === "string") {
|
|
18
|
+
const [agentId, channelName, body] = args;
|
|
19
|
+
return this._createAlarm(agentId, channelName, body);
|
|
20
|
+
}
|
|
21
|
+
const id = args[0];
|
|
22
|
+
return this._createAlarm(id.agentId, id.channelName, args[1]);
|
|
23
|
+
}
|
|
24
|
+
_createAlarm(agentId, channelName, body) {
|
|
12
25
|
return this.rest.post(`/agents/${agentId}/channels/${channelName}/alarms`, body);
|
|
13
26
|
}
|
|
14
|
-
getAlarm(
|
|
27
|
+
getAlarm(...args) {
|
|
28
|
+
if (typeof args[0] === "string") {
|
|
29
|
+
const [agentId, channelName, alarmId] = args;
|
|
30
|
+
return this._getAlarm(agentId, channelName, alarmId);
|
|
31
|
+
}
|
|
32
|
+
const id = args[0];
|
|
33
|
+
return this._getAlarm(id.agentId, id.channelName, args[1]);
|
|
34
|
+
}
|
|
35
|
+
_getAlarm(agentId, channelName, alarmId) {
|
|
15
36
|
return this.rest.get(`/agents/${agentId}/channels/${channelName}/alarms/${alarmId}`);
|
|
16
37
|
}
|
|
17
|
-
putAlarm(
|
|
38
|
+
putAlarm(...args) {
|
|
39
|
+
if (typeof args[0] === "string") {
|
|
40
|
+
const [agentId, channelName, alarmId, body] = args;
|
|
41
|
+
return this._putAlarm(agentId, channelName, alarmId, body);
|
|
42
|
+
}
|
|
43
|
+
const id = args[0];
|
|
44
|
+
return this._putAlarm(id.agentId, id.channelName, args[1], args[2]);
|
|
45
|
+
}
|
|
46
|
+
_putAlarm(agentId, channelName, alarmId, body) {
|
|
18
47
|
return this.rest.put(`/agents/${agentId}/channels/${channelName}/alarms/${alarmId}`, body);
|
|
19
48
|
}
|
|
20
|
-
patchAlarm(
|
|
49
|
+
patchAlarm(...args) {
|
|
50
|
+
if (typeof args[0] === "string") {
|
|
51
|
+
const [agentId, channelName, alarmId, body] = args;
|
|
52
|
+
return this._patchAlarm(agentId, channelName, alarmId, body);
|
|
53
|
+
}
|
|
54
|
+
const id = args[0];
|
|
55
|
+
return this._patchAlarm(id.agentId, id.channelName, args[1], args[2]);
|
|
56
|
+
}
|
|
57
|
+
_patchAlarm(agentId, channelName, alarmId, body) {
|
|
21
58
|
return this.rest.patch(`/agents/${agentId}/channels/${channelName}/alarms/${alarmId}`, body);
|
|
22
59
|
}
|
|
23
|
-
deleteAlarm(
|
|
60
|
+
deleteAlarm(...args) {
|
|
61
|
+
if (typeof args[0] === "string") {
|
|
62
|
+
const [agentId, channelName, alarmId] = args;
|
|
63
|
+
return this._deleteAlarm(agentId, channelName, alarmId);
|
|
64
|
+
}
|
|
65
|
+
const id = args[0];
|
|
66
|
+
return this._deleteAlarm(id.agentId, id.channelName, args[1]);
|
|
67
|
+
}
|
|
68
|
+
_deleteAlarm(agentId, channelName, alarmId) {
|
|
24
69
|
return this.rest.delete(`/agents/${agentId}/channels/${channelName}/alarms/${alarmId}`);
|
|
25
70
|
}
|
|
26
71
|
}
|
|
@@ -17,11 +17,48 @@ export interface DataSeriesParams {
|
|
|
17
17
|
export declare class ChannelsApi {
|
|
18
18
|
private readonly rest;
|
|
19
19
|
constructor(rest: RestClient);
|
|
20
|
-
listChannels(agentId: string, options?: ListChannelsOptions): Promise<Channel
|
|
21
|
-
|
|
20
|
+
listChannels(agentId: string, options?: ListChannelsOptions): Promise<Channel[]>;
|
|
21
|
+
listChannels(identifier: {
|
|
22
|
+
agentId: string;
|
|
23
|
+
}, options?: ListChannelsOptions): Promise<Channel[]>;
|
|
24
|
+
private _listChannels;
|
|
25
|
+
getChannel(agentId: string, channelName: string, options?: GetChannelOptions): Promise<Channel>;
|
|
26
|
+
getChannel(identifier: {
|
|
27
|
+
agentId: string;
|
|
28
|
+
channelName: string;
|
|
29
|
+
}, options?: GetChannelOptions): Promise<Channel>;
|
|
30
|
+
private _getChannel;
|
|
22
31
|
createChannel(agentId: string, channelName: string, body: CreateChannelRequest): Promise<{
|
|
23
32
|
id: string;
|
|
24
33
|
}>;
|
|
25
|
-
|
|
34
|
+
createChannel(identifier: {
|
|
35
|
+
agentId: string;
|
|
36
|
+
channelName: string;
|
|
37
|
+
}, body: CreateChannelRequest): Promise<{
|
|
38
|
+
id: string;
|
|
39
|
+
}>;
|
|
40
|
+
private _createChannel;
|
|
41
|
+
putChannel(agentId: string, channelName: string, body: PutChannelRequest): Promise<Channel>;
|
|
42
|
+
putChannel(identifier: {
|
|
43
|
+
agentId: string;
|
|
44
|
+
channelName: string;
|
|
45
|
+
}, body: PutChannelRequest): Promise<Channel>;
|
|
46
|
+
private _putChannel;
|
|
47
|
+
archiveChannel(agentId: string, channelName: string): Promise<unknown>;
|
|
48
|
+
archiveChannel(identifier: {
|
|
49
|
+
agentId: string;
|
|
50
|
+
channelName: string;
|
|
51
|
+
}): Promise<unknown>;
|
|
52
|
+
private _archiveChannel;
|
|
53
|
+
unarchiveChannel(agentId: string, channelName: string): Promise<unknown>;
|
|
54
|
+
unarchiveChannel(identifier: {
|
|
55
|
+
agentId: string;
|
|
56
|
+
channelName: string;
|
|
57
|
+
}): Promise<unknown>;
|
|
58
|
+
private _unarchiveChannel;
|
|
26
59
|
listDataSeries(agentId: string, params: DataSeriesParams): Promise<DataSeries>;
|
|
60
|
+
listDataSeries(identifier: {
|
|
61
|
+
agentId: string;
|
|
62
|
+
}, params: DataSeriesParams): Promise<DataSeries>;
|
|
63
|
+
private _listDataSeries;
|
|
27
64
|
}
|