@synnaxlabs/client 0.43.0 → 0.44.1
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 +1 -1
- package/dist/access/payload.d.ts.map +1 -1
- package/dist/access/policy/client.d.ts +263 -6
- package/dist/access/policy/client.d.ts.map +1 -1
- package/dist/access/policy/external.d.ts +0 -1
- package/dist/access/policy/external.d.ts.map +1 -1
- package/dist/access/policy/payload.d.ts +105 -93
- package/dist/access/policy/payload.d.ts.map +1 -1
- package/dist/auth/auth.d.ts +1 -1
- package/dist/auth/auth.d.ts.map +1 -1
- package/dist/channel/client.d.ts +12 -13
- package/dist/channel/client.d.ts.map +1 -1
- package/dist/channel/payload.d.ts +77 -19
- package/dist/channel/payload.d.ts.map +1 -1
- package/dist/channel/retriever.d.ts +9 -16
- package/dist/channel/retriever.d.ts.map +1 -1
- package/dist/channel/writer.d.ts +1 -1
- package/dist/channel/writer.d.ts.map +1 -1
- package/dist/client.cjs +27 -135
- package/dist/client.d.ts +3 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +8619 -28938
- package/dist/connection/checker.d.ts +1 -1
- package/dist/connection/checker.d.ts.map +1 -1
- package/dist/control/client.d.ts +1 -0
- package/dist/control/client.d.ts.map +1 -1
- package/dist/control/state.d.ts +6 -6
- package/dist/control/state.d.ts.map +1 -1
- package/dist/errors.d.ts +18 -5
- package/dist/errors.d.ts.map +1 -1
- package/dist/framer/adapter.d.ts +3 -3
- package/dist/framer/adapter.d.ts.map +1 -1
- package/dist/framer/client.d.ts +4 -13
- package/dist/framer/client.d.ts.map +1 -1
- package/dist/framer/codec.d.ts +1 -1
- package/dist/framer/codec.d.ts.map +1 -1
- package/dist/framer/deleter.d.ts +5 -5
- package/dist/framer/deleter.d.ts.map +1 -1
- package/dist/framer/frame.d.ts +5 -7
- package/dist/framer/frame.d.ts.map +1 -1
- package/dist/framer/streamProxy.d.ts +1 -1
- package/dist/framer/streamProxy.d.ts.map +1 -1
- package/dist/framer/streamer.d.ts +139 -20
- package/dist/framer/streamer.d.ts.map +1 -1
- package/dist/framer/writer.d.ts +222 -33
- package/dist/framer/writer.d.ts.map +1 -1
- package/dist/hardware/device/client.d.ts +49 -28
- package/dist/hardware/device/client.d.ts.map +1 -1
- package/dist/hardware/device/payload.d.ts +126 -46
- package/dist/hardware/device/payload.d.ts.map +1 -1
- package/dist/hardware/rack/client.d.ts +78 -22
- package/dist/hardware/rack/client.d.ts.map +1 -1
- package/dist/hardware/rack/payload.d.ts +99 -56
- package/dist/hardware/rack/payload.d.ts.map +1 -1
- package/dist/hardware/task/client.d.ts +100 -41
- package/dist/hardware/task/client.d.ts.map +1 -1
- package/dist/hardware/task/payload.d.ts +83 -61
- package/dist/hardware/task/payload.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/label/client.d.ts +138 -20
- package/dist/label/client.d.ts.map +1 -1
- package/dist/label/external.d.ts +0 -2
- package/dist/label/external.d.ts.map +1 -1
- package/dist/label/payload.d.ts +4 -5
- package/dist/label/payload.d.ts.map +1 -1
- package/dist/ontology/client.d.ts +45 -135
- package/dist/ontology/client.d.ts.map +1 -1
- package/dist/ontology/group/group.d.ts +3 -3
- package/dist/ontology/group/group.d.ts.map +1 -1
- package/dist/ontology/group/payload.d.ts +3 -27
- package/dist/ontology/group/payload.d.ts.map +1 -1
- package/dist/ontology/payload.d.ts +113 -243
- package/dist/ontology/payload.d.ts.map +1 -1
- package/dist/ontology/writer.d.ts +4 -4
- package/dist/ontology/writer.d.ts.map +1 -1
- package/dist/ranger/alias.d.ts +11 -5
- package/dist/ranger/alias.d.ts.map +1 -1
- package/dist/ranger/client.d.ts +87 -30
- 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 +10 -12
- package/dist/ranger/kv.d.ts.map +1 -1
- package/dist/ranger/payload.d.ts +23 -44
- package/dist/ranger/payload.d.ts.map +1 -1
- package/dist/ranger/writer.d.ts +22 -19
- package/dist/ranger/writer.d.ts.map +1 -1
- package/dist/testutil/client.d.ts +4 -0
- package/dist/testutil/client.d.ts.map +1 -0
- package/dist/user/client.d.ts +59 -6
- package/dist/user/client.d.ts.map +1 -1
- package/dist/user/payload.d.ts +4 -6
- package/dist/user/payload.d.ts.map +1 -1
- package/dist/user/retriever.d.ts +2 -2
- package/dist/user/retriever.d.ts.map +1 -1
- package/dist/util/decodeJSONString.d.ts +2 -2
- package/dist/util/decodeJSONString.d.ts.map +1 -1
- package/dist/util/parseWithoutKeyConversion.d.ts +2 -2
- package/dist/util/parseWithoutKeyConversion.d.ts.map +1 -1
- package/dist/util/retrieve.d.ts +1 -1
- package/dist/util/retrieve.d.ts.map +1 -1
- package/dist/util/zod.d.ts +1 -1
- package/dist/util/zod.d.ts.map +1 -1
- package/dist/workspace/client.d.ts +17 -6
- package/dist/workspace/client.d.ts.map +1 -1
- package/dist/workspace/lineplot/client.d.ts +2 -2
- package/dist/workspace/lineplot/client.d.ts.map +1 -1
- package/dist/workspace/lineplot/payload.d.ts +8 -9
- package/dist/workspace/lineplot/payload.d.ts.map +1 -1
- package/dist/workspace/log/client.d.ts +2 -2
- package/dist/workspace/log/client.d.ts.map +1 -1
- package/dist/workspace/log/payload.d.ts +8 -9
- package/dist/workspace/log/payload.d.ts.map +1 -1
- package/dist/workspace/payload.d.ts +10 -11
- package/dist/workspace/payload.d.ts.map +1 -1
- package/dist/workspace/schematic/client.d.ts +2 -2
- package/dist/workspace/schematic/client.d.ts.map +1 -1
- package/dist/workspace/schematic/payload.d.ts +10 -11
- package/dist/workspace/schematic/payload.d.ts.map +1 -1
- package/dist/workspace/table/client.d.ts +2 -2
- package/dist/workspace/table/client.d.ts.map +1 -1
- package/dist/workspace/table/payload.d.ts +10 -11
- package/dist/workspace/table/payload.d.ts.map +1 -1
- package/examples/node/package-lock.json +47 -39
- package/examples/node/package.json +2 -1
- package/examples/node/streamWrite.js +5 -11
- package/package.json +14 -13
- package/src/access/payload.ts +1 -1
- package/src/access/policy/client.ts +87 -32
- package/src/access/policy/external.ts +0 -1
- package/src/access/policy/payload.ts +4 -4
- package/src/access/policy/policy.spec.ts +86 -83
- package/src/auth/auth.spec.ts +29 -18
- package/src/auth/auth.ts +1 -1
- package/src/channel/batchRetriever.spec.ts +4 -9
- package/src/channel/channel.spec.ts +24 -6
- package/src/channel/client.ts +31 -46
- package/src/channel/payload.ts +13 -14
- package/src/channel/retriever.ts +26 -41
- package/src/channel/writer.ts +3 -3
- package/src/client.ts +4 -4
- package/src/connection/checker.ts +1 -1
- package/src/connection/connection.spec.ts +31 -23
- package/src/control/client.ts +2 -2
- package/src/control/state.spec.ts +3 -3
- package/src/control/state.ts +1 -1
- package/src/errors.spec.ts +9 -5
- package/src/errors.ts +28 -15
- package/src/framer/adapter.spec.ts +118 -9
- package/src/framer/adapter.ts +24 -11
- package/src/framer/client.spec.ts +125 -2
- package/src/framer/client.ts +41 -47
- package/src/framer/codec.ts +1 -1
- package/src/framer/deleter.spec.ts +2 -2
- package/src/framer/deleter.ts +1 -1
- package/src/framer/frame.ts +1 -4
- package/src/framer/iterator.spec.ts +8 -8
- package/src/framer/iterator.ts +1 -1
- package/src/framer/streamProxy.ts +1 -1
- package/src/framer/streamer.spec.ts +185 -36
- package/src/framer/streamer.ts +28 -36
- package/src/framer/writer.spec.ts +6 -6
- package/src/framer/writer.ts +97 -111
- package/src/hardware/device/client.ts +45 -131
- package/src/hardware/device/device.spec.ts +163 -52
- package/src/hardware/device/payload.ts +10 -21
- package/src/hardware/rack/client.ts +87 -105
- package/src/hardware/rack/payload.ts +4 -13
- package/src/hardware/rack/rack.spec.ts +28 -35
- package/src/hardware/task/client.ts +335 -291
- package/src/hardware/task/payload.ts +86 -62
- package/src/hardware/task/task.spec.ts +208 -32
- package/src/index.ts +2 -1
- package/src/label/client.ts +100 -95
- package/src/label/external.ts +0 -2
- package/src/label/label.spec.ts +8 -6
- package/src/label/payload.ts +3 -4
- package/src/ontology/client.ts +41 -324
- package/src/ontology/group/group.spec.ts +2 -2
- package/src/ontology/group/group.ts +4 -5
- package/src/ontology/group/payload.ts +2 -25
- package/src/ontology/group/writer.ts +1 -1
- package/src/ontology/ontology.spec.ts +355 -41
- package/src/ontology/payload.ts +74 -112
- package/src/ontology/writer.ts +8 -17
- package/src/ranger/alias.ts +19 -37
- package/src/ranger/client.ts +118 -150
- package/src/ranger/external.ts +9 -1
- package/src/ranger/kv.ts +6 -27
- package/src/ranger/payload.ts +21 -37
- package/src/ranger/ranger.spec.ts +37 -56
- package/src/ranger/writer.ts +1 -1
- package/src/{signals/index.ts → testutil/client.ts} +11 -1
- package/src/user/client.ts +122 -47
- package/src/user/payload.ts +2 -5
- package/src/user/retriever.ts +1 -1
- package/src/user/user.spec.ts +31 -31
- package/src/user/writer.ts +1 -1
- package/src/util/decodeJSONString.ts +3 -3
- package/src/util/parseWithoutKeyConversion.ts +2 -2
- package/src/util/retrieve.ts +1 -1
- package/src/util/zod.ts +1 -1
- package/src/workspace/client.ts +20 -36
- package/src/workspace/lineplot/client.ts +5 -7
- package/src/workspace/lineplot/lineplot.spec.ts +2 -2
- package/src/workspace/lineplot/payload.ts +4 -7
- package/src/workspace/log/client.ts +5 -7
- package/src/workspace/log/log.spec.ts +2 -2
- package/src/workspace/log/payload.ts +4 -7
- package/src/workspace/payload.ts +4 -7
- package/src/workspace/schematic/client.ts +5 -7
- package/src/workspace/schematic/payload.ts +4 -7
- package/src/workspace/schematic/schematic.spec.ts +2 -2
- package/src/workspace/table/client.ts +5 -7
- package/src/workspace/table/payload.ts +4 -7
- package/src/workspace/table/table.spec.ts +2 -2
- package/src/workspace/workspace.spec.ts +2 -2
- package/dist/access/policy/ontology.d.ts +0 -5
- package/dist/access/policy/ontology.d.ts.map +0 -1
- package/dist/access/policy/retriever.d.ts +0 -40
- package/dist/access/policy/retriever.d.ts.map +0 -1
- package/dist/access/policy/writer.d.ts +0 -9
- package/dist/access/policy/writer.d.ts.map +0 -1
- package/dist/label/retriever.d.ts +0 -14
- package/dist/label/retriever.d.ts.map +0 -1
- package/dist/label/writer.d.ts +0 -54
- package/dist/label/writer.d.ts.map +0 -1
- package/dist/setupspecs.d.ts +0 -5
- package/dist/setupspecs.d.ts.map +0 -1
- package/dist/signals/external.d.ts +0 -2
- package/dist/signals/external.d.ts.map +0 -1
- package/dist/signals/index.d.ts +0 -2
- package/dist/signals/index.d.ts.map +0 -1
- package/dist/signals/observable.d.ts +0 -12
- package/dist/signals/observable.d.ts.map +0 -1
- package/src/access/policy/ontology.ts +0 -17
- package/src/access/policy/retriever.ts +0 -44
- package/src/access/policy/writer.ts +0 -65
- package/src/label/retriever.ts +0 -63
- package/src/label/writer.ts +0 -95
- package/src/setupspecs.ts +0 -27
- package/src/signals/external.ts +0 -10
- package/src/signals/observable.ts +0 -42
package/src/framer/writer.ts
CHANGED
|
@@ -8,14 +8,9 @@
|
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
10
|
import { EOF, type Stream, type WebSocketClient } from "@synnaxlabs/freighter";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
type CrudeTimeStamp,
|
|
15
|
-
TimeSpan,
|
|
16
|
-
TimeStamp,
|
|
17
|
-
} from "@synnaxlabs/x/telem";
|
|
18
|
-
import { z } from "zod/v4";
|
|
11
|
+
import { control, errors } from "@synnaxlabs/x";
|
|
12
|
+
import { type CrudeSeries, TimeSpan, TimeStamp } from "@synnaxlabs/x/telem";
|
|
13
|
+
import { z } from "zod";
|
|
19
14
|
|
|
20
15
|
import { channel } from "@/channel";
|
|
21
16
|
import { SynnaxError } from "@/errors";
|
|
@@ -36,22 +31,6 @@ export enum WriterMode {
|
|
|
36
31
|
Stream = 3,
|
|
37
32
|
}
|
|
38
33
|
|
|
39
|
-
export type CrudeWriterMode = "persist" | "stream" | "persistStream" | WriterMode;
|
|
40
|
-
|
|
41
|
-
const constructWriterMode = (mode: CrudeWriterMode): WriterMode => {
|
|
42
|
-
switch (mode) {
|
|
43
|
-
case "persist":
|
|
44
|
-
return WriterMode.Persist;
|
|
45
|
-
case "stream":
|
|
46
|
-
return WriterMode.Stream;
|
|
47
|
-
case "persistStream":
|
|
48
|
-
return WriterMode.PersistStream;
|
|
49
|
-
default:
|
|
50
|
-
if (typeof mode === "number" && mode in WriterMode) return mode;
|
|
51
|
-
throw new Error(`invalid writer mode: ${mode}`);
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
|
|
55
34
|
export const ALWAYS_INDEX_PERSIST_ON_AUTO_COMMIT: TimeSpan = new TimeSpan(-1);
|
|
56
35
|
|
|
57
36
|
export class WriterClosedError extends SynnaxError.sub("writer_closed") {
|
|
@@ -60,27 +39,75 @@ export class WriterClosedError extends SynnaxError.sub("writer_closed") {
|
|
|
60
39
|
}
|
|
61
40
|
}
|
|
62
41
|
|
|
63
|
-
const
|
|
42
|
+
const writerModeZ = z.enum(WriterMode).or(
|
|
43
|
+
z.enum(["persist", "stream", "persistStream"]).transform((mode) => {
|
|
44
|
+
switch (mode) {
|
|
45
|
+
case "persist":
|
|
46
|
+
return WriterMode.Persist;
|
|
47
|
+
case "stream":
|
|
48
|
+
return WriterMode.Stream;
|
|
49
|
+
case "persistStream":
|
|
50
|
+
return WriterMode.PersistStream;
|
|
51
|
+
}
|
|
52
|
+
}),
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
export type CrudeWriterMode = z.input<typeof writerModeZ>;
|
|
56
|
+
|
|
57
|
+
const baseWriterConfigZ = z.object({
|
|
58
|
+
// start sets the starting timestamp for the first sample in the writer.
|
|
64
59
|
start: TimeStamp.z.optional(),
|
|
60
|
+
// controlSubject sets the control subject of the writer.
|
|
65
61
|
controlSubject: control.subjectZ.optional(),
|
|
62
|
+
// authorities set the control authority to set for each channel on the writer.
|
|
63
|
+
// Defaults to absolute authority. If not working with concurrent control,
|
|
64
|
+
// it's best to leave this as the default.
|
|
65
|
+
authorities: z
|
|
66
|
+
.union([control.authorityZ.transform((a) => [a]), control.authorityZ.array()])
|
|
67
|
+
.default([control.ABSOLUTE_AUTHORITY]),
|
|
68
|
+
// mode sets the persistence and streaming mode of the writer. The default
|
|
69
|
+
// mode is WriterModePersistStream.
|
|
70
|
+
mode: writerModeZ.default(WriterMode.PersistStream),
|
|
71
|
+
// errOnUnauthorized sets whether the writer raises an error when it attempts to write
|
|
72
|
+
// to a channel without permission.
|
|
73
|
+
errOnUnauthorized: z.boolean().default(false),
|
|
74
|
+
// enableAutoCommit determines whether the writer will automatically commit.
|
|
75
|
+
// If enableAutoCommit is true, then the writer will commit after each write, and
|
|
76
|
+
// will flush that commit to index after the specified autoIndexPersistInterval.
|
|
77
|
+
enableAutoCommit: z.boolean().default(false),
|
|
78
|
+
// autoIndexPersistInterval sets the interval at which commits to the index will be
|
|
79
|
+
autoIndexPersistInterval: TimeSpan.z.default(TimeSpan.SECOND),
|
|
80
|
+
// useExperimentalCodec sets whether the writer will use the experimental codec.
|
|
81
|
+
useExperimentalCodec: z.boolean().default(false),
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const netWriterConfigZ = baseWriterConfigZ.extend({
|
|
66
85
|
keys: channel.keyZ.array().optional(),
|
|
67
|
-
authorities: control.authorityZ.array().optional(),
|
|
68
|
-
mode: z.enum(WriterMode).optional(),
|
|
69
|
-
errOnUnauthorized: z.boolean().optional(),
|
|
70
|
-
enableAutoCommit: z.boolean().optional(),
|
|
71
|
-
autoIndexPersistInterval: TimeSpan.z.optional(),
|
|
72
86
|
});
|
|
73
87
|
|
|
74
|
-
|
|
88
|
+
export type NetWriterConfig = z.input<typeof netWriterConfigZ>;
|
|
89
|
+
|
|
90
|
+
// Intermediate utility type to allow for the use of paramsZ in the writer config.
|
|
91
|
+
const intermediateWriterConfigZ = baseWriterConfigZ.extend({
|
|
92
|
+
channels: channel.paramsZ,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
export const writerConfigZ = intermediateWriterConfigZ.or(
|
|
96
|
+
channel.paramsZ.transform((channels) =>
|
|
97
|
+
intermediateWriterConfigZ.parse({ channels, start: TimeStamp.now() }),
|
|
98
|
+
),
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
export type WriterConfig = z.input<typeof writerConfigZ>;
|
|
75
102
|
|
|
76
103
|
const reqZ = z.object({
|
|
77
104
|
command: z.enum(WriterCommand),
|
|
78
|
-
config:
|
|
105
|
+
config: netWriterConfigZ.optional(),
|
|
79
106
|
frame: frameZ.optional(),
|
|
80
107
|
buffer: z.instanceof(Uint8Array).optional(),
|
|
81
108
|
});
|
|
82
109
|
|
|
83
|
-
export interface WriteRequest extends z.
|
|
110
|
+
export interface WriteRequest extends z.input<typeof reqZ> {}
|
|
84
111
|
|
|
85
112
|
const resZ = z.object({
|
|
86
113
|
command: z.enum(WriterCommand),
|
|
@@ -88,35 +115,32 @@ const resZ = z.object({
|
|
|
88
115
|
err: errors.payloadZ.optional(),
|
|
89
116
|
});
|
|
90
117
|
|
|
91
|
-
|
|
118
|
+
const authorityArgsZ = z
|
|
119
|
+
.tuple([
|
|
120
|
+
z.union([
|
|
121
|
+
z.record(channel.keyZ.or(channel.nameZ), control.authorityZ),
|
|
122
|
+
channel.keyZ.or(channel.nameZ),
|
|
123
|
+
control.authorityZ,
|
|
124
|
+
]),
|
|
125
|
+
control.authorityZ.optional(),
|
|
126
|
+
])
|
|
127
|
+
.transform(([value, authority]) => {
|
|
128
|
+
if (control.authorityZ.safeParse(value).success)
|
|
129
|
+
return { keys: [], authorities: [value as control.Authority] };
|
|
130
|
+
if (channel.keyZ.or(channel.nameZ).safeParse(value).success) {
|
|
131
|
+
if (authority == null)
|
|
132
|
+
throw new Error(
|
|
133
|
+
"authority is required when setting authority for a single channel",
|
|
134
|
+
);
|
|
135
|
+
return { keys: [value] as channel.KeysOrNames, authorities: [authority] };
|
|
136
|
+
}
|
|
137
|
+
const oValue = value as Record<channel.KeyOrName, control.Authority>;
|
|
138
|
+
return { keys: Object.keys(oValue), authorities: Object.values(oValue) };
|
|
139
|
+
});
|
|
92
140
|
|
|
93
|
-
export
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
// start sets the starting timestamp for the first sample in the writer.
|
|
97
|
-
start?: CrudeTimeStamp;
|
|
98
|
-
// controlSubject sets the control subject of the writer.
|
|
99
|
-
controlSubject?: control.Subject;
|
|
100
|
-
// authorities set the control authority to set for each channel on the writer.
|
|
101
|
-
// Defaults to absolute authority. If not working with concurrent control,
|
|
102
|
-
// it's best to leave this as the default.
|
|
103
|
-
authorities?: control.Authority | control.Authority[];
|
|
104
|
-
// mode sets the persistence and streaming mode of the writer. The default
|
|
105
|
-
// mode is WriterModePersistStream.
|
|
106
|
-
mode?: CrudeWriterMode;
|
|
107
|
-
// errOnUnauthorized sets whether the writer raises an error when it attempts to write
|
|
108
|
-
// to a channel without permission.
|
|
109
|
-
errOnUnauthorized?: boolean;
|
|
110
|
-
// enableAutoCommit determines whether the writer will automatically commit.
|
|
111
|
-
// If enableAutoCommit is true, then the writer will commit after each write, and
|
|
112
|
-
// will flush that commit to index after the specified autoIndexPersistInterval.
|
|
113
|
-
enableAutoCommit?: boolean;
|
|
114
|
-
// autoIndexPersistInterval sets the interval at which commits to the index will be
|
|
115
|
-
// persisted. To persist every commit to guarantee minimal loss of data, set
|
|
116
|
-
// auto_index_persist_interval to AlwaysAutoIndexPersist.
|
|
117
|
-
autoIndexPersistInterval?: TimeSpan;
|
|
118
|
-
useExperimentalCodec?: boolean;
|
|
119
|
-
}
|
|
141
|
+
export type AuthorityArgs = z.input<typeof authorityArgsZ>;
|
|
142
|
+
|
|
143
|
+
interface Response extends z.infer<typeof resZ> {}
|
|
120
144
|
|
|
121
145
|
/**
|
|
122
146
|
* Writer is used to write telemetry to a set of channels in time order.
|
|
@@ -170,35 +194,17 @@ export class Writer {
|
|
|
170
194
|
static async _open(
|
|
171
195
|
retriever: channel.Retriever,
|
|
172
196
|
client: WebSocketClient,
|
|
173
|
-
|
|
174
|
-
channels,
|
|
175
|
-
start = TimeStamp.now(),
|
|
176
|
-
authorities = control.ABSOLUTE_AUTHORITY,
|
|
177
|
-
controlSubject: subject,
|
|
178
|
-
mode = WriterMode.PersistStream,
|
|
179
|
-
errOnUnauthorized = false,
|
|
180
|
-
enableAutoCommit = false,
|
|
181
|
-
autoIndexPersistInterval = TimeSpan.SECOND,
|
|
182
|
-
useExperimentalCodec = true,
|
|
183
|
-
}: WriterConfig,
|
|
197
|
+
config: WriterConfig,
|
|
184
198
|
): Promise<Writer> {
|
|
185
|
-
const
|
|
186
|
-
|
|
199
|
+
const cfg = writerConfigZ.parse(config);
|
|
200
|
+
const adapter = await WriteAdapter.open(retriever, cfg.channels);
|
|
201
|
+
if (cfg.useExperimentalCodec)
|
|
187
202
|
client = client.withCodec(new WSWriterCodec(adapter.codec));
|
|
188
203
|
const stream = await client.stream(Writer.ENDPOINT, reqZ, resZ);
|
|
189
204
|
const writer = new Writer(stream, adapter);
|
|
190
205
|
await writer.execute({
|
|
191
206
|
command: WriterCommand.Open,
|
|
192
|
-
config: {
|
|
193
|
-
start: new TimeStamp(start),
|
|
194
|
-
keys: adapter.keys,
|
|
195
|
-
controlSubject: subject,
|
|
196
|
-
authorities: array.toArray(authorities),
|
|
197
|
-
mode: constructWriterMode(mode),
|
|
198
|
-
errOnUnauthorized,
|
|
199
|
-
enableAutoCommit,
|
|
200
|
-
autoIndexPersistInterval,
|
|
201
|
-
},
|
|
207
|
+
config: { ...cfg, keys: adapter.keys },
|
|
202
208
|
});
|
|
203
209
|
return writer;
|
|
204
210
|
}
|
|
@@ -243,36 +249,16 @@ export class Writer {
|
|
|
243
249
|
this.stream.send({ command: WriterCommand.Write, frame: frame.toPayload() });
|
|
244
250
|
}
|
|
245
251
|
|
|
246
|
-
async setAuthority(value: number): Promise<void>;
|
|
247
|
-
|
|
248
252
|
async setAuthority(
|
|
249
|
-
|
|
250
|
-
authority
|
|
251
|
-
): Promise<void>;
|
|
252
|
-
|
|
253
|
-
async setAuthority(
|
|
254
|
-
value: Record<channel.KeyOrName, control.Authority>,
|
|
255
|
-
): Promise<void>;
|
|
256
|
-
|
|
257
|
-
async setAuthority(
|
|
258
|
-
value: Record<channel.KeyOrName, control.Authority> | channel.KeyOrName | number,
|
|
259
|
-
authority?: control.Authority,
|
|
253
|
+
value: AuthorityArgs[0],
|
|
254
|
+
authority?: AuthorityArgs[1],
|
|
260
255
|
): Promise<void> {
|
|
261
256
|
if (this.closeErr != null) throw this.closeErr;
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
if (typeof value === "string" || typeof value === "number")
|
|
268
|
-
oValue = { [value]: authority } as Record<channel.KeyOrName, control.Authority>;
|
|
269
|
-
else oValue = value;
|
|
270
|
-
oValue = await this.adapter.adaptObjectKeys(oValue);
|
|
271
|
-
config = {
|
|
272
|
-
keys: Object.keys(oValue).map((k) => Number(k)),
|
|
273
|
-
authorities: Object.values(oValue),
|
|
274
|
-
};
|
|
275
|
-
}
|
|
257
|
+
const parsed = authorityArgsZ.parse([value, authority]);
|
|
258
|
+
const config = {
|
|
259
|
+
keys: await this.adapter.adaptParams(parsed.keys),
|
|
260
|
+
authorities: parsed.authorities,
|
|
261
|
+
};
|
|
276
262
|
await this.execute({ command: WriterCommand.SetAuthority, config });
|
|
277
263
|
}
|
|
278
264
|
|
|
@@ -8,11 +8,9 @@
|
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
10
|
import { sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
|
|
11
|
-
import { array, type
|
|
12
|
-
import {
|
|
13
|
-
import { z } from "zod/v4";
|
|
11
|
+
import { array, type record } from "@synnaxlabs/x";
|
|
12
|
+
import { z } from "zod";
|
|
14
13
|
|
|
15
|
-
import { framer } from "@/framer";
|
|
16
14
|
import {
|
|
17
15
|
type Device,
|
|
18
16
|
deviceZ,
|
|
@@ -20,150 +18,109 @@ import {
|
|
|
20
18
|
keyZ,
|
|
21
19
|
type New,
|
|
22
20
|
newZ,
|
|
23
|
-
ONTOLOGY_TYPE,
|
|
24
|
-
type State,
|
|
25
|
-
stateZ,
|
|
26
21
|
} from "@/hardware/device/payload";
|
|
27
22
|
import { keyZ as rackKeyZ } from "@/hardware/rack/payload";
|
|
28
|
-
import { ontology } from "@/ontology";
|
|
29
|
-
import { signals } from "@/signals";
|
|
23
|
+
import { type ontology } from "@/ontology";
|
|
30
24
|
import { checkForMultipleOrNoResults } from "@/util/retrieve";
|
|
31
25
|
import { nullableArrayZ } from "@/util/zod";
|
|
32
26
|
|
|
33
|
-
const SET_CHANNEL_NAME = "sy_device_set";
|
|
34
|
-
const DELETE_CHANNEL_NAME = "sy_device_delete";
|
|
35
|
-
const
|
|
27
|
+
export const SET_CHANNEL_NAME = "sy_device_set";
|
|
28
|
+
export const DELETE_CHANNEL_NAME = "sy_device_delete";
|
|
29
|
+
export const STATUS_CHANNEL_NAME = "sy_device_status";
|
|
36
30
|
|
|
37
31
|
const RETRIEVE_ENDPOINT = "/hardware/device/retrieve";
|
|
38
32
|
const CREATE_ENDPOINT = "/hardware/device/create";
|
|
39
33
|
const DELETE_ENDPOINT = "/hardware/device/delete";
|
|
40
34
|
|
|
41
35
|
const createReqZ = z.object({ devices: newZ.array() });
|
|
42
|
-
|
|
43
36
|
const createResZ = z.object({ devices: deviceZ.array() });
|
|
44
37
|
|
|
45
38
|
const deleteReqZ = z.object({ keys: keyZ.array() });
|
|
46
|
-
|
|
47
39
|
const deleteResZ = z.object({});
|
|
48
40
|
|
|
49
|
-
const
|
|
41
|
+
const retrieveRequestZ = z.object({
|
|
50
42
|
keys: keyZ.array().optional(),
|
|
51
43
|
names: z.string().array().optional(),
|
|
52
44
|
makes: z.string().array().optional(),
|
|
53
45
|
models: z.string().array().optional(),
|
|
54
46
|
locations: z.string().array().optional(),
|
|
55
47
|
racks: rackKeyZ.array().optional(),
|
|
56
|
-
|
|
48
|
+
searchTerm: z.string().optional(),
|
|
57
49
|
limit: z.number().optional(),
|
|
58
50
|
offset: z.number().optional(),
|
|
59
|
-
|
|
60
|
-
includeState: z.boolean().optional(),
|
|
51
|
+
includeStatus: z.boolean().optional(),
|
|
61
52
|
});
|
|
53
|
+
const retrieveResZ = z.object({ devices: nullableArrayZ(deviceZ) });
|
|
62
54
|
|
|
63
|
-
|
|
55
|
+
const singleRetrieveArgsZ = z
|
|
56
|
+
.object({
|
|
57
|
+
key: keyZ,
|
|
58
|
+
includeStatus: z.boolean().optional(),
|
|
59
|
+
})
|
|
60
|
+
.transform(({ key, includeStatus }) => ({
|
|
61
|
+
keys: [key],
|
|
62
|
+
includeStatus,
|
|
63
|
+
}));
|
|
64
64
|
|
|
65
|
-
export
|
|
66
|
-
|
|
67
|
-
RetrieveRequest,
|
|
68
|
-
"limit" | "offset" | "makes" | "ignoreNotFound" | "includeState"
|
|
69
|
-
> {}
|
|
65
|
+
export type SingleRetrieveArgs = z.input<typeof singleRetrieveArgsZ>;
|
|
66
|
+
export type MultiRetrieveArgs = z.input<typeof retrieveRequestZ>;
|
|
70
67
|
|
|
71
|
-
|
|
68
|
+
const retrieveArgsZ = z.union([singleRetrieveArgsZ, retrieveRequestZ]);
|
|
72
69
|
|
|
73
|
-
|
|
70
|
+
export type RetrieveArgs = z.input<typeof retrieveArgsZ>;
|
|
74
71
|
|
|
75
|
-
export class Client
|
|
76
|
-
readonly type =
|
|
72
|
+
export class Client {
|
|
73
|
+
readonly type = "device";
|
|
77
74
|
private readonly client: UnaryClient;
|
|
78
|
-
private readonly frameClient: framer.Client;
|
|
79
75
|
|
|
80
|
-
constructor(client: UnaryClient
|
|
76
|
+
constructor(client: UnaryClient) {
|
|
81
77
|
this.client = client;
|
|
82
|
-
this.frameClient = frameClient;
|
|
83
78
|
}
|
|
84
79
|
|
|
85
80
|
async retrieve<
|
|
86
|
-
Properties extends
|
|
81
|
+
Properties extends record.Unknown = record.Unknown,
|
|
87
82
|
Make extends string = string,
|
|
88
83
|
Model extends string = string,
|
|
89
|
-
|
|
90
|
-
>(
|
|
91
|
-
key: string,
|
|
92
|
-
options?: RetrieveOptions,
|
|
93
|
-
): Promise<Device<Properties, Make, Model, StateDetails>>;
|
|
84
|
+
>(args: SingleRetrieveArgs): Promise<Device<Properties, Make, Model>>;
|
|
94
85
|
|
|
95
86
|
async retrieve<
|
|
96
|
-
Properties extends
|
|
87
|
+
Properties extends record.Unknown = record.Unknown,
|
|
97
88
|
Make extends string = string,
|
|
98
89
|
Model extends string = string,
|
|
99
|
-
|
|
100
|
-
>(
|
|
101
|
-
keys: string[],
|
|
102
|
-
options?: RetrieveOptions,
|
|
103
|
-
): Promise<Array<Device<Properties, Make, Model, StateDetails>>>;
|
|
90
|
+
>(args: MultiRetrieveArgs): Promise<Array<Device<Properties, Make, Model>>>;
|
|
104
91
|
|
|
105
92
|
async retrieve<
|
|
106
|
-
Properties extends
|
|
93
|
+
Properties extends record.Unknown = record.Unknown,
|
|
107
94
|
Make extends string = string,
|
|
108
95
|
Model extends string = string,
|
|
109
|
-
StateDetails extends {} = UnknownRecord,
|
|
110
96
|
>(
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
| Device<Properties, Make, Model, StateDetails>
|
|
115
|
-
| Array<Device<Properties, Make, Model, StateDetails>>
|
|
116
|
-
> {
|
|
117
|
-
const isSingle = !Array.isArray(keys);
|
|
97
|
+
args: RetrieveArgs,
|
|
98
|
+
): Promise<Device<Properties, Make, Model> | Array<Device<Properties, Make, Model>>> {
|
|
99
|
+
const isSingle = typeof args === "object" && "key" in args;
|
|
118
100
|
const res = await sendRequired(
|
|
119
101
|
this.client,
|
|
120
102
|
RETRIEVE_ENDPOINT,
|
|
121
|
-
|
|
122
|
-
|
|
103
|
+
args,
|
|
104
|
+
retrieveArgsZ,
|
|
123
105
|
retrieveResZ,
|
|
124
106
|
);
|
|
125
|
-
checkForMultipleOrNoResults("Device",
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
: (res.devices as Array<Device<Properties, Make, Model, StateDetails>>);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
async search(term: string, options?: RetrieveOptions): Promise<Device[]> {
|
|
132
|
-
return (
|
|
133
|
-
await sendRequired(
|
|
134
|
-
this.client,
|
|
135
|
-
RETRIEVE_ENDPOINT,
|
|
136
|
-
{ search: term, ...options },
|
|
137
|
-
retrieveReqZ,
|
|
138
|
-
retrieveResZ,
|
|
139
|
-
)
|
|
140
|
-
).devices;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
async page(offset: number, limit: number, options?: PageOptions): Promise<Device[]> {
|
|
144
|
-
return (
|
|
145
|
-
await sendRequired(
|
|
146
|
-
this.client,
|
|
147
|
-
RETRIEVE_ENDPOINT,
|
|
148
|
-
{ offset, limit, ...options },
|
|
149
|
-
retrieveReqZ,
|
|
150
|
-
retrieveResZ,
|
|
151
|
-
)
|
|
152
|
-
).devices;
|
|
107
|
+
checkForMultipleOrNoResults("Device", args, res.devices, isSingle);
|
|
108
|
+
const devices = res.devices as Device<Properties, Make, Model>[];
|
|
109
|
+
return isSingle ? devices[0] : devices;
|
|
153
110
|
}
|
|
154
111
|
|
|
155
112
|
async create<
|
|
156
|
-
Properties extends
|
|
113
|
+
Properties extends record.Unknown = record.Unknown,
|
|
157
114
|
Make extends string = string,
|
|
158
115
|
Model extends string = string,
|
|
159
116
|
>(device: New<Properties, Make>): Promise<Device<Properties, Make, Model>>;
|
|
160
117
|
async create<
|
|
161
|
-
Properties extends
|
|
118
|
+
Properties extends record.Unknown = record.Unknown,
|
|
162
119
|
Make extends string = string,
|
|
163
120
|
Model extends string = string,
|
|
164
121
|
>(devices: New<Properties, Make>[]): Promise<Device<Properties, Make, Model>[]>;
|
|
165
122
|
async create<
|
|
166
|
-
Properties extends
|
|
123
|
+
Properties extends record.Unknown = record.Unknown,
|
|
167
124
|
Make extends string = string,
|
|
168
125
|
Model extends string = string,
|
|
169
126
|
>(
|
|
@@ -177,9 +134,8 @@ export class Client implements AsyncTermSearcher<string, Key, Device> {
|
|
|
177
134
|
createReqZ,
|
|
178
135
|
createResZ,
|
|
179
136
|
);
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
: (res.devices as Device<Properties, Make, Model>[]);
|
|
137
|
+
const created = res.devices as Device<Properties, Make, Model>[];
|
|
138
|
+
return isSingle ? created[0] : created;
|
|
183
139
|
}
|
|
184
140
|
|
|
185
141
|
async delete(keys: string | string[]): Promise<void> {
|
|
@@ -191,48 +147,6 @@ export class Client implements AsyncTermSearcher<string, Key, Device> {
|
|
|
191
147
|
deleteResZ,
|
|
192
148
|
);
|
|
193
149
|
}
|
|
194
|
-
|
|
195
|
-
async openDeviceTracker(): Promise<signals.Observable<string, Device>> {
|
|
196
|
-
return await signals.openObservable<string, Device>(
|
|
197
|
-
this.frameClient,
|
|
198
|
-
SET_CHANNEL_NAME,
|
|
199
|
-
DELETE_CHANNEL_NAME,
|
|
200
|
-
decodeDeviceChanges,
|
|
201
|
-
);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
async openStateObserver<Details extends {} = UnknownRecord>(): Promise<
|
|
205
|
-
framer.ObservableStreamer<State<Details>[]>
|
|
206
|
-
> {
|
|
207
|
-
return new framer.ObservableStreamer<State<Details>[]>(
|
|
208
|
-
await this.frameClient.openStreamer(STATE_CHANNEL_NAME),
|
|
209
|
-
(frame) => {
|
|
210
|
-
const s = frame.get(STATE_CHANNEL_NAME);
|
|
211
|
-
if (s.length === 0) return [null, false];
|
|
212
|
-
const states = s.parseJSON(stateZ);
|
|
213
|
-
return [states as State<Details>[], true];
|
|
214
|
-
},
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
newSearcherWithOptions(
|
|
219
|
-
options: RetrieveOptions,
|
|
220
|
-
): AsyncTermSearcher<string, Key, Device> {
|
|
221
|
-
return {
|
|
222
|
-
type: this.type,
|
|
223
|
-
search: async (term: string) => await this.search(term, options),
|
|
224
|
-
retrieve: async (keys: string[]) => await this.retrieve(keys, options),
|
|
225
|
-
page: async (offset: number, limit: number) =>
|
|
226
|
-
await this.page(offset, limit, options),
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
150
|
}
|
|
230
151
|
|
|
231
|
-
const
|
|
232
|
-
if (variant === "delete")
|
|
233
|
-
return data.toStrings().map((k) => ({ variant, key: k, value: undefined }));
|
|
234
|
-
return data.parseJSON(deviceZ).map((d) => ({ variant, key: d.key, value: d }));
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
export const ontologyID = (key: Key): ontology.ID =>
|
|
238
|
-
new ontology.ID({ type: ONTOLOGY_TYPE, key });
|
|
152
|
+
export const ontologyID = (key: Key): ontology.ID => ({ type: "device", key });
|