@synnaxlabs/client 0.38.0 → 0.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/.turbo/turbo-build.log +7 -7
  2. package/dist/access/payload.d.ts +6 -6
  3. package/dist/access/payload.d.ts.map +1 -1
  4. package/dist/access/policy/client.d.ts +5 -3
  5. package/dist/access/policy/client.d.ts.map +1 -1
  6. package/dist/access/policy/external.d.ts +1 -0
  7. package/dist/access/policy/external.d.ts.map +1 -1
  8. package/dist/access/policy/ontology.d.ts +5 -0
  9. package/dist/access/policy/ontology.d.ts.map +1 -0
  10. package/dist/access/policy/payload.d.ts +86 -89
  11. package/dist/access/policy/payload.d.ts.map +1 -1
  12. package/dist/access/policy/retriever.d.ts +7 -6
  13. package/dist/access/policy/retriever.d.ts.map +1 -1
  14. package/dist/access/policy/writer.d.ts +2 -2
  15. package/dist/access/policy/writer.d.ts.map +1 -1
  16. package/dist/auth/auth.d.ts +2 -1
  17. package/dist/auth/auth.d.ts.map +1 -1
  18. package/dist/channel/client.d.ts +8 -7
  19. package/dist/channel/client.d.ts.map +1 -1
  20. package/dist/channel/payload.d.ts +13 -11
  21. package/dist/channel/payload.d.ts.map +1 -1
  22. package/dist/channel/retriever.d.ts +9 -6
  23. package/dist/channel/retriever.d.ts.map +1 -1
  24. package/dist/channel/writer.d.ts +6 -4
  25. package/dist/channel/writer.d.ts.map +1 -1
  26. package/dist/client.cjs +30 -30
  27. package/dist/client.d.ts +4 -2
  28. package/dist/client.d.ts.map +1 -1
  29. package/dist/client.js +3488 -3500
  30. package/dist/connection/checker.d.ts +5 -4
  31. package/dist/connection/checker.d.ts.map +1 -1
  32. package/dist/control/state.d.ts +10 -8
  33. package/dist/control/state.d.ts.map +1 -1
  34. package/dist/errors.d.ts +5 -0
  35. package/dist/errors.d.ts.map +1 -1
  36. package/dist/framer/adapter.d.ts +14 -15
  37. package/dist/framer/adapter.d.ts.map +1 -1
  38. package/dist/framer/client.d.ts +13 -15
  39. package/dist/framer/client.d.ts.map +1 -1
  40. package/dist/framer/deleter.d.ts +3 -2
  41. package/dist/framer/deleter.d.ts.map +1 -1
  42. package/dist/framer/frame.d.ts +31 -27
  43. package/dist/framer/frame.d.ts.map +1 -1
  44. package/dist/framer/iterator.d.ts +4 -5
  45. package/dist/framer/iterator.d.ts.map +1 -1
  46. package/dist/framer/streamer.d.ts +5 -6
  47. package/dist/framer/streamer.d.ts.map +1 -1
  48. package/dist/framer/writer.d.ts +42 -39
  49. package/dist/framer/writer.d.ts.map +1 -1
  50. package/dist/hardware/device/client.d.ts +17 -12
  51. package/dist/hardware/device/client.d.ts.map +1 -1
  52. package/dist/hardware/device/payload.d.ts +19 -16
  53. package/dist/hardware/device/payload.d.ts.map +1 -1
  54. package/dist/hardware/rack/client.d.ts +15 -15
  55. package/dist/hardware/rack/client.d.ts.map +1 -1
  56. package/dist/hardware/rack/payload.d.ts +9 -8
  57. package/dist/hardware/rack/payload.d.ts.map +1 -1
  58. package/dist/hardware/task/client.d.ts +38 -29
  59. package/dist/hardware/task/client.d.ts.map +1 -1
  60. package/dist/hardware/task/payload.d.ts +58 -53
  61. package/dist/hardware/task/payload.d.ts.map +1 -1
  62. package/dist/label/client.d.ts +4 -3
  63. package/dist/label/client.d.ts.map +1 -1
  64. package/dist/label/payload.d.ts +4 -4
  65. package/dist/label/payload.d.ts.map +1 -1
  66. package/dist/label/retriever.d.ts.map +1 -1
  67. package/dist/label/writer.d.ts +13 -10
  68. package/dist/label/writer.d.ts.map +1 -1
  69. package/dist/ontology/client.d.ts +12 -10
  70. package/dist/ontology/client.d.ts.map +1 -1
  71. package/dist/ontology/group/client.d.ts +5 -4
  72. package/dist/ontology/group/client.d.ts.map +1 -1
  73. package/dist/ontology/group/group.d.ts +7 -5
  74. package/dist/ontology/group/group.d.ts.map +1 -1
  75. package/dist/ontology/group/payload.d.ts +6 -5
  76. package/dist/ontology/group/payload.d.ts.map +1 -1
  77. package/dist/ontology/group/writer.d.ts +8 -8
  78. package/dist/ontology/group/writer.d.ts.map +1 -1
  79. package/dist/ontology/payload.d.ts +72 -62
  80. package/dist/ontology/payload.d.ts.map +1 -1
  81. package/dist/ontology/writer.d.ts.map +1 -1
  82. package/dist/ranger/alias.d.ts +9 -10
  83. package/dist/ranger/alias.d.ts.map +1 -1
  84. package/dist/ranger/client.d.ts +18 -18
  85. package/dist/ranger/client.d.ts.map +1 -1
  86. package/dist/ranger/external.d.ts +1 -1
  87. package/dist/ranger/external.d.ts.map +1 -1
  88. package/dist/ranger/kv.d.ts +18 -14
  89. package/dist/ranger/kv.d.ts.map +1 -1
  90. package/dist/ranger/payload.d.ts +13 -13
  91. package/dist/ranger/payload.d.ts.map +1 -1
  92. package/dist/ranger/writer.d.ts +14 -14
  93. package/dist/ranger/writer.d.ts.map +1 -1
  94. package/dist/setupspecs.d.ts.map +1 -1
  95. package/dist/signals/observable.d.ts +3 -1
  96. package/dist/signals/observable.d.ts.map +1 -1
  97. package/dist/user/client.d.ts +5 -3
  98. package/dist/user/client.d.ts.map +1 -1
  99. package/dist/user/payload.d.ts +7 -6
  100. package/dist/user/payload.d.ts.map +1 -1
  101. package/dist/user/retriever.d.ts +2 -1
  102. package/dist/user/retriever.d.ts.map +1 -1
  103. package/dist/user/writer.d.ts +2 -2
  104. package/dist/user/writer.d.ts.map +1 -1
  105. package/dist/util/decodeJSONString.d.ts +3 -0
  106. package/dist/util/decodeJSONString.d.ts.map +1 -0
  107. package/dist/util/parseWithoutKeyConversion.d.ts +3 -0
  108. package/dist/util/parseWithoutKeyConversion.d.ts.map +1 -0
  109. package/dist/util/retrieve.d.ts +1 -1
  110. package/dist/util/retrieve.d.ts.map +1 -1
  111. package/dist/util/telem.d.ts.map +1 -1
  112. package/dist/util/zod.d.ts.map +1 -1
  113. package/dist/workspace/client.d.ts +6 -60
  114. package/dist/workspace/client.d.ts.map +1 -1
  115. package/dist/workspace/external.d.ts +3 -0
  116. package/dist/workspace/external.d.ts.map +1 -0
  117. package/dist/workspace/index.d.ts +1 -1
  118. package/dist/workspace/index.d.ts.map +1 -1
  119. package/dist/workspace/lineplot/client.d.ts +5 -44
  120. package/dist/workspace/lineplot/client.d.ts.map +1 -1
  121. package/dist/workspace/lineplot/external.d.ts +3 -0
  122. package/dist/workspace/lineplot/external.d.ts.map +1 -0
  123. package/dist/workspace/lineplot/index.d.ts +1 -1
  124. package/dist/workspace/lineplot/index.d.ts.map +1 -1
  125. package/dist/workspace/lineplot/payload.d.ts +45 -0
  126. package/dist/workspace/lineplot/payload.d.ts.map +1 -0
  127. package/dist/workspace/log/client.d.ts +5 -44
  128. package/dist/workspace/log/client.d.ts.map +1 -1
  129. package/dist/workspace/log/external.d.ts +3 -0
  130. package/dist/workspace/log/external.d.ts.map +1 -0
  131. package/dist/workspace/log/index.d.ts +1 -1
  132. package/dist/workspace/log/index.d.ts.map +1 -1
  133. package/dist/workspace/log/payload.d.ts +45 -0
  134. package/dist/workspace/log/payload.d.ts.map +1 -0
  135. package/dist/workspace/payload.d.ts +60 -0
  136. package/dist/workspace/payload.d.ts.map +1 -0
  137. package/dist/workspace/schematic/client.d.ts +5 -68
  138. package/dist/workspace/schematic/client.d.ts.map +1 -1
  139. package/dist/workspace/schematic/external.d.ts +3 -0
  140. package/dist/workspace/schematic/external.d.ts.map +1 -0
  141. package/dist/workspace/schematic/index.d.ts +1 -1
  142. package/dist/workspace/schematic/index.d.ts.map +1 -1
  143. package/dist/workspace/schematic/payload.d.ts +71 -0
  144. package/dist/workspace/schematic/payload.d.ts.map +1 -0
  145. package/dist/workspace/table/client.d.ts +5 -57
  146. package/dist/workspace/table/client.d.ts.map +1 -1
  147. package/dist/workspace/table/external.d.ts +3 -0
  148. package/dist/workspace/table/external.d.ts.map +1 -0
  149. package/dist/workspace/table/index.d.ts +1 -1
  150. package/dist/workspace/table/index.d.ts.map +1 -1
  151. package/dist/workspace/table/payload.d.ts +60 -0
  152. package/dist/workspace/table/payload.d.ts.map +1 -0
  153. package/eslint.config.js +1 -1
  154. package/examples/node/basicReadWrite.js +27 -27
  155. package/examples/node/liveStream.js +16 -16
  156. package/examples/node/seriesAndFrames.js +39 -39
  157. package/examples/node/streamWrite.js +48 -46
  158. package/package.json +14 -12
  159. package/src/access/client.ts +1 -1
  160. package/src/access/external.ts +1 -1
  161. package/src/access/index.ts +1 -1
  162. package/src/access/payload.ts +13 -13
  163. package/src/access/policy/client.ts +14 -13
  164. package/src/access/policy/external.ts +2 -1
  165. package/src/access/policy/index.ts +1 -1
  166. package/src/access/policy/ontology.ts +17 -0
  167. package/src/access/policy/payload.ts +8 -20
  168. package/src/access/policy/policy.spec.ts +17 -17
  169. package/src/access/policy/retriever.ts +3 -2
  170. package/src/access/policy/writer.ts +5 -5
  171. package/src/auth/auth.spec.ts +28 -24
  172. package/src/auth/auth.ts +8 -12
  173. package/src/auth/index.ts +1 -1
  174. package/src/channel/batchRetriever.spec.ts +26 -23
  175. package/src/channel/channel.spec.ts +1 -1
  176. package/src/channel/client.ts +24 -24
  177. package/src/channel/external.ts +1 -1
  178. package/src/channel/index.ts +1 -1
  179. package/src/channel/payload.ts +17 -21
  180. package/src/channel/retriever.ts +21 -22
  181. package/src/channel/writer.ts +12 -14
  182. package/src/client.ts +7 -17
  183. package/src/connection/checker.ts +10 -12
  184. package/src/connection/connection.spec.ts +18 -6
  185. package/src/connection/index.ts +1 -1
  186. package/src/control/client.ts +1 -1
  187. package/src/control/external.ts +1 -1
  188. package/src/control/index.ts +1 -1
  189. package/src/control/state.spec.ts +1 -1
  190. package/src/control/state.ts +9 -10
  191. package/src/errors.spec.ts +2 -2
  192. package/src/errors.ts +9 -1
  193. package/src/framer/adapter.spec.ts +29 -24
  194. package/src/framer/adapter.ts +38 -42
  195. package/src/framer/client.spec.ts +6 -12
  196. package/src/framer/client.ts +35 -39
  197. package/src/framer/deleter.spec.ts +1 -1
  198. package/src/framer/deleter.ts +6 -7
  199. package/src/framer/external.ts +1 -1
  200. package/src/framer/frame.spec.ts +1 -1
  201. package/src/framer/frame.ts +63 -51
  202. package/src/framer/index.ts +1 -1
  203. package/src/framer/iterator.spec.ts +1 -1
  204. package/src/framer/iterator.ts +12 -17
  205. package/src/framer/streamProxy.ts +2 -2
  206. package/src/framer/streamer.spec.ts +3 -11
  207. package/src/framer/streamer.ts +16 -20
  208. package/src/framer/writer.spec.ts +49 -8
  209. package/src/framer/writer.ts +40 -32
  210. package/src/hardware/client.ts +1 -1
  211. package/src/hardware/device/client.ts +65 -40
  212. package/src/hardware/device/device.spec.ts +50 -34
  213. package/src/hardware/device/external.ts +1 -1
  214. package/src/hardware/device/index.ts +1 -1
  215. package/src/hardware/device/payload.ts +30 -30
  216. package/src/hardware/external.ts +1 -1
  217. package/src/hardware/index.ts +1 -1
  218. package/src/hardware/rack/client.ts +53 -66
  219. package/src/hardware/rack/external.ts +1 -1
  220. package/src/hardware/rack/index.ts +1 -1
  221. package/src/hardware/rack/payload.ts +10 -19
  222. package/src/hardware/rack/rack.spec.ts +13 -1
  223. package/src/hardware/task/client.ts +161 -132
  224. package/src/hardware/task/external.ts +1 -1
  225. package/src/hardware/task/index.ts +1 -1
  226. package/src/hardware/task/payload.ts +50 -69
  227. package/src/hardware/task/task.spec.ts +99 -82
  228. package/src/index.ts +1 -1
  229. package/src/label/client.ts +13 -16
  230. package/src/label/external.ts +1 -1
  231. package/src/label/index.ts +1 -1
  232. package/src/label/label.spec.ts +1 -1
  233. package/src/label/payload.ts +4 -10
  234. package/src/label/retriever.ts +4 -8
  235. package/src/label/writer.ts +9 -16
  236. package/src/ontology/client.ts +31 -29
  237. package/src/ontology/external.ts +1 -1
  238. package/src/ontology/group/client.ts +6 -6
  239. package/src/ontology/group/external.ts +1 -1
  240. package/src/ontology/group/group.spec.ts +5 -5
  241. package/src/ontology/group/group.ts +11 -8
  242. package/src/ontology/group/index.ts +1 -1
  243. package/src/ontology/group/payload.ts +12 -36
  244. package/src/ontology/group/writer.ts +23 -27
  245. package/src/ontology/index.ts +1 -1
  246. package/src/ontology/ontology.spec.ts +16 -16
  247. package/src/ontology/payload.ts +68 -44
  248. package/src/ontology/writer.ts +17 -24
  249. package/src/ranger/alias.ts +26 -43
  250. package/src/ranger/client.ts +34 -41
  251. package/src/ranger/external.ts +2 -2
  252. package/src/ranger/index.ts +1 -1
  253. package/src/ranger/kv.ts +10 -33
  254. package/src/ranger/payload.ts +15 -37
  255. package/src/ranger/ranger.spec.ts +2 -3
  256. package/src/ranger/writer.ts +9 -27
  257. package/src/setupspecs.ts +1 -1
  258. package/src/signals/external.ts +1 -1
  259. package/src/signals/index.ts +1 -1
  260. package/src/signals/observable.ts +4 -5
  261. package/src/transport.ts +1 -1
  262. package/src/user/client.ts +9 -5
  263. package/src/user/external.ts +1 -1
  264. package/src/user/index.ts +1 -1
  265. package/src/user/payload.ts +6 -10
  266. package/src/user/retriever.ts +2 -2
  267. package/src/user/user.spec.ts +18 -16
  268. package/src/user/writer.ts +4 -11
  269. package/src/util/decodeJSONString.ts +13 -0
  270. package/src/util/parseWithoutKeyConversion.ts +19 -0
  271. package/src/util/retrieve.spec.ts +4 -14
  272. package/src/util/retrieve.ts +3 -13
  273. package/src/util/telem.ts +2 -2
  274. package/src/util/zod.ts +1 -1
  275. package/src/vite-env.d.ts +2 -1
  276. package/src/workspace/client.ts +39 -57
  277. package/src/workspace/external.ts +11 -0
  278. package/src/workspace/index.ts +2 -2
  279. package/src/workspace/lineplot/client.ts +31 -36
  280. package/src/workspace/lineplot/external.ts +11 -0
  281. package/src/workspace/lineplot/index.ts +2 -2
  282. package/src/workspace/lineplot/linePlot.spec.ts +2 -3
  283. package/src/workspace/lineplot/payload.ts +32 -0
  284. package/src/workspace/log/client.ts +34 -39
  285. package/src/workspace/log/external.ts +11 -0
  286. package/src/workspace/log/index.ts +2 -2
  287. package/src/workspace/log/log.spec.ts +6 -19
  288. package/src/workspace/log/payload.ts +32 -0
  289. package/src/workspace/payload.ts +36 -0
  290. package/src/workspace/schematic/client.ts +39 -56
  291. package/src/workspace/schematic/external.ts +11 -0
  292. package/src/workspace/schematic/index.ts +2 -2
  293. package/src/workspace/schematic/payload.ts +37 -0
  294. package/src/workspace/schematic/schematic.spec.ts +16 -7
  295. package/src/workspace/table/client.ts +36 -50
  296. package/src/workspace/table/external.ts +11 -0
  297. package/src/workspace/table/index.ts +2 -2
  298. package/src/workspace/table/payload.ts +36 -0
  299. package/src/workspace/table/table.spec.ts +1 -1
  300. package/src/workspace/workspace.spec.ts +2 -3
  301. package/vite.config.ts +1 -1
  302. package/dist/channel/creator.d.ts +0 -9
  303. package/dist/channel/creator.d.ts.map +0 -1
  304. package/src/channel/creator.ts +0 -37
@@ -1,4 +1,4 @@
1
- // Copyright 2024 Synnax Labs, Inc.
1
+ // Copyright 2025 Synnax Labs, Inc.
2
2
  //
3
3
  // Use of this software is governed by the Business Source License included in the file
4
4
  // licenses/BSL.txt.
@@ -20,20 +20,17 @@ import {
20
20
  } from "@synnaxlabs/x/telem";
21
21
  import { z } from "zod";
22
22
 
23
- import {
24
- type Key,
25
- type KeyOrName,
26
- type Keys,
27
- type Names,
28
- type Params,
29
- } from "@/channel/payload";
23
+ import { type channel } from "@/channel";
30
24
  import { UnexpectedError, ValidationError } from "@/errors";
31
25
 
26
+ export const ONTOLOGY_TYPE = "framer";
27
+ export type OntologyType = typeof ONTOLOGY_TYPE;
28
+
32
29
  type ColumnType = "key" | "name" | null;
33
30
 
34
- export interface FrameDigest extends Record<KeyOrName, SeriesDigest[]> {}
31
+ export interface Digest extends Record<channel.KeyOrName, SeriesDigest[]> {}
35
32
 
36
- const columnType = (columns: Params): ColumnType => {
33
+ const columnType = (columns: channel.Params): ColumnType => {
37
34
  const arrKeys = toArray(columns);
38
35
  if (arrKeys.length === 0) return null;
39
36
  if (typeof arrKeys[0] === "number") return "key";
@@ -41,7 +38,10 @@ const columnType = (columns: Params): ColumnType => {
41
38
  return "name";
42
39
  };
43
40
 
44
- const validateMatchedColsAndSeries = (columns: Params, series: Series[]): void => {
41
+ const validateMatchedColsAndSeries = (
42
+ columns: channel.Params,
43
+ series: Series[],
44
+ ): void => {
45
45
  const colsArr = toArray(columns);
46
46
  if (colsArr.length === series.length) return;
47
47
  const colType = columnType(columns);
@@ -55,11 +55,11 @@ const validateMatchedColsAndSeries = (columns: Params, series: Series[]): void =
55
55
  );
56
56
  };
57
57
 
58
- export type CrudeFrame =
58
+ export type Crude =
59
59
  | Frame
60
- | CrudeFramePayload
61
- | Map<KeyOrName, Series[] | Series>
62
- | Record<KeyOrName, Series[] | Series>;
60
+ | CrudePayload
61
+ | Map<channel.KeyOrName, Series[] | Series>
62
+ | Record<channel.KeyOrName, Series[] | Series>;
63
63
 
64
64
  /**
65
65
  * A frame is a collection of series mapped to a particular channel. Frames
@@ -97,10 +97,13 @@ export type CrudeFrame =
97
97
  * and array can be square.
98
98
  */
99
99
  export class Frame {
100
- readonly columns: Keys | Names = [];
100
+ readonly columns: channel.Keys | channel.Names = [];
101
101
  readonly series: Series[] = [];
102
102
 
103
- constructor(columnsOrData: Params | CrudeFrame = [], series: Series | Series[] = []) {
103
+ constructor(
104
+ columnsOrData: channel.Params | Crude = [],
105
+ series: Series | Series[] = [],
106
+ ) {
104
107
  if (columnsOrData instanceof Frame) {
105
108
  this.columns = columnsOrData.columns;
106
109
  this.series = columnsOrData.series;
@@ -118,7 +121,7 @@ export class Frame {
118
121
  // Construction from a payload.
119
122
  if (isObject) {
120
123
  if ("keys" in columnsOrData && "series" in columnsOrData) {
121
- const data_ = columnsOrData as FramePayload;
124
+ const data_ = columnsOrData as Payload;
122
125
  data_.series ??= [];
123
126
  data_.keys ??= [];
124
127
  const series = data_.series.map((a) => seriesFromPayload(a));
@@ -139,7 +142,7 @@ export class Frame {
139
142
  ["string", "number"].includes(typeof columnsOrData)
140
143
  ) {
141
144
  const data_ = toArray(series);
142
- const cols = toArray(columnsOrData) as Keys | Names;
145
+ const cols = toArray(columnsOrData) as channel.Keys | channel.Names;
143
146
  validateMatchedColsAndSeries(cols, data_);
144
147
  data_.forEach((d, i) => this.push(cols[i], d));
145
148
  return;
@@ -166,16 +169,16 @@ export class Frame {
166
169
  * @returns the channel keys if the frame is keyed by channel key, and throws an error
167
170
  * otherwise.
168
171
  */
169
- get keys(): Keys {
172
+ get keys(): channel.Keys {
170
173
  if (this.colType === "name") throw new UnexpectedError("colType is not key");
171
- return (this.columns as Keys) ?? [];
174
+ return (this.columns as channel.Keys) ?? [];
172
175
  }
173
176
 
174
177
  /**
175
178
  * @returns the unique channel keys if the frame is keyed by channel key, and throws an
176
179
  * error otherwise.
177
180
  */
178
- get uniqueKeys(): Keys {
181
+ get uniqueKeys(): channel.Keys {
179
182
  return unique.unique(this.keys);
180
183
  }
181
184
 
@@ -183,27 +186,27 @@ export class Frame {
183
186
  * @returns the channel names if the frame is keyed by channel name, and throws an error
184
187
  * otherwise.
185
188
  */
186
- get names(): Names {
189
+ get names(): channel.Names {
187
190
  if (this.colType === "key") throw new UnexpectedError("colType is not name");
188
- return (this.columns as Names) ?? [];
191
+ return (this.columns as channel.Names) ?? [];
189
192
  }
190
193
 
191
194
  /**
192
195
  * @returns the unique channel names if the frame is keyed by channel name, and throws an
193
196
  * otherwise.
194
197
  */
195
- get uniqueNames(): Names {
198
+ get uniqueNames(): channel.Names {
196
199
  return unique.unique(this.names);
197
200
  }
198
201
 
199
202
  /**
200
203
  * @returns the unique columns in the frame.
201
204
  */
202
- get uniqueColumns(): Keys | Names {
205
+ get uniqueColumns(): channel.Keys | channel.Names {
203
206
  return this.colType === "key" ? this.uniqueKeys : this.uniqueNames;
204
207
  }
205
208
 
206
- toPayload(): FramePayload {
209
+ toPayload(): Payload {
207
210
  return {
208
211
  series: this.series.map((a) => seriesToPayload(a)),
209
212
  keys: this.keys,
@@ -249,7 +252,7 @@ export class Frame {
249
252
  return ranges.every((tr) => tr.equals(ranges[0]));
250
253
  }
251
254
 
252
- timeRange(col?: KeyOrName): TimeRange {
255
+ timeRange(col?: channel.KeyOrName): TimeRange {
253
256
  if (col == null) {
254
257
  if (this.columns.length === 0) return TimeRange.ZERO;
255
258
  const start = TimeStamp.min(...this.series.map((a) => a.timeRange.start));
@@ -273,16 +276,17 @@ export class Frame {
273
276
  * @returns lazy series matching the given channel key or name.
274
277
  * @param key the channel key or name.
275
278
  */
276
- get(key: KeyOrName): MultiSeries;
279
+ get(key: channel.KeyOrName): MultiSeries;
277
280
 
278
281
  /**
279
282
  * @returns a frame with the given channel keys or names.
280
283
  * @param keys the channel keys or names.
281
284
  */
282
- get(keys: Keys | Names): Frame;
285
+ get(keys: channel.Keys | channel.Names): Frame;
283
286
 
284
- get(key: KeyOrName | Keys | Names): MultiSeries | Frame {
285
- if (Array.isArray(key)) return this.filter((k) => (key as Keys).includes(k as Key));
287
+ get(key: channel.KeyOrName | channel.Keys | channel.Names): MultiSeries | Frame {
288
+ if (Array.isArray(key))
289
+ return this.filter((k) => (key as channel.Keys).includes(k as channel.Key));
286
290
  return new MultiSeries(this.series.filter((_, i) => this.columns[i] === key));
287
291
  }
288
292
 
@@ -292,7 +296,7 @@ export class Frame {
292
296
  * @param key the channel key or name;
293
297
  * @param v the series to push.
294
298
  */
295
- push(key: KeyOrName, ...v: Series[]): void;
299
+ push(key: channel.KeyOrName, ...v: Series[]): void;
296
300
 
297
301
  /**
298
302
  * Pushes the frame onto the current frame.
@@ -301,20 +305,20 @@ export class Frame {
301
305
  */
302
306
  push(frame: Frame): void;
303
307
 
304
- push(keyOrFrame: KeyOrName | Frame, ...v: Series[]): void {
308
+ push(keyOrFrame: channel.KeyOrName | Frame, ...v: Series[]): void {
305
309
  if (keyOrFrame instanceof Frame) {
306
310
  if (this.colType !== null && keyOrFrame.colType !== this.colType)
307
311
  throw new ValidationError("keyVariant must match");
308
312
  this.series.push(...keyOrFrame.series);
309
- (this.columns as Keys).push(...(keyOrFrame.columns as Keys));
313
+ (this.columns as channel.Keys).push(...(keyOrFrame.columns as channel.Keys));
310
314
  } else {
311
315
  this.series.push(...v);
312
316
  if (typeof keyOrFrame === "string" && this.colType === "key")
313
317
  throw new ValidationError("keyVariant must match");
314
318
  else if (typeof keyOrFrame !== "string" && this.colType === "name")
315
319
  throw new ValidationError("keyVariant must match");
316
- (this.columns as Keys).push(
317
- ...(Array.from({ length: v.length }, () => keyOrFrame) as Keys),
320
+ (this.columns as channel.Keys).push(
321
+ ...(Array.from({ length: v.length }, () => keyOrFrame) as channel.Keys),
318
322
  );
319
323
  }
320
324
  }
@@ -324,7 +328,7 @@ export class Frame {
324
328
  * provided frame.
325
329
  */
326
330
  concat(frame: Frame): Frame {
327
- return new Frame([...this.columns, ...frame.columns] as Keys, [
331
+ return new Frame([...this.columns, ...frame.columns] as channel.Keys, [
328
332
  ...this.series,
329
333
  ...frame.series,
330
334
  ]);
@@ -334,10 +338,10 @@ export class Frame {
334
338
  * @returns true if the frame contains the provided channel key or name.
335
339
  * @param channel the channel key or name to check.
336
340
  */
337
- has(channel: KeyOrName): boolean {
341
+ has(channel: channel.KeyOrName): boolean {
338
342
  if (typeof channel === "string" && this.colType === "key") return false;
339
343
  if (typeof channel === "number" && this.colType === "name") return false;
340
- return (this.columns as Keys).includes(channel as Key);
344
+ return (this.columns as channel.Keys).includes(channel as channel.Key);
341
345
  }
342
346
 
343
347
  /**
@@ -345,7 +349,9 @@ export class Frame {
345
349
  * @param fn a function that takes a channel key and series and returns a
346
350
  * boolean.
347
351
  */
348
- map(fn: (k: KeyOrName, arr: Series, i: number) => [KeyOrName, Series]): Frame {
352
+ map(
353
+ fn: (k: channel.KeyOrName, arr: Series, i: number) => [channel.KeyOrName, Series],
354
+ ): Frame {
349
355
  const frame = new Frame();
350
356
  this.forEach((k, arr, i) => frame.push(...fn(k, arr, i)));
351
357
  return frame;
@@ -356,19 +362,25 @@ export class Frame {
356
362
  *
357
363
  * @param fn a function that takes a channel key and series.
358
364
  */
359
- forEach(fn: (k: KeyOrName, arr: Series, i: number) => void): void {
365
+ forEach(fn: (k: channel.KeyOrName, arr: Series, i: number) => void): void {
360
366
  this.columns.forEach((k, i) => {
361
367
  const a = this.series[i];
362
368
  fn(k, a, i);
363
369
  });
364
370
  }
365
371
 
366
- at(index: number, required: true): Record<KeyOrName, TelemValue>;
372
+ at(index: number, required: true): Record<channel.KeyOrName, TelemValue>;
367
373
 
368
- at(index: number, required?: false): Record<KeyOrName, TelemValue | undefined>;
374
+ at(
375
+ index: number,
376
+ required?: false,
377
+ ): Record<channel.KeyOrName, TelemValue | undefined>;
369
378
 
370
- at(index: number, required = false): Record<KeyOrName, TelemValue | undefined> {
371
- const res: Record<KeyOrName, TelemValue> = {};
379
+ at(
380
+ index: number,
381
+ required = false,
382
+ ): Record<channel.KeyOrName, TelemValue | undefined> {
383
+ const res: Record<channel.KeyOrName, TelemValue> = {};
372
384
  this.uniqueColumns.forEach((k) => {
373
385
  res[k] = this.get(k).at(index, required as true);
374
386
  });
@@ -380,7 +392,7 @@ export class Frame {
380
392
  * the provided filter function.
381
393
  * @param fn a function that takes a channel key and series and returns a boolean.
382
394
  */
383
- filter(fn: (k: KeyOrName, arr: Series, i: number) => boolean): Frame {
395
+ filter(fn: (k: channel.KeyOrName, arr: Series, i: number) => boolean): Frame {
384
396
  const frame = new Frame();
385
397
  this.columns.forEach((k, i) => {
386
398
  const a = this.series[i];
@@ -398,8 +410,8 @@ export class Frame {
398
410
  * @returns a digest of information about the structure of the frame for debugging
399
411
  * purposes.
400
412
  */
401
- get digest(): FrameDigest {
402
- const digest: FrameDigest = {};
413
+ get digest(): Digest {
414
+ const digest: Digest = {};
403
415
  this.keys.forEach((k, i) => {
404
416
  const sd = this.series[i].digest;
405
417
  if (k in digest) digest[k].push(sd);
@@ -425,9 +437,9 @@ export const frameZ = z.object({
425
437
  ]),
426
438
  });
427
439
 
428
- export type FramePayload = z.output<typeof frameZ>;
440
+ export interface Payload extends z.output<typeof frameZ> {}
429
441
 
430
- export type CrudeFramePayload = z.input<typeof frameZ>;
442
+ export interface CrudePayload extends z.input<typeof frameZ> {}
431
443
 
432
444
  export const seriesFromPayload = (series: SeriesPayload): Series => {
433
445
  const { dataType, data, timeRange, alignment } = series;
@@ -1,4 +1,4 @@
1
- // Copyright 2024 Synnax Labs, Inc.
1
+ // Copyright 2025 Synnax Labs, Inc.
2
2
  //
3
3
  // Use of this software is governed by the Business Source License included in the file
4
4
  // licenses/BSL.txt.
@@ -1,4 +1,4 @@
1
- // Copyright 2024 Synnax Labs, Inc.
1
+ // Copyright 2025 Synnax Labs, Inc.
2
2
  //
3
3
  // Use of this software is governed by the Business Source License included in the file
4
4
  // licenses/BSL.txt.
@@ -1,4 +1,4 @@
1
- // Copyright 2024 Synnax Labs, Inc.
1
+ // Copyright 2025 Synnax Labs, Inc.
2
2
  //
3
3
  // Use of this software is governed by the Business Source License included in the file
4
4
  // licenses/BSL.txt.
@@ -18,9 +18,8 @@ import {
18
18
  } from "@synnaxlabs/x/telem";
19
19
  import { z } from "zod";
20
20
 
21
- import { type Params } from "@/channel/payload";
22
- import { type Retriever } from "@/channel/retriever";
23
- import { ReadFrameAdapter } from "@/framer/adapter";
21
+ import { channel } from "@/channel";
22
+ import { ReadAdapter } from "@/framer/adapter";
24
23
  import { Frame, frameZ } from "@/framer/frame";
25
24
  import { StreamProxy } from "@/framer/streamProxy";
26
25
 
@@ -49,11 +48,10 @@ const reqZ = z.object({
49
48
  span: TimeSpan.z.optional(),
50
49
  bounds: TimeRange.z.optional(),
51
50
  stamp: TimeStamp.z.optional(),
52
- keys: z.number().array().optional(),
51
+ keys: channel.keyZ.array().optional(),
53
52
  chunkSize: z.number().optional(),
54
53
  });
55
-
56
- type Request = z.infer<typeof reqZ>;
54
+ interface Request extends z.infer<typeof reqZ> {}
57
55
 
58
56
  const resZ = z.object({
59
57
  variant: z.nativeEnum(ResponseVariant),
@@ -65,8 +63,8 @@ const resZ = z.object({
65
63
 
66
64
  export interface IteratorConfig {
67
65
  /** chunkSize is the maximum number of samples contained per channel in the frame
68
- * resulting from a call to next with {@link AUTO_SPAN}.
69
- */
66
+ * resulting from a call to next with {@link AUTO_SPAN}.
67
+ */
70
68
  chunkSize?: number;
71
69
  }
72
70
 
@@ -81,13 +79,10 @@ export interface IteratorConfig {
81
79
  export class Iterator {
82
80
  private static readonly ENDPOINT = "/frame/iterate";
83
81
  private readonly stream: StreamProxy<typeof reqZ, typeof resZ>;
84
- private readonly adapter: ReadFrameAdapter;
82
+ private readonly adapter: ReadAdapter;
85
83
  value: Frame;
86
84
 
87
- private constructor(
88
- stream: Stream<typeof reqZ, typeof resZ>,
89
- adapter: ReadFrameAdapter,
90
- ) {
85
+ private constructor(stream: Stream<typeof reqZ, typeof resZ>, adapter: ReadAdapter) {
91
86
  this.stream = new StreamProxy("Iterator", stream);
92
87
  this.value = new Frame();
93
88
  this.adapter = adapter;
@@ -106,12 +101,12 @@ export class Iterator {
106
101
  */
107
102
  static async _open(
108
103
  tr: CrudeTimeRange,
109
- channels: Params,
110
- retriever: Retriever,
104
+ channels: channel.Params,
105
+ retriever: channel.Retriever,
111
106
  client: StreamClient,
112
107
  opts: IteratorConfig = {},
113
108
  ): Promise<Iterator> {
114
- const adapter = await ReadFrameAdapter.open(retriever, channels);
109
+ const adapter = await ReadAdapter.open(retriever, channels);
115
110
  const stream = await client.stream(Iterator.ENDPOINT, reqZ, resZ);
116
111
  const iter = new Iterator(stream, adapter);
117
112
  await iter.execute({
@@ -1,4 +1,4 @@
1
- // Copyright 2024 Synnax Labs, Inc.
1
+ // Copyright 2025 Synnax Labs, Inc.
2
2
  //
3
3
  // Use of this software is governed by the Business Source License included in the file
4
4
  // licenses/BSL.txt.
@@ -35,7 +35,7 @@ export class StreamProxy<RQ extends z.ZodTypeAny, RS extends z.ZodTypeAny> {
35
35
  const [res, err] = await this.stream.receive();
36
36
  if (res != null)
37
37
  console.warn(
38
- `${this.name} received unexpected response on closure.
38
+ `${this.name} received unexpected response on closure.
39
39
  Please report this error to the Synnax team. ${JSON.stringify(res)}`,
40
40
  );
41
41
  if (err != null) {
@@ -1,4 +1,4 @@
1
- // Copyright 2024 Synnax Labs, Inc.
1
+ // Copyright 2025 Synnax Labs, Inc.
2
2
  //
3
3
  // Use of this software is governed by the Business Source License included in the file
4
4
  // licenses/BSL.txt.
@@ -239,16 +239,8 @@ describe("Streamer - Calculated Channels", () => {
239
239
 
240
240
  // Create source channels
241
241
  const [channelA, channelB] = await client.channels.create([
242
- {
243
- name: "multi_test_a",
244
- dataType: DataType.FLOAT64,
245
- index: timeChannel.key,
246
- },
247
- {
248
- name: "multi_test_b",
249
- dataType: DataType.FLOAT64,
250
- index: timeChannel.key,
251
- },
242
+ { name: "multi_test_a", dataType: DataType.FLOAT64, index: timeChannel.key },
243
+ { name: "multi_test_b", dataType: DataType.FLOAT64, index: timeChannel.key },
252
244
  ]);
253
245
 
254
246
  // Create calculated channel with multiple operations
@@ -1,4 +1,4 @@
1
- // Copyright 2024 Synnax Labs, Inc.
1
+ // Copyright 2025 Synnax Labs, Inc.
2
2
  //
3
3
  // Use of this software is governed by the Business Source License included in the file
4
4
  // licenses/BSL.txt.
@@ -11,50 +11,43 @@ import { EOF, errorZ, type Stream, type StreamClient } from "@synnaxlabs/freight
11
11
  import { observe } from "@synnaxlabs/x";
12
12
  import { z } from "zod";
13
13
 
14
- import { type Key, type Params } from "@/channel/payload";
15
- import { type Retriever } from "@/channel/retriever";
16
- import { ReadFrameAdapter } from "@/framer/adapter";
14
+ import { type channel } from "@/channel";
15
+ import { ReadAdapter } from "@/framer/adapter";
17
16
  import { Frame, frameZ } from "@/framer/frame";
18
17
  import { StreamProxy } from "@/framer/streamProxy";
19
18
 
20
- const reqZ = z.object({ keys: z.number().array() , downsampleFactor: z.number() });
19
+ const reqZ = z.object({ keys: z.number().array(), downsampleFactor: z.number() });
21
20
 
22
- const resZ = z.object({
23
- frame: frameZ,
24
- error: errorZ.optional().nullable(),
25
- });
21
+ const resZ = z.object({ frame: frameZ, error: errorZ.optional().nullable() });
26
22
 
27
23
  const ENDPOINT = "/frame/stream";
28
24
 
29
25
  export interface StreamerConfig {
30
- channels: Params;
26
+ channels: channel.Params;
31
27
  downsampleFactor?: number;
32
28
  }
33
29
 
34
30
  export class Streamer implements AsyncIterator<Frame>, AsyncIterable<Frame> {
35
31
  private readonly stream: StreamProxy<typeof reqZ, typeof resZ>;
36
- private readonly adapter: ReadFrameAdapter;
32
+ private readonly adapter: ReadAdapter;
37
33
  private readonly downsampleFactor: number;
38
34
 
39
- private constructor(
40
- stream: Stream<typeof reqZ, typeof resZ>,
41
- adapter: ReadFrameAdapter,
42
- ) {
35
+ private constructor(stream: Stream<typeof reqZ, typeof resZ>, adapter: ReadAdapter) {
43
36
  this.stream = new StreamProxy("Streamer", stream);
44
37
  this.adapter = adapter;
45
38
  this.downsampleFactor = 1;
46
39
  }
47
40
 
48
- get keys(): Key[] {
41
+ get keys(): channel.Key[] {
49
42
  return this.adapter.keys;
50
43
  }
51
44
 
52
45
  static async _open(
53
- retriever: Retriever,
46
+ retriever: channel.Retriever,
54
47
  client: StreamClient,
55
48
  { channels, downsampleFactor }: StreamerConfig,
56
49
  ): Promise<Streamer> {
57
- const adapter = await ReadFrameAdapter.open(retriever, channels);
50
+ const adapter = await ReadAdapter.open(retriever, channels);
58
51
  const stream = await client.stream(ENDPOINT, reqZ, resZ);
59
52
  const streamer = new Streamer(stream, adapter);
60
53
  stream.send({ keys: adapter.keys, downsampleFactor: downsampleFactor ?? 1 });
@@ -77,9 +70,12 @@ export class Streamer implements AsyncIterator<Frame>, AsyncIterable<Frame> {
77
70
  return this.adapter.adapt(new Frame((await this.stream.receive()).frame));
78
71
  }
79
72
 
80
- async update(channels: Params): Promise<void> {
73
+ async update(channels: channel.Params): Promise<void> {
81
74
  await this.adapter.update(channels);
82
- this.stream.send({ keys: this.adapter.keys, downsampleFactor: this.downsampleFactor });
75
+ this.stream.send({
76
+ keys: this.adapter.keys,
77
+ downsampleFactor: this.downsampleFactor,
78
+ });
83
79
  }
84
80
 
85
81
  close(): void {
@@ -1,4 +1,4 @@
1
- // Copyright 2024 Synnax Labs, Inc.
1
+ // Copyright 2025 Synnax Labs, Inc.
2
2
  //
3
3
  // Use of this software is governed by the Business Source License included in the file
4
4
  // licenses/BSL.txt.
@@ -12,7 +12,7 @@ import { DataType, Rate, TimeRange, TimeSpan, TimeStamp } from "@synnaxlabs/x/te
12
12
  import { describe, expect, test } from "vitest";
13
13
 
14
14
  import { type channel } from "@/channel";
15
- import { UnauthorizedError } from "@/errors";
15
+ import { UnauthorizedError, ValidationError } from "@/errors";
16
16
  import { ALWAYS_INDEX_PERSIST_ON_AUTO_COMMIT, WriterMode } from "@/framer/writer";
17
17
  import { newClient } from "@/setupspecs";
18
18
  import { randomSeries } from "@/util/telem";
@@ -22,7 +22,7 @@ const client = newClient();
22
22
  const newChannel = async (): Promise<channel.Channel> =>
23
23
  await client.channels.create({
24
24
  leaseholder: 1,
25
- name: `test-${id.id()}`,
25
+ name: `test-${id.create()}`,
26
26
  rate: Rate.hz(1),
27
27
  dataType: DataType.FLOAT64,
28
28
  });
@@ -40,6 +40,7 @@ describe("Writer", () => {
40
40
  }
41
41
  expect(true).toBeTruthy();
42
42
  });
43
+
43
44
  test("write to unknown channel key", async () => {
44
45
  const ch = await newChannel();
45
46
  const writer = await client.openWriter({ start: 0, channels: ch.key });
@@ -48,6 +49,7 @@ describe("Writer", () => {
48
49
  ).rejects.toThrow("Channel billy bob not found");
49
50
  await writer.close();
50
51
  });
52
+
51
53
  test("stream when mode is set ot persist only", async () => {
52
54
  const ch = await newChannel();
53
55
  const stream = await client.openStreamer(ch.key);
@@ -68,6 +70,7 @@ describe("Writer", () => {
68
70
  ]);
69
71
  expect(v).toEqual(123);
70
72
  });
73
+
71
74
  test("write with auto commit on", async () => {
72
75
  const ch = await newChannel();
73
76
  const writer = await client.openWriter({
@@ -85,6 +88,7 @@ describe("Writer", () => {
85
88
  const f = await client.read(new TimeRange(0, TimeStamp.seconds(10)), ch.key);
86
89
  expect(f.length).toEqual(10);
87
90
  });
91
+
88
92
  test("write with auto commit and alwaysPersist", async () => {
89
93
  const ch = await newChannel();
90
94
  const writer = await client.openWriter({
@@ -100,6 +104,7 @@ describe("Writer", () => {
100
104
  }
101
105
  expect(true).toBeTruthy();
102
106
  });
107
+
103
108
  test("write with auto commit and a set interval", async () => {
104
109
  const ch = await newChannel();
105
110
  const writer = await client.openWriter({
@@ -115,6 +120,41 @@ describe("Writer", () => {
115
120
  }
116
121
  expect(true).toBeTruthy();
117
122
  });
123
+
124
+ test("write with out of order timestamp", async () => {
125
+ const indexCh = await client.channels.create({
126
+ name: "idx",
127
+ dataType: DataType.TIMESTAMP,
128
+ isIndex: true,
129
+ });
130
+
131
+ const dataCh = await client.channels.create({
132
+ name: "data",
133
+ dataType: DataType.FLOAT64,
134
+ index: indexCh.key,
135
+ });
136
+
137
+ const writer = await client.openWriter({
138
+ start: TimeStamp.now(),
139
+ channels: [indexCh.key, dataCh.key],
140
+ enableAutoCommit: true,
141
+ });
142
+
143
+ let errAccumulated: boolean = false;
144
+ for (let i = 0; i < 10; i++) {
145
+ await new Promise((resolve) => setTimeout(resolve, 5));
146
+ errAccumulated = !(await writer.write({
147
+ [indexCh.key]: BigInt(i),
148
+ [dataCh.key]: i,
149
+ }));
150
+ if (errAccumulated) break;
151
+ }
152
+
153
+ expect(errAccumulated).toBeTruthy();
154
+
155
+ await expect(writer.close()).rejects.toThrow(ValidationError);
156
+ });
157
+
118
158
  test("write with errOnUnauthorized", async () => {
119
159
  const ch = await newChannel();
120
160
  const w1 = await client.openWriter({
@@ -123,14 +163,11 @@ describe("Writer", () => {
123
163
  });
124
164
 
125
165
  await expect(
126
- client.openWriter({
127
- start: 0,
128
- channels: ch.key,
129
- errOnUnauthorized: true,
130
- }),
166
+ client.openWriter({ start: 0, channels: ch.key, errOnUnauthorized: true }),
131
167
  ).rejects.toThrow(UnauthorizedError);
132
168
  await w1.close();
133
169
  });
170
+
134
171
  test("setAuthority", async () => {
135
172
  const ch = await newChannel();
136
173
  const w1 = await client.openWriter({
@@ -159,6 +196,7 @@ describe("Writer", () => {
159
196
  await w1.close();
160
197
  await w2.close();
161
198
  });
199
+
162
200
  test("setAuthority with name keys", async () => {
163
201
  const ch = await newChannel();
164
202
  const w1 = await client.openWriter({
@@ -187,6 +225,7 @@ describe("Writer", () => {
187
225
  await w1.close();
188
226
  await w2.close();
189
227
  });
228
+
190
229
  test("setAuthority with name-value pair", async () => {
191
230
  const ch = await newChannel();
192
231
  const w1 = await client.openWriter({
@@ -215,6 +254,7 @@ describe("Writer", () => {
215
254
  await w1.close();
216
255
  await w2.close();
217
256
  });
257
+
218
258
  test("setAuthority on all channels", async () => {
219
259
  const ch = await newChannel();
220
260
  const w1 = await client.openWriter({
@@ -244,6 +284,7 @@ describe("Writer", () => {
244
284
  await w2.close();
245
285
  });
246
286
  });
287
+
247
288
  describe("Client", () => {
248
289
  test("Client - basic write", async () => {
249
290
  const ch = await newChannel();