@synnaxlabs/client 0.22.1 → 0.23.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.
Files changed (228) hide show
  1. package/.turbo/turbo-build.log +7 -6
  2. package/dist/auth/auth.d.ts.map +1 -1
  3. package/dist/channel/client.d.ts +14 -4
  4. package/dist/channel/client.d.ts.map +1 -1
  5. package/dist/channel/creator.d.ts +1 -1
  6. package/dist/channel/creator.d.ts.map +1 -1
  7. package/dist/channel/external.d.ts +1 -1
  8. package/dist/channel/external.d.ts.map +1 -1
  9. package/dist/channel/payload.d.ts +21 -8
  10. package/dist/channel/payload.d.ts.map +1 -1
  11. package/dist/channel/retriever.d.ts +6 -6
  12. package/dist/channel/retriever.d.ts.map +1 -1
  13. package/dist/channel/writer.d.ts +13 -1
  14. package/dist/channel/writer.d.ts.map +1 -1
  15. package/dist/client.cjs +17 -18
  16. package/dist/client.d.ts +4 -2
  17. package/dist/client.d.ts.map +1 -1
  18. package/dist/client.js +5487 -13615
  19. package/dist/connection/checker.d.ts +4 -4
  20. package/dist/control/client.d.ts +9 -0
  21. package/dist/control/client.d.ts.map +1 -0
  22. package/dist/control/external.d.ts +1 -1
  23. package/dist/control/external.d.ts.map +1 -1
  24. package/dist/control/state.d.ts +17 -52
  25. package/dist/control/state.d.ts.map +1 -1
  26. package/dist/errors.d.ts +6 -0
  27. package/dist/errors.d.ts.map +1 -1
  28. package/dist/framer/adapter.d.ts +1 -1
  29. package/dist/framer/adapter.d.ts.map +1 -1
  30. package/dist/framer/client.d.ts +7 -5
  31. package/dist/framer/client.d.ts.map +1 -1
  32. package/dist/framer/deleter.d.ts +68 -0
  33. package/dist/framer/deleter.d.ts.map +1 -0
  34. package/dist/framer/deleter.spec.d.ts +2 -0
  35. package/dist/framer/deleter.spec.d.ts.map +1 -0
  36. package/dist/framer/frame.d.ts +45 -241
  37. package/dist/framer/frame.d.ts.map +1 -1
  38. package/dist/framer/iterator.d.ts +1 -1
  39. package/dist/framer/iterator.d.ts.map +1 -1
  40. package/dist/framer/streamProxy.d.ts.map +1 -1
  41. package/dist/framer/streamer.d.ts.map +1 -1
  42. package/dist/framer/writer.d.ts +86 -231
  43. package/dist/framer/writer.d.ts.map +1 -1
  44. package/dist/hardware/device/client.d.ts +9 -7
  45. package/dist/hardware/device/client.d.ts.map +1 -1
  46. package/dist/hardware/task/client.d.ts +17 -14
  47. package/dist/hardware/task/client.d.ts.map +1 -1
  48. package/dist/index.d.ts +12 -11
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/label/client.d.ts.map +1 -1
  51. package/dist/label/external.d.ts +2 -2
  52. package/dist/label/external.d.ts.map +1 -1
  53. package/dist/label/writer.d.ts +4 -2
  54. package/dist/label/writer.d.ts.map +1 -1
  55. package/dist/ontology/client.d.ts +8 -8
  56. package/dist/ontology/client.d.ts.map +1 -1
  57. package/dist/ontology/group/client.d.ts +1 -1
  58. package/dist/ontology/group/client.d.ts.map +1 -1
  59. package/dist/ontology/group/external.d.ts +1 -1
  60. package/dist/ontology/group/external.d.ts.map +1 -1
  61. package/dist/ontology/group/writer.d.ts +1 -1
  62. package/dist/ontology/group/writer.d.ts.map +1 -1
  63. package/dist/ontology/payload.d.ts +14 -26
  64. package/dist/ontology/payload.d.ts.map +1 -1
  65. package/dist/ontology/writer.d.ts.map +1 -1
  66. package/dist/ranger/active.d.ts +1 -1
  67. package/dist/ranger/active.d.ts.map +1 -1
  68. package/dist/ranger/alias.d.ts.map +1 -1
  69. package/dist/ranger/client.d.ts +16 -100
  70. package/dist/ranger/client.d.ts.map +1 -1
  71. package/dist/ranger/external.d.ts +2 -2
  72. package/dist/ranger/external.d.ts.map +1 -1
  73. package/dist/ranger/kv.d.ts.map +1 -1
  74. package/dist/ranger/payload.d.ts +34 -270
  75. package/dist/ranger/payload.d.ts.map +1 -1
  76. package/dist/ranger/range.d.ts +1 -1
  77. package/dist/ranger/range.d.ts.map +1 -1
  78. package/dist/ranger/writer.d.ts.map +1 -1
  79. package/dist/transport.d.ts.map +1 -1
  80. package/dist/util/retrieve.d.ts.map +1 -1
  81. package/dist/util/zod.d.ts.map +1 -1
  82. package/dist/workspace/client.d.ts.map +1 -1
  83. package/dist/workspace/external.d.ts +1 -1
  84. package/dist/workspace/external.d.ts.map +1 -1
  85. package/dist/workspace/lineplot/client.d.ts +1 -1
  86. package/dist/workspace/lineplot/client.d.ts.map +1 -1
  87. package/dist/workspace/lineplot/external.d.ts +1 -1
  88. package/dist/workspace/lineplot/external.d.ts.map +1 -1
  89. package/dist/workspace/lineplot/payload.d.ts +2 -2
  90. package/dist/workspace/lineplot/retriever.d.ts.map +1 -1
  91. package/dist/workspace/lineplot/writer.d.ts +4 -4
  92. package/dist/workspace/lineplot/writer.d.ts.map +1 -1
  93. package/dist/workspace/payload.d.ts +6 -4
  94. package/dist/workspace/payload.d.ts.map +1 -1
  95. package/dist/workspace/retriever.d.ts.map +1 -1
  96. package/dist/workspace/schematic/client.d.ts.map +1 -1
  97. package/dist/workspace/schematic/external.d.ts +1 -1
  98. package/dist/workspace/schematic/external.d.ts.map +1 -1
  99. package/dist/workspace/schematic/payload.d.ts +2 -2
  100. package/dist/workspace/schematic/retriever.d.ts +1 -1
  101. package/dist/workspace/schematic/retriever.d.ts.map +1 -1
  102. package/dist/workspace/schematic/writer.d.ts +4 -4
  103. package/dist/workspace/schematic/writer.d.ts.map +1 -1
  104. package/dist/workspace/writer.d.ts +7 -5
  105. package/dist/workspace/writer.d.ts.map +1 -1
  106. package/eslint.config.js +12 -0
  107. package/examples/node/basicReadWrite.js +11 -2
  108. package/examples/node/liveStream.js +13 -4
  109. package/examples/node/seriesAndFrames.js +12 -3
  110. package/examples/node/streamWrite.js +15 -6
  111. package/package.json +11 -8
  112. package/src/auth/auth.spec.ts +7 -6
  113. package/src/auth/auth.ts +17 -13
  114. package/src/auth/index.ts +1 -1
  115. package/src/channel/batchRetriever.spec.ts +16 -5
  116. package/src/channel/channel.spec.ts +42 -4
  117. package/src/channel/client.ts +26 -9
  118. package/src/channel/creator.ts +2 -2
  119. package/src/channel/external.ts +2 -2
  120. package/src/channel/index.ts +1 -1
  121. package/src/channel/payload.ts +3 -1
  122. package/src/channel/retriever.ts +6 -4
  123. package/src/channel/writer.ts +23 -4
  124. package/src/client.ts +5 -3
  125. package/src/connection/checker.ts +1 -1
  126. package/src/connection/connection.spec.ts +1 -1
  127. package/src/connection/index.ts +1 -1
  128. package/src/control/client.ts +17 -0
  129. package/src/control/external.ts +2 -2
  130. package/src/control/index.ts +1 -1
  131. package/src/control/state.spec.ts +2 -3
  132. package/src/control/state.ts +20 -84
  133. package/src/errors.ts +18 -7
  134. package/src/framer/adapter.spec.ts +9 -0
  135. package/src/framer/adapter.ts +3 -3
  136. package/src/framer/client.spec.ts +1 -1
  137. package/src/framer/client.ts +30 -12
  138. package/src/framer/deleter.spec.ts +129 -0
  139. package/src/framer/deleter.ts +49 -0
  140. package/src/framer/external.ts +1 -1
  141. package/src/framer/frame.spec.ts +1 -1
  142. package/src/framer/frame.ts +14 -14
  143. package/src/framer/index.ts +1 -1
  144. package/src/framer/iterator.spec.ts +2 -2
  145. package/src/framer/iterator.ts +2 -2
  146. package/src/framer/streamProxy.ts +2 -4
  147. package/src/framer/streamer.spec.ts +2 -2
  148. package/src/framer/streamer.ts +6 -5
  149. package/src/framer/writer.spec.ts +18 -1
  150. package/src/framer/writer.ts +19 -27
  151. package/src/hardware/device/client.ts +2 -2
  152. package/src/hardware/device/index.ts +1 -1
  153. package/src/hardware/external.ts +1 -1
  154. package/src/hardware/index.ts +1 -1
  155. package/src/hardware/rack/rack.spec.ts +1 -1
  156. package/src/hardware/task/client.ts +3 -3
  157. package/src/hardware/task/task.spec.ts +2 -2
  158. package/src/index.ts +26 -25
  159. package/src/label/client.ts +2 -2
  160. package/src/label/external.ts +3 -3
  161. package/src/label/index.ts +1 -1
  162. package/src/label/label.spec.ts +1 -1
  163. package/src/label/payload.ts +1 -1
  164. package/src/label/retriever.ts +1 -1
  165. package/src/label/writer.ts +1 -1
  166. package/src/ontology/client.ts +7 -7
  167. package/src/ontology/external.ts +1 -1
  168. package/src/ontology/group/client.ts +3 -3
  169. package/src/ontology/group/external.ts +2 -2
  170. package/src/ontology/group/group.spec.ts +2 -2
  171. package/src/ontology/group/group.ts +1 -1
  172. package/src/ontology/group/index.ts +1 -1
  173. package/src/ontology/group/payload.ts +1 -1
  174. package/src/ontology/group/writer.ts +22 -6
  175. package/src/ontology/index.ts +1 -1
  176. package/src/ontology/ontology.spec.ts +2 -2
  177. package/src/ontology/payload.ts +3 -3
  178. package/src/ontology/writer.ts +2 -2
  179. package/src/ranger/active.ts +2 -2
  180. package/src/ranger/alias.ts +2 -2
  181. package/src/ranger/client.ts +15 -16
  182. package/src/ranger/external.ts +3 -3
  183. package/src/ranger/index.ts +1 -1
  184. package/src/ranger/kv.ts +2 -2
  185. package/src/ranger/payload.ts +1 -1
  186. package/src/ranger/range.ts +2 -2
  187. package/src/ranger/ranger.spec.ts +1 -1
  188. package/src/ranger/writer.ts +3 -3
  189. package/src/setupspecs.ts +1 -1
  190. package/src/signals/external.ts +1 -1
  191. package/src/signals/index.ts +1 -1
  192. package/src/signals/observable.ts +1 -1
  193. package/src/transport.ts +2 -2
  194. package/src/user/index.ts +1 -1
  195. package/src/user/payload.ts +1 -1
  196. package/src/util/retrieve.spec.ts +1 -1
  197. package/src/util/retrieve.ts +1 -1
  198. package/src/util/telem.ts +1 -1
  199. package/src/util/zod.ts +9 -0
  200. package/src/vite-env.d.ts +2 -2
  201. package/src/workspace/client.ts +2 -2
  202. package/src/workspace/external.ts +2 -2
  203. package/src/workspace/index.ts +1 -1
  204. package/src/workspace/lineplot/client.ts +2 -2
  205. package/src/workspace/lineplot/external.ts +2 -2
  206. package/src/workspace/lineplot/index.ts +1 -1
  207. package/src/workspace/lineplot/linePlot.spec.ts +2 -2
  208. package/src/workspace/lineplot/payload.ts +1 -1
  209. package/src/workspace/lineplot/retriever.ts +4 -10
  210. package/src/workspace/lineplot/writer.ts +4 -4
  211. package/src/workspace/payload.ts +3 -6
  212. package/src/workspace/retriever.ts +4 -8
  213. package/src/workspace/schematic/client.ts +2 -2
  214. package/src/workspace/schematic/external.ts +2 -2
  215. package/src/workspace/schematic/index.ts +1 -1
  216. package/src/workspace/schematic/payload.ts +1 -1
  217. package/src/workspace/schematic/retriever.ts +17 -18
  218. package/src/workspace/schematic/schematic.spec.ts +2 -2
  219. package/src/workspace/schematic/writer.ts +5 -5
  220. package/src/workspace/workspace.spec.ts +2 -2
  221. package/src/workspace/writer.ts +3 -3
  222. package/vite.config.ts +3 -4
  223. package/.eslintrc.cjs +0 -18
  224. package/dist/client.cjs.map +0 -1
  225. package/dist/client.js.map +0 -1
  226. package/dist/control/authority.d.ts +0 -8
  227. package/dist/control/authority.d.ts.map +0 -1
  228. package/src/control/authority.ts +0 -26
@@ -0,0 +1,129 @@
1
+ // Copyright 2024 Synnax Labs, Inc.
2
+ //
3
+ // Use of this software is governed by the Business Source License included in the file
4
+ // licenses/BSL.txt.
5
+ //
6
+ // As of the Change Date specified in that file, in accordance with the Business Source
7
+ // License, use of this software will be governed by the Apache License, Version 2.0,
8
+ // included in the file licenses/APL.txt.
9
+
10
+ import { DataType, Rate, TimeRange, TimeStamp } from "@synnaxlabs/x/telem";
11
+ import { describe, expect, test } from "vitest";
12
+ import { NotFoundError, UnauthorizedError } from "@/errors"
13
+
14
+ import { type channel } from "@/channel";
15
+ import { newClient } from "@/setupspecs";
16
+ import { randomSeries } from "@/util/telem";
17
+
18
+ const client = newClient();
19
+
20
+ const newChannel = async (): Promise<channel.Channel> =>
21
+ await client.channels.create({
22
+ name: "test",
23
+ leaseholder: 1,
24
+ rate: Rate.hz(1),
25
+ dataType: DataType.FLOAT64,
26
+ });
27
+
28
+ const newIndexDataChannelPair = async (): Promise<channel.Channel[]> => {
29
+ const ind = await client.channels.create({
30
+ name: "index",
31
+ leaseholder: 1,
32
+ isIndex: true,
33
+ dataType: DataType.TIMESTAMP,
34
+ })
35
+ const data = await client.channels.create({
36
+ name: "data",
37
+ leaseholder: 1,
38
+ index: ind.key,
39
+ dataType: DataType.INT64,
40
+ })
41
+
42
+ return [ind, data]
43
+ }
44
+
45
+ describe("Deleter", () => {
46
+ test("Client - basic delete", async () => {
47
+ const ch = await newChannel();
48
+ const data = randomSeries(10, ch.dataType);
49
+ await client.write(TimeStamp.seconds(0), ch.key, data);
50
+
51
+ await client.delete(ch.key, TimeStamp.seconds(2).range(TimeStamp.seconds(5)))
52
+
53
+ const res = await client.read(TimeRange.MAX, ch.key);
54
+ expect(res.length).toEqual(data.length - 3);
55
+ expect(res.data.slice(0, 2)).toEqual(data.slice(0, 2))
56
+ expect(res.data.slice(2)).toEqual(data.slice(5))
57
+ });
58
+ test("Client - basic delete by name", async () => {
59
+ const ch = await newChannel()
60
+ const data = randomSeries(10, ch.dataType);
61
+ await client.write(TimeStamp.seconds(0), ch.key, data);
62
+
63
+ await client.delete(ch.name, TimeStamp.seconds(2).range(TimeStamp.seconds(5)))
64
+
65
+ const res = await client.read(TimeRange.MAX, ch.key);
66
+ expect(res.length).toEqual(data.length - 3);
67
+ expect(res.data.slice(0, 2)).toEqual(data.slice(0, 2))
68
+ expect(res.data.slice(2)).toEqual(data.slice(5))
69
+ })
70
+ test("Client - delete name not found", async () => {
71
+ const ch = await newChannel();
72
+ const data = randomSeries(10, ch.dataType);
73
+ await client.write(TimeStamp.seconds(0), ch.key, data);
74
+
75
+ await expect(
76
+ client.delete(["billy bob", ch.name], TimeRange.MAX)
77
+ ).rejects.toThrow(NotFoundError)
78
+
79
+ const res = await client.read(TimeRange.MAX, ch.key);
80
+ expect(res.data).toEqual(data);
81
+ })
82
+ test("Client - delete key not found", async () => {
83
+ const ch = await newChannel();
84
+ const data = randomSeries(10, ch.dataType);
85
+ await client.write(TimeStamp.seconds(0), ch.key, data);
86
+
87
+ await expect(
88
+ client.delete([ch.key, 1232], TimeRange.MAX)
89
+ ).rejects.toThrow(NotFoundError)
90
+
91
+ const res = await client.read(TimeRange.MAX, ch.key);
92
+ expect(res.data).toEqual(data);
93
+ })
94
+
95
+ test("Client - delete with writer", async () => {
96
+ const ch = await newChannel();
97
+
98
+ const writer = await client.openWriter({
99
+ start: TimeStamp.seconds(10),
100
+ channels: [ch.key],
101
+ });
102
+
103
+ await expect(
104
+ client.delete(
105
+ [ch.key], TimeStamp.seconds(12).range(TimeStamp.seconds(30)))
106
+ ).rejects.toThrow(UnauthorizedError)
107
+
108
+ await writer.close()
109
+ })
110
+
111
+ test("Client - delete index channel alone", async () => {
112
+ const chs = await newIndexDataChannelPair()
113
+ const index = chs[0]
114
+ const dat = chs[1]
115
+ const data = randomSeries(10, dat.dataType)
116
+
117
+ const time = BigInt64Array.from({ length: 10 },
118
+ (_, i) => (TimeStamp.milliseconds(i)).valueOf());
119
+
120
+ await index.write(0, time)
121
+ await dat.write(0, data)
122
+
123
+ await expect(
124
+ client.delete(
125
+ [index.key], TimeStamp.milliseconds(2).range(TimeStamp.milliseconds(5))
126
+ )
127
+ ).rejects.toThrow()
128
+ })
129
+ });
@@ -0,0 +1,49 @@
1
+ // Copyright 2024 Synnax Labs, Inc.
2
+ //
3
+ // Use of this software is governed by the Business Source License included in the file
4
+ // licenses/BSL.txt.
5
+ //
6
+ // As of the Change Date specified in that file, in accordance with the Business Source
7
+ // License, use of this software will be governed by the Apache License, Version 2.0,
8
+ // included in the file licenses/APL.txt.
9
+
10
+ import { sendRequired, UnaryClient } from "@synnaxlabs/freighter";
11
+ import { TimeRange } from "@synnaxlabs/x";
12
+ import { z } from "zod";
13
+
14
+ import { keyZ } from "@/channel/payload";
15
+
16
+ const reqZ = z.object({
17
+ keys: keyZ.array().optional(),
18
+ names: z.string().array().optional(),
19
+ bounds: TimeRange.z,
20
+ });
21
+
22
+ type RequestProps = z.infer<typeof reqZ>;
23
+
24
+ const resZ = z.object({});
25
+
26
+ const ENDPOINT = "/frame/delete";
27
+
28
+ export class Deleter {
29
+ /*
30
+ Deleter is used to delete a time range of telemetry from the data engine.
31
+ */
32
+ private readonly client: UnaryClient;
33
+
34
+ constructor(
35
+ client: UnaryClient,
36
+ ) {
37
+ this.client = client;
38
+ }
39
+
40
+ async delete(props: RequestProps): Promise<void> {
41
+ await sendRequired<typeof reqZ, typeof resZ>(
42
+ this.client,
43
+ ENDPOINT,
44
+ props,
45
+ reqZ,
46
+ resZ,
47
+ );
48
+ }
49
+ }
@@ -1,4 +1,4 @@
1
- // Copyright 2023 Synnax Labs, Inc.
1
+ // Copyright 2024 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.
@@ -1,4 +1,4 @@
1
- // Copyright 2023 Synnax Labs, Inc.
1
+ // Copyright 2024 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.
@@ -1,4 +1,4 @@
1
- // Copyright 2023 Synnax Labs, Inc.
1
+ // Copyright 2024 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.
@@ -8,13 +8,13 @@
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
10
  import {
11
- Size,
11
+ DataType,
12
+ MultiSeries,
12
13
  Series,
14
+ Size,
15
+ type TelemValue,
13
16
  TimeRange,
14
- DataType,
15
17
  TimeStamp,
16
- type TelemValue,
17
- MultiSeries,
18
18
  } from "@synnaxlabs/x/telem";
19
19
  import { toArray } from "@synnaxlabs/x/toArray";
20
20
  import { unique } from "@synnaxlabs/x/unique";
@@ -60,7 +60,7 @@ export type CrudeFrame =
60
60
  | Record<KeyOrName, Series[] | Series>;
61
61
 
62
62
  /**
63
- * A frame is a collection of related typed arrays keyed to a particular channel. Frames
63
+ * A frame is a collection of series mapped to a particular channel. Frames
64
64
  * can be keyed by channel name or channel key, but not both.
65
65
  *
66
66
  * Frames have two important characteristics: alignment and orientation.
@@ -283,10 +283,10 @@ export class Frame {
283
283
  }
284
284
 
285
285
  /**
286
- * Pushes a set of typed arrays for the given channel onto the frame.
286
+ * Pushes a set of series for the given channel onto the frame.
287
287
  *
288
288
  * @param key the channel key or name;
289
- * @param v the typed arrays to push.
289
+ * @param v the series to push.
290
290
  */
291
291
  push(key: KeyOrName, ...v: Series[]): void;
292
292
 
@@ -316,7 +316,7 @@ export class Frame {
316
316
  }
317
317
 
318
318
  /**
319
- * @returns a shallow copy of this frame containing all typed arrays in the current frame and the
319
+ * @returns a shallow copy of this frame containing all series in the current frame and the
320
320
  * provided frame.
321
321
  */
322
322
  concat(frame: Frame): Frame {
@@ -338,7 +338,7 @@ export class Frame {
338
338
 
339
339
  /**
340
340
  * @returns a new frame containing the mapped output of the provided function.
341
- * @param fn a function that takes a channel key and typed array and returns a
341
+ * @param fn a function that takes a channel key and series and returns a
342
342
  * boolean.
343
343
  */
344
344
  map(fn: (k: KeyOrName, arr: Series, i: number) => [KeyOrName, Series]): Frame {
@@ -348,9 +348,9 @@ export class Frame {
348
348
  }
349
349
 
350
350
  /**
351
- * Iterates over all typed arrays in the current frame.
351
+ * Iterates over all series in the current frame.
352
352
  *
353
- * @param fn a function that takes a channel key and typed array.
353
+ * @param fn a function that takes a channel key and series.
354
354
  */
355
355
  forEach(fn: (k: KeyOrName, arr: Series, i: number) => void): void {
356
356
  this.columns.forEach((k, i) => {
@@ -372,9 +372,9 @@ export class Frame {
372
372
  }
373
373
 
374
374
  /**
375
- * @returns a new frame containing all typed arrays in the current frame that pass
375
+ * @returns a new frame containing all series in the current frame that pass
376
376
  * the provided filter function.
377
- * @param fn a function that takes a channel key and typed array and returns a boolean.
377
+ * @param fn a function that takes a channel key and series and returns a boolean.
378
378
  */
379
379
  filter(fn: (k: KeyOrName, arr: Series, i: number) => boolean): Frame {
380
380
  const frame = new Frame();
@@ -1,4 +1,4 @@
1
- // Copyright 2023 Synnax Labs, Inc.
1
+ // Copyright 2024 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.
@@ -1,4 +1,4 @@
1
- // Copyright 2023 Synnax Labs, Inc.
1
+ // Copyright 2024 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.
@@ -8,7 +8,7 @@
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
10
  import { DataType, Rate, TimeRange, TimeSpan, TimeStamp } from "@synnaxlabs/x/telem";
11
- import { describe, test, expect } from "vitest";
11
+ import { describe, expect,test } from "vitest";
12
12
 
13
13
  import { type channel } from "@/channel";
14
14
  import { newClient } from "@/setupspecs";
@@ -1,4 +1,4 @@
1
- // Copyright 2023 Synnax Labs, Inc.
1
+ // Copyright 2024 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.
@@ -9,12 +9,12 @@
9
9
 
10
10
  import { errorZ, type Stream, type StreamClient } from "@synnaxlabs/freighter";
11
11
  import {
12
+ type CrudeTimeRange,
12
13
  type CrudeTimeSpan,
13
14
  type CrudeTimeStamp,
14
15
  TimeRange,
15
16
  TimeSpan,
16
17
  TimeStamp,
17
- type CrudeTimeRange,
18
18
  } from "@synnaxlabs/x/telem";
19
19
  import { z } from "zod";
20
20
 
@@ -1,4 +1,4 @@
1
- // Copyright 2023 Synnax Labs, Inc.
1
+ // Copyright 2024 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.
@@ -7,11 +7,9 @@
7
7
  // License, use of this software will be governed by the Apache License, Version 2.0,
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
- import { type Stream, EOF } from "@synnaxlabs/freighter";
10
+ import { EOF, type Stream } from "@synnaxlabs/freighter";
11
11
  import { type z } from "zod";
12
12
 
13
- import { UnexpectedError } from "@/errors";
14
-
15
13
  export class StreamProxy<RQ extends z.ZodTypeAny, RS extends z.ZodTypeAny> {
16
14
  readonly name: string;
17
15
  private readonly stream: Stream<RQ, RS>;
@@ -1,4 +1,4 @@
1
- // Copyright 2023 Synnax Labs, Inc.
1
+ // Copyright 2024 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.
@@ -7,8 +7,8 @@
7
7
  // License, use of this software will be governed by the Apache License, Version 2.0,
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
- import { describe, test, expect, it } from "vitest";
11
10
  import { DataType, Rate, TimeStamp } from "@synnaxlabs/x/telem";
11
+ import { describe, expect, it,test } from "vitest";
12
12
 
13
13
  import { type channel } from "@/channel";
14
14
  import { newClient } from "@/setupspecs";
@@ -1,4 +1,4 @@
1
- // Copyright 2023 Synnax Labs, Inc.
1
+ // Copyright 2024 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.
@@ -7,9 +7,9 @@
7
7
  // License, use of this software will be governed by the Apache License, Version 2.0,
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
- import { errorZ, type Stream, type StreamClient } from "@synnaxlabs/freighter";
10
+ import { EOF, errorZ, type Stream, type StreamClient } from "@synnaxlabs/freighter";
11
11
  import { observe } from "@synnaxlabs/x";
12
- import { TimeStamp, type CrudeTimeStamp } from "@synnaxlabs/x/telem";
12
+ import { type CrudeTimeStamp, TimeStamp } from "@synnaxlabs/x/telem";
13
13
  import { z } from "zod";
14
14
 
15
15
  import { type Key, type Params } from "@/channel/payload";
@@ -67,8 +67,9 @@ export class Streamer implements AsyncIterator<Frame>, AsyncIterable<Frame> {
67
67
  try {
68
68
  const frame = await this.read();
69
69
  return { done: false, value: frame };
70
- } catch (EOF) {
71
- return { done: true, value: undefined };
70
+ } catch (err) {
71
+ if (err instanceof EOF) return { done: true, value: undefined };
72
+ throw err;
72
73
  }
73
74
  }
74
75
 
@@ -1,4 +1,4 @@
1
- // Copyright 2023 Synnax Labs, Inc.
1
+ // Copyright 2024 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.
@@ -11,6 +11,7 @@ import { DataType, Rate, TimeRange, TimeSpan, TimeStamp } from "@synnaxlabs/x/te
11
11
  import { describe, expect, test } from "vitest";
12
12
 
13
13
  import { type channel } from "@/channel";
14
+ import { UnauthorizedError } from "@/errors";
14
15
  import { ALWAYS_INDEX_PERSIST_ON_AUTO_COMMIT, WriterMode } from "@/framer/writer";
15
16
  import { newClient } from "@/setupspecs";
16
17
  import { randomSeries } from "@/util/telem";
@@ -113,6 +114,22 @@ describe("Writer", () => {
113
114
  }
114
115
  expect(true).toBeTruthy();
115
116
  });
117
+ test("write with errOnUnauthorized", async () => {
118
+ const ch = await newChannel();
119
+ const w1 = await client.openWriter({
120
+ start: 0,
121
+ channels: ch.key,
122
+ });
123
+
124
+ await expect(
125
+ client.openWriter({
126
+ start: 0,
127
+ channels: ch.key,
128
+ errOnUnauthorized: true,
129
+ }),
130
+ ).rejects.toThrow(UnauthorizedError);
131
+ await w1.close();
132
+ });
116
133
  });
117
134
  describe("Client", () => {
118
135
  test("Client - basic write", async () => {
@@ -1,4 +1,4 @@
1
- // Copyright 2023 Synnax Labs, Inc.
1
+ // Copyright 2024 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.
@@ -7,32 +7,27 @@
7
7
  // License, use of this software will be governed by the Apache License, Version 2.0,
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
- /* eslint-disable @typescript-eslint/no-throw-literal */
11
10
  import type { Stream, StreamClient } from "@synnaxlabs/freighter";
12
11
  import { decodeError, errorZ } from "@synnaxlabs/freighter";
12
+ import { control } from "@synnaxlabs/x";
13
13
  import {
14
- TimeStamp,
15
- type CrudeTimeStamp,
16
14
  type CrudeSeries,
15
+ type CrudeTimeStamp,
17
16
  TimeSpan,
17
+ TimeStamp,
18
18
  } from "@synnaxlabs/x/telem";
19
19
  import { toArray } from "@synnaxlabs/x/toArray";
20
20
  import { z } from "zod";
21
21
 
22
22
  import {
23
- type KeysOrNames,
24
23
  type Key,
25
24
  type KeyOrName,
25
+ type KeysOrNames,
26
26
  type Params,
27
27
  } from "@/channel/payload";
28
28
  import { type Retriever } from "@/channel/retriever";
29
- import { Authority } from "@/control/authority";
30
- import {
31
- subjectZ as controlSubjectZ,
32
- type Subject as ControlSubject,
33
- } from "@/control/state";
34
29
  import { WriteFrameAdapter } from "@/framer/adapter";
35
- import { frameZ, type CrudeFrame } from "@/framer/frame";
30
+ import { type CrudeFrame, frameZ } from "@/framer/frame";
36
31
  import { StreamProxy } from "@/framer/streamProxy";
37
32
 
38
33
  enum Command {
@@ -41,7 +36,6 @@ enum Command {
41
36
  Commit = 2,
42
37
  Error = 3,
43
38
  SetAuthority = 4,
44
- SetMode = 5,
45
39
  }
46
40
 
47
41
  export enum WriterMode {
@@ -54,10 +48,11 @@ export const ALWAYS_INDEX_PERSIST_ON_AUTO_COMMIT: TimeSpan = new TimeSpan(-1);
54
48
 
55
49
  const netConfigZ = z.object({
56
50
  start: TimeStamp.z.optional(),
57
- controlSubject: controlSubjectZ.optional(),
51
+ controlSubject: control.subjectZ.optional(),
58
52
  keys: z.number().array().optional(),
59
- authorities: Authority.z.array().optional(),
53
+ authorities: control.Authority.z.array().optional(),
60
54
  mode: z.nativeEnum(WriterMode).optional(),
55
+ errOnUnauthorized: z.boolean().optional(),
61
56
  enableAutoCommit: z.boolean().optional(),
62
57
  autoIndexPersistInterval: TimeSpan.z.optional(),
63
58
  });
@@ -84,14 +79,17 @@ export interface WriterConfig {
84
79
  // start sets the starting timestamp for the first sample in the writer.
85
80
  start?: CrudeTimeStamp;
86
81
  // controlSubject sets the control subject of the writer.
87
- controlSubject?: ControlSubject;
82
+ controlSubject?: control.Subject;
88
83
  // authorities set the control authority to set for each channel on the writer.
89
84
  // Defaults to absolute authority. If not working with concurrent control,
90
85
  // it's best to leave this as the default.
91
- authorities?: Authority | Authority[];
86
+ authorities?: control.Authority | control.Authority[];
92
87
  // mode sets the persistence and streaming mode of the writer. The default
93
88
  // mode is WriterModePersistStream.
94
89
  mode?: WriterMode;
90
+ // errOnUnauthorized sets whether the writer raises an error when it attempts to write
91
+ // to a channel without permission.
92
+ errOnUnauthorized?: boolean,
95
93
  // enableAutoCommit determines whether the writer will automatically commit.
96
94
  // If enableAutoCommit is true, then the writer will commit after each write, and
97
95
  // will flush that commit to index after the specified autoIndexPersistInterval.
@@ -159,9 +157,10 @@ export class Writer {
159
157
  {
160
158
  channels,
161
159
  start = TimeStamp.now(),
162
- authorities = Authority.Absolute,
160
+ authorities = control.Authority.Absolute,
163
161
  controlSubject: subject,
164
162
  mode = WriterMode.PersistStream,
163
+ errOnUnauthorized = false,
165
164
  enableAutoCommit = false,
166
165
  autoIndexPersistInterval = TimeSpan.SECOND,
167
166
  }: WriterConfig,
@@ -177,6 +176,7 @@ export class Writer {
177
176
  controlSubject: subject,
178
177
  authorities: toArray(authorities),
179
178
  mode,
179
+ errOnUnauthorized,
180
180
  enableAutoCommit,
181
181
  autoIndexPersistInterval,
182
182
  },
@@ -219,7 +219,7 @@ export class Writer {
219
219
  return true;
220
220
  }
221
221
 
222
- async setAuthority(value: Record<Key, Authority>): Promise<boolean> {
222
+ async setAuthority(value: Record<Key, control.Authority>): Promise<boolean> {
223
223
  const res = await this.execute({
224
224
  command: Command.SetAuthority,
225
225
  config: {
@@ -230,14 +230,6 @@ export class Writer {
230
230
  return res.ack;
231
231
  }
232
232
 
233
- async setMode(mode: WriterMode): Promise<boolean> {
234
- const res = await this.execute({
235
- command: Command.SetMode,
236
- config: { mode },
237
- });
238
- return res.ack;
239
- }
240
-
241
233
  /**
242
234
  * Commits the written frames to the database. Commit is synchronous, meaning that it
243
235
  * will not return until all frames have been commited to the database.
@@ -272,7 +264,7 @@ export class Writer {
272
264
  }
273
265
 
274
266
  async execute(req: Request): Promise<Response> {
275
- // @ts-expect-error
267
+ // @ts-expect-error - frame payload adjustments
276
268
  this.stream.send(req);
277
269
  while (true) {
278
270
  const res = await this.stream.receive();
@@ -7,8 +7,8 @@
7
7
  // License, use of this software will be governed by the Apache License, Version 2.0,
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
- import { type UnaryClient, sendRequired } from "@synnaxlabs/freighter";
11
- import { type UnknownRecord, toArray } from "@synnaxlabs/x";
10
+ import { sendRequired,type UnaryClient } from "@synnaxlabs/freighter";
11
+ import { toArray,type UnknownRecord } from "@synnaxlabs/x";
12
12
  import { binary } from "@synnaxlabs/x/binary";
13
13
  import { type AsyncTermSearcher } from "@synnaxlabs/x/search";
14
14
  import { z } from "zod";
@@ -1,4 +1,4 @@
1
- // Copyright 2023 Synnax Labs, Inc.
1
+ // Copyright 2024 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.
@@ -1,4 +1,4 @@
1
- // Copyright 2023 Synnax Labs, Inc.
1
+ // Copyright 2024 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.
@@ -1,4 +1,4 @@
1
- // Copyright 2023 Synnax Labs, Inc.
1
+ // Copyright 2024 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.
@@ -22,7 +22,7 @@ describe("Rack", () => {
22
22
  expect(r.key).toBeGreaterThan(0n);
23
23
  });
24
24
  it("should return an error if the rack doesn't have a name", async () => {
25
- // @ts-expect-error
25
+ // @ts-expect-error - Testing for error
26
26
  await expect(client.hardware.racks.create({})).rejects.toThrow(ZodError);
27
27
  });
28
28
  });
@@ -7,11 +7,11 @@
7
7
  // License, use of this software will be governed by the Apache License, Version 2.0,
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
- import { type UnaryClient, sendRequired } from "@synnaxlabs/freighter";
10
+ import { sendRequired,type UnaryClient } from "@synnaxlabs/freighter";
11
11
  import { binary, type observe } from "@synnaxlabs/x";
12
12
  import { type UnknownRecord } from "@synnaxlabs/x/record";
13
13
  import { type AsyncTermSearcher } from "@synnaxlabs/x/search";
14
- import { TimeSpan, type CrudeTimeSpan } from "@synnaxlabs/x/telem";
14
+ import { type CrudeTimeSpan,TimeSpan } from "@synnaxlabs/x/telem";
15
15
  import { toArray } from "@synnaxlabs/x/toArray";
16
16
  import { nanoid } from "nanoid";
17
17
  import { z } from "zod";
@@ -316,7 +316,7 @@ export class Client implements AsyncTermSearcher<string, TaskKey, Payload> {
316
316
  { number: "rack", string: "keys" },
317
317
  { convertNumericStrings: false },
318
318
  );
319
- let req: RetrieveRequest = { ...options };
319
+ const req: RetrieveRequest = { ...options };
320
320
  if (variant === "rack") req.rack = rack as number;
321
321
  else req.keys = normalized as string[];
322
322
  const tasks = await this.execRetrieve(req);
@@ -7,11 +7,11 @@
7
7
  // License, use of this software will be governed by the Apache License, Version 2.0,
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
+ import { nanoid } from "nanoid";
10
11
  import { describe, expect, it } from "vitest";
11
12
 
12
- import { newClient } from "@/setupspecs";
13
13
  import { task } from "@/hardware/task";
14
- import { nanoid } from "nanoid";
14
+ import { newClient } from "@/setupspecs";
15
15
 
16
16
  const client = newClient();
17
17