@synnaxlabs/client 0.38.0 → 0.39.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/.turbo/turbo-build.log +7 -7
- package/dist/access/payload.d.ts +6 -6
- package/dist/access/payload.d.ts.map +1 -1
- package/dist/access/policy/client.d.ts +5 -3
- package/dist/access/policy/client.d.ts.map +1 -1
- package/dist/access/policy/external.d.ts +1 -0
- package/dist/access/policy/external.d.ts.map +1 -1
- package/dist/access/policy/ontology.d.ts +5 -0
- package/dist/access/policy/ontology.d.ts.map +1 -0
- package/dist/access/policy/payload.d.ts +86 -89
- package/dist/access/policy/payload.d.ts.map +1 -1
- package/dist/access/policy/retriever.d.ts +7 -6
- package/dist/access/policy/retriever.d.ts.map +1 -1
- package/dist/access/policy/writer.d.ts +2 -2
- package/dist/access/policy/writer.d.ts.map +1 -1
- package/dist/auth/auth.d.ts +2 -1
- package/dist/auth/auth.d.ts.map +1 -1
- package/dist/channel/client.d.ts +8 -7
- package/dist/channel/client.d.ts.map +1 -1
- package/dist/channel/payload.d.ts +13 -11
- package/dist/channel/payload.d.ts.map +1 -1
- package/dist/channel/retriever.d.ts +9 -6
- package/dist/channel/retriever.d.ts.map +1 -1
- package/dist/channel/writer.d.ts +6 -4
- package/dist/channel/writer.d.ts.map +1 -1
- package/dist/client.cjs +30 -30
- package/dist/client.d.ts +4 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +3488 -3500
- package/dist/connection/checker.d.ts +5 -4
- package/dist/connection/checker.d.ts.map +1 -1
- package/dist/control/state.d.ts +10 -8
- package/dist/control/state.d.ts.map +1 -1
- package/dist/errors.d.ts +5 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/framer/adapter.d.ts +14 -15
- package/dist/framer/adapter.d.ts.map +1 -1
- package/dist/framer/client.d.ts +13 -15
- package/dist/framer/client.d.ts.map +1 -1
- package/dist/framer/deleter.d.ts +3 -2
- package/dist/framer/deleter.d.ts.map +1 -1
- package/dist/framer/frame.d.ts +31 -27
- package/dist/framer/frame.d.ts.map +1 -1
- package/dist/framer/iterator.d.ts +4 -5
- package/dist/framer/iterator.d.ts.map +1 -1
- package/dist/framer/streamer.d.ts +5 -6
- package/dist/framer/streamer.d.ts.map +1 -1
- package/dist/framer/writer.d.ts +42 -39
- package/dist/framer/writer.d.ts.map +1 -1
- package/dist/hardware/device/client.d.ts +17 -12
- package/dist/hardware/device/client.d.ts.map +1 -1
- package/dist/hardware/device/payload.d.ts +19 -16
- package/dist/hardware/device/payload.d.ts.map +1 -1
- package/dist/hardware/rack/client.d.ts +15 -15
- package/dist/hardware/rack/client.d.ts.map +1 -1
- package/dist/hardware/rack/payload.d.ts +9 -8
- package/dist/hardware/rack/payload.d.ts.map +1 -1
- package/dist/hardware/task/client.d.ts +38 -29
- package/dist/hardware/task/client.d.ts.map +1 -1
- package/dist/hardware/task/payload.d.ts +58 -53
- package/dist/hardware/task/payload.d.ts.map +1 -1
- package/dist/label/client.d.ts +4 -3
- package/dist/label/client.d.ts.map +1 -1
- package/dist/label/payload.d.ts +4 -4
- package/dist/label/payload.d.ts.map +1 -1
- package/dist/label/retriever.d.ts.map +1 -1
- package/dist/label/writer.d.ts +13 -10
- package/dist/label/writer.d.ts.map +1 -1
- package/dist/ontology/client.d.ts +12 -10
- package/dist/ontology/client.d.ts.map +1 -1
- package/dist/ontology/group/client.d.ts +5 -4
- package/dist/ontology/group/client.d.ts.map +1 -1
- package/dist/ontology/group/group.d.ts +7 -5
- package/dist/ontology/group/group.d.ts.map +1 -1
- package/dist/ontology/group/payload.d.ts +6 -5
- package/dist/ontology/group/payload.d.ts.map +1 -1
- package/dist/ontology/group/writer.d.ts +8 -8
- package/dist/ontology/group/writer.d.ts.map +1 -1
- package/dist/ontology/payload.d.ts +72 -62
- package/dist/ontology/payload.d.ts.map +1 -1
- package/dist/ontology/writer.d.ts.map +1 -1
- package/dist/ranger/alias.d.ts +9 -10
- package/dist/ranger/alias.d.ts.map +1 -1
- package/dist/ranger/client.d.ts +18 -18
- package/dist/ranger/client.d.ts.map +1 -1
- package/dist/ranger/external.d.ts +1 -1
- package/dist/ranger/external.d.ts.map +1 -1
- package/dist/ranger/kv.d.ts +18 -14
- package/dist/ranger/kv.d.ts.map +1 -1
- package/dist/ranger/payload.d.ts +13 -13
- package/dist/ranger/payload.d.ts.map +1 -1
- package/dist/ranger/writer.d.ts +14 -14
- package/dist/ranger/writer.d.ts.map +1 -1
- package/dist/setupspecs.d.ts.map +1 -1
- package/dist/signals/observable.d.ts +3 -1
- package/dist/signals/observable.d.ts.map +1 -1
- package/dist/user/client.d.ts +5 -3
- package/dist/user/client.d.ts.map +1 -1
- package/dist/user/payload.d.ts +7 -6
- package/dist/user/payload.d.ts.map +1 -1
- package/dist/user/retriever.d.ts +2 -1
- package/dist/user/retriever.d.ts.map +1 -1
- package/dist/user/writer.d.ts +2 -2
- package/dist/user/writer.d.ts.map +1 -1
- package/dist/util/decodeJSONString.d.ts +3 -0
- package/dist/util/decodeJSONString.d.ts.map +1 -0
- package/dist/util/parseWithoutKeyConversion.d.ts +3 -0
- package/dist/util/parseWithoutKeyConversion.d.ts.map +1 -0
- package/dist/util/retrieve.d.ts +1 -1
- package/dist/util/retrieve.d.ts.map +1 -1
- package/dist/util/telem.d.ts.map +1 -1
- package/dist/util/zod.d.ts.map +1 -1
- package/dist/workspace/client.d.ts +6 -60
- package/dist/workspace/client.d.ts.map +1 -1
- package/dist/workspace/external.d.ts +3 -0
- package/dist/workspace/external.d.ts.map +1 -0
- package/dist/workspace/index.d.ts +1 -1
- package/dist/workspace/index.d.ts.map +1 -1
- package/dist/workspace/lineplot/client.d.ts +5 -44
- package/dist/workspace/lineplot/client.d.ts.map +1 -1
- package/dist/workspace/lineplot/external.d.ts +3 -0
- package/dist/workspace/lineplot/external.d.ts.map +1 -0
- package/dist/workspace/lineplot/index.d.ts +1 -1
- package/dist/workspace/lineplot/index.d.ts.map +1 -1
- package/dist/workspace/lineplot/payload.d.ts +45 -0
- package/dist/workspace/lineplot/payload.d.ts.map +1 -0
- package/dist/workspace/log/client.d.ts +5 -44
- package/dist/workspace/log/client.d.ts.map +1 -1
- package/dist/workspace/log/external.d.ts +3 -0
- package/dist/workspace/log/external.d.ts.map +1 -0
- package/dist/workspace/log/index.d.ts +1 -1
- package/dist/workspace/log/index.d.ts.map +1 -1
- package/dist/workspace/log/payload.d.ts +45 -0
- package/dist/workspace/log/payload.d.ts.map +1 -0
- package/dist/workspace/payload.d.ts +60 -0
- package/dist/workspace/payload.d.ts.map +1 -0
- package/dist/workspace/schematic/client.d.ts +5 -68
- package/dist/workspace/schematic/client.d.ts.map +1 -1
- package/dist/workspace/schematic/external.d.ts +3 -0
- package/dist/workspace/schematic/external.d.ts.map +1 -0
- package/dist/workspace/schematic/index.d.ts +1 -1
- package/dist/workspace/schematic/index.d.ts.map +1 -1
- package/dist/workspace/schematic/payload.d.ts +71 -0
- package/dist/workspace/schematic/payload.d.ts.map +1 -0
- package/dist/workspace/table/client.d.ts +5 -57
- package/dist/workspace/table/client.d.ts.map +1 -1
- package/dist/workspace/table/external.d.ts +3 -0
- package/dist/workspace/table/external.d.ts.map +1 -0
- package/dist/workspace/table/index.d.ts +1 -1
- package/dist/workspace/table/index.d.ts.map +1 -1
- package/dist/workspace/table/payload.d.ts +60 -0
- package/dist/workspace/table/payload.d.ts.map +1 -0
- package/eslint.config.js +1 -1
- package/examples/node/basicReadWrite.js +27 -27
- package/examples/node/liveStream.js +16 -16
- package/examples/node/seriesAndFrames.js +39 -39
- package/examples/node/streamWrite.js +48 -46
- package/package.json +14 -12
- package/src/access/client.ts +1 -1
- package/src/access/external.ts +1 -1
- package/src/access/index.ts +1 -1
- package/src/access/payload.ts +13 -13
- package/src/access/policy/client.ts +14 -13
- package/src/access/policy/external.ts +2 -1
- package/src/access/policy/index.ts +1 -1
- package/src/access/policy/ontology.ts +17 -0
- package/src/access/policy/payload.ts +8 -20
- package/src/access/policy/policy.spec.ts +17 -17
- package/src/access/policy/retriever.ts +3 -2
- package/src/access/policy/writer.ts +5 -5
- package/src/auth/auth.spec.ts +28 -24
- package/src/auth/auth.ts +8 -12
- package/src/auth/index.ts +1 -1
- package/src/channel/batchRetriever.spec.ts +26 -23
- package/src/channel/channel.spec.ts +1 -1
- package/src/channel/client.ts +24 -24
- package/src/channel/external.ts +1 -1
- package/src/channel/index.ts +1 -1
- package/src/channel/payload.ts +17 -21
- package/src/channel/retriever.ts +21 -22
- package/src/channel/writer.ts +12 -14
- package/src/client.ts +7 -17
- package/src/connection/checker.ts +10 -12
- package/src/connection/connection.spec.ts +18 -6
- package/src/connection/index.ts +1 -1
- package/src/control/client.ts +1 -1
- package/src/control/external.ts +1 -1
- package/src/control/index.ts +1 -1
- package/src/control/state.spec.ts +1 -1
- package/src/control/state.ts +9 -10
- package/src/errors.spec.ts +2 -2
- package/src/errors.ts +9 -1
- package/src/framer/adapter.spec.ts +29 -24
- package/src/framer/adapter.ts +38 -42
- package/src/framer/client.spec.ts +6 -12
- package/src/framer/client.ts +35 -39
- package/src/framer/deleter.spec.ts +1 -1
- package/src/framer/deleter.ts +6 -7
- package/src/framer/external.ts +1 -1
- package/src/framer/frame.spec.ts +1 -1
- package/src/framer/frame.ts +63 -51
- package/src/framer/index.ts +1 -1
- package/src/framer/iterator.spec.ts +1 -1
- package/src/framer/iterator.ts +12 -17
- package/src/framer/streamProxy.ts +2 -2
- package/src/framer/streamer.spec.ts +3 -11
- package/src/framer/streamer.ts +16 -20
- package/src/framer/writer.spec.ts +49 -8
- package/src/framer/writer.ts +40 -32
- package/src/hardware/client.ts +1 -1
- package/src/hardware/device/client.ts +65 -40
- package/src/hardware/device/device.spec.ts +50 -34
- package/src/hardware/device/external.ts +1 -1
- package/src/hardware/device/index.ts +1 -1
- package/src/hardware/device/payload.ts +30 -30
- package/src/hardware/external.ts +1 -1
- package/src/hardware/index.ts +1 -1
- package/src/hardware/rack/client.ts +53 -66
- package/src/hardware/rack/external.ts +1 -1
- package/src/hardware/rack/index.ts +1 -1
- package/src/hardware/rack/payload.ts +10 -19
- package/src/hardware/rack/rack.spec.ts +13 -1
- package/src/hardware/task/client.ts +161 -132
- package/src/hardware/task/external.ts +1 -1
- package/src/hardware/task/index.ts +1 -1
- package/src/hardware/task/payload.ts +50 -69
- package/src/hardware/task/task.spec.ts +99 -82
- package/src/index.ts +1 -1
- package/src/label/client.ts +13 -16
- package/src/label/external.ts +1 -1
- package/src/label/index.ts +1 -1
- package/src/label/label.spec.ts +1 -1
- package/src/label/payload.ts +4 -10
- package/src/label/retriever.ts +4 -8
- package/src/label/writer.ts +9 -16
- package/src/ontology/client.ts +31 -29
- package/src/ontology/external.ts +1 -1
- package/src/ontology/group/client.ts +6 -6
- package/src/ontology/group/external.ts +1 -1
- package/src/ontology/group/group.spec.ts +5 -5
- package/src/ontology/group/group.ts +11 -8
- package/src/ontology/group/index.ts +1 -1
- package/src/ontology/group/payload.ts +12 -36
- package/src/ontology/group/writer.ts +23 -27
- package/src/ontology/index.ts +1 -1
- package/src/ontology/ontology.spec.ts +16 -16
- package/src/ontology/payload.ts +68 -44
- package/src/ontology/writer.ts +17 -24
- package/src/ranger/alias.ts +26 -43
- package/src/ranger/client.ts +34 -41
- package/src/ranger/external.ts +2 -2
- package/src/ranger/index.ts +1 -1
- package/src/ranger/kv.ts +10 -33
- package/src/ranger/payload.ts +15 -37
- package/src/ranger/ranger.spec.ts +2 -3
- package/src/ranger/writer.ts +9 -27
- package/src/setupspecs.ts +1 -1
- package/src/signals/external.ts +1 -1
- package/src/signals/index.ts +1 -1
- package/src/signals/observable.ts +4 -5
- package/src/transport.ts +1 -1
- package/src/user/client.ts +9 -5
- package/src/user/external.ts +1 -1
- package/src/user/index.ts +1 -1
- package/src/user/payload.ts +6 -10
- package/src/user/retriever.ts +2 -2
- package/src/user/user.spec.ts +18 -16
- package/src/user/writer.ts +4 -11
- package/src/util/decodeJSONString.ts +13 -0
- package/src/util/parseWithoutKeyConversion.ts +19 -0
- package/src/util/retrieve.spec.ts +4 -14
- package/src/util/retrieve.ts +3 -13
- package/src/util/telem.ts +2 -2
- package/src/util/zod.ts +1 -1
- package/src/vite-env.d.ts +2 -1
- package/src/workspace/client.ts +39 -57
- package/src/workspace/external.ts +11 -0
- package/src/workspace/index.ts +2 -2
- package/src/workspace/lineplot/client.ts +31 -36
- package/src/workspace/lineplot/external.ts +11 -0
- package/src/workspace/lineplot/index.ts +2 -2
- package/src/workspace/lineplot/linePlot.spec.ts +2 -3
- package/src/workspace/lineplot/payload.ts +32 -0
- package/src/workspace/log/client.ts +34 -39
- package/src/workspace/log/external.ts +11 -0
- package/src/workspace/log/index.ts +2 -2
- package/src/workspace/log/log.spec.ts +6 -19
- package/src/workspace/log/payload.ts +32 -0
- package/src/workspace/payload.ts +36 -0
- package/src/workspace/schematic/client.ts +39 -56
- package/src/workspace/schematic/external.ts +11 -0
- package/src/workspace/schematic/index.ts +2 -2
- package/src/workspace/schematic/payload.ts +37 -0
- package/src/workspace/schematic/schematic.spec.ts +16 -7
- package/src/workspace/table/client.ts +36 -50
- package/src/workspace/table/external.ts +11 -0
- package/src/workspace/table/index.ts +2 -2
- package/src/workspace/table/payload.ts +36 -0
- package/src/workspace/table/table.spec.ts +1 -1
- package/src/workspace/workspace.spec.ts +2 -3
- package/vite.config.ts +1 -1
- package/dist/channel/creator.d.ts +0 -9
- package/dist/channel/creator.d.ts.map +0 -1
- package/src/channel/creator.ts +0 -37
package/src/framer/writer.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Use of this software is governed by the Business Source License included in the file
|
|
4
4
|
// licenses/BSL.txt.
|
|
@@ -23,10 +23,9 @@ import {
|
|
|
23
23
|
import { toArray } from "@synnaxlabs/x/toArray";
|
|
24
24
|
import { z } from "zod";
|
|
25
25
|
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import { type CrudeFrame, frameZ } from "@/framer/frame";
|
|
26
|
+
import { channel } from "@/channel";
|
|
27
|
+
import { WriteAdapter } from "@/framer/adapter";
|
|
28
|
+
import { type Crude, frameZ } from "@/framer/frame";
|
|
30
29
|
import { StreamProxy } from "@/framer/streamProxy";
|
|
31
30
|
|
|
32
31
|
enum Command {
|
|
@@ -64,7 +63,7 @@ export const ALWAYS_INDEX_PERSIST_ON_AUTO_COMMIT: TimeSpan = new TimeSpan(-1);
|
|
|
64
63
|
const netConfigZ = z.object({
|
|
65
64
|
start: TimeStamp.z.optional(),
|
|
66
65
|
controlSubject: control.subjectZ.optional(),
|
|
67
|
-
keys:
|
|
66
|
+
keys: channel.keyZ.array().optional(),
|
|
68
67
|
authorities: control.Authority.z.array().optional(),
|
|
69
68
|
mode: z.nativeEnum(WriterMode).optional(),
|
|
70
69
|
errOnUnauthorized: z.boolean().optional(),
|
|
@@ -72,7 +71,7 @@ const netConfigZ = z.object({
|
|
|
72
71
|
autoIndexPersistInterval: TimeSpan.z.optional(),
|
|
73
72
|
});
|
|
74
73
|
|
|
75
|
-
|
|
74
|
+
interface Config extends z.infer<typeof netConfigZ> {}
|
|
76
75
|
|
|
77
76
|
const reqZ = z.object({
|
|
78
77
|
command: z.nativeEnum(Command),
|
|
@@ -80,7 +79,7 @@ const reqZ = z.object({
|
|
|
80
79
|
frame: frameZ.optional(),
|
|
81
80
|
});
|
|
82
81
|
|
|
83
|
-
|
|
82
|
+
interface Request extends z.infer<typeof reqZ> {}
|
|
84
83
|
|
|
85
84
|
const resZ = z.object({
|
|
86
85
|
ack: z.boolean(),
|
|
@@ -88,11 +87,11 @@ const resZ = z.object({
|
|
|
88
87
|
error: errorZ.optional().nullable(),
|
|
89
88
|
});
|
|
90
89
|
|
|
91
|
-
|
|
90
|
+
interface Response extends z.infer<typeof resZ> {}
|
|
92
91
|
|
|
93
92
|
export interface WriterConfig {
|
|
94
93
|
// channels denote the channels to write to.
|
|
95
|
-
channels: Params;
|
|
94
|
+
channels: channel.Params;
|
|
96
95
|
// start sets the starting timestamp for the first sample in the writer.
|
|
97
96
|
start?: CrudeTimeStamp;
|
|
98
97
|
// controlSubject sets the control subject of the writer.
|
|
@@ -158,23 +157,21 @@ export interface WriterConfig {
|
|
|
158
157
|
export class Writer {
|
|
159
158
|
private static readonly ENDPOINT = "/frame/write";
|
|
160
159
|
private readonly stream: StreamProxy<typeof reqZ, typeof resZ>;
|
|
161
|
-
private readonly adapter:
|
|
160
|
+
private readonly adapter: WriteAdapter;
|
|
161
|
+
private errAccumulated: boolean = false;
|
|
162
162
|
|
|
163
|
-
private constructor(
|
|
164
|
-
stream: Stream<typeof reqZ, typeof resZ>,
|
|
165
|
-
adapter: WriteFrameAdapter,
|
|
166
|
-
) {
|
|
163
|
+
private constructor(stream: Stream<typeof reqZ, typeof resZ>, adapter: WriteAdapter) {
|
|
167
164
|
this.stream = new StreamProxy("Writer", stream);
|
|
168
165
|
this.adapter = adapter;
|
|
169
166
|
}
|
|
170
167
|
|
|
171
168
|
static async _open(
|
|
172
|
-
retriever: Retriever,
|
|
169
|
+
retriever: channel.Retriever,
|
|
173
170
|
client: StreamClient,
|
|
174
171
|
{
|
|
175
172
|
channels,
|
|
176
173
|
start = TimeStamp.now(),
|
|
177
|
-
authorities = control.Authority.
|
|
174
|
+
authorities = control.Authority.ABSOLUTE,
|
|
178
175
|
controlSubject: subject,
|
|
179
176
|
mode = WriterMode.PersistStream,
|
|
180
177
|
errOnUnauthorized = false,
|
|
@@ -182,7 +179,7 @@ export class Writer {
|
|
|
182
179
|
autoIndexPersistInterval = TimeSpan.SECOND,
|
|
183
180
|
}: WriterConfig,
|
|
184
181
|
): Promise<Writer> {
|
|
185
|
-
const adapter = await
|
|
182
|
+
const adapter = await WriteAdapter.open(retriever, channels);
|
|
186
183
|
const stream = await client.stream(Writer.ENDPOINT, reqZ, resZ);
|
|
187
184
|
const writer = new Writer(stream, adapter);
|
|
188
185
|
await writer.execute({
|
|
@@ -201,14 +198,19 @@ export class Writer {
|
|
|
201
198
|
return writer;
|
|
202
199
|
}
|
|
203
200
|
|
|
204
|
-
async
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
201
|
+
private async checkForAccumulatedError(): Promise<boolean> {
|
|
202
|
+
if (!this.errAccumulated && this.stream.received()) {
|
|
203
|
+
this.errAccumulated = true;
|
|
204
|
+
while (this.stream.received()) await this.stream.receive();
|
|
205
|
+
}
|
|
206
|
+
return this.errAccumulated;
|
|
207
|
+
}
|
|
209
208
|
|
|
209
|
+
async write(channel: channel.KeyOrName, data: CrudeSeries): Promise<boolean>;
|
|
210
|
+
async write(channel: channel.KeysOrNames, data: CrudeSeries[]): Promise<boolean>;
|
|
211
|
+
async write(frame: Crude | Record<channel.KeyOrName, CrudeSeries>): Promise<boolean>;
|
|
210
212
|
async write(
|
|
211
|
-
channelsOrData: Params | Record<KeyOrName, CrudeSeries> |
|
|
213
|
+
channelsOrData: channel.Params | Record<channel.KeyOrName, CrudeSeries> | Crude,
|
|
212
214
|
series?: CrudeSeries | CrudeSeries[],
|
|
213
215
|
): Promise<boolean>;
|
|
214
216
|
|
|
@@ -227,9 +229,10 @@ export class Writer {
|
|
|
227
229
|
* should acknowledge the error by calling the error method or closing the writer.
|
|
228
230
|
*/
|
|
229
231
|
async write(
|
|
230
|
-
channelsOrData: Params | Record<KeyOrName, CrudeSeries> |
|
|
232
|
+
channelsOrData: channel.Params | Record<channel.KeyOrName, CrudeSeries> | Crude,
|
|
231
233
|
series?: CrudeSeries | CrudeSeries[],
|
|
232
234
|
): Promise<boolean> {
|
|
235
|
+
if (await this.checkForAccumulatedError()) return false;
|
|
233
236
|
const frame = await this.adapter.adapt(channelsOrData, series);
|
|
234
237
|
this.stream.send({ command: Command.Write, frame: frame.toPayload() });
|
|
235
238
|
return true;
|
|
@@ -237,21 +240,27 @@ export class Writer {
|
|
|
237
240
|
|
|
238
241
|
async setAuthority(value: number): Promise<boolean>;
|
|
239
242
|
|
|
240
|
-
async setAuthority(
|
|
243
|
+
async setAuthority(
|
|
244
|
+
key: channel.KeyOrName,
|
|
245
|
+
authority: control.Authority,
|
|
246
|
+
): Promise<boolean>;
|
|
241
247
|
|
|
242
|
-
async setAuthority(
|
|
248
|
+
async setAuthority(
|
|
249
|
+
value: Record<channel.KeyOrName, control.Authority>,
|
|
250
|
+
): Promise<boolean>;
|
|
243
251
|
|
|
244
252
|
async setAuthority(
|
|
245
|
-
value: Record<KeyOrName, control.Authority> | KeyOrName | number,
|
|
253
|
+
value: Record<channel.KeyOrName, control.Authority> | channel.KeyOrName | number,
|
|
246
254
|
authority?: control.Authority,
|
|
247
255
|
): Promise<boolean> {
|
|
256
|
+
if (await this.checkForAccumulatedError()) return false;
|
|
248
257
|
let config: Config;
|
|
249
258
|
if (typeof value === "number" && authority == null)
|
|
250
259
|
config = { keys: [], authorities: [value] };
|
|
251
260
|
else {
|
|
252
|
-
let oValue: Record<KeyOrName, control.Authority>;
|
|
261
|
+
let oValue: Record<channel.KeyOrName, control.Authority>;
|
|
253
262
|
if (typeof value === "string" || typeof value === "number")
|
|
254
|
-
oValue = { [value]: authority } as Record<KeyOrName, control.Authority>;
|
|
263
|
+
oValue = { [value]: authority } as Record<channel.KeyOrName, control.Authority>;
|
|
255
264
|
else oValue = value;
|
|
256
265
|
oValue = await this.adapter.adaptObjectKeys(oValue);
|
|
257
266
|
config = {
|
|
@@ -272,7 +281,7 @@ export class Writer {
|
|
|
272
281
|
* After the caller acknowledges the error, they can attempt to commit again.
|
|
273
282
|
*/
|
|
274
283
|
async commit(): Promise<boolean> {
|
|
275
|
-
if (this.
|
|
284
|
+
if (await this.checkForAccumulatedError()) return false;
|
|
276
285
|
const res = await this.execute({ command: Command.Commit });
|
|
277
286
|
return res.ack;
|
|
278
287
|
}
|
|
@@ -282,7 +291,6 @@ export class Writer {
|
|
|
282
291
|
* state, allowing the writer to be used again.
|
|
283
292
|
*/
|
|
284
293
|
async error(): Promise<Error | null> {
|
|
285
|
-
this.stream.send({ command: Command.Error });
|
|
286
294
|
const res = await this.execute({ command: Command.Error });
|
|
287
295
|
return res.error != null ? decodeError(res.error) : null;
|
|
288
296
|
}
|
package/src/hardware/client.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Use of this software is governed by the Business Source License included in the file
|
|
4
4
|
// licenses/BSL.txt.
|
|
@@ -15,28 +15,30 @@ import { z } from "zod";
|
|
|
15
15
|
import { type framer } from "@/framer";
|
|
16
16
|
import {
|
|
17
17
|
type Device,
|
|
18
|
-
type DeviceKey,
|
|
19
|
-
deviceKeyZ,
|
|
20
18
|
deviceZ,
|
|
21
|
-
type
|
|
22
|
-
|
|
19
|
+
type Key,
|
|
20
|
+
keyZ,
|
|
21
|
+
type New,
|
|
22
|
+
newZ,
|
|
23
|
+
ONTOLOGY_TYPE,
|
|
23
24
|
} from "@/hardware/device/payload";
|
|
25
|
+
import { ontology } from "@/ontology";
|
|
24
26
|
import { signals } from "@/signals";
|
|
25
27
|
import { checkForMultipleOrNoResults } from "@/util/retrieve";
|
|
26
28
|
import { nullableArrayZ } from "@/util/zod";
|
|
27
29
|
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
+
const SET_CHANNEL_NAME = "sy_device_set";
|
|
31
|
+
const DELETE_CHANNEL_NAME = "sy_device_delete";
|
|
30
32
|
|
|
31
33
|
const RETRIEVE_ENDPOINT = "/hardware/device/retrieve";
|
|
32
34
|
const CREATE_ENDPOINT = "/hardware/device/create";
|
|
33
35
|
const DELETE_ENDPOINT = "/hardware/device/delete";
|
|
34
36
|
|
|
35
|
-
const createReqZ = z.object({ devices:
|
|
37
|
+
const createReqZ = z.object({ devices: newZ.array() });
|
|
36
38
|
|
|
37
39
|
const createResZ = z.object({ devices: deviceZ.array() });
|
|
38
40
|
|
|
39
|
-
const deleteReqZ = z.object({ keys:
|
|
41
|
+
const deleteReqZ = z.object({ keys: keyZ.array() });
|
|
40
42
|
|
|
41
43
|
const deleteResZ = z.object({});
|
|
42
44
|
|
|
@@ -44,21 +46,22 @@ const retrieveReqZ = z.object({
|
|
|
44
46
|
search: z.string().optional(),
|
|
45
47
|
limit: z.number().optional(),
|
|
46
48
|
offset: z.number().optional(),
|
|
47
|
-
keys:
|
|
49
|
+
keys: keyZ.array().optional(),
|
|
48
50
|
names: z.string().array().optional(),
|
|
49
51
|
makes: z.string().array().optional(),
|
|
50
52
|
});
|
|
51
53
|
|
|
52
|
-
|
|
54
|
+
interface RetrieveRequest extends z.input<typeof retrieveReqZ> {}
|
|
53
55
|
|
|
54
|
-
export
|
|
56
|
+
export interface RetrieveOptions
|
|
57
|
+
extends Pick<RetrieveRequest, "limit" | "offset" | "makes"> {}
|
|
55
58
|
|
|
56
|
-
|
|
59
|
+
interface PageOptions extends Pick<RetrieveOptions, "makes"> {}
|
|
57
60
|
|
|
58
61
|
const retrieveResZ = z.object({ devices: nullableArrayZ(deviceZ) });
|
|
59
62
|
|
|
60
|
-
export class Client implements AsyncTermSearcher<string,
|
|
61
|
-
readonly type =
|
|
63
|
+
export class Client implements AsyncTermSearcher<string, Key, Device> {
|
|
64
|
+
readonly type = ONTOLOGY_TYPE;
|
|
62
65
|
private readonly client: UnaryClient;
|
|
63
66
|
private readonly frameClient: framer.Client;
|
|
64
67
|
|
|
@@ -67,20 +70,29 @@ export class Client implements AsyncTermSearcher<string, DeviceKey, Device> {
|
|
|
67
70
|
this.frameClient = frameClient;
|
|
68
71
|
}
|
|
69
72
|
|
|
70
|
-
async retrieve<
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
async retrieve<
|
|
74
|
+
Properties extends UnknownRecord = UnknownRecord,
|
|
75
|
+
Make extends string = string,
|
|
76
|
+
Model extends string = string,
|
|
77
|
+
>(key: string, options?: RetrieveOptions): Promise<Device<Properties, Make, Model>>;
|
|
78
|
+
|
|
79
|
+
async retrieve<
|
|
80
|
+
Properties extends UnknownRecord = UnknownRecord,
|
|
81
|
+
Make extends string = string,
|
|
82
|
+
Model extends string = string,
|
|
83
|
+
>(
|
|
76
84
|
keys: string[],
|
|
77
85
|
options?: RetrieveOptions,
|
|
78
|
-
): Promise<Array<Device<
|
|
86
|
+
): Promise<Array<Device<Properties, Make, Model>>>;
|
|
79
87
|
|
|
80
|
-
async retrieve<
|
|
88
|
+
async retrieve<
|
|
89
|
+
Properties extends UnknownRecord = UnknownRecord,
|
|
90
|
+
Make extends string = string,
|
|
91
|
+
Model extends string = string,
|
|
92
|
+
>(
|
|
81
93
|
keys: string | string[],
|
|
82
94
|
options?: RetrieveOptions,
|
|
83
|
-
): Promise<Device<
|
|
95
|
+
): Promise<Device<Properties, Make, Model> | Array<Device<Properties, Make, Model>>> {
|
|
84
96
|
const isSingle = !Array.isArray(keys);
|
|
85
97
|
const res = await sendRequired(
|
|
86
98
|
this.client,
|
|
@@ -90,7 +102,9 @@ export class Client implements AsyncTermSearcher<string, DeviceKey, Device> {
|
|
|
90
102
|
retrieveResZ,
|
|
91
103
|
);
|
|
92
104
|
checkForMultipleOrNoResults("Device", keys, res.devices, isSingle);
|
|
93
|
-
return
|
|
105
|
+
return isSingle
|
|
106
|
+
? (res.devices[0] as Device<Properties, Make, Model>)
|
|
107
|
+
: (res.devices as Array<Device<Properties, Make, Model>>);
|
|
94
108
|
}
|
|
95
109
|
|
|
96
110
|
async search(term: string, options?: RetrieveOptions): Promise<Device[]> {
|
|
@@ -117,17 +131,23 @@ export class Client implements AsyncTermSearcher<string, DeviceKey, Device> {
|
|
|
117
131
|
).devices;
|
|
118
132
|
}
|
|
119
133
|
|
|
120
|
-
async create<
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
134
|
+
async create<
|
|
135
|
+
Properties extends UnknownRecord = UnknownRecord,
|
|
136
|
+
Make extends string = string,
|
|
137
|
+
Model extends string = string,
|
|
138
|
+
>(device: New<Properties, Make>): Promise<Device<Properties, Make, Model>>;
|
|
139
|
+
async create<
|
|
140
|
+
Properties extends UnknownRecord = UnknownRecord,
|
|
141
|
+
Make extends string = string,
|
|
142
|
+
Model extends string = string,
|
|
143
|
+
>(devices: New<Properties, Make>[]): Promise<Device<Properties, Make, Model>[]>;
|
|
144
|
+
async create<
|
|
145
|
+
Properties extends UnknownRecord = UnknownRecord,
|
|
146
|
+
Make extends string = string,
|
|
147
|
+
Model extends string = string,
|
|
148
|
+
>(
|
|
149
|
+
devices: New<Properties, Make> | New<Properties, Make>[],
|
|
150
|
+
): Promise<Device<Properties, Make, Model> | Device<Properties, Make, Model>[]> {
|
|
131
151
|
const isSingle = !Array.isArray(devices);
|
|
132
152
|
const res = await sendRequired(
|
|
133
153
|
this.client,
|
|
@@ -136,7 +156,9 @@ export class Client implements AsyncTermSearcher<string, DeviceKey, Device> {
|
|
|
136
156
|
createReqZ,
|
|
137
157
|
createResZ,
|
|
138
158
|
);
|
|
139
|
-
return isSingle
|
|
159
|
+
return isSingle
|
|
160
|
+
? (res.devices[0] as Device<Properties, Make, Model>)
|
|
161
|
+
: (res.devices as Device<Properties, Make, Model>[]);
|
|
140
162
|
}
|
|
141
163
|
|
|
142
164
|
async delete(keys: string | string[]): Promise<void> {
|
|
@@ -152,15 +174,15 @@ export class Client implements AsyncTermSearcher<string, DeviceKey, Device> {
|
|
|
152
174
|
async openDeviceTracker(): Promise<signals.Observable<string, Device>> {
|
|
153
175
|
return await signals.openObservable<string, Device>(
|
|
154
176
|
this.frameClient,
|
|
155
|
-
|
|
156
|
-
|
|
177
|
+
SET_CHANNEL_NAME,
|
|
178
|
+
DELETE_CHANNEL_NAME,
|
|
157
179
|
decodeDeviceChanges,
|
|
158
180
|
);
|
|
159
181
|
}
|
|
160
182
|
|
|
161
183
|
newSearcherWithOptions(
|
|
162
184
|
options: RetrieveOptions,
|
|
163
|
-
): AsyncTermSearcher<string,
|
|
185
|
+
): AsyncTermSearcher<string, Key, Device> {
|
|
164
186
|
return {
|
|
165
187
|
type: this.type,
|
|
166
188
|
search: async (term: string) => await this.search(term, options),
|
|
@@ -176,3 +198,6 @@ const decodeDeviceChanges: signals.Decoder<string, Device> = (variant, data) =>
|
|
|
176
198
|
return data.toStrings().map((k) => ({ variant, key: k, value: undefined }));
|
|
177
199
|
return data.parseJSON(deviceZ).map((d) => ({ variant, key: d.key, value: d }));
|
|
178
200
|
};
|
|
201
|
+
|
|
202
|
+
export const ontologyID = (key: Key): ontology.ID =>
|
|
203
|
+
new ontology.ID({ type: ONTOLOGY_TYPE, key });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Use of this software is governed by the Business Source License included in the file
|
|
4
4
|
// licenses/BSL.txt.
|
|
@@ -13,42 +13,58 @@ import { newClient } from "@/setupspecs";
|
|
|
13
13
|
|
|
14
14
|
const client = newClient();
|
|
15
15
|
|
|
16
|
-
describe("Device", () => {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
properties: { cat: "dog" },
|
|
29
|
-
});
|
|
30
|
-
expect(d.key).toEqual("SN222");
|
|
31
|
-
expect(d.name).toBe("test");
|
|
32
|
-
expect(d.make).toBe("ni");
|
|
16
|
+
describe("Device", async () => {
|
|
17
|
+
const testRack = await client.hardware.racks.create({ name: "test" });
|
|
18
|
+
describe("create", () => {
|
|
19
|
+
it("should create a device on a rack", async () => {
|
|
20
|
+
const d = await client.hardware.devices.create({
|
|
21
|
+
rack: testRack.key,
|
|
22
|
+
location: "Dev1",
|
|
23
|
+
key: "SN222",
|
|
24
|
+
name: "test",
|
|
25
|
+
make: "ni",
|
|
26
|
+
model: "dog",
|
|
27
|
+
properties: { cat: "dog" },
|
|
33
28
|
});
|
|
29
|
+
expect(d.key).toEqual("SN222");
|
|
30
|
+
expect(d.name).toBe("test");
|
|
31
|
+
expect(d.make).toBe("ni");
|
|
34
32
|
});
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
33
|
+
});
|
|
34
|
+
it("should properly encode and decode properties", async () => {
|
|
35
|
+
const properties = {
|
|
36
|
+
rate: 10,
|
|
37
|
+
stateIndexChannel: 234,
|
|
38
|
+
inputChannels: { port1: 34214 },
|
|
39
|
+
outputChannels: [{ port2: 232 }],
|
|
40
|
+
};
|
|
41
|
+
const d = await client.hardware.devices.create({
|
|
42
|
+
key: "SN222",
|
|
43
|
+
rack: testRack.key,
|
|
44
|
+
location: "Dev1",
|
|
45
|
+
name: "test",
|
|
46
|
+
make: "ni",
|
|
47
|
+
model: "dog",
|
|
48
|
+
properties,
|
|
49
|
+
});
|
|
50
|
+
const retrieved = await client.hardware.devices.retrieve(d.key);
|
|
51
|
+
expect(retrieved.properties).toEqual(properties);
|
|
52
|
+
});
|
|
53
|
+
describe("retrieve", () => {
|
|
54
|
+
it("should retrieve a device by its key", async () => {
|
|
55
|
+
const d = await client.hardware.devices.create({
|
|
56
|
+
key: "SN222",
|
|
57
|
+
rack: testRack.key,
|
|
58
|
+
location: "Dev1",
|
|
59
|
+
name: "test",
|
|
60
|
+
make: "ni",
|
|
61
|
+
model: "dog",
|
|
62
|
+
properties: { cat: "dog" },
|
|
51
63
|
});
|
|
64
|
+
const retrieved = await client.hardware.devices.retrieve(d.key);
|
|
65
|
+
expect(retrieved.key).toBe(d.key);
|
|
66
|
+
expect(retrieved.name).toBe("test");
|
|
67
|
+
expect(retrieved.make).toBe("ni");
|
|
52
68
|
});
|
|
53
69
|
});
|
|
54
70
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Use of this software is governed by the Business Source License included in the file
|
|
4
4
|
// licenses/BSL.txt.
|
|
@@ -10,44 +10,44 @@
|
|
|
10
10
|
import { binary, type UnknownRecord } from "@synnaxlabs/x";
|
|
11
11
|
import { z } from "zod";
|
|
12
12
|
|
|
13
|
-
import { rackKeyZ } from "@/hardware/rack/payload";
|
|
14
|
-
import {
|
|
13
|
+
import { keyZ as rackKeyZ } from "@/hardware/rack/payload";
|
|
14
|
+
import { decodeJSONString } from "@/util/decodeJSONString";
|
|
15
15
|
|
|
16
|
-
export const
|
|
16
|
+
export const keyZ = z.string();
|
|
17
|
+
export type Key = z.infer<typeof keyZ>;
|
|
17
18
|
|
|
18
19
|
export const deviceZ = z.object({
|
|
19
|
-
key:
|
|
20
|
+
key: keyZ,
|
|
20
21
|
rack: rackKeyZ,
|
|
21
22
|
name: z.string(),
|
|
22
23
|
make: z.string(),
|
|
23
24
|
model: z.string(),
|
|
24
25
|
location: z.string(),
|
|
25
26
|
configured: z.boolean().optional(),
|
|
26
|
-
properties: z.record(z.unknown()).or(
|
|
27
|
-
z.string().transform((c) => {
|
|
28
|
-
if (c === "") return {};
|
|
29
|
-
return binary.JSON_CODEC.decodeString(c);
|
|
30
|
-
}),
|
|
31
|
-
) as z.ZodType<UnknownRecord>,
|
|
27
|
+
properties: z.record(z.unknown()).or(z.string().transform(decodeJSONString)),
|
|
32
28
|
});
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
>
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
29
|
+
export interface Device<
|
|
30
|
+
Properties extends UnknownRecord = UnknownRecord,
|
|
31
|
+
Make extends string = string,
|
|
32
|
+
Model extends string = string,
|
|
33
|
+
> extends Omit<z.output<typeof deviceZ>, "properties"> {
|
|
34
|
+
properties: Properties;
|
|
35
|
+
make: Make;
|
|
36
|
+
model: Model;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const newZ = deviceZ.extend({
|
|
42
40
|
properties: z.unknown().transform((c) => binary.JSON_CODEC.encodeString(c)),
|
|
43
41
|
});
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
>
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
42
|
+
export interface New<
|
|
43
|
+
Properties extends UnknownRecord = UnknownRecord,
|
|
44
|
+
Make extends string = string,
|
|
45
|
+
Model extends string = string,
|
|
46
|
+
> extends Omit<z.input<typeof newZ>, "properties"> {
|
|
47
|
+
properties: Properties;
|
|
48
|
+
make: Make;
|
|
49
|
+
model: Model;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const ONTOLOGY_TYPE = "device";
|
|
53
|
+
export type OntologyType = typeof ONTOLOGY_TYPE;
|
package/src/hardware/external.ts
CHANGED
package/src/hardware/index.ts
CHANGED