@synnaxlabs/client 0.33.0 → 0.35.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 (107) hide show
  1. package/.turbo/turbo-build.log +7 -7
  2. package/dist/access/policy/payload.d.ts +40 -40
  3. package/dist/access/policy/retriever.d.ts +5 -5
  4. package/dist/auth/auth.d.ts.map +1 -1
  5. package/dist/channel/writer.d.ts.map +1 -1
  6. package/dist/client.cjs +29 -29
  7. package/dist/client.js +1880 -1686
  8. package/dist/control/client.d.ts.map +1 -1
  9. package/dist/control/state.d.ts.map +1 -1
  10. package/dist/errors.d.ts +3 -3
  11. package/dist/errors.d.ts.map +1 -1
  12. package/dist/framer/adapter.d.ts.map +1 -1
  13. package/dist/framer/client.d.ts.map +1 -1
  14. package/dist/framer/deleter.d.ts.map +1 -1
  15. package/dist/framer/frame.d.ts.map +1 -1
  16. package/dist/framer/writer.d.ts.map +1 -1
  17. package/dist/hardware/device/client.d.ts +2 -2
  18. package/dist/hardware/device/client.d.ts.map +1 -1
  19. package/dist/hardware/device/payload.d.ts.map +1 -1
  20. package/dist/hardware/rack/client.d.ts.map +1 -1
  21. package/dist/hardware/task/client.d.ts +5 -3
  22. package/dist/hardware/task/client.d.ts.map +1 -1
  23. package/dist/hardware/task/ni/types.d.ts.map +1 -1
  24. package/dist/hardware/task/payload.d.ts +7 -3
  25. package/dist/hardware/task/payload.d.ts.map +1 -1
  26. package/dist/index.d.ts +1 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/label/client.d.ts.map +1 -1
  29. package/dist/label/writer.d.ts +5 -5
  30. package/dist/ontology/client.d.ts +8 -8
  31. package/dist/ontology/client.d.ts.map +1 -1
  32. package/dist/ontology/payload.d.ts +43 -43
  33. package/dist/ontology/payload.d.ts.map +1 -1
  34. package/dist/ranger/alias.d.ts.map +1 -1
  35. package/dist/ranger/client.d.ts.map +1 -1
  36. package/dist/ranger/kv.d.ts.map +1 -1
  37. package/dist/ranger/payload.d.ts.map +1 -1
  38. package/dist/ranger/writer.d.ts +5 -5
  39. package/dist/util/telem.d.ts.map +1 -1
  40. package/dist/workspace/client.d.ts +2 -0
  41. package/dist/workspace/client.d.ts.map +1 -1
  42. package/dist/workspace/lineplot/payload.d.ts.map +1 -1
  43. package/dist/workspace/log/payload.d.ts.map +1 -1
  44. package/dist/workspace/payload.d.ts.map +1 -1
  45. package/dist/workspace/schematic/payload.d.ts.map +1 -1
  46. package/dist/workspace/table/client.d.ts +16 -0
  47. package/dist/workspace/table/client.d.ts.map +1 -0
  48. package/dist/workspace/table/external.d.ts +3 -0
  49. package/dist/workspace/table/external.d.ts.map +1 -0
  50. package/dist/workspace/table/index.d.ts +2 -0
  51. package/dist/workspace/table/index.d.ts.map +1 -0
  52. package/dist/workspace/table/payload.d.ts +36 -0
  53. package/dist/workspace/table/payload.d.ts.map +1 -0
  54. package/dist/workspace/table/retriever.d.ts +8 -0
  55. package/dist/workspace/table/retriever.d.ts.map +1 -0
  56. package/dist/workspace/table/table.spec.d.ts +2 -0
  57. package/dist/workspace/table/table.spec.d.ts.map +1 -0
  58. package/dist/workspace/table/writer.d.ts +35 -0
  59. package/dist/workspace/table/writer.d.ts.map +1 -0
  60. package/eslint.config.js +1 -1
  61. package/package.json +12 -12
  62. package/src/access/policy/policy.spec.ts +2 -4
  63. package/src/auth/auth.spec.ts +1 -1
  64. package/src/auth/auth.ts +17 -18
  65. package/src/channel/writer.ts +2 -2
  66. package/src/connection/checker.ts +1 -1
  67. package/src/control/client.ts +1 -1
  68. package/src/control/state.ts +1 -1
  69. package/src/errors.spec.ts +1 -1
  70. package/src/errors.ts +14 -15
  71. package/src/framer/adapter.ts +5 -6
  72. package/src/framer/client.ts +9 -4
  73. package/src/framer/deleter.ts +1 -1
  74. package/src/framer/frame.ts +9 -11
  75. package/src/framer/iterator.spec.ts +2 -3
  76. package/src/framer/writer.ts +1 -1
  77. package/src/hardware/device/client.ts +13 -7
  78. package/src/hardware/device/payload.ts +1 -1
  79. package/src/hardware/rack/client.ts +3 -3
  80. package/src/hardware/task/client.ts +64 -14
  81. package/src/hardware/task/ni/types.ts +1 -1
  82. package/src/hardware/task/payload.ts +22 -7
  83. package/src/hardware/task/task.spec.ts +1 -1
  84. package/src/index.ts +1 -0
  85. package/src/label/client.ts +1 -1
  86. package/src/ontology/client.ts +1 -3
  87. package/src/ontology/group/payload.ts +2 -2
  88. package/src/ontology/payload.ts +2 -1
  89. package/src/ranger/alias.ts +2 -3
  90. package/src/ranger/client.ts +7 -9
  91. package/src/ranger/kv.ts +2 -2
  92. package/src/ranger/payload.ts +2 -2
  93. package/src/ranger/ranger.spec.ts +2 -2
  94. package/src/user/user.spec.ts +1 -2
  95. package/src/util/telem.ts +1 -3
  96. package/src/workspace/client.ts +3 -0
  97. package/src/workspace/lineplot/payload.ts +1 -1
  98. package/src/workspace/log/payload.ts +1 -1
  99. package/src/workspace/payload.ts +1 -1
  100. package/src/workspace/schematic/payload.ts +1 -1
  101. package/src/workspace/table/client.ts +51 -0
  102. package/src/workspace/table/external.ts +11 -0
  103. package/src/workspace/table/index.ts +10 -0
  104. package/src/workspace/table/payload.ts +36 -0
  105. package/src/workspace/table/retriever.ts +33 -0
  106. package/src/workspace/table/table.spec.ts +65 -0
  107. package/src/workspace/table/writer.ts +102 -0
@@ -19,18 +19,21 @@ import { framer } from "@/framer";
19
19
  import { type Frame } from "@/framer/frame";
20
20
  import { rack } from "@/hardware/rack";
21
21
  import {
22
- NewTask,
22
+ type Command,
23
+ type CommandObservable,
24
+ commandZ,
25
+ type NewTask,
23
26
  newTaskZ,
24
- Payload,
25
- State,
26
- StateObservable,
27
+ type Payload,
28
+ type State,
29
+ type StateObservable,
27
30
  stateZ,
28
- TaskKey,
31
+ type TaskKey,
29
32
  taskKeyZ,
30
33
  taskZ,
31
34
  } from "@/hardware/task/payload";
32
35
  import { ontology } from "@/ontology";
33
- import { ranger } from "@/ranger";
36
+ import { type ranger } from "@/ranger";
34
37
  import { signals } from "@/signals";
35
38
  import { analyzeParams, checkForMultipleOrNoResults } from "@/util/retrieve";
36
39
  import { nullableArrayZ } from "@/util/zod";
@@ -46,7 +49,7 @@ export class Task<
46
49
  T extends string = string,
47
50
  > {
48
51
  readonly key: TaskKey;
49
- readonly name: string;
52
+ name: string;
50
53
  readonly internal: boolean;
51
54
  readonly type: T;
52
55
  config: C;
@@ -123,9 +126,7 @@ export class Task<
123
126
  if (parsed.success) {
124
127
  res = parsed.data as State<D>;
125
128
  if (res.key === cmdKey) break;
126
- } else {
127
- console.error(parsed.error);
128
- }
129
+ } else console.error(parsed.error);
129
130
  }
130
131
  streamer.close();
131
132
  return res;
@@ -141,7 +142,10 @@ export class Task<
141
142
  const s = frame.get(TASK_STATE_CHANNEL);
142
143
  if (s.length === 0) return [null, false];
143
144
  const parse = stateZ.safeParse(s.at(-1));
144
- if (!parse.success) return [null, false];
145
+ if (!parse.success) {
146
+ console.error(parse.error);
147
+ return [null, false];
148
+ }
145
149
  const state = parse.data as State<D>;
146
150
  if (state.task !== this.key) return [null, false];
147
151
  return [state, true];
@@ -149,6 +153,27 @@ export class Task<
149
153
  );
150
154
  }
151
155
 
156
+ async openCommandObserver<A extends UnknownRecord = UnknownRecord>(): Promise<
157
+ CommandObservable<A>
158
+ > {
159
+ if (this.frameClient == null) throw TASK_NOT_CREATED;
160
+ return new framer.ObservableStreamer<Command<A>>(
161
+ await this.frameClient.openStreamer(TASK_CMD_CHANNEL),
162
+ (frame) => {
163
+ const s = frame.get(TASK_CMD_CHANNEL);
164
+ if (s.length === 0) return [null, false];
165
+ const parse = commandZ.safeParse(s.at(-1));
166
+ if (!parse.success) {
167
+ console.error(parse.error);
168
+ return [null, false];
169
+ }
170
+ const cmd = parse.data as Command<A>;
171
+ if (cmd.task !== this.key) return [null, false];
172
+ return [cmd, true];
173
+ },
174
+ );
175
+ }
176
+
152
177
  async snapshottedTo(): Promise<ontology.Resource | null> {
153
178
  if (this.ontologyClient == null || this.rangeClient == null) throw TASK_NOT_CREATED;
154
179
  if (!this.snapshot) return null;
@@ -316,10 +341,14 @@ export class Client implements AsyncTermSearcher<string, TaskKey, Payload> {
316
341
  return this.sugar([res.task])[0];
317
342
  }
318
343
 
319
- async retrieveByName(name: string, rack?: number): Promise<Task> {
344
+ async retrieveByName<
345
+ C extends UnknownRecord = UnknownRecord,
346
+ D extends {} = UnknownRecord,
347
+ T extends string = string,
348
+ >(name: string, rack?: number): Promise<Task<C, D, T>> {
320
349
  const tasks = await this.execRetrieve({ names: [name], rack });
321
350
  checkForMultipleOrNoResults("Task", name, tasks, true);
322
- return this.sugar(tasks)[0];
351
+ return this.sugar(tasks)[0] as Task<C, D, T>;
323
352
  }
324
353
 
325
354
  private async execRetrieve(req: RetrieveRequest): Promise<Payload[]> {
@@ -374,9 +403,30 @@ export class Client implements AsyncTermSearcher<string, TaskKey, Payload> {
374
403
  const s = frame.get(TASK_STATE_CHANNEL);
375
404
  if (s.length === 0) return [null, false];
376
405
  const parse = stateZ.safeParse(s.at(-1));
377
- if (!parse.success) return [null, false];
406
+ if (!parse.success) {
407
+ console.error(parse.error);
408
+ return [null, false];
409
+ }
378
410
  return [parse.data as State<D>, true];
379
411
  },
380
412
  );
381
413
  }
414
+
415
+ async openCommandObserver<A extends UnknownRecord = UnknownRecord>(): Promise<
416
+ CommandObservable<A>
417
+ > {
418
+ return new framer.ObservableStreamer<Command<A>>(
419
+ await this.frameClient.openStreamer(TASK_CMD_CHANNEL),
420
+ (frame) => {
421
+ const s = frame.get(TASK_CMD_CHANNEL);
422
+ if (s.length === 0) return [null, false];
423
+ const parse = commandZ.safeParse(s.at(-1));
424
+ if (!parse.success) {
425
+ console.error(parse.error);
426
+ return [null, false];
427
+ }
428
+ return [parse.data as Command<A>, true];
429
+ },
430
+ );
431
+ }
382
432
  }
@@ -10,7 +10,7 @@
10
10
  import { z } from "zod";
11
11
 
12
12
  import { device } from "@/hardware/device";
13
- import { task } from "@/hardware/task";
13
+ import { type task } from "@/hardware/task";
14
14
 
15
15
  export const unitsVoltsZ = z.literal("Volts");
16
16
  export type UnitsVolts = z.infer<typeof unitsVoltsZ>;
@@ -7,7 +7,7 @@
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 { binary, observe, UnknownRecord } from "@synnaxlabs/x";
10
+ import { binary, type observe, type UnknownRecord } from "@synnaxlabs/x";
11
11
  import { z } from "zod";
12
12
 
13
13
  import { ontology } from "@/ontology";
@@ -85,17 +85,32 @@ export const commandZ = z.object({
85
85
  task: taskKeyZ,
86
86
  type: z.string(),
87
87
  key: z.string(),
88
- args: z.record(z.unknown()).or(
89
- z.string().transform((c) => {
90
- if (c === "") return {};
91
- return JSON.parse(c);
92
- }),
93
- ) as z.ZodType<UnknownRecord>,
88
+ args: z
89
+ .record(z.unknown())
90
+ .or(
91
+ z.string().transform((c) => {
92
+ if (c === "") return {};
93
+ return JSON.parse(c);
94
+ }),
95
+ )
96
+ .or(z.array(z.unknown()))
97
+ .or(z.null())
98
+ .optional() as z.ZodOptional<z.ZodType<UnknownRecord>>,
94
99
  });
95
100
 
101
+ export type Command<A extends {} = UnknownRecord> = Omit<
102
+ z.infer<typeof commandZ>,
103
+ "args"
104
+ > & {
105
+ args?: A;
106
+ };
107
+
96
108
  export type StateObservable<D extends UnknownRecord = UnknownRecord> =
97
109
  observe.ObservableAsyncCloseable<State<D>>;
98
110
 
111
+ export type CommandObservable<A extends UnknownRecord = UnknownRecord> =
112
+ observe.ObservableAsyncCloseable<Command<A>>;
113
+
99
114
  export const ONTOLOGY_TYPE: ontology.ResourceType = "task";
100
115
 
101
116
  export const ontologyID = (key: TaskKey): ontology.ID =>
@@ -10,7 +10,7 @@
10
10
  import { id } from "@synnaxlabs/x";
11
11
  import { describe, expect, it } from "vitest";
12
12
 
13
- import { task } from "@/hardware/task";
13
+ import { type task } from "@/hardware/task";
14
14
  import { newClient } from "@/setupspecs";
15
15
 
16
16
  const client = newClient();
package/src/index.ts CHANGED
@@ -39,6 +39,7 @@ export { workspace } from "@/workspace";
39
39
  export { linePlot } from "@/workspace/lineplot";
40
40
  export { log } from "@/workspace/log";
41
41
  export { schematic } from "@/workspace/schematic";
42
+ export { table } from "@/workspace/table";
42
43
  export {
43
44
  type CrudeDataType,
44
45
  type CrudeDensity,
@@ -14,7 +14,7 @@ import { type AsyncTermSearcher } from "@synnaxlabs/x/search";
14
14
  import { type framer } from "@/framer";
15
15
  import { type Key, type Label, labelZ } from "@/label/payload";
16
16
  import { Retriever } from "@/label/retriever";
17
- import { type NewLabelPayload, SetOptions, Writer } from "@/label/writer";
17
+ import { type NewLabelPayload, type SetOptions, Writer } from "@/label/writer";
18
18
  import { ontology } from "@/ontology";
19
19
  import { signals } from "@/signals";
20
20
 
@@ -290,9 +290,7 @@ export class ChangeTracker {
290
290
  }
291
291
 
292
292
  private async start(): Promise<void> {
293
- for await (const frame of this.streamer) {
294
- await this.update(frame);
295
- }
293
+ for await (const frame of this.streamer) await this.update(frame);
296
294
  }
297
295
 
298
296
  private async update(frame: framer.Frame): Promise<void> {
@@ -52,9 +52,9 @@ export type ParamAnalysisResult =
52
52
 
53
53
  export const analyzeParams = (groups: Params): ParamAnalysisResult => {
54
54
  const normal = toArray(groups) as Keys | Names;
55
- if (normal.length === 0) {
55
+ if (normal.length === 0)
56
56
  throw new Error("No groups specified");
57
- }
57
+
58
58
  const isKey = keyZ.safeParse(normal[0]).success;
59
59
  return {
60
60
  single: !Array.isArray(groups),
@@ -7,7 +7,7 @@
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 { change, UnknownRecord } from "@synnaxlabs/x";
10
+ import { type change, type UnknownRecord } from "@synnaxlabs/x";
11
11
  import { z } from "zod";
12
12
 
13
13
  export type ResourceChange = change.Change<ID, Resource>;
@@ -37,6 +37,7 @@ export const resourceTypeZ = z.union([
37
37
  z.literal("device"),
38
38
  z.literal("task"),
39
39
  z.literal("policy"),
40
+ z.literal("table"),
40
41
  ]);
41
42
  export type ResourceType = z.infer<typeof resourceTypeZ>;
42
43
 
@@ -12,7 +12,7 @@ import { type change } from "@synnaxlabs/x/change";
12
12
  import { z } from "zod";
13
13
 
14
14
  import { type channel } from "@/channel";
15
- import { type Key as ChannelKey,keyZ as channelKeyZ } from "@/channel/payload";
15
+ import { type Key as ChannelKey, keyZ as channelKeyZ } from "@/channel/payload";
16
16
  import { type Client as FrameClient } from "@/framer/client";
17
17
  import { type Key, keyZ } from "@/ranger/payload";
18
18
  import { signals } from "@/signals";
@@ -161,7 +161,7 @@ const aliasSeparator = "---";
161
161
  const decodeAliasChanges =
162
162
  (rangeKey: Key): signals.Decoder<string, Alias> =>
163
163
  (variant, data) => {
164
- if (variant === "delete") {
164
+ if (variant === "delete")
165
165
  return data
166
166
  .toStrings()
167
167
  .filter((k) => k.split(aliasSeparator)[0] === rangeKey)
@@ -170,7 +170,6 @@ const decodeAliasChanges =
170
170
  key: alias,
171
171
  value: undefined,
172
172
  }));
173
- }
174
173
  return data.parseJSON(aliasZ).map((alias) => ({
175
174
  variant,
176
175
  key: alias.alias,
@@ -8,21 +8,20 @@
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
10
  import { sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
11
- import { CrudeTimeRange, observe, TimeRange } from "@synnaxlabs/x";
11
+ import { type CrudeTimeRange, observe, TimeRange } from "@synnaxlabs/x";
12
12
  import { type AsyncTermSearcher } from "@synnaxlabs/x/search";
13
13
  import { type Series } from "@synnaxlabs/x/telem";
14
14
  import { toArray } from "@synnaxlabs/x/toArray";
15
15
  import { z } from "zod";
16
16
 
17
- import { Key as ChannelKey } from "@/channel/payload";
17
+ import { type Key as ChannelKey } from "@/channel/payload";
18
18
  import { type Retriever as ChannelRetriever } from "@/channel/retriever";
19
- import { MultipleFoundError, NotFoundError } from "@/errors";
20
- import { QueryError } from "@/errors";
19
+ import { MultipleFoundError, NotFoundError, QueryError } from "@/errors";
21
20
  import { type framer } from "@/framer";
22
21
  import { type label } from "@/label";
23
22
  import { type Label } from "@/label/payload";
24
23
  import { ontology } from "@/ontology";
25
- import { Resource } from "@/ontology/payload";
24
+ import { type Resource } from "@/ontology/payload";
26
25
  import { type Alias, Aliaser } from "@/ranger/alias";
27
26
  import { KV } from "@/ranger/kv";
28
27
  import {
@@ -37,7 +36,7 @@ import {
37
36
  type Payload,
38
37
  payloadZ,
39
38
  } from "@/ranger/payload";
40
- import { CreateOptions, type Writer } from "@/ranger/writer";
39
+ import { type CreateOptions, type Writer } from "@/ranger/writer";
41
40
  import { signals } from "@/signals";
42
41
  import { nullableArrayZ } from "@/util/zod";
43
42
 
@@ -98,9 +97,8 @@ export class Range {
98
97
 
99
98
  async setAlias(channel: ChannelKey | Name, alias: string): Promise<void> {
100
99
  const ch = await this.channels.retrieve(channel);
101
- if (ch.length === 0) {
102
- throw new QueryError(`Channel ${channel} does not exist`);
103
- }
100
+ if (ch.length === 0) throw new QueryError(`Channel ${channel} does not exist`);
101
+
104
102
  await this.aliaser.set({ [ch[0].key]: alias });
105
103
  }
106
104
 
package/src/ranger/kv.ts CHANGED
@@ -12,7 +12,7 @@ import { isObject } from "@synnaxlabs/x/identity";
12
12
  import { toArray } from "@synnaxlabs/x/toArray";
13
13
  import { z } from "zod";
14
14
 
15
- import { framer } from "@/framer";
15
+ import { type framer } from "@/framer";
16
16
  import { type Key, keyZ } from "@/ranger/payload";
17
17
  import { signals } from "@/signals";
18
18
  import { nullableArrayZ } from "@/util/zod";
@@ -96,7 +96,7 @@ export class KV {
96
96
  key: k,
97
97
  value: v,
98
98
  }));
99
- else pairs = [{ range: this.rangeKey, key: key, value: value }];
99
+ else pairs = [{ range: this.rangeKey, key, value }];
100
100
  await sendRequired(
101
101
  this.client,
102
102
  KV.SET_ENDPOINT,
@@ -79,7 +79,7 @@ export const ONTOLOGY_TYPE: ontology.ResourceType = "range";
79
79
  export const ALIAS_ONTOLOGY_TYPE: ontology.ResourceType = "range-alias";
80
80
 
81
81
  export const rangeOntologyID = (key: Key): ontology.ID =>
82
- new ontology.ID({ type: ONTOLOGY_TYPE, key: key });
82
+ new ontology.ID({ type: ONTOLOGY_TYPE, key });
83
83
 
84
84
  export const rangeAliasOntologyID = (key: Key): ontology.ID =>
85
- new ontology.ID({ type: ALIAS_ONTOLOGY_TYPE, key: key });
85
+ new ontology.ID({ type: ALIAS_ONTOLOGY_TYPE, key });
@@ -7,12 +7,12 @@
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 { change } from "@synnaxlabs/x";
10
+ import { type change } from "@synnaxlabs/x";
11
11
  import { DataType, Rate, TimeSpan, TimeStamp } from "@synnaxlabs/x/telem";
12
12
  import { describe, expect, it } from "vitest";
13
13
 
14
14
  import { QueryError } from "@/errors";
15
- import { ranger } from "@/ranger";
15
+ import { type ranger } from "@/ranger";
16
16
  import { type NewPayload } from "@/ranger/payload";
17
17
  import { newClient } from "@/setupspecs";
18
18
 
@@ -183,9 +183,8 @@ describe("User", () => {
183
183
  });
184
184
  });
185
185
  test("not found", async () => {
186
- for (const u of userArray) {
186
+ for (const u of userArray)
187
187
  await expect(client.user.delete(u.key as string)).resolves.toBeUndefined();
188
- }
189
188
  await expect(
190
189
  client.user.retrieve(userArray.map((u) => u.key as string)),
191
190
  ).rejects.toThrow(NotFoundError);
package/src/util/telem.ts CHANGED
@@ -12,8 +12,6 @@ import { type DataType, type TypedArray } from "@synnaxlabs/x/telem";
12
12
  export const randomSeries = (length: number, dataType: DataType): TypedArray => {
13
13
  // generate random bytes of the correct length
14
14
  const bytes = new Uint8Array(length * dataType.density.valueOf());
15
- for (let i = 0; i < bytes.byteLength; i++) {
16
- bytes[i] = Math.floor(Math.random() * 256);
17
- }
15
+ for (let i = 0; i < bytes.byteLength; i++) bytes[i] = Math.floor(Math.random() * 256);
18
16
  return new dataType.Array(bytes.buffer);
19
17
  };
@@ -16,6 +16,7 @@ import { log } from "@/workspace/log";
16
16
  import { type Key, type Workspace } from "@/workspace/payload";
17
17
  import { Retriever } from "@/workspace/retriever";
18
18
  import { schematic } from "@/workspace/schematic";
19
+ import { table } from "@/workspace/table";
19
20
  import { type NewWorkspace, Writer } from "@/workspace/writer";
20
21
 
21
22
  export class Client implements AsyncTermSearcher<string, Key, Workspace> {
@@ -23,6 +24,7 @@ export class Client implements AsyncTermSearcher<string, Key, Workspace> {
23
24
  readonly schematic: schematic.Client;
24
25
  readonly linePlot: linePlot.Client;
25
26
  readonly log: log.Client;
27
+ readonly table: table.Client;
26
28
  private readonly retriever: Retriever;
27
29
  private readonly writer: Writer;
28
30
 
@@ -32,6 +34,7 @@ export class Client implements AsyncTermSearcher<string, Key, Workspace> {
32
34
  this.retriever = new Retriever(client);
33
35
  this.log = new log.Client(client);
34
36
  this.writer = new Writer(client);
37
+ this.table = new table.Client(client);
35
38
  }
36
39
 
37
40
  async search(term: string): Promise<Workspace[]> {
@@ -27,4 +27,4 @@ export type LinePlot = z.infer<typeof linePlotZ>;
27
27
  export const ONTOLOGY_TYPE: ontology.ResourceType = "lineplot";
28
28
 
29
29
  export const ontologyID = (key: Key): ontology.ID =>
30
- new ontology.ID({ type: ONTOLOGY_TYPE, key: key });
30
+ new ontology.ID({ type: ONTOLOGY_TYPE, key });
@@ -33,4 +33,4 @@ export type Log = z.infer<typeof logZ>;
33
33
  export const ONTOLOGY_TYPE: ontology.ResourceType = "log";
34
34
 
35
35
  export const ontologyID = (key: Key): ontology.ID =>
36
- new ontology.ID({ type: ONTOLOGY_TYPE, key: key });
36
+ new ontology.ID({ type: ONTOLOGY_TYPE, key });
@@ -41,4 +41,4 @@ export type Workspace = z.infer<typeof workspaceZ>;
41
41
  export const ONTOLOGY_TYPE: ontology.ResourceType = "workspace";
42
42
 
43
43
  export const ontologyID = (key: Key): ontology.ID =>
44
- new ontology.ID({ type: ONTOLOGY_TYPE, key: key });
44
+ new ontology.ID({ type: ONTOLOGY_TYPE, key });
@@ -35,4 +35,4 @@ export type Schematic = z.infer<typeof schematicZ>;
35
35
  export const ONTOLOGY_TYPE: ontology.ResourceType = "schematic";
36
36
 
37
37
  export const ontologyID = (key: Key): ontology.ID =>
38
- new ontology.ID({ type: ONTOLOGY_TYPE, key: key });
38
+ new ontology.ID({ type: ONTOLOGY_TYPE, key });
@@ -0,0 +1,51 @@
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 UnaryClient } from "@synnaxlabs/freighter";
11
+ import { type UnknownRecord } from "@synnaxlabs/x/record";
12
+
13
+ import { type Key, type Params, type Table } from "@/workspace/table/payload";
14
+ import { Retriever } from "@/workspace/table/retriever";
15
+ import { type NewTable, Writer } from "@/workspace/table/writer";
16
+
17
+ export class Client {
18
+ private readonly writer: Writer;
19
+ private readonly retriever: Retriever;
20
+
21
+ constructor(client: UnaryClient) {
22
+ this.writer = new Writer(client);
23
+ this.retriever = new Retriever(client);
24
+ }
25
+
26
+ async create(workspace: string, table: NewTable): Promise<Table> {
27
+ return await this.writer.create(workspace, table);
28
+ }
29
+
30
+ async rename(key: Key, name: string): Promise<void> {
31
+ await this.writer.rename(key, name);
32
+ }
33
+
34
+ async setData(key: Key, data: UnknownRecord): Promise<void> {
35
+ await this.writer.setData(key, data);
36
+ }
37
+
38
+ async retrieve(key: Key): Promise<Table>;
39
+
40
+ async retrieve(keys: Key[]): Promise<Table[]>;
41
+
42
+ async retrieve(keys: Params): Promise<Table | Table[]> {
43
+ const isMany = Array.isArray(keys);
44
+ const res = await this.retriever.retrieve(keys);
45
+ return isMany ? res : res[0];
46
+ }
47
+
48
+ async delete(keys: Params): Promise<void> {
49
+ await this.writer.delete(keys);
50
+ }
51
+ }
@@ -0,0 +1,11 @@
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
+ export * from "@/workspace/table/client";
11
+ export * from "@/workspace/table/payload";
@@ -0,0 +1,10 @@
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
+ export * as table from "@/workspace/table/external";
@@ -0,0 +1,36 @@
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 UnknownRecord, unknownRecordZ } from "@synnaxlabs/x/record";
11
+ import { z } from "zod";
12
+
13
+ import { ontology } from "@/ontology";
14
+
15
+ export const keyZ = z.string().uuid();
16
+ export type Key = z.infer<typeof keyZ>;
17
+ export type Params = Key | Key[];
18
+
19
+ export const tableZ = z.object({
20
+ key: z.string(),
21
+ name: z.string(),
22
+ data: unknownRecordZ.or(z.string().transform((s) => JSON.parse(s) as UnknownRecord)),
23
+ });
24
+
25
+ export const tableRemoteZ = z.object({
26
+ key: z.string(),
27
+ name: z.string(),
28
+ data: z.string().transform((s) => JSON.parse(s) as UnknownRecord),
29
+ });
30
+
31
+ export type Table = z.infer<typeof tableZ>;
32
+
33
+ export const ONTOLOGY_TYPE: ontology.ResourceType = "table";
34
+
35
+ export const ontologyID = (key: Key): ontology.ID =>
36
+ new ontology.ID({ type: ONTOLOGY_TYPE, key });
@@ -0,0 +1,33 @@
1
+ // Copyright 2024 Synnax Labs, Inc.
2
+ //
3
+ // Use of this software is governed by the Business Source License included in the file
4
+ // licenses/BSL.txt.
5
+ //
6
+ // As of the Change Date specified in that file, in accordance with the Business Source
7
+ // License, use of this software will be governed by the Apache License, Version 2.0,
8
+ // included in the file licenses/APL.txt.
9
+
10
+ import { sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
11
+ import { toArray } from "@synnaxlabs/x/toArray";
12
+ import { z } from "zod";
13
+
14
+ import { type Params, type Table, tableRemoteZ } from "@/workspace/table/payload";
15
+
16
+ const reqZ = z.object({ keys: z.string().array() });
17
+ const resZ = z.object({ tables: tableRemoteZ.array() });
18
+
19
+ const ENDPOINT = "/workspace/table/retrieve";
20
+
21
+ export class Retriever {
22
+ private readonly client: UnaryClient;
23
+
24
+ constructor(client: UnaryClient) {
25
+ this.client = client;
26
+ }
27
+
28
+ async retrieve(tables: Params): Promise<Table[]> {
29
+ return (
30
+ await sendRequired(this.client, ENDPOINT, { keys: toArray(tables) }, reqZ, resZ)
31
+ ).tables;
32
+ }
33
+ }