@synnaxlabs/client 0.22.0 → 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 (229) 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 -13607
  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 +1 -1
  82. package/dist/util/zod.d.ts.map +1 -1
  83. package/dist/workspace/client.d.ts.map +1 -1
  84. package/dist/workspace/external.d.ts +1 -1
  85. package/dist/workspace/external.d.ts.map +1 -1
  86. package/dist/workspace/lineplot/client.d.ts +1 -1
  87. package/dist/workspace/lineplot/client.d.ts.map +1 -1
  88. package/dist/workspace/lineplot/external.d.ts +1 -1
  89. package/dist/workspace/lineplot/external.d.ts.map +1 -1
  90. package/dist/workspace/lineplot/payload.d.ts +2 -2
  91. package/dist/workspace/lineplot/retriever.d.ts.map +1 -1
  92. package/dist/workspace/lineplot/writer.d.ts +4 -4
  93. package/dist/workspace/lineplot/writer.d.ts.map +1 -1
  94. package/dist/workspace/payload.d.ts +6 -4
  95. package/dist/workspace/payload.d.ts.map +1 -1
  96. package/dist/workspace/retriever.d.ts.map +1 -1
  97. package/dist/workspace/schematic/client.d.ts.map +1 -1
  98. package/dist/workspace/schematic/external.d.ts +1 -1
  99. package/dist/workspace/schematic/external.d.ts.map +1 -1
  100. package/dist/workspace/schematic/payload.d.ts +2 -2
  101. package/dist/workspace/schematic/retriever.d.ts +1 -1
  102. package/dist/workspace/schematic/retriever.d.ts.map +1 -1
  103. package/dist/workspace/schematic/writer.d.ts +4 -4
  104. package/dist/workspace/schematic/writer.d.ts.map +1 -1
  105. package/dist/workspace/writer.d.ts +7 -5
  106. package/dist/workspace/writer.d.ts.map +1 -1
  107. package/eslint.config.js +12 -0
  108. package/examples/node/basicReadWrite.js +11 -2
  109. package/examples/node/liveStream.js +13 -4
  110. package/examples/node/seriesAndFrames.js +12 -3
  111. package/examples/node/streamWrite.js +15 -6
  112. package/package.json +11 -8
  113. package/src/auth/auth.spec.ts +7 -6
  114. package/src/auth/auth.ts +17 -13
  115. package/src/auth/index.ts +1 -1
  116. package/src/channel/batchRetriever.spec.ts +16 -5
  117. package/src/channel/channel.spec.ts +42 -4
  118. package/src/channel/client.ts +26 -9
  119. package/src/channel/creator.ts +2 -2
  120. package/src/channel/external.ts +2 -2
  121. package/src/channel/index.ts +1 -1
  122. package/src/channel/payload.ts +3 -1
  123. package/src/channel/retriever.ts +6 -4
  124. package/src/channel/writer.ts +23 -4
  125. package/src/client.ts +5 -3
  126. package/src/connection/checker.ts +1 -1
  127. package/src/connection/connection.spec.ts +1 -1
  128. package/src/connection/index.ts +1 -1
  129. package/src/control/client.ts +17 -0
  130. package/src/control/external.ts +2 -2
  131. package/src/control/index.ts +1 -1
  132. package/src/control/state.spec.ts +2 -3
  133. package/src/control/state.ts +20 -84
  134. package/src/errors.ts +18 -7
  135. package/src/framer/adapter.spec.ts +9 -0
  136. package/src/framer/adapter.ts +3 -3
  137. package/src/framer/client.spec.ts +1 -1
  138. package/src/framer/client.ts +34 -14
  139. package/src/framer/deleter.spec.ts +129 -0
  140. package/src/framer/deleter.ts +49 -0
  141. package/src/framer/external.ts +1 -1
  142. package/src/framer/frame.spec.ts +1 -1
  143. package/src/framer/frame.ts +14 -14
  144. package/src/framer/index.ts +1 -1
  145. package/src/framer/iterator.spec.ts +2 -2
  146. package/src/framer/iterator.ts +2 -2
  147. package/src/framer/streamProxy.ts +2 -4
  148. package/src/framer/streamer.spec.ts +2 -2
  149. package/src/framer/streamer.ts +6 -5
  150. package/src/framer/writer.spec.ts +18 -1
  151. package/src/framer/writer.ts +19 -27
  152. package/src/hardware/device/client.ts +2 -2
  153. package/src/hardware/device/index.ts +1 -1
  154. package/src/hardware/external.ts +1 -1
  155. package/src/hardware/index.ts +1 -1
  156. package/src/hardware/rack/rack.spec.ts +1 -1
  157. package/src/hardware/task/client.ts +3 -3
  158. package/src/hardware/task/task.spec.ts +2 -2
  159. package/src/index.ts +26 -25
  160. package/src/label/client.ts +2 -2
  161. package/src/label/external.ts +3 -3
  162. package/src/label/index.ts +1 -1
  163. package/src/label/label.spec.ts +1 -1
  164. package/src/label/payload.ts +1 -1
  165. package/src/label/retriever.ts +1 -1
  166. package/src/label/writer.ts +1 -1
  167. package/src/ontology/client.ts +7 -7
  168. package/src/ontology/external.ts +1 -1
  169. package/src/ontology/group/client.ts +3 -3
  170. package/src/ontology/group/external.ts +2 -2
  171. package/src/ontology/group/group.spec.ts +2 -2
  172. package/src/ontology/group/group.ts +1 -1
  173. package/src/ontology/group/index.ts +1 -1
  174. package/src/ontology/group/payload.ts +1 -1
  175. package/src/ontology/group/writer.ts +22 -6
  176. package/src/ontology/index.ts +1 -1
  177. package/src/ontology/ontology.spec.ts +2 -2
  178. package/src/ontology/payload.ts +3 -3
  179. package/src/ontology/writer.ts +2 -2
  180. package/src/ranger/active.ts +2 -2
  181. package/src/ranger/alias.ts +2 -2
  182. package/src/ranger/client.ts +15 -16
  183. package/src/ranger/external.ts +3 -3
  184. package/src/ranger/index.ts +1 -1
  185. package/src/ranger/kv.ts +2 -2
  186. package/src/ranger/payload.ts +1 -1
  187. package/src/ranger/range.ts +2 -2
  188. package/src/ranger/ranger.spec.ts +1 -1
  189. package/src/ranger/writer.ts +3 -3
  190. package/src/setupspecs.ts +1 -1
  191. package/src/signals/external.ts +1 -1
  192. package/src/signals/index.ts +1 -1
  193. package/src/signals/observable.ts +1 -1
  194. package/src/transport.ts +2 -2
  195. package/src/user/index.ts +1 -1
  196. package/src/user/payload.ts +1 -1
  197. package/src/util/retrieve.spec.ts +1 -1
  198. package/src/util/retrieve.ts +1 -1
  199. package/src/util/telem.ts +1 -1
  200. package/src/util/zod.ts +11 -2
  201. package/src/vite-env.d.ts +2 -2
  202. package/src/workspace/client.ts +2 -2
  203. package/src/workspace/external.ts +2 -2
  204. package/src/workspace/index.ts +1 -1
  205. package/src/workspace/lineplot/client.ts +2 -2
  206. package/src/workspace/lineplot/external.ts +2 -2
  207. package/src/workspace/lineplot/index.ts +1 -1
  208. package/src/workspace/lineplot/linePlot.spec.ts +2 -2
  209. package/src/workspace/lineplot/payload.ts +1 -1
  210. package/src/workspace/lineplot/retriever.ts +4 -10
  211. package/src/workspace/lineplot/writer.ts +4 -4
  212. package/src/workspace/payload.ts +11 -6
  213. package/src/workspace/retriever.ts +12 -6
  214. package/src/workspace/schematic/client.ts +2 -2
  215. package/src/workspace/schematic/external.ts +2 -2
  216. package/src/workspace/schematic/index.ts +1 -1
  217. package/src/workspace/schematic/payload.ts +1 -1
  218. package/src/workspace/schematic/retriever.ts +17 -18
  219. package/src/workspace/schematic/schematic.spec.ts +2 -2
  220. package/src/workspace/schematic/writer.ts +5 -5
  221. package/src/workspace/workspace.spec.ts +2 -2
  222. package/src/workspace/writer.ts +3 -3
  223. package/vite.config.ts +3 -4
  224. package/.eslintrc.cjs +0 -18
  225. package/dist/client.cjs.map +0 -1
  226. package/dist/client.js.map +0 -1
  227. package/dist/control/authority.d.ts +0 -8
  228. package/dist/control/authority.d.ts.map +0 -1
  229. package/src/control/authority.ts +0 -26
@@ -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.
@@ -27,6 +27,7 @@ export const payload = z.object({
27
27
  leaseholder: z.number(),
28
28
  index: z.number(),
29
29
  isIndex: z.boolean(),
30
+ internal: z.boolean(),
30
31
  alias: z.string().optional(),
31
32
  });
32
33
 
@@ -38,6 +39,7 @@ export const newPayload = payload.extend({
38
39
  index: z.number().optional(),
39
40
  rate: Rate.z.optional().default(0),
40
41
  isIndex: z.boolean().optional(),
42
+ internal: z.boolean().optional().default(false),
41
43
  virtual: z.boolean().optional().default(false),
42
44
  });
43
45
 
@@ -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 @@ import {
22
22
  payload,
23
23
  } from "@/channel/payload";
24
24
  import { QueryError } from "@/errors";
25
- import { type ParamAnalysisResult, analyzeParams } from "@/util/retrieve";
25
+ import { analyzeParams, type ParamAnalysisResult } from "@/util/retrieve";
26
26
  import { nullableArrayZ } from "@/util/zod";
27
27
 
28
28
  const reqZ = z.object({
@@ -76,7 +76,9 @@ export class ClusterRetriever implements Retriever {
76
76
  }
77
77
 
78
78
  async retrieve(channels: Params, options?: RetrieveOptions): Promise<Payload[]> {
79
- let { variant, normalized } = analyzeChannelParams(channels);
79
+ const res = analyzeChannelParams(channels);
80
+ const { variant } = res;
81
+ let { normalized } = res;
80
82
  if (variant === "keys" && (normalized as Key[]).indexOf(0) !== -1)
81
83
  normalized = (normalized as Key[]).filter((k) => k !== 0);
82
84
  if (normalized.length === 0) return [];
@@ -185,7 +187,7 @@ export class DebouncedBatchRetriever implements Retriever {
185
187
  const { normalized, variant } = analyzeChannelParams(channels);
186
188
  // Bypass on name fetches for now.
187
189
  if (variant === "names") return await this.wrapped.retrieve(normalized);
188
- // eslint-disable-next-line @typescript-eslint/promise-function-async
190
+
189
191
  const a = new Promise<Payload[]>((resolve, reject) => {
190
192
  void this.mu.runExclusive(() => {
191
193
  this.requests.set(normalized as Key[], { resolve, reject });
@@ -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,11 +11,12 @@ import { sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
11
11
  import { z } from "zod";
12
12
 
13
13
  import {
14
+ Key,
15
+ keyZ,
16
+ type NewPayload,
17
+ newPayload,
14
18
  type Payload,
15
19
  payload,
16
- newPayload,
17
- type NewPayload,
18
- keyZ,
19
20
  } from "@/channel/payload";
20
21
 
21
22
  const createReqZ = z.object({ channels: newPayload.array() });
@@ -27,10 +28,18 @@ const deleteReqZ = z.object({
27
28
  });
28
29
  const deleteResZ = z.object({});
29
30
 
31
+ const renameReqZ = z.object({
32
+ keys: keyZ.array(),
33
+ names: z.string().array(),
34
+ });
35
+ const renameResZ = z.object({});
36
+
30
37
  const CREATE_ENDPOINT = "/channel/create";
31
38
  const DELETE_ENDPOINT = "/channel/delete";
39
+ const RENAME_ENDPOINT = "/channel/rename";
32
40
 
33
41
  export type DeleteProps = z.input<typeof deleteReqZ>;
42
+ export type RenameProps = z.input<typeof renameReqZ>;
34
43
 
35
44
  export class Writer {
36
45
  private readonly client: UnaryClient;
@@ -60,4 +69,14 @@ export class Writer {
60
69
  deleteResZ,
61
70
  );
62
71
  }
72
+
73
+ async rename(keys: Key[], names: string[]): Promise<void> {
74
+ await sendRequired<typeof renameReqZ, typeof renameResZ>(
75
+ this.client,
76
+ RENAME_ENDPOINT,
77
+ { keys, names },
78
+ renameReqZ,
79
+ renameResZ,
80
+ );
81
+ }
63
82
  }
package/src/client.ts CHANGED
@@ -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.
@@ -14,6 +14,7 @@ import { z } from "zod";
14
14
  import { auth } from "@/auth";
15
15
  import { channel } from "@/channel";
16
16
  import { connection } from "@/connection";
17
+ import { control } from "@/control";
17
18
  import { errorsMiddleware } from "@/errors";
18
19
  import { framer } from "@/framer";
19
20
  import { hardware } from "@/hardware";
@@ -59,7 +60,6 @@ export type ParsedSynnaxProps = z.output<typeof synnaxPropsZ>;
59
60
  * @property connectivity - Client for retrieving connectivity information.
60
61
  * @property ontology - Client for querying the cluster's ontology.
61
62
  */
62
- // eslint-disable-next-line import/no-default-export
63
63
  export default class Synnax extends framer.Client {
64
64
  readonly createdAt: TimeStamp;
65
65
  readonly props: ParsedSynnaxProps;
@@ -71,6 +71,7 @@ export default class Synnax extends framer.Client {
71
71
  readonly workspaces: workspace.Client;
72
72
  readonly labels: label.Client;
73
73
  readonly hardware: hardware.Client;
74
+ readonly control: control.Client;
74
75
  static readonly connectivity = connection.Checker;
75
76
  private readonly transport: Transport;
76
77
 
@@ -106,7 +107,7 @@ export default class Synnax extends framer.Client {
106
107
  new channel.ClusterRetriever(transport.unary),
107
108
  );
108
109
  const chCreator = new channel.Writer(transport.unary);
109
- super(transport.stream, chRetriever);
110
+ super(transport.stream, transport.unary, chRetriever);
110
111
  this.createdAt = TimeStamp.now();
111
112
  this.props = props;
112
113
  this.auth = auth_;
@@ -117,6 +118,7 @@ export default class Synnax extends framer.Client {
117
118
  connectivityPollFrequency,
118
119
  props.name,
119
120
  );
121
+ this.control = new control.Client(this);
120
122
  this.ontology = new ontology.Client(transport.unary, this);
121
123
  const rangeWriter = new ranger.Writer(this.transport.unary);
122
124
  this.labels = new label.Client(this.transport.unary, this);
@@ -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.
@@ -0,0 +1,17 @@
1
+ import { StateTracker } from "@/control/state";
2
+ import { framer } from "@/framer";
3
+
4
+ const CONTROL_STATE_KEY = "sy_node_1_control";
5
+
6
+ export class Client {
7
+ private readonly framer: framer.Client;
8
+
9
+ constructor(framer: framer.Client) {
10
+ this.framer = framer;
11
+ }
12
+
13
+ async openStateTracker(): Promise<StateTracker> {
14
+ const stream = await this.framer.openStreamer(CONTROL_STATE_KEY);
15
+ return new StateTracker(stream);
16
+ }
17
+ }
@@ -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,5 +7,5 @@
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
- export * from "@/control/authority";
10
+ export * from "@/control/client";
11
11
  export * from "@/control/state";
@@ -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.
@@ -9,14 +9,13 @@
9
9
 
10
10
  import { describe, expect, it } from "vitest";
11
11
 
12
- import { control } from "@/control";
13
12
  import { newClient } from "@/setupspecs";
14
13
 
15
14
  const client = newClient();
16
15
 
17
16
  describe("state", () => {
18
17
  it("should receive the initial control state from the cluster", async () => {
19
- const s = await control.StateTracker.open(client);
18
+ const s = await client.control.openStateTracker();
20
19
  await new Promise((resolve) => setTimeout(resolve, 50));
21
20
  expect(s.states.size).toBeGreaterThan(0);
22
21
  await s.close();
@@ -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,65 +7,21 @@
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 { control } from "@synnaxlabs/x";
10
11
  import { binary } from "@synnaxlabs/x/binary";
11
- import { type Destructor } from "@synnaxlabs/x/destructor";
12
12
  import { observe } from "@synnaxlabs/x/observe";
13
13
  import { z } from "zod";
14
14
 
15
15
  import { type Key as ChannelKey } from "@/channel/payload";
16
- import { Authority } from "@/control/authority";
17
- import { type Client as FrameClient } from "@/framer/client";
16
+ import { framer } from "@/framer";
18
17
  import { type Streamer as FrameStreamer } from "@/framer/streamer";
19
18
 
20
- export const subjectZ = z.object({
21
- name: z.string(),
22
- key: z.string(),
23
- });
24
-
25
- export interface Subject {
26
- name: string;
27
- key: string;
28
- }
29
-
30
- export const stateZ = z.object({
31
- subject: subjectZ,
32
- resource: z.number(),
33
- authority: Authority.z,
34
- });
35
-
36
- export interface State {
37
- subject: Subject;
38
- resource: ChannelKey;
39
- authority: Authority;
40
- }
41
-
42
- export const filterTransfersByChannelKey =
43
- (...resources: ChannelKey[]) =>
44
- (transfers: Transfer[]): Transfer[] =>
45
- transfers.filter((t) => {
46
- let ok = false;
47
- if (t.to != null) ok = resources.includes(t.to.resource);
48
- if (t.from != null && !ok) ok = resources.includes(t.from.resource);
49
- return ok;
50
- });
51
-
52
- interface Release {
53
- from: State;
54
- to?: null;
55
- }
56
-
57
- interface Acquire {
58
- from?: null;
59
- to: State;
60
- }
61
-
62
- export type Transfer =
63
- | {
64
- from: State;
65
- to: State;
66
- }
67
- | Release
68
- | Acquire;
19
+ export type Authority = control.Authority;
20
+ export const Authority = control.Authority;
21
+ export type Transfer = control.Transfer<ChannelKey>;
22
+ export type State = control.State<ChannelKey>;
23
+ export type Subject = control.Subject;
24
+ export const stateZ = control.stateZ(z.number());
69
25
 
70
26
  export const transferString = (t: Transfer): string => {
71
27
  if (t.to == null) return `${t.from?.resource} - ${t.from?.subject.name} -> released`;
@@ -79,22 +35,24 @@ export const transferString = (t: Transfer): string => {
79
35
  };
80
36
 
81
37
  interface Update {
82
- transfers: Transfer[];
38
+ transfers: control.Transfer<ChannelKey>[];
83
39
  }
84
40
 
85
- export class StateTracker implements observe.Observable<Transfer[]> {
41
+ export class StateTracker
42
+ extends framer.ObservableStreamer<Transfer[]>
43
+ implements observe.ObservableAsyncCloseable<Transfer[]>
44
+ {
86
45
  readonly states: Map<ChannelKey, State>;
87
- private readonly streamer: FrameStreamer;
88
46
  private readonly ecd: binary.EncoderDecoder;
89
- private readonly observer: observe.Observer<Transfer[]>;
90
- private readonly closePromise: Promise<void>;
91
47
 
92
- private constructor(streamer: FrameStreamer) {
48
+ constructor(streamer: FrameStreamer) {
49
+ super(streamer, (frame) => {
50
+ const update: Update = this.ecd.decode(frame.series[0].buffer);
51
+ this.merge(update);
52
+ return [update.transfers, true];
53
+ });
93
54
  this.states = new Map();
94
55
  this.ecd = new binary.JSONEncoderDecoder();
95
- this.observer = new observe.Observer<Transfer[]>();
96
- this.streamer = streamer;
97
- this.closePromise = this.stream();
98
56
  }
99
57
 
100
58
  subjects(): Subject[] {
@@ -103,28 +61,6 @@ export class StateTracker implements observe.Observable<Transfer[]> {
103
61
  return Array.from(subjects.values());
104
62
  }
105
63
 
106
- onChange(handler: observe.Handler<Transfer[]>): Destructor {
107
- return this.observer.onChange(handler);
108
- }
109
-
110
- async close(): Promise<void> {
111
- this.streamer.close();
112
- await this.closePromise;
113
- }
114
-
115
- static async open(client: FrameClient): Promise<StateTracker> {
116
- const streamer = await client.openStreamer("sy_node_1_control");
117
- return new StateTracker(streamer);
118
- }
119
-
120
- private async stream(): Promise<void> {
121
- for await (const frame of this.streamer) {
122
- const update: Update = this.ecd.decode(frame.series[0].buffer);
123
- this.merge(update);
124
- this.observer.notify(update.transfers);
125
- }
126
- }
127
-
128
64
  private merge(update: Update): void {
129
65
  update.transfers.forEach((t) => {
130
66
  if (t.from == null && t.to == null) console.warn("Invalid transfer: ", t);
package/src/errors.ts CHANGED
@@ -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,10 +8,10 @@
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
10
  import {
11
+ type ErrorPayload,
11
12
  type Middleware,
12
13
  registerError,
13
14
  Unreachable,
14
- type ErrorPayload,
15
15
  } from "@synnaxlabs/freighter";
16
16
 
17
17
  const _FREIGHTER_EXCEPTION_PREFIX = "sy.";
@@ -99,6 +99,14 @@ export class RouteError extends Error {
99
99
  }
100
100
  }
101
101
 
102
+ export class ControlError extends Error {
103
+ static readonly TYPE = _FREIGHTER_EXCEPTION_PREFIX + "control";
104
+ }
105
+
106
+ export class UnauthorizedError extends ControlError {
107
+ static readonly TYPE = ControlError.TYPE + ".unauthorized";
108
+ }
109
+
102
110
  /**
103
111
  * Raised when time-series data is not contiguous.
104
112
  */
@@ -109,9 +117,7 @@ const decode = (payload: ErrorPayload): Error | null => {
109
117
  if (payload.type.startsWith(ValidationError.TYPE)) {
110
118
  if (payload.type === FieldError.TYPE) {
111
119
  const values = payload.data.split(": ");
112
- if (values.length < 2) {
113
- return new ValidationError(payload.data);
114
- }
120
+ if (values.length < 2) return new ValidationError(payload.data);
115
121
  return new FieldError(values[0], values[1]);
116
122
  }
117
123
  return new ValidationError(payload.data);
@@ -135,10 +141,15 @@ const decode = (payload: ErrorPayload): Error | null => {
135
141
  return new QueryError(payload.data);
136
142
  }
137
143
 
138
- if (payload.type.startsWith(RouteError.TYPE)) {
139
- return new RouteError(payload.data, payload.data);
144
+ if (payload.type.startsWith(ControlError.TYPE)) {
145
+ if (payload.type.startsWith(UnauthorizedError.TYPE))
146
+ return new UnauthorizedError(payload.data);
147
+ return new ControlError(payload.data);
140
148
  }
141
149
 
150
+ if (payload.type.startsWith(RouteError.TYPE))
151
+ return new RouteError(payload.data, payload.data);
152
+
142
153
  return new UnexpectedError(payload.data);
143
154
  };
144
155
 
@@ -1,3 +1,12 @@
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
+
1
10
  import { DataType, Series, TimeStamp } from "@synnaxlabs/x/telem";
2
11
  import { beforeAll, describe, expect, it } from "vitest";
3
12
 
@@ -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,14 +11,14 @@ import { type CrudeSeries, Series } from "@synnaxlabs/x/telem";
11
11
 
12
12
  import {
13
13
  type Key,
14
+ type KeyOrName,
14
15
  type Name,
15
16
  type Params,
16
- type KeyOrName,
17
17
  type Payload,
18
18
  } from "@/channel/payload";
19
19
  import {
20
- type Retriever,
21
20
  analyzeChannelParams,
21
+ type Retriever,
22
22
  retrieveRequired,
23
23
  } from "@/channel/retriever";
24
24
  import { ValidationError } from "@/errors";
@@ -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.
@@ -7,28 +7,35 @@
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 StreamClient } from "@synnaxlabs/freighter";
10
+ import {type StreamClient, UnaryClient } from "@synnaxlabs/freighter";
11
11
  import {
12
- type CrudeTimeStamp,
13
12
  type CrudeSeries,
14
13
  type CrudeTimeRange,
14
+ type CrudeTimeStamp,
15
15
  type MultiSeries,
16
- } from "@synnaxlabs/x/telem";
16
+ TimeRange,
17
+ TimeSpan,
18
+ } from "@synnaxlabs/x";
17
19
 
18
- import { KeysOrNames, type KeyOrName, type Params } from "@/channel/payload";
19
- import { type Retriever, analyzeChannelParams } from "@/channel/retriever";
20
+ import { type Key, type KeyOrName, KeysOrNames, type Params} from "@/channel/payload";
21
+ import { analyzeChannelParams,type Retriever } from "@/channel/retriever";
20
22
  import { Frame } from "@/framer/frame";
21
23
  import { Iterator } from "@/framer/iterator";
22
24
  import { Streamer, type StreamerConfig } from "@/framer/streamer";
23
- import { Writer, WriterMode, type WriterConfig } from "@/framer/writer";
25
+ import { Writer, type WriterConfig,WriterMode } from "@/framer/writer";
26
+ import { Deleter } from "@/framer/deleter";
24
27
 
25
28
  export class Client {
26
- private readonly stream: StreamClient;
29
+ private readonly streamClient: StreamClient;
30
+ // private readonly unaryClient: UnaryClient;
27
31
  private readonly retriever: Retriever;
32
+ private readonly deleter: Deleter;
28
33
 
29
- constructor(stream: StreamClient, retriever: Retriever) {
30
- this.stream = stream;
34
+ constructor(stream: StreamClient, unary: UnaryClient, retriever: Retriever) {
35
+ this.streamClient = stream;
36
+ // this.unaryClient = unary;
31
37
  this.retriever = retriever;
38
+ this.deleter = new Deleter(unary);
32
39
  }
33
40
 
34
41
  /**
@@ -39,7 +46,7 @@ export class Client {
39
46
  * @returns a new {@link TypedIterator}.
40
47
  */
41
48
  async openIterator(tr: CrudeTimeRange, channels: Params): Promise<Iterator> {
42
- return await Iterator._open(tr, channels, this.retriever, this.stream);
49
+ return await Iterator._open(tr, channels, this.retriever, this.streamClient);
43
50
  }
44
51
 
45
52
  /**
@@ -52,7 +59,7 @@ export class Client {
52
59
  async openWriter(config: WriterConfig | Params): Promise<Writer> {
53
60
  if (Array.isArray(config) || typeof config !== "object")
54
61
  config = { channels: config as Params };
55
- return await Writer._open(this.retriever, this.stream, config);
62
+ return await Writer._open(this.retriever, this.streamClient, config);
56
63
  }
57
64
 
58
65
  /***
@@ -82,7 +89,7 @@ export class Client {
82
89
  async openStreamer(config: StreamerConfig | Params): Promise<Streamer> {
83
90
  if (Array.isArray(config) || typeof config !== "object")
84
91
  config = { channels: config as Params };
85
- return await Streamer._open(this.retriever, this.stream, config);
92
+ return await Streamer._open(this.retriever, this.streamClient, config);
86
93
  }
87
94
 
88
95
  async write(
@@ -135,10 +142,12 @@ export class Client {
135
142
  start,
136
143
  channels: channels as Params,
137
144
  mode: WriterMode.PersistOnly,
145
+ errOnUnauthorized: true,
146
+ enableAutoCommit: true,
147
+ autoIndexPersistInterval: TimeSpan.MAX,
138
148
  });
139
149
  try {
140
150
  await w.write(channels as Params, data);
141
- await w.commit();
142
151
  } finally {
143
152
  await w.close();
144
153
  }
@@ -165,4 +174,15 @@ export class Client {
165
174
  }
166
175
  return frame;
167
176
  }
177
+
178
+ async delete(
179
+ channels: Params,
180
+ timeRange : TimeRange,
181
+ ): Promise<void> {
182
+
183
+ const { normalized, variant } = analyzeChannelParams(channels);
184
+ if (variant === "keys")
185
+ return await this.deleter.delete({ keys: normalized as Key[], bounds: timeRange });
186
+ return await this.deleter.delete({ names: normalized as string[], bounds: timeRange });
187
+ }
168
188
  }