@synnaxlabs/client 0.43.1 → 0.44.2

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.
Files changed (245) hide show
  1. package/.turbo/turbo-build.log +7 -7
  2. package/dist/access/payload.d.ts +1 -1
  3. package/dist/access/payload.d.ts.map +1 -1
  4. package/dist/access/policy/client.d.ts +263 -6
  5. package/dist/access/policy/client.d.ts.map +1 -1
  6. package/dist/access/policy/external.d.ts +0 -1
  7. package/dist/access/policy/external.d.ts.map +1 -1
  8. package/dist/access/policy/payload.d.ts +105 -93
  9. package/dist/access/policy/payload.d.ts.map +1 -1
  10. package/dist/auth/auth.d.ts +1 -1
  11. package/dist/auth/auth.d.ts.map +1 -1
  12. package/dist/channel/client.d.ts +23 -17
  13. package/dist/channel/client.d.ts.map +1 -1
  14. package/dist/channel/payload.d.ts +151 -21
  15. package/dist/channel/payload.d.ts.map +1 -1
  16. package/dist/channel/retriever.d.ts +9 -16
  17. package/dist/channel/retriever.d.ts.map +1 -1
  18. package/dist/channel/writer.d.ts +1 -1
  19. package/dist/channel/writer.d.ts.map +1 -1
  20. package/dist/client.cjs +27 -135
  21. package/dist/client.d.ts +3 -3
  22. package/dist/client.d.ts.map +1 -1
  23. package/dist/client.js +8657 -28963
  24. package/dist/connection/checker.d.ts +1 -1
  25. package/dist/connection/checker.d.ts.map +1 -1
  26. package/dist/control/client.d.ts +1 -0
  27. package/dist/control/client.d.ts.map +1 -1
  28. package/dist/control/state.d.ts +6 -6
  29. package/dist/control/state.d.ts.map +1 -1
  30. package/dist/errors.d.ts +18 -5
  31. package/dist/errors.d.ts.map +1 -1
  32. package/dist/framer/adapter.d.ts +3 -3
  33. package/dist/framer/adapter.d.ts.map +1 -1
  34. package/dist/framer/client.d.ts +4 -13
  35. package/dist/framer/client.d.ts.map +1 -1
  36. package/dist/framer/codec.d.ts +1 -1
  37. package/dist/framer/codec.d.ts.map +1 -1
  38. package/dist/framer/deleter.d.ts +5 -5
  39. package/dist/framer/deleter.d.ts.map +1 -1
  40. package/dist/framer/frame.d.ts +5 -7
  41. package/dist/framer/frame.d.ts.map +1 -1
  42. package/dist/framer/streamProxy.d.ts +1 -1
  43. package/dist/framer/streamProxy.d.ts.map +1 -1
  44. package/dist/framer/streamer.d.ts +235 -20
  45. package/dist/framer/streamer.d.ts.map +1 -1
  46. package/dist/framer/writer.d.ts +302 -33
  47. package/dist/framer/writer.d.ts.map +1 -1
  48. package/dist/hardware/device/client.d.ts +49 -28
  49. package/dist/hardware/device/client.d.ts.map +1 -1
  50. package/dist/hardware/device/payload.d.ts +126 -46
  51. package/dist/hardware/device/payload.d.ts.map +1 -1
  52. package/dist/hardware/rack/client.d.ts +78 -22
  53. package/dist/hardware/rack/client.d.ts.map +1 -1
  54. package/dist/hardware/rack/payload.d.ts +99 -56
  55. package/dist/hardware/rack/payload.d.ts.map +1 -1
  56. package/dist/hardware/task/client.d.ts +100 -41
  57. package/dist/hardware/task/client.d.ts.map +1 -1
  58. package/dist/hardware/task/payload.d.ts +83 -61
  59. package/dist/hardware/task/payload.d.ts.map +1 -1
  60. package/dist/index.d.ts +2 -2
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/label/client.d.ts +138 -20
  63. package/dist/label/client.d.ts.map +1 -1
  64. package/dist/label/external.d.ts +0 -2
  65. package/dist/label/external.d.ts.map +1 -1
  66. package/dist/label/payload.d.ts +4 -5
  67. package/dist/label/payload.d.ts.map +1 -1
  68. package/dist/ontology/client.d.ts +45 -135
  69. package/dist/ontology/client.d.ts.map +1 -1
  70. package/dist/ontology/group/group.d.ts +3 -3
  71. package/dist/ontology/group/group.d.ts.map +1 -1
  72. package/dist/ontology/group/payload.d.ts +3 -27
  73. package/dist/ontology/group/payload.d.ts.map +1 -1
  74. package/dist/ontology/payload.d.ts +114 -243
  75. package/dist/ontology/payload.d.ts.map +1 -1
  76. package/dist/ontology/writer.d.ts +4 -4
  77. package/dist/ontology/writer.d.ts.map +1 -1
  78. package/dist/ranger/alias.d.ts +15 -5
  79. package/dist/ranger/alias.d.ts.map +1 -1
  80. package/dist/ranger/client.d.ts +91 -30
  81. package/dist/ranger/client.d.ts.map +1 -1
  82. package/dist/ranger/external.d.ts +1 -1
  83. package/dist/ranger/external.d.ts.map +1 -1
  84. package/dist/ranger/kv.d.ts +11 -12
  85. package/dist/ranger/kv.d.ts.map +1 -1
  86. package/dist/ranger/payload.d.ts +19 -44
  87. package/dist/ranger/payload.d.ts.map +1 -1
  88. package/dist/ranger/writer.d.ts +22 -19
  89. package/dist/ranger/writer.d.ts.map +1 -1
  90. package/dist/testutil/client.d.ts +4 -0
  91. package/dist/testutil/client.d.ts.map +1 -0
  92. package/dist/user/client.d.ts +59 -6
  93. package/dist/user/client.d.ts.map +1 -1
  94. package/dist/user/payload.d.ts +4 -6
  95. package/dist/user/payload.d.ts.map +1 -1
  96. package/dist/user/retriever.d.ts +2 -2
  97. package/dist/user/retriever.d.ts.map +1 -1
  98. package/dist/util/decodeJSONString.d.ts +2 -2
  99. package/dist/util/decodeJSONString.d.ts.map +1 -1
  100. package/dist/util/parseWithoutKeyConversion.d.ts +2 -2
  101. package/dist/util/parseWithoutKeyConversion.d.ts.map +1 -1
  102. package/dist/util/retrieve.d.ts +1 -1
  103. package/dist/util/retrieve.d.ts.map +1 -1
  104. package/dist/util/zod.d.ts +1 -1
  105. package/dist/util/zod.d.ts.map +1 -1
  106. package/dist/workspace/client.d.ts +17 -6
  107. package/dist/workspace/client.d.ts.map +1 -1
  108. package/dist/workspace/lineplot/client.d.ts +2 -2
  109. package/dist/workspace/lineplot/client.d.ts.map +1 -1
  110. package/dist/workspace/lineplot/payload.d.ts +8 -9
  111. package/dist/workspace/lineplot/payload.d.ts.map +1 -1
  112. package/dist/workspace/log/client.d.ts +2 -2
  113. package/dist/workspace/log/client.d.ts.map +1 -1
  114. package/dist/workspace/log/payload.d.ts +8 -9
  115. package/dist/workspace/log/payload.d.ts.map +1 -1
  116. package/dist/workspace/payload.d.ts +10 -11
  117. package/dist/workspace/payload.d.ts.map +1 -1
  118. package/dist/workspace/schematic/client.d.ts +2 -2
  119. package/dist/workspace/schematic/client.d.ts.map +1 -1
  120. package/dist/workspace/schematic/payload.d.ts +10 -11
  121. package/dist/workspace/schematic/payload.d.ts.map +1 -1
  122. package/dist/workspace/table/client.d.ts +2 -2
  123. package/dist/workspace/table/client.d.ts.map +1 -1
  124. package/dist/workspace/table/payload.d.ts +10 -11
  125. package/dist/workspace/table/payload.d.ts.map +1 -1
  126. package/examples/node/package-lock.json +47 -39
  127. package/examples/node/package.json +2 -1
  128. package/examples/node/streamWrite.js +5 -11
  129. package/package.json +14 -13
  130. package/src/access/payload.ts +1 -1
  131. package/src/access/policy/client.ts +87 -32
  132. package/src/access/policy/external.ts +0 -1
  133. package/src/access/policy/payload.ts +4 -4
  134. package/src/access/policy/policy.spec.ts +86 -83
  135. package/src/auth/auth.spec.ts +29 -18
  136. package/src/auth/auth.ts +1 -1
  137. package/src/channel/batchRetriever.spec.ts +4 -9
  138. package/src/channel/channel.spec.ts +24 -6
  139. package/src/channel/client.ts +52 -51
  140. package/src/channel/payload.ts +15 -16
  141. package/src/channel/retriever.ts +26 -41
  142. package/src/channel/writer.ts +7 -4
  143. package/src/client.ts +4 -4
  144. package/src/connection/checker.ts +1 -1
  145. package/src/connection/connection.spec.ts +31 -23
  146. package/src/control/client.ts +2 -2
  147. package/src/control/state.spec.ts +3 -3
  148. package/src/control/state.ts +1 -1
  149. package/src/errors.spec.ts +9 -5
  150. package/src/errors.ts +28 -15
  151. package/src/framer/adapter.spec.ts +118 -9
  152. package/src/framer/adapter.ts +24 -11
  153. package/src/framer/client.spec.ts +125 -2
  154. package/src/framer/client.ts +41 -47
  155. package/src/framer/codec.ts +1 -1
  156. package/src/framer/deleter.spec.ts +2 -2
  157. package/src/framer/deleter.ts +1 -1
  158. package/src/framer/frame.ts +1 -4
  159. package/src/framer/iterator.spec.ts +8 -8
  160. package/src/framer/iterator.ts +1 -1
  161. package/src/framer/streamProxy.ts +1 -1
  162. package/src/framer/streamer.spec.ts +185 -36
  163. package/src/framer/streamer.ts +28 -36
  164. package/src/framer/writer.spec.ts +7 -6
  165. package/src/framer/writer.ts +97 -111
  166. package/src/hardware/device/client.ts +45 -131
  167. package/src/hardware/device/device.spec.ts +163 -52
  168. package/src/hardware/device/payload.ts +10 -21
  169. package/src/hardware/rack/client.ts +87 -105
  170. package/src/hardware/rack/payload.ts +4 -13
  171. package/src/hardware/rack/rack.spec.ts +28 -35
  172. package/src/hardware/task/client.ts +335 -291
  173. package/src/hardware/task/payload.ts +86 -62
  174. package/src/hardware/task/task.spec.ts +208 -32
  175. package/src/index.ts +2 -1
  176. package/src/label/client.ts +100 -95
  177. package/src/label/external.ts +0 -2
  178. package/src/label/label.spec.ts +8 -6
  179. package/src/label/payload.ts +3 -4
  180. package/src/ontology/client.ts +41 -324
  181. package/src/ontology/group/group.spec.ts +2 -2
  182. package/src/ontology/group/group.ts +4 -5
  183. package/src/ontology/group/payload.ts +2 -25
  184. package/src/ontology/group/writer.ts +1 -1
  185. package/src/ontology/ontology.spec.ts +355 -41
  186. package/src/ontology/payload.ts +77 -112
  187. package/src/ontology/writer.ts +8 -17
  188. package/src/ranger/alias.ts +45 -37
  189. package/src/ranger/client.ts +144 -149
  190. package/src/ranger/external.ts +1 -1
  191. package/src/ranger/kv.ts +9 -27
  192. package/src/ranger/payload.ts +23 -37
  193. package/src/ranger/ranger.spec.ts +37 -56
  194. package/src/ranger/writer.ts +1 -1
  195. package/src/{signals/index.ts → testutil/client.ts} +11 -1
  196. package/src/user/client.ts +122 -47
  197. package/src/user/payload.ts +2 -5
  198. package/src/user/retriever.ts +1 -1
  199. package/src/user/user.spec.ts +31 -31
  200. package/src/user/writer.ts +1 -1
  201. package/src/util/decodeJSONString.ts +3 -3
  202. package/src/util/parseWithoutKeyConversion.ts +2 -2
  203. package/src/util/retrieve.ts +1 -1
  204. package/src/util/zod.ts +1 -1
  205. package/src/workspace/client.ts +20 -36
  206. package/src/workspace/lineplot/client.ts +5 -7
  207. package/src/workspace/lineplot/lineplot.spec.ts +2 -2
  208. package/src/workspace/lineplot/payload.ts +4 -7
  209. package/src/workspace/log/client.ts +5 -7
  210. package/src/workspace/log/log.spec.ts +2 -2
  211. package/src/workspace/log/payload.ts +4 -7
  212. package/src/workspace/payload.ts +4 -7
  213. package/src/workspace/schematic/client.ts +5 -7
  214. package/src/workspace/schematic/payload.ts +4 -7
  215. package/src/workspace/schematic/schematic.spec.ts +2 -2
  216. package/src/workspace/table/client.ts +5 -7
  217. package/src/workspace/table/payload.ts +4 -7
  218. package/src/workspace/table/table.spec.ts +2 -2
  219. package/src/workspace/workspace.spec.ts +2 -2
  220. package/dist/access/policy/ontology.d.ts +0 -5
  221. package/dist/access/policy/ontology.d.ts.map +0 -1
  222. package/dist/access/policy/retriever.d.ts +0 -40
  223. package/dist/access/policy/retriever.d.ts.map +0 -1
  224. package/dist/access/policy/writer.d.ts +0 -9
  225. package/dist/access/policy/writer.d.ts.map +0 -1
  226. package/dist/label/retriever.d.ts +0 -14
  227. package/dist/label/retriever.d.ts.map +0 -1
  228. package/dist/label/writer.d.ts +0 -54
  229. package/dist/label/writer.d.ts.map +0 -1
  230. package/dist/setupspecs.d.ts +0 -5
  231. package/dist/setupspecs.d.ts.map +0 -1
  232. package/dist/signals/external.d.ts +0 -2
  233. package/dist/signals/external.d.ts.map +0 -1
  234. package/dist/signals/index.d.ts +0 -2
  235. package/dist/signals/index.d.ts.map +0 -1
  236. package/dist/signals/observable.d.ts +0 -12
  237. package/dist/signals/observable.d.ts.map +0 -1
  238. package/src/access/policy/ontology.ts +0 -17
  239. package/src/access/policy/retriever.ts +0 -44
  240. package/src/access/policy/writer.ts +0 -65
  241. package/src/label/retriever.ts +0 -63
  242. package/src/label/writer.ts +0 -95
  243. package/src/setupspecs.ts +0 -27
  244. package/src/signals/external.ts +0 -10
  245. package/src/signals/observable.ts +0 -42
@@ -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 { array, control, errors } from "@synnaxlabs/x";
12
- import {
13
- type CrudeSeries,
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 netConfigZ = z.object({
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
- interface Config extends z.infer<typeof netConfigZ> {}
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: netConfigZ.optional(),
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.infer<typeof reqZ> {}
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
- interface Response extends z.infer<typeof resZ> {}
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 interface WriterConfig {
94
- // channels denote the channels to write to.
95
- channels: channel.Params;
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 adapter = await WriteAdapter.open(retriever, channels);
186
- if (useExperimentalCodec)
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
- key: channel.KeyOrName,
250
- authority: control.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
- let config: Config;
263
- if (typeof value === "number" && authority == null)
264
- config = { keys: [], authorities: [value] };
265
- else {
266
- let oValue: Record<channel.KeyOrName, control.Authority>;
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 UnknownRecord } from "@synnaxlabs/x";
12
- import { type AsyncTermSearcher } from "@synnaxlabs/x/search";
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 STATE_CHANNEL_NAME = "sy_device_state";
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 retrieveReqZ = z.object({
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
- search: z.string().optional(),
48
+ searchTerm: z.string().optional(),
57
49
  limit: z.number().optional(),
58
50
  offset: z.number().optional(),
59
- ignoreNotFound: z.boolean().optional(),
60
- includeState: z.boolean().optional(),
51
+ includeStatus: z.boolean().optional(),
61
52
  });
53
+ const retrieveResZ = z.object({ devices: nullableArrayZ(deviceZ) });
62
54
 
63
- interface RetrieveRequest extends z.input<typeof retrieveReqZ> {}
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 interface RetrieveOptions
66
- extends Pick<
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
- interface PageOptions extends Pick<RetrieveOptions, "makes"> {}
68
+ const retrieveArgsZ = z.union([singleRetrieveArgsZ, retrieveRequestZ]);
72
69
 
73
- const retrieveResZ = z.object({ devices: nullableArrayZ(deviceZ) });
70
+ export type RetrieveArgs = z.input<typeof retrieveArgsZ>;
74
71
 
75
- export class Client implements AsyncTermSearcher<string, Key, Device> {
76
- readonly type = ONTOLOGY_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, frameClient: framer.Client) {
76
+ constructor(client: UnaryClient) {
81
77
  this.client = client;
82
- this.frameClient = frameClient;
83
78
  }
84
79
 
85
80
  async retrieve<
86
- Properties extends UnknownRecord = UnknownRecord,
81
+ Properties extends record.Unknown = record.Unknown,
87
82
  Make extends string = string,
88
83
  Model extends string = string,
89
- StateDetails extends {} = UnknownRecord,
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 UnknownRecord = UnknownRecord,
87
+ Properties extends record.Unknown = record.Unknown,
97
88
  Make extends string = string,
98
89
  Model extends string = string,
99
- StateDetails extends {} = UnknownRecord,
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 UnknownRecord = UnknownRecord,
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
- keys: string | string[],
112
- options?: RetrieveOptions,
113
- ): Promise<
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
- { keys: array.toArray(keys), ...options },
122
- retrieveReqZ,
103
+ args,
104
+ retrieveArgsZ,
123
105
  retrieveResZ,
124
106
  );
125
- checkForMultipleOrNoResults("Device", keys, res.devices, isSingle);
126
- return isSingle
127
- ? (res.devices[0] as Device<Properties, Make, Model, StateDetails>)
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 UnknownRecord = UnknownRecord,
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 UnknownRecord = UnknownRecord,
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 UnknownRecord = UnknownRecord,
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
- return isSingle
181
- ? (res.devices[0] as Device<Properties, Make, Model>)
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 decodeDeviceChanges: signals.Decoder<string, Device> = (variant, data) => {
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 });