@synnaxlabs/client 0.13.6 → 0.14.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 (135) hide show
  1. package/.turbo/turbo-build.log +10 -10
  2. package/dist/auth/index.d.ts +1 -1
  3. package/dist/channel/client.d.ts +8 -7
  4. package/dist/channel/creator.d.ts +1 -1
  5. package/dist/channel/external.d.ts +4 -4
  6. package/dist/channel/index.d.ts +1 -1
  7. package/dist/channel/payload.d.ts +6 -0
  8. package/dist/channel/retriever.d.ts +7 -7
  9. package/dist/client.cjs.js +14 -23043
  10. package/dist/client.cjs.js.map +1 -1
  11. package/dist/client.d.ts +5 -0
  12. package/dist/client.es.js +11867 -17730
  13. package/dist/client.es.js.map +1 -1
  14. package/dist/connection/checker.d.ts +2 -1
  15. package/dist/connection/index.d.ts +1 -1
  16. package/dist/control/external.d.ts +2 -2
  17. package/dist/control/index.d.ts +1 -1
  18. package/dist/control/state.d.ts +1 -1
  19. package/dist/framer/adapter.d.ts +1 -1
  20. package/dist/framer/client.d.ts +4 -4
  21. package/dist/framer/external.d.ts +5 -5
  22. package/dist/framer/index.d.ts +1 -1
  23. package/dist/framer/iterator.d.ts +1 -1
  24. package/dist/framer/streamer.d.ts +1 -1
  25. package/dist/framer/writer.d.ts +1 -1
  26. package/dist/hardware/client.d.ts +9 -0
  27. package/dist/hardware/device/client.d.ts +16 -0
  28. package/dist/hardware/device/device.spec.d.ts +1 -0
  29. package/dist/hardware/device/external.d.ts +3 -0
  30. package/dist/hardware/device/index.d.ts +1 -0
  31. package/dist/hardware/device/payload.d.ts +29 -0
  32. package/dist/hardware/device/retriever.d.ts +7 -0
  33. package/dist/hardware/device/writer.d.ts +8 -0
  34. package/dist/hardware/external.d.ts +2 -0
  35. package/dist/hardware/index.d.ts +1 -0
  36. package/dist/hardware/rack/client.d.ts +29 -0
  37. package/dist/hardware/rack/external.d.ts +3 -0
  38. package/dist/hardware/rack/index.d.ts +1 -0
  39. package/dist/hardware/rack/payload.d.ts +25 -0
  40. package/dist/hardware/rack/rack.spec.d.ts +1 -0
  41. package/dist/hardware/rack/retriever.d.ts +7 -0
  42. package/dist/hardware/rack/writer.d.ts +8 -0
  43. package/dist/hardware/task/client.d.ts +12 -0
  44. package/dist/hardware/task/external.d.ts +3 -0
  45. package/dist/hardware/task/index.d.ts +1 -0
  46. package/dist/hardware/task/payload.d.ts +40 -0
  47. package/dist/hardware/task/retriever.d.ts +20 -0
  48. package/dist/hardware/task/task.spec.d.ts +1 -0
  49. package/dist/hardware/task/writer.d.ts +8 -0
  50. package/dist/index.d.ts +1 -0
  51. package/dist/label/client.d.ts +2 -2
  52. package/dist/label/external.d.ts +4 -4
  53. package/dist/label/index.d.ts +1 -1
  54. package/dist/label/retriever.d.ts +1 -1
  55. package/dist/label/writer.d.ts +1 -1
  56. package/dist/ontology/client.d.ts +4 -4
  57. package/dist/ontology/external.d.ts +3 -3
  58. package/dist/ontology/group/client.d.ts +2 -2
  59. package/dist/ontology/group/external.d.ts +2 -2
  60. package/dist/ontology/group/group.d.ts +1 -1
  61. package/dist/ontology/group/index.d.ts +1 -1
  62. package/dist/ontology/group/writer.d.ts +2 -2
  63. package/dist/ontology/index.d.ts +1 -1
  64. package/dist/ontology/payload.d.ts +47 -47
  65. package/dist/ontology/retriever.d.ts +1 -1
  66. package/dist/ontology/signals.d.ts +6 -2
  67. package/dist/ontology/writer.d.ts +1 -1
  68. package/dist/ranger/alias.d.ts +1 -1
  69. package/dist/ranger/client.d.ts +4 -4
  70. package/dist/ranger/external.d.ts +6 -6
  71. package/dist/ranger/index.d.ts +1 -1
  72. package/dist/ranger/kv.d.ts +1 -1
  73. package/dist/ranger/range.d.ts +2 -2
  74. package/dist/ranger/writer.d.ts +1 -1
  75. package/dist/signals/external.d.ts +1 -1
  76. package/dist/signals/index.d.ts +1 -1
  77. package/dist/user/index.d.ts +1 -1
  78. package/dist/workspace/client.d.ts +4 -4
  79. package/dist/workspace/external.d.ts +2 -2
  80. package/dist/workspace/index.d.ts +1 -1
  81. package/dist/workspace/lineplot/client.d.ts +2 -2
  82. package/dist/workspace/lineplot/external.d.ts +2 -2
  83. package/dist/workspace/lineplot/index.d.ts +1 -1
  84. package/dist/workspace/lineplot/retriever.d.ts +1 -1
  85. package/dist/workspace/lineplot/writer.d.ts +1 -1
  86. package/dist/workspace/pid/client.d.ts +2 -2
  87. package/dist/workspace/pid/external.d.ts +2 -2
  88. package/dist/workspace/pid/index.d.ts +1 -1
  89. package/dist/workspace/pid/writer.d.ts +1 -1
  90. package/dist/workspace/retriever.d.ts +1 -1
  91. package/package.json +8 -8
  92. package/src/channel/client.ts +11 -9
  93. package/src/channel/payload.ts +1 -0
  94. package/src/channel/retriever.ts +13 -15
  95. package/src/client.ts +23 -0
  96. package/src/connection/checker.ts +4 -2
  97. package/src/framer/frame.spec.ts +67 -79
  98. package/src/framer/frame.ts +1 -1
  99. package/src/framer/writer.ts +1 -1
  100. package/src/hardware/client.ts +24 -0
  101. package/src/hardware/device/client.ts +54 -0
  102. package/src/hardware/device/device.spec.ts +45 -0
  103. package/src/hardware/device/external.ts +3 -0
  104. package/src/hardware/device/index.ts +1 -0
  105. package/src/hardware/device/payload.ts +18 -0
  106. package/src/hardware/device/retriever.ts +39 -0
  107. package/src/hardware/device/writer.ts +48 -0
  108. package/src/hardware/external.ts +11 -0
  109. package/src/hardware/index.ts +10 -0
  110. package/src/hardware/rack/client.ts +96 -0
  111. package/src/hardware/rack/external.ts +3 -0
  112. package/src/hardware/rack/index.ts +1 -0
  113. package/src/hardware/rack/payload.ts +17 -0
  114. package/src/hardware/rack/rack.spec.ts +29 -0
  115. package/src/hardware/rack/retriever.ts +32 -0
  116. package/src/hardware/rack/writer.ts +57 -0
  117. package/src/hardware/task/client.ts +47 -0
  118. package/src/hardware/task/external.ts +12 -0
  119. package/src/hardware/task/index.ts +10 -0
  120. package/src/hardware/task/payload.ts +37 -0
  121. package/src/hardware/task/retriever.ts +45 -0
  122. package/src/hardware/task/task.spec.ts +47 -0
  123. package/src/hardware/task/writer.ts +63 -0
  124. package/src/index.ts +1 -0
  125. package/src/label/writer.ts +1 -1
  126. package/src/ontology/client.ts +1 -1
  127. package/src/ontology/group/client.ts +3 -3
  128. package/src/ontology/payload.ts +1 -0
  129. package/src/ontology/signals.ts +4 -0
  130. package/vite.config.ts +1 -1
  131. package/.pytest_cache/README.md +0 -8
  132. package/dist/cdc/external.d.ts +0 -1
  133. package/dist/cdc/index.d.ts +0 -1
  134. package/dist/cdc/observable.d.ts +0 -17
  135. package/dist/ontology/cdc.d.ts +0 -25
@@ -45,6 +45,7 @@ export class Channel {
45
45
  leaseholder: number;
46
46
  index: Key;
47
47
  isIndex: boolean;
48
+ alias: string | undefined;
48
49
 
49
50
  constructor({
50
51
  dataType,
@@ -52,10 +53,10 @@ export class Channel {
52
53
  name,
53
54
  leaseholder = 0,
54
55
  key = 0,
55
- density = 0,
56
56
  isIndex = false,
57
57
  index = 0,
58
58
  frameClient,
59
+ alias,
59
60
  }: NewPayload & {
60
61
  frameClient?: framer.Client;
61
62
  density?: CrudeDensity;
@@ -67,6 +68,7 @@ export class Channel {
67
68
  this.leaseholder = leaseholder;
68
69
  this.index = index;
69
70
  this.isIndex = isIndex;
71
+ this.alias = alias;
70
72
  this._frameClient = frameClient ?? null;
71
73
  }
72
74
 
@@ -145,9 +147,9 @@ export class Client implements AsyncTermSearcher<string, Key, Channel> {
145
147
  return single ? res[0] : res;
146
148
  }
147
149
 
148
- async retrieve(channel: KeyOrName): Promise<Channel>;
150
+ async retrieve(channel: KeyOrName, rangeKey?: string): Promise<Channel>;
149
151
 
150
- async retrieve(channels: Params): Promise<Channel[]>;
152
+ async retrieve(channels: Params, rangeKey?: string): Promise<Channel[]>;
151
153
 
152
154
  /**
153
155
  * Retrieves a channel from the database using the given parameters.
@@ -157,10 +159,10 @@ export class Client implements AsyncTermSearcher<string, Key, Channel> {
157
159
  * @returns The retrieved channel.
158
160
  * @raises {QueryError} If the channel does not exist or if multiple results are returned.
159
161
  */
160
- async retrieve(channels: Params): Promise<Channel | Channel[]> {
162
+ async retrieve(channels: Params, rangeKey?: string): Promise<Channel | Channel[]> {
161
163
  const { single, actual, normalized } = analyzeParams(channels);
162
164
  if (normalized.length === 0) return [];
163
- const res = this.sugar(await this.retriever.retrieve(channels));
165
+ const res = this.sugar(await this.retriever.retrieve(channels, rangeKey));
164
166
  if (!single) return res;
165
167
  if (res.length === 0) throw new QueryError(`channel matching ${actual} not found`);
166
168
  if (res.length > 1)
@@ -176,8 +178,8 @@ export class Client implements AsyncTermSearcher<string, Key, Channel> {
176
178
  return new SearcherUnderRange(this, rangeKey);
177
179
  }
178
180
 
179
- async page(offset: number, limit: number): Promise<Channel[]> {
180
- return this.sugar(await this.retriever.page(offset, limit));
181
+ async page(offset: number, limit: number, rangeKey?: string): Promise<Channel[]> {
182
+ return this.sugar(await this.retriever.page(offset, limit, rangeKey));
181
183
  }
182
184
 
183
185
  private sugar(payloads: Payload[]): Channel[] {
@@ -200,10 +202,10 @@ class SearcherUnderRange implements AsyncTermSearcher<string, Key, Channel> {
200
202
  }
201
203
 
202
204
  async page(offset: number, limit: number): Promise<Channel[]> {
203
- return await this.client.page(offset, limit);
205
+ return await this.client.page(offset, limit, this.rangeKey);
204
206
  }
205
207
 
206
208
  async retrieve(channels: Key[]): Promise<Channel[]> {
207
- return await this.client.retrieve(channels);
209
+ return await this.client.retrieve(channels, this.rangeKey);
208
210
  }
209
211
  }
@@ -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
+ alias: z.string().optional(),
30
31
  });
31
32
 
32
33
  export type Payload = z.infer<typeof payload>;
@@ -22,14 +22,13 @@ import {
22
22
  type Payload,
23
23
  payload,
24
24
  } from "@/channel/payload";
25
- import { QueryError } from "@/errors";
26
25
 
27
26
  const reqZ = z.object({
28
27
  leaseholder: z.number().optional(),
29
28
  keys: z.number().array().optional(),
30
29
  names: z.string().array().optional(),
31
30
  search: z.string().optional(),
32
- searchRangeKey: z.string().optional(),
31
+ rangeKey: z.string().optional(),
33
32
  limit: z.number().optional(),
34
33
  offset: z.number().optional(),
35
34
  });
@@ -41,9 +40,9 @@ const resZ = z.object({
41
40
  });
42
41
 
43
42
  export interface Retriever {
44
- retrieve: (channels: Params) => Promise<Payload[]>;
43
+ retrieve: (channels: Params, rangeKey?: string) => Promise<Payload[]>;
45
44
  search: (term: string, rangeKey?: string) => Promise<Payload[]>;
46
- page: (offset: number, limit: number) => Promise<Payload[]>;
45
+ page: (offset: number, limit: number, rangeKey?: string) => Promise<Payload[]>;
47
46
  }
48
47
 
49
48
  export class ClusterRetriever implements Retriever {
@@ -55,16 +54,16 @@ export class ClusterRetriever implements Retriever {
55
54
  }
56
55
 
57
56
  async search(term: string, rangeKey?: string): Promise<Payload[]> {
58
- return await this.execute({ search: term, searchRangeKey: rangeKey });
57
+ return await this.execute({ search: term, rangeKey });
59
58
  }
60
59
 
61
- async retrieve(channels: Params): Promise<Payload[]> {
60
+ async retrieve(channels: Params, rangeKey?: string): Promise<Payload[]> {
62
61
  const { variant, normalized } = analyzeParams(channels);
63
- return await this.execute({ [variant]: normalized });
62
+ return await this.execute({ [variant]: normalized, rangeKey});
64
63
  }
65
64
 
66
- async page(offset: number, limit: number): Promise<Payload[]> {
67
- return await this.execute({ offset, limit });
65
+ async page(offset: number, limit: number, rangeKey?: string): Promise<Payload[]> {
66
+ return await this.execute({ offset, limit, rangeKey});
68
67
  }
69
68
 
70
69
  private async execute(request: Request): Promise<Payload[]> {
@@ -85,12 +84,12 @@ export class CacheRetriever implements Retriever {
85
84
  this.wrapped = wrapped;
86
85
  }
87
86
 
88
- async search(term: string, searchRangeKey?: string): Promise<Payload[]> {
89
- return await this.wrapped.search(term, searchRangeKey);
87
+ async search(term: string, rangeKey?: string): Promise<Payload[]> {
88
+ return await this.wrapped.search(term, rangeKey);
90
89
  }
91
90
 
92
- async page(offset: number, limit: number): Promise<Payload[]> {
93
- return await this.wrapped.page(offset, limit);
91
+ async page(offset: number, limit: number, rangeKey?: string): Promise<Payload[]> {
92
+ return await this.wrapped.page(offset, limit, rangeKey);
94
93
  }
95
94
 
96
95
  async retrieve(channels: Params): Promise<Payload[]> {
@@ -149,8 +148,7 @@ export type ParamAnalysisResult =
149
148
  };
150
149
 
151
150
  export const analyzeParams = (channels: Params): ParamAnalysisResult => {
152
- const normal = toArray(channels) as KeysOrNames;
153
- if (normal.length === 0) throw new QueryError("No channels provided");
151
+ const normal = (toArray(channels) as KeysOrNames).filter((c) => c != 0);
154
152
  return {
155
153
  single: !Array.isArray(channels),
156
154
  variant: typeof normal[0] === "number" ? "keys" : "names",
package/src/client.ts CHANGED
@@ -20,6 +20,10 @@ import { ontology } from "@/ontology";
20
20
  import { ranger } from "@/ranger";
21
21
  import { Transport } from "@/transport";
22
22
  import { workspace } from "@/workspace";
23
+ import { hardware } from "./hardware";
24
+ import { device } from "./hardware/device";
25
+ import { rack } from "./hardware/rack";
26
+ import { task } from "./hardware/task";
23
27
 
24
28
  export const synnaxPropsZ = z.object({
25
29
  host: z.string().min(1),
@@ -28,6 +32,7 @@ export const synnaxPropsZ = z.object({
28
32
  password: z.string().optional(),
29
33
  connectivityPollFrequency: TimeSpan.z.default(TimeSpan.seconds(30)),
30
34
  secure: z.boolean().optional().default(false),
35
+ name: z.string().optional(),
31
36
  });
32
37
 
33
38
  export type SynnaxProps = z.input<typeof synnaxPropsZ>;
@@ -54,6 +59,7 @@ export default class Synnax {
54
59
  readonly props: ParsedSynnaxProps;
55
60
  readonly workspaces: workspace.Client;
56
61
  readonly labels: label.Client;
62
+ readonly hardware: hardware.Client;
57
63
  static readonly connectivity = connection.Checker;
58
64
 
59
65
  /**
@@ -94,6 +100,7 @@ export default class Synnax {
94
100
  this.connectivity = new connection.Checker(
95
101
  this.transport.unary,
96
102
  connectivityPollFrequency,
103
+ props.name,
97
104
  );
98
105
  this.ontology = new ontology.Client(this.transport.unary, this.telem);
99
106
  const rangeRetriever = new ranger.Retriever(this.transport.unary);
@@ -108,6 +115,22 @@ export default class Synnax {
108
115
  this.labels,
109
116
  );
110
117
  this.workspaces = new workspace.Client(this.transport.unary);
118
+ const devices = new device.Client(
119
+ new device.Retriever(this.transport.unary),
120
+ new device.Writer(this.transport.unary),
121
+ this.telem,
122
+ );
123
+ const taskRetriever = new task.Retriever(this.transport.unary);
124
+ const taskWriter = new task.Writer(this.transport.unary);
125
+ const tasks = new task.Client(taskRetriever, taskWriter);
126
+ const racks = new rack.Client(
127
+ new rack.Retriever(this.transport.unary),
128
+ new rack.Writer(this.transport.unary),
129
+ this.telem,
130
+ taskWriter,
131
+ taskRetriever,
132
+ );
133
+ this.hardware = new hardware.Client(tasks, racks, devices);
111
134
  }
112
135
 
113
136
  close(): void {
@@ -42,6 +42,7 @@ export class Checker {
42
42
  private readonly _state: State;
43
43
  private readonly pollFrequency = TimeSpan.seconds(30);
44
44
  private readonly client: UnaryClient;
45
+ private readonly name?: string;
45
46
  private interval?: NodeJS.Timeout;
46
47
  private readonly onChangeHandlers: Array<(state: State) => void> = [];
47
48
  static readonly connectionStateZ = state;
@@ -51,10 +52,11 @@ export class Checker {
51
52
  * @param pollFreq - The frequency at which to poll the cluster for
52
53
  * connectivity information.
53
54
  */
54
- constructor(client: UnaryClient, pollFreq: TimeSpan = TimeSpan.seconds(30)) {
55
+ constructor(client: UnaryClient, pollFreq: TimeSpan = TimeSpan.seconds(30), name?: string) {
55
56
  this._state = { ...DEFAULT };
56
57
  this.client = client;
57
58
  this.pollFrequency = pollFreq;
59
+ this.name = name;
58
60
  void this.check();
59
61
  this.startChecking();
60
62
  }
@@ -74,7 +76,7 @@ export class Checker {
74
76
  const [res, err] = await this.client.send(Checker.ENDPOINT, null, responseZ);
75
77
  if (err != null) throw err;
76
78
  this._state.status = "connected";
77
- this._state.message = `Connected to cluster ${res.clusterKey}`;
79
+ this._state.message = `Connected to ${this.name ?? "cluster"}`;
78
80
  this._state.clusterKey = res.clusterKey;
79
81
  } catch (err) {
80
82
  this._state.status = "failed";
@@ -19,9 +19,9 @@ describe("framer.Frame", () => {
19
19
  const f = new framer.Frame(
20
20
  ["a", "b", "c"],
21
21
  [
22
- new Series(new Float32Array([1, 2, 3])),
23
- new Series(new Float32Array([1, 2, 3])),
24
- new Series(new Float32Array([1, 2, 3])),
22
+ new Series({data: new Float32Array([1, 2, 3])}),
23
+ new Series({data: new Float32Array([1, 2, 3])}),
24
+ new Series({data: new Float32Array([1, 2, 3])}),
25
25
  ],
26
26
  );
27
27
  expect(f.length).toEqual(9);
@@ -32,9 +32,9 @@ describe("framer.Frame", () => {
32
32
  const f = new framer.Frame(
33
33
  [12, 13, 14],
34
34
  [
35
- new Series(new Float32Array([1, 2, 3])),
36
- new Series(new Float32Array([1, 2, 3])),
37
- new Series(new Float32Array([1, 2, 3])),
35
+ new Series({data: new Float32Array([1, 2, 3])}),
36
+ new Series({data: new Float32Array([1, 2, 3])}),
37
+ new Series({data: new Float32Array([1, 2, 3])}),
38
38
  ],
39
39
  );
40
40
  expect(f.length).toEqual(9);
@@ -42,25 +42,25 @@ describe("framer.Frame", () => {
42
42
  });
43
43
 
44
44
  test("from a single name and an array of arrays", () => {
45
- const f = new framer.Frame("a", [new Series(new Float32Array([1, 2, 3]))]);
45
+ const f = new framer.Frame("a", [new Series({data: new Float32Array([1, 2, 3])})]);
46
46
  expect(f.length).toEqual(3);
47
47
  expect(f.colType).toEqual("name");
48
48
  });
49
49
 
50
50
  test("from a single key and an array of arrays", () => {
51
- const f = new framer.Frame(12, [new Series(new Float32Array([1, 2, 3]))]);
51
+ const f = new framer.Frame(12, [new Series({data: new Float32Array([1, 2, 3])})]);
52
52
  expect(f.length).toEqual(3);
53
53
  expect(f.colType).toEqual("key");
54
54
  });
55
55
 
56
56
  test("from a single key and a single array", () => {
57
- const f = new framer.Frame(12, new Series(new Float32Array([1, 2, 3])));
57
+ const f = new framer.Frame(12, new Series({data: new Float32Array([1, 2, 3])}));
58
58
  expect(f.length).toEqual(3);
59
59
  expect(f.colType).toEqual("key");
60
60
  });
61
61
 
62
62
  test("from a single name and a single array", () => {
63
- const f = new framer.Frame("a", new Series(new Float32Array([1, 2, 3])));
63
+ const f = new framer.Frame("a", new Series({data: new Float32Array([1, 2, 3])}));
64
64
  expect(f.length).toEqual(3);
65
65
  expect(f.colType).toEqual("name");
66
66
  });
@@ -82,7 +82,7 @@ describe("framer.Frame", () => {
82
82
 
83
83
  test("from record", () => {
84
84
  const f = new framer.Frame({
85
- a: new Series(new Float32Array([1, 2, 3])),
85
+ a: new Series({data: new Float32Array([1, 2, 3])}),
86
86
  });
87
87
  expect(f.length.valueOf()).toEqual(3);
88
88
  expect(f.columns.length).toEqual(1);
@@ -91,7 +91,7 @@ describe("framer.Frame", () => {
91
91
 
92
92
  test("from map", () => {
93
93
  const f = new framer.Frame(
94
- new Map([[12, new Series(new Float32Array([1, 2, 3]))]]),
94
+ new Map([[12, new Series({data: new Float32Array([1, 2, 3])})]]),
95
95
  );
96
96
  expect(f.length).toEqual(3);
97
97
  expect(f.columns.length).toEqual(1);
@@ -106,8 +106,8 @@ describe("framer.Frame", () => {
106
106
  new framer.Frame(
107
107
  ["a", "b", "c"],
108
108
  [
109
- new Series(new Float32Array([1, 2, 3])),
110
- new Series(new Float32Array([1, 2, 3])),
109
+ new Series({data: new Float32Array([1, 2, 3])}),
110
+ new Series({data: new Float32Array([1, 2, 3])}),
111
111
  ],
112
112
  ),
113
113
  ).toThrow();
@@ -119,12 +119,12 @@ describe("framer.Frame", () => {
119
119
  it("should return false if a key has more than one array", () => {
120
120
  const f = new framer.Frame(
121
121
  new Map([
122
- [12, [new Series(new Float32Array([1, 2, 3]))]],
122
+ [12, [new Series({data: new Float32Array([1, 2, 3])})]],
123
123
  [
124
124
  13,
125
125
  [
126
- new Series(new Float32Array([1, 2, 3])),
127
- new Series(new Float32Array([1, 2, 3])),
126
+ new Series({data: new Float32Array([1, 2, 3])}),
127
+ new Series({data: new Float32Array([1, 2, 3])}),
128
128
  ],
129
129
  ],
130
130
  ]),
@@ -137,8 +137,8 @@ describe("framer.Frame", () => {
137
137
  it("should return false if there is more than one key", () => {
138
138
  const f = new framer.Frame(
139
139
  new Map([
140
- [12, [new Series(new Float32Array([1, 2, 3]))]],
141
- [13, [new Series(new Float32Array([1, 2, 3]))]],
140
+ [12, [new Series({data: new Float32Array([1, 2, 3])})]],
141
+ [13, [new Series({data: new Float32Array([1, 2, 3])})]],
142
142
  ]),
143
143
  );
144
144
  expect(f.isHorizontal).toEqual(false);
@@ -152,21 +152,19 @@ describe("framer.Frame", () => {
152
152
  [
153
153
  12,
154
154
  [
155
- new Series(
156
- new Float32Array([1, 2, 3]),
157
- undefined,
158
- new TimeRange(500, 50000),
159
- ),
155
+ new Series({
156
+ data: new Float32Array([1, 2, 3]),
157
+ timeRange: new TimeRange(500, 50000),
158
+ }),
160
159
  ],
161
160
  ],
162
161
  [
163
162
  13,
164
163
  [
165
- new Series(
166
- new Float32Array([1, 2, 3]),
167
- undefined,
168
- new TimeRange(500, 50000),
169
- ),
164
+ new Series({
165
+ data: new Float32Array([1, 2, 3]),
166
+ timeRange: new TimeRange(500, 50000),
167
+ }),
170
168
  ],
171
169
  ],
172
170
  ]),
@@ -180,21 +178,19 @@ describe("framer.Frame", () => {
180
178
  [
181
179
  12,
182
180
  [
183
- new Series(
184
- new Float32Array([1, 2, 3]),
185
- undefined,
186
- new TimeRange(500, 50000),
187
- ),
181
+ new Series({
182
+ data: new Float32Array([1, 2, 3]),
183
+ timeRange: new TimeRange(500, 50000),
184
+ }),
188
185
  ],
189
186
  ],
190
187
  [
191
188
  13,
192
189
  [
193
- new Series(
194
- new Float32Array([1, 2, 3]),
195
- undefined,
196
- new TimeRange(500, 50001),
197
- ),
190
+ new Series({
191
+ data: new Float32Array([1, 2, 3]),
192
+ timeRange: new TimeRange(500, 50001),
193
+ }),
198
194
  ],
199
195
  ],
200
196
  ]),
@@ -211,21 +207,19 @@ describe("framer.Frame", () => {
211
207
  [
212
208
  12,
213
209
  [
214
- new Series(
215
- new Float32Array([1, 2, 3]),
216
- undefined,
217
- new TimeRange(40, 50000),
218
- ),
210
+ new Series({
211
+ data: new Float32Array([1, 2, 3]),
212
+ timeRange: new TimeRange(40, 50000),
213
+ }),
219
214
  ],
220
215
  ],
221
216
  [
222
217
  13,
223
218
  [
224
- new Series(
225
- new Float32Array([1, 2, 3]),
226
- undefined,
227
- new TimeRange(500, 50001),
228
- ),
219
+ new Series({
220
+ data: new Float32Array([1, 2, 3]),
221
+ timeRange: new TimeRange(500, 50001),
222
+ }),
229
223
  ],
230
224
  ],
231
225
  ]),
@@ -237,16 +231,14 @@ describe("framer.Frame", () => {
237
231
  describe("key provided", () => {
238
232
  it("should return the time range of the key", () => {
239
233
  const f = new framer.Frame({
240
- a: new Series(
241
- new Float32Array([1, 2, 3]),
242
- undefined,
243
- new TimeRange(40, 50000),
244
- ),
245
- b: new Series(
246
- new Float32Array([1, 2, 3]),
247
- undefined,
248
- new TimeRange(500, 50001),
249
- ),
234
+ a: new Series({
235
+ data: new Float32Array([1, 2, 3]),
236
+ timeRange: new TimeRange(40, 50000),
237
+ }),
238
+ b: new Series({
239
+ data: new Float32Array([1, 2, 3]),
240
+ timeRange: new TimeRange(500, 50001),
241
+ }),
250
242
  });
251
243
  expect(f.timeRange("a")).toEqual(new TimeRange(40, 50000));
252
244
  });
@@ -259,21 +251,19 @@ describe("framer.Frame", () => {
259
251
  [
260
252
  12,
261
253
  [
262
- new Series(
263
- new Float32Array([1, 2, 3]),
264
- undefined,
265
- new TimeRange(40, 50000),
266
- ),
254
+ new Series({
255
+ data: new Float32Array([1, 2, 3]),
256
+ timeRange: new TimeRange(40, 50000),
257
+ }),
267
258
  ],
268
259
  ],
269
260
  [
270
261
  13,
271
262
  [
272
- new Series(
273
- new Float32Array([1, 2, 3]),
274
- undefined,
275
- new TimeRange(500, 50001),
276
- ),
263
+ new Series({
264
+ data: new Float32Array([1, 2, 3]),
265
+ timeRange: new TimeRange(500, 50001),
266
+ }),
277
267
  ],
278
268
  ],
279
269
  ]),
@@ -290,21 +280,19 @@ describe("framer.Frame", () => {
290
280
  [
291
281
  12,
292
282
  [
293
- new Series(
294
- new Float32Array([1, 2, 3]),
295
- undefined,
296
- new TimeRange(40, 50000),
297
- ),
283
+ new Series({
284
+ data: new Float32Array([1, 2, 3]),
285
+ timeRange: new TimeRange(40, 50000),
286
+ }),
298
287
  ],
299
288
  ],
300
289
  [
301
290
  13,
302
291
  [
303
- new Series(
304
- new Float32Array([1, 2, 3]),
305
- undefined,
306
- new TimeRange(500, 50001),
307
- ),
292
+ new Series({
293
+ data: new Float32Array([1, 2, 3]),
294
+ timeRange: new TimeRange(500, 50001),
295
+ }),
308
296
  ],
309
297
  ],
310
298
  ]),
@@ -399,7 +399,7 @@ export type FramePayload = z.infer<typeof frameZ>;
399
399
 
400
400
  export const seriesFromPayload = (series: SeriesPayload): Series => {
401
401
  const { dataType, data, timeRange, alignment } = series;
402
- return new Series(data, dataType, timeRange, 0, "static", alignment);
402
+ return new Series({data, dataType, timeRange, glBufferUsage: "static", alignment});
403
403
  };
404
404
 
405
405
  export const seriesToPayload = (series: Series): SeriesPayload => {
@@ -168,7 +168,7 @@ export class Writer {
168
168
  ): Promise<boolean> {
169
169
  const isKeyOrName = ["string", "number"].includes(typeof frame);
170
170
  if (isKeyOrName) {
171
- frame = new Frame(frame, new Series(data as NativeTypedArray));
171
+ frame = new Frame(frame, new Series({data: data as NativeTypedArray}));
172
172
  }
173
173
  frame = this.adapter.adapt(new Frame(frame));
174
174
  // @ts-expect-error
@@ -0,0 +1,24 @@
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 { type device } from "@/hardware/device";
11
+ import { type rack } from "@/hardware/rack";
12
+ import { type task } from "@/hardware/task";
13
+
14
+ export class Client {
15
+ readonly tasks: task.Client;
16
+ readonly racks: rack.Client;
17
+ readonly devices: device.Client;
18
+
19
+ constructor(tasks: task.Client, racks: rack.Client, devices: device.Client) {
20
+ this.tasks = tasks;
21
+ this.racks = racks;
22
+ this.devices = devices;
23
+ }
24
+ }
@@ -0,0 +1,54 @@
1
+ import { toArray } from "@synnaxlabs/x";
2
+
3
+ import { type framer } from "@/framer";
4
+ import { type Device, deviceZ } from "@/hardware/device/payload";
5
+ import { type Retriever } from "@/hardware/device/retriever";
6
+ import { type Writer } from "@/hardware/device/writer";
7
+ import { signals } from "@/signals";
8
+
9
+ const DEVICE_SET_NAME = "sy_device_set";
10
+ const DEVICE_DELETE_NAME = "sy_device_delete";
11
+
12
+ export class Client {
13
+ private readonly retriever: Retriever;
14
+ private readonly writer: Writer;
15
+ private readonly frameClient: framer.Client;
16
+
17
+ constructor(retriever: Retriever, writer: Writer, frameClient: framer.Client) {
18
+ this.retriever = retriever;
19
+ this.writer = writer;
20
+ this.frameClient = frameClient;
21
+ }
22
+
23
+ async create(device: Device): Promise<Device> {
24
+ const res = await this.writer.create([device]);
25
+ return res[0];
26
+ }
27
+
28
+ async retrieve(key: string): Promise<Device>;
29
+ async retrieve(keys: string[]): Promise<Device[]>;
30
+
31
+ async retrieve(keys: string | string[]): Promise<Device | Device[]> {
32
+ const res = await this.retriever.retrieve(toArray(keys));
33
+ return Array.isArray(keys) ? res : res[0];
34
+ }
35
+
36
+ async delete(keys: string[]): Promise<void> {
37
+ await this.writer.delete(keys);
38
+ }
39
+
40
+ async openDeviceTracker(): Promise<signals.Observable<string, Device>> {
41
+ return await signals.Observable.open<string, Device>(
42
+ this.frameClient,
43
+ DEVICE_SET_NAME,
44
+ DEVICE_DELETE_NAME,
45
+ decodeDeviceChanges,
46
+ );
47
+ }
48
+ }
49
+
50
+ const decodeDeviceChanges: signals.Decoder<string, Device> = (variant, data) => {
51
+ if (variant === "delete")
52
+ return data.toStrings().map((k) => ({ variant, key: k, value: undefined }));
53
+ return data.parseJSON(deviceZ).map((d) => ({ variant, key: d.key, value: d }));
54
+ };
@@ -0,0 +1,45 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ import { newClient } from "@/setupspecs";
4
+
5
+ const client = newClient();
6
+
7
+ describe("Device", () => {
8
+ describe("Device", () => {
9
+ describe("create", () => {
10
+ it("should create a device on a rack", async () => {
11
+ const rack = await client.hardware.racks.create({ name: "test" });
12
+ const d = await client.hardware.devices.create({
13
+ rack: rack.key,
14
+ location: "Dev1",
15
+ key: "SN222",
16
+ name: "test",
17
+ make: "ni",
18
+ model: "dog",
19
+ properties: "dog",
20
+ });
21
+ expect(d.key).toEqual("SN222");
22
+ expect(d.name).toBe("test");
23
+ expect(d.make).toBe("ni");
24
+ });
25
+ });
26
+ describe("retrieve", () => {
27
+ it("should retrieve a device by its key", async () => {
28
+ const rack = await client.hardware.racks.create({ name: "test" });
29
+ const d = await client.hardware.devices.create({
30
+ key: "SN222",
31
+ rack: rack.key,
32
+ location: "Dev1",
33
+ name: "test",
34
+ make: "ni",
35
+ model: "dog",
36
+ properties: "dog",
37
+ });
38
+ const retrieved = await client.hardware.devices.retrieve(d.key);
39
+ expect(retrieved.key).toBe(d.key);
40
+ expect(retrieved.name).toBe("test");
41
+ expect(retrieved.make).toBe("ni");
42
+ });
43
+ });
44
+ });
45
+ });