@synnaxlabs/client 0.45.1 → 0.46.1

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 (164) hide show
  1. package/.turbo/turbo-build.log +7 -7
  2. package/dist/access/policy/client.d.ts +38 -26
  3. package/dist/access/policy/client.d.ts.map +1 -1
  4. package/dist/access/policy/payload.d.ts +22 -10
  5. package/dist/access/policy/payload.d.ts.map +1 -1
  6. package/dist/arc/client.d.ts +72 -0
  7. package/dist/arc/client.d.ts.map +1 -0
  8. package/dist/arc/external.d.ts +3 -0
  9. package/dist/arc/external.d.ts.map +1 -0
  10. package/dist/arc/index.d.ts +2 -0
  11. package/dist/arc/index.d.ts.map +1 -0
  12. package/dist/arc/payload.d.ts +155 -0
  13. package/dist/arc/payload.d.ts.map +1 -0
  14. package/dist/channel/client.d.ts +2 -3
  15. package/dist/channel/client.d.ts.map +1 -1
  16. package/dist/channel/payload.d.ts +23 -63
  17. package/dist/channel/payload.d.ts.map +1 -1
  18. package/dist/channel/retriever.d.ts.map +1 -1
  19. package/dist/client.cjs +44 -25
  20. package/dist/client.d.ts +5 -1
  21. package/dist/client.d.ts.map +1 -1
  22. package/dist/client.js +7479 -4756
  23. package/dist/framer/client.d.ts +2 -2
  24. package/dist/framer/client.d.ts.map +1 -1
  25. package/dist/framer/deleter.d.ts +2 -2
  26. package/dist/framer/frame.d.ts +2 -2
  27. package/dist/framer/streamer.d.ts +42 -56
  28. package/dist/framer/streamer.d.ts.map +1 -1
  29. package/dist/framer/writer.d.ts +45 -43
  30. package/dist/framer/writer.d.ts.map +1 -1
  31. package/dist/hardware/device/client.d.ts +5 -6
  32. package/dist/hardware/device/client.d.ts.map +1 -1
  33. package/dist/hardware/device/payload.d.ts +83 -18
  34. package/dist/hardware/device/payload.d.ts.map +1 -1
  35. package/dist/hardware/rack/client.d.ts +4 -5
  36. package/dist/hardware/rack/client.d.ts.map +1 -1
  37. package/dist/hardware/rack/payload.d.ts +81 -17
  38. package/dist/hardware/rack/payload.d.ts.map +1 -1
  39. package/dist/hardware/task/client.d.ts +67 -12
  40. package/dist/hardware/task/client.d.ts.map +1 -1
  41. package/dist/hardware/task/payload.d.ts +18 -51
  42. package/dist/hardware/task/payload.d.ts.map +1 -1
  43. package/dist/index.d.ts +3 -1
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/label/client.d.ts +14 -9
  46. package/dist/label/client.d.ts.map +1 -1
  47. package/dist/label/payload.d.ts +10 -11
  48. package/dist/label/payload.d.ts.map +1 -1
  49. package/dist/ontology/client.d.ts +7 -3
  50. package/dist/ontology/client.d.ts.map +1 -1
  51. package/dist/ontology/group/client.d.ts +45 -9
  52. package/dist/ontology/group/client.d.ts.map +1 -1
  53. package/dist/ontology/group/external.d.ts +0 -1
  54. package/dist/ontology/group/external.d.ts.map +1 -1
  55. package/dist/ontology/group/payload.d.ts +3 -1
  56. package/dist/ontology/group/payload.d.ts.map +1 -1
  57. package/dist/ontology/payload.d.ts +30 -17
  58. package/dist/ontology/payload.d.ts.map +1 -1
  59. package/dist/ontology/writer.d.ts +161 -0
  60. package/dist/ontology/writer.d.ts.map +1 -1
  61. package/dist/ranger/alias.d.ts +1 -1
  62. package/dist/ranger/alias.d.ts.map +1 -1
  63. package/dist/ranger/client.d.ts +9 -8
  64. package/dist/ranger/client.d.ts.map +1 -1
  65. package/dist/ranger/kv.d.ts.map +1 -1
  66. package/dist/ranger/payload.d.ts +5 -5
  67. package/dist/ranger/payload.d.ts.map +1 -1
  68. package/dist/ranger/writer.d.ts +6 -4
  69. package/dist/ranger/writer.d.ts.map +1 -1
  70. package/dist/status/client.d.ts +63 -0
  71. package/dist/status/client.d.ts.map +1 -0
  72. package/dist/status/external.d.ts +3 -0
  73. package/dist/status/external.d.ts.map +1 -0
  74. package/dist/status/index.d.ts +2 -0
  75. package/dist/status/index.d.ts.map +1 -0
  76. package/dist/status/payload.d.ts +32 -0
  77. package/dist/status/payload.d.ts.map +1 -0
  78. package/dist/status/status.spec.d.ts +2 -0
  79. package/dist/status/status.spec.d.ts.map +1 -0
  80. package/dist/user/client.d.ts.map +1 -1
  81. package/dist/user/retriever.d.ts.map +1 -1
  82. package/dist/workspace/client.d.ts +11 -6
  83. package/dist/workspace/client.d.ts.map +1 -1
  84. package/dist/workspace/lineplot/client.d.ts +28 -5
  85. package/dist/workspace/lineplot/client.d.ts.map +1 -1
  86. package/dist/workspace/lineplot/index.d.ts +1 -1
  87. package/dist/workspace/log/client.d.ts +28 -5
  88. package/dist/workspace/log/client.d.ts.map +1 -1
  89. package/dist/workspace/schematic/client.d.ts +35 -6
  90. package/dist/workspace/schematic/client.d.ts.map +1 -1
  91. package/dist/workspace/schematic/symbol/client.d.ts +6 -7
  92. package/dist/workspace/schematic/symbol/client.d.ts.map +1 -1
  93. package/dist/workspace/table/client.d.ts +28 -5
  94. package/dist/workspace/table/client.d.ts.map +1 -1
  95. package/examples/node/package-lock.json +30 -95
  96. package/examples/node/package.json +1 -1
  97. package/package.json +10 -10
  98. package/src/access/policy/client.ts +5 -6
  99. package/src/access/policy/payload.ts +4 -4
  100. package/src/access/policy/policy.spec.ts +4 -4
  101. package/src/arc/client.ts +117 -0
  102. package/src/{util/zod.ts → arc/external.ts} +2 -7
  103. package/src/arc/index.ts +10 -0
  104. package/src/arc/payload.ts +69 -0
  105. package/src/channel/client.ts +3 -4
  106. package/src/channel/payload.ts +4 -6
  107. package/src/channel/retriever.ts +2 -2
  108. package/src/client.ts +8 -2
  109. package/src/errors.spec.ts +1 -1
  110. package/src/framer/client.ts +4 -3
  111. package/src/framer/codec.spec.ts +1 -1
  112. package/src/hardware/device/client.ts +6 -8
  113. package/src/hardware/device/payload.ts +7 -6
  114. package/src/hardware/rack/client.ts +6 -8
  115. package/src/hardware/rack/payload.ts +2 -1
  116. package/src/hardware/task/client.ts +142 -100
  117. package/src/hardware/task/payload.ts +4 -4
  118. package/src/hardware/task/task.spec.ts +53 -2
  119. package/src/index.ts +3 -1
  120. package/src/label/client.ts +5 -8
  121. package/src/label/payload.ts +6 -11
  122. package/src/ontology/client.ts +3 -3
  123. package/src/ontology/group/client.ts +51 -18
  124. package/src/ontology/group/external.ts +0 -1
  125. package/src/ontology/group/group.spec.ts +6 -5
  126. package/src/ontology/group/payload.ts +5 -1
  127. package/src/ontology/ontology.spec.ts +88 -21
  128. package/src/ontology/payload.ts +15 -6
  129. package/src/ontology/writer.ts +3 -5
  130. package/src/ranger/alias.ts +2 -2
  131. package/src/ranger/client.ts +7 -3
  132. package/src/ranger/kv.ts +1 -2
  133. package/src/ranger/payload.ts +13 -1
  134. package/src/ranger/ranger.spec.ts +65 -1
  135. package/src/status/client.ts +129 -0
  136. package/src/status/external.ts +11 -0
  137. package/src/status/index.ts +10 -0
  138. package/src/status/payload.ts +35 -0
  139. package/src/status/status.spec.ts +352 -0
  140. package/src/user/client.ts +1 -2
  141. package/src/user/payload.ts +1 -1
  142. package/src/user/retriever.ts +2 -2
  143. package/src/user/user.spec.ts +41 -41
  144. package/src/workspace/client.ts +18 -15
  145. package/src/workspace/lineplot/client.ts +27 -13
  146. package/src/workspace/lineplot/index.ts +1 -1
  147. package/src/workspace/lineplot/lineplot.spec.ts +13 -10
  148. package/src/workspace/log/client.ts +26 -12
  149. package/src/workspace/log/log.spec.ts +13 -10
  150. package/src/workspace/payload.ts +1 -1
  151. package/src/workspace/schematic/client.ts +42 -17
  152. package/src/workspace/schematic/schematic.spec.ts +29 -25
  153. package/src/workspace/schematic/symbol/client.spec.ts +27 -24
  154. package/src/workspace/schematic/symbol/client.ts +6 -9
  155. package/src/workspace/table/client.ts +26 -12
  156. package/src/workspace/table/table.spec.ts +13 -10
  157. package/dist/ontology/group/group.d.ts +0 -10
  158. package/dist/ontology/group/group.d.ts.map +0 -1
  159. package/dist/ontology/group/writer.d.ts +0 -14
  160. package/dist/ontology/group/writer.d.ts.map +0 -1
  161. package/dist/util/zod.d.ts +0 -3
  162. package/dist/util/zod.d.ts.map +0 -1
  163. package/src/ontology/group/group.ts +0 -27
  164. package/src/ontology/group/writer.ts +0 -71
@@ -92,6 +92,7 @@ describe("Task", async () => {
92
92
  const w = await client.openWriter([task.STATUS_CHANNEL_NAME]);
93
93
  const communicatedStatus: task.Status = {
94
94
  key: id.create(),
95
+ name: "test",
95
96
  variant: "success",
96
97
  details: { task: t.key, running: false, data: {} },
97
98
  message: "test",
@@ -263,6 +264,50 @@ describe("Task", async () => {
263
264
  })
264
265
  .toBe(true);
265
266
  });
267
+
268
+ it("should filter tasks by snapshot parameter", async () => {
269
+ const regularTask = await testRack.createTask({
270
+ name: "regular_test_task",
271
+ type: "ni",
272
+ config: { test: true },
273
+ });
274
+
275
+ const snapshotTask = await client.hardware.tasks.copy(
276
+ regularTask.key,
277
+ "snapshot_test_task",
278
+ true,
279
+ );
280
+
281
+ const snapshotOnlyResult = await client.hardware.tasks.retrieve({
282
+ snapshot: true,
283
+ });
284
+ expect(snapshotOnlyResult.some((t) => t.key === snapshotTask.key)).toBe(true);
285
+ expect(snapshotOnlyResult.every((t) => t.snapshot === true)).toBe(true);
286
+
287
+ const regularOnlyResult = await client.hardware.tasks.retrieve({
288
+ snapshot: false,
289
+ });
290
+ expect(regularOnlyResult.some((t) => t.key === regularTask.key)).toBe(true);
291
+ expect(regularOnlyResult.every((t) => t.snapshot === false)).toBe(true);
292
+ });
293
+
294
+ it("should combine snapshot filter with other filters", async () => {
295
+ const task1 = await testRack.createTask({
296
+ name: "combined_filter_task",
297
+ type: "ni",
298
+ config: { test: true },
299
+ });
300
+
301
+ const result = await client.hardware.tasks.retrieve({
302
+ rack: testRack.key,
303
+ types: ["ni"],
304
+ snapshot: false,
305
+ });
306
+
307
+ expect(result.some((t) => t.key === task1.key)).toBe(true);
308
+ expect(result.every((t) => t.type === "ni")).toBe(true);
309
+ expect(result.every((t) => t.snapshot === false)).toBe(true);
310
+ });
266
311
  });
267
312
  });
268
313
 
@@ -289,7 +334,11 @@ describe("Task", async () => {
289
334
  type: "ni",
290
335
  });
291
336
  const streamer = await client.openStreamer(task.COMMAND_CHANNEL_NAME);
292
- const key = await client.hardware.tasks.executeCommand(t.key, type, args);
337
+ const key = await client.hardware.tasks.executeCommand({
338
+ task: t.key,
339
+ type,
340
+ args,
341
+ });
293
342
  await expect
294
343
  .poll<Promise<task.Command>>(async () => {
295
344
  const fr = await streamer.read();
@@ -305,7 +354,9 @@ describe("Task", async () => {
305
354
  config: {},
306
355
  type: "ni",
307
356
  });
308
- await expect(t.executeCommandSync("test", 0)).rejects.toThrow("timed out");
357
+ await expect(t.executeCommandSync({ type: "test", timeout: 0 })).rejects.toThrow(
358
+ "timed out",
359
+ );
309
360
  });
310
361
  });
311
362
  });
package/src/index.ts CHANGED
@@ -9,6 +9,7 @@
9
9
 
10
10
  export { access } from "@/access";
11
11
  export { policy } from "@/access/policy";
12
+ export { arc } from "@/arc";
12
13
  export { channel } from "@/channel";
13
14
  export { Channel, isCalculated } from "@/channel/client";
14
15
  export { default as Synnax, type SynnaxProps, synnaxPropsZ } from "@/client";
@@ -35,10 +36,11 @@ export { label } from "@/label";
35
36
  export { ontology } from "@/ontology";
36
37
  export { group } from "@/ontology/group";
37
38
  export { ranger } from "@/ranger";
39
+ export { status } from "@/status";
38
40
  export { createTestClient, TEST_CLIENT_PROPS } from "@/testutil/client";
39
41
  export { user } from "@/user";
40
42
  export { workspace } from "@/workspace";
41
- export { linePlot } from "@/workspace/lineplot";
43
+ export { lineplot } from "@/workspace/lineplot";
42
44
  export { log } from "@/workspace/log";
43
45
  export { schematic } from "@/workspace/schematic";
44
46
  export { table } from "@/workspace/table";
@@ -14,7 +14,6 @@ import z from "zod";
14
14
  import { type Key, keyZ, type Label, labelZ } from "@/label/payload";
15
15
  import { ontology } from "@/ontology";
16
16
  import { checkForMultipleOrNoResults } from "@/util/retrieve";
17
- import { nullableArrayZ } from "@/util/zod";
18
17
 
19
18
  export const SET_CHANNEL_NAME = "sy_label_set";
20
19
  export const DELETE_CHANNEL_NAME = "sy_label_delete";
@@ -58,10 +57,10 @@ const singleRetrieveArgsZ = z
58
57
  const retrieveArgsZ = z.union([singleRetrieveArgsZ, retrieveRequestZ]);
59
58
 
60
59
  export type RetrieveArgs = z.input<typeof retrieveArgsZ>;
61
- export type SingleRetrieveArgs = z.input<typeof singleRetrieveArgsZ>;
62
- export type MultiRetrieveArgs = z.input<typeof retrieveRequestZ>;
60
+ export type RetrieveSingleParams = z.input<typeof singleRetrieveArgsZ>;
61
+ export type RetrieveMultipleParams = z.input<typeof retrieveRequestZ>;
63
62
 
64
- const retrieveResponseZ = z.object({ labels: nullableArrayZ(labelZ) });
63
+ const retrieveResponseZ = z.object({ labels: array.nullableZ(labelZ) });
65
64
 
66
65
  export class Client {
67
66
  readonly type: string = "label";
@@ -71,8 +70,8 @@ export class Client {
71
70
  this.client = client;
72
71
  }
73
72
 
74
- async retrieve(args: SingleRetrieveArgs): Promise<Label>;
75
- async retrieve(args: MultiRetrieveArgs): Promise<Label[]>;
73
+ async retrieve(args: RetrieveSingleParams): Promise<Label>;
74
+ async retrieve(args: RetrieveMultipleParams): Promise<Label[]>;
76
75
  async retrieve(args: RetrieveArgs): Promise<Label | Label[]> {
77
76
  const isSingle = "key" in args;
78
77
  const res = await sendRequired(
@@ -120,8 +119,6 @@ export class Client {
120
119
  return isMany ? res.labels : res.labels[0];
121
120
  }
122
121
 
123
- async delete(key: Key): Promise<void>;
124
- async delete(keys: Key[]): Promise<void>;
125
122
  async delete(keys: Key | Key[]): Promise<void> {
126
123
  await sendRequired<typeof deleteReqZ, typeof emptyResZ>(
127
124
  this.client,
@@ -7,18 +7,13 @@
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 { z } from "zod";
10
+ import { label } from "@synnaxlabs/x";
11
11
 
12
- export const keyZ = z.uuid();
13
- export type Key = z.infer<typeof keyZ>;
12
+ export type Params = label.Key | label.Key[];
14
13
 
15
- export type Params = Key | Key[];
16
-
17
- export const labelZ = z.object({
18
- key: keyZ,
19
- name: z.string().min(1),
20
- color: z.string(),
21
- });
22
- export interface Label extends z.infer<typeof labelZ> {}
14
+ export const keyZ = label.keyZ;
15
+ export type Key = label.Key;
16
+ export const labelZ = label.labelZ;
17
+ export type Label = label.Label;
23
18
 
24
19
  export const LABELED_BY_ONTOLOGY_RELATIONSHIP_TYPE = "labeled_by";
@@ -71,7 +71,7 @@ export class Client {
71
71
  * @returns The resource with the given ID.
72
72
  * @throws {QueryError} If no resource is found with the given ID.
73
73
  */
74
- async retrieve(id: ID | string, options?: RetrieveOptions): Promise<Resource>;
74
+ async retrieve(id: ID, options?: RetrieveOptions): Promise<Resource>;
75
75
 
76
76
  /**
77
77
  * Retrieves the resources in the ontology with the given IDs.
@@ -83,12 +83,12 @@ export class Client {
83
83
  * @returns The resources with the given IDs.
84
84
  * @throws {QueryError} If no resource is found with any of the given IDs.
85
85
  */
86
- async retrieve(ids: ID[] | string[], options?: RetrieveOptions): Promise<Resource[]>;
86
+ async retrieve(ids: ID[], options?: RetrieveOptions): Promise<Resource[]>;
87
87
 
88
88
  async retrieve(params: RetrieveRequest): Promise<Resource[]>;
89
89
 
90
90
  async retrieve(
91
- ids: ID | ID[] | string | string[] | RetrieveRequest,
91
+ ids: ID | ID[] | RetrieveRequest,
92
92
  options?: RetrieveOptions,
93
93
  ): Promise<Resource | Resource[]> {
94
94
  if (!Array.isArray(ids) && typeof ids === "object" && !("key" in ids))
@@ -7,36 +7,69 @@
7
7
  // License, use of this software will be governed by the Apache License, Version 2.0,
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
- import { type UnaryClient } from "@synnaxlabs/freighter";
10
+ import { sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
11
+ import { array } from "@synnaxlabs/x";
12
+ import z from "zod";
11
13
 
12
- import { type ontology } from "@/ontology";
13
- import { Group } from "@/ontology/group/group";
14
- import { type Key, type Name, type Payload } from "@/ontology/group/payload";
15
- import { Writer } from "@/ontology/group/writer";
14
+ import { type Group, groupZ, type Key, keyZ } from "@/ontology/group/payload";
15
+ import { idZ as ontologyIDZ } from "@/ontology/payload";
16
16
 
17
17
  export const SET_CHANNEL_NAME = "sy_group_set";
18
18
  export const DELETE_CHANNEL_NAME = "sy_group_delete";
19
19
 
20
- export class Client {
21
- private readonly creator: Writer;
20
+ const resZ = z.object({ group: groupZ });
22
21
 
23
- constructor(unary: UnaryClient) {
24
- this.creator = new Writer(unary);
25
- }
22
+ const createReqZ = z.object({
23
+ parent: ontologyIDZ,
24
+ key: keyZ.optional(),
25
+ name: z.string(),
26
+ });
27
+
28
+ const renameReqZ = z.object({ key: keyZ, name: z.string() });
29
+
30
+ const deleteReqZ = z.object({ keys: z.array(keyZ) });
31
+
32
+ const CREATE_ENDPOINT = "/ontology/create-group";
33
+ const RENAME_ENDPOINT = "/ontology/rename-group";
34
+ const DELETE_ENDPOINT = "/ontology/delete-group";
35
+
36
+ export interface CreateArgs extends z.infer<typeof createReqZ> {}
37
+
38
+ export class Client {
39
+ client: UnaryClient;
26
40
 
27
- async create(parent: ontology.ID, name: Name, key?: Key): Promise<Group> {
28
- return this.sugar(await this.creator.create(parent, name, key));
41
+ constructor(client: UnaryClient) {
42
+ this.client = client;
29
43
  }
30
44
 
31
- async rename(key: Key, name: Name): Promise<void> {
32
- return await this.creator.rename(key, name);
45
+ async create(args: CreateArgs): Promise<Group> {
46
+ const res = await sendRequired(
47
+ this.client,
48
+ CREATE_ENDPOINT,
49
+ args,
50
+ createReqZ,
51
+ resZ,
52
+ );
53
+ return res.group;
33
54
  }
34
55
 
35
- async delete(...keys: Key[]): Promise<void> {
36
- return await this.creator.delete(keys);
56
+ async rename(key: Key, name: string): Promise<void> {
57
+ await sendRequired(
58
+ this.client,
59
+ RENAME_ENDPOINT,
60
+ { key, name },
61
+ renameReqZ,
62
+ z.object({}),
63
+ );
37
64
  }
38
65
 
39
- private sugar(payload: Payload): Group {
40
- return new Group(payload.name, payload.key);
66
+ async delete(keys: Key | Key[]): Promise<void> {
67
+ await sendRequired(
68
+ this.client,
69
+ DELETE_ENDPOINT,
70
+ { keys: array.toArray(keys) },
71
+ deleteReqZ,
72
+ z.object({}),
73
+ );
41
74
  }
42
75
  }
@@ -8,5 +8,4 @@
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
10
  export * from "@/ontology/group/client";
11
- export * from "@/ontology/group/group";
12
11
  export * from "@/ontology/group/payload";
@@ -11,6 +11,7 @@ import { describe, expect, it } from "vitest";
11
11
 
12
12
  import { NotFoundError } from "@/errors";
13
13
  import { ontology } from "@/ontology";
14
+ import { group } from "@/ontology/group";
14
15
  import { createTestClient } from "@/testutil/client";
15
16
 
16
17
  const client = createTestClient();
@@ -19,27 +20,27 @@ describe("Group", () => {
19
20
  describe("create", () => {
20
21
  it("should correctly create a group", async () => {
21
22
  const name = `group-${Math.random()}`;
22
- const g = await client.ontology.groups.create(ontology.ROOT_ID, name);
23
+ const g = await client.ontology.groups.create({ parent: ontology.ROOT_ID, name });
23
24
  expect(g.name).toEqual(name);
24
25
  });
25
26
  });
26
27
  describe("rename", () => {
27
28
  it("should correctly rename a group", async () => {
28
29
  const name = `group-${Math.random()}`;
29
- const g = await client.ontology.groups.create(ontology.ROOT_ID, name);
30
+ const g = await client.ontology.groups.create({ parent: ontology.ROOT_ID, name });
30
31
  const newName = `group-${Math.random()}`;
31
32
  await client.ontology.groups.rename(g.key, newName);
32
- const g2 = await client.ontology.retrieve(g.ontologyID);
33
+ const g2 = await client.ontology.retrieve(group.ontologyID(g.key));
33
34
  expect(g2.name).toEqual(newName);
34
35
  });
35
36
  });
36
37
  describe("delete", () => {
37
38
  it("should correctly delete the group", async () => {
38
39
  const name = `group-${Math.random()}`;
39
- const g = await client.ontology.groups.create(ontology.ROOT_ID, name);
40
+ const g = await client.ontology.groups.create({ parent: ontology.ROOT_ID, name });
40
41
  await client.ontology.groups.delete(g.key);
41
42
  await expect(
42
- async () => await client.ontology.retrieve(g.ontologyID),
43
+ async () => await client.ontology.retrieve(group.ontologyID(g.key)),
43
44
  ).rejects.toThrowError(NotFoundError);
44
45
  });
45
46
  });
@@ -9,6 +9,8 @@
9
9
 
10
10
  import { z } from "zod";
11
11
 
12
+ import { type ID as OntologyID } from "@/ontology/payload";
13
+
12
14
  export const keyZ = z.uuid();
13
15
  export type Key = z.infer<typeof keyZ>;
14
16
  export const nameZ = z.string();
@@ -17,4 +19,6 @@ export type Keys = Key[];
17
19
  export type Names = Name[];
18
20
  export type Params = Key | Name | Keys | Names;
19
21
  export const groupZ = z.object({ key: keyZ, name: nameZ });
20
- export interface Payload extends z.infer<typeof groupZ> {}
22
+ export interface Group extends z.infer<typeof groupZ> {}
23
+
24
+ export const ontologyID = (key: Key): OntologyID => ({ type: "group", key });
@@ -10,6 +10,7 @@
10
10
  import { describe, expect, it, test } from "vitest";
11
11
 
12
12
  import { ontology } from "@/ontology";
13
+ import { group } from "@/ontology/group";
13
14
  import { createTestClient } from "@/testutil/client";
14
15
 
15
16
  const client = createTestClient();
@@ -125,59 +126,88 @@ describe("Ontology", () => {
125
126
  describe("retrieve", () => {
126
127
  test("retrieve", async () => {
127
128
  const name = randomName();
128
- const g = await client.ontology.groups.create(ontology.ROOT_ID, name);
129
- const g2 = await client.ontology.retrieve(g.ontologyID);
129
+ const g = await client.ontology.groups.create({ parent: ontology.ROOT_ID, name });
130
+ const g2 = await client.ontology.retrieve(group.ontologyID(g.key));
130
131
  expect(g2.name).toEqual(name);
131
132
  });
132
133
  test("retrieve children", async () => {
133
134
  const name = randomName();
134
- const g = await client.ontology.groups.create(ontology.ROOT_ID, name);
135
+ const g = await client.ontology.groups.create({ parent: ontology.ROOT_ID, name });
135
136
  const name2 = randomName();
136
- await client.ontology.groups.create(g.ontologyID, name2);
137
- const children = await client.ontology.retrieveChildren(g.ontologyID);
137
+ await client.ontology.groups.create({
138
+ parent: group.ontologyID(g.key),
139
+ name: name2,
140
+ });
141
+ const children = await client.ontology.retrieveChildren(group.ontologyID(g.key));
138
142
  expect(children.length).toEqual(1);
139
143
  expect(children[0].name).toEqual(name2);
140
144
  });
141
145
  test("retrieve parents", async () => {
142
146
  const name = randomName();
143
- const g = await client.ontology.groups.create(ontology.ROOT_ID, name);
147
+ const g = await client.ontology.groups.create({ parent: ontology.ROOT_ID, name });
144
148
  const name2 = randomName();
145
- const g2 = await client.ontology.groups.create(g.ontologyID, name2);
146
- const parents = await client.ontology.retrieveParents(g2.ontologyID);
149
+ const g2 = await client.ontology.groups.create({
150
+ parent: group.ontologyID(g.key),
151
+ name: name2,
152
+ });
153
+ const parents = await client.ontology.retrieveParents(group.ontologyID(g2.key));
147
154
  expect(parents.length).toEqual(1);
148
155
  expect(parents[0].name).toEqual(name);
149
156
  });
150
157
  });
158
+
151
159
  describe("write", () => {
152
160
  test("add children", async () => {
153
161
  const name = randomName();
154
- const g = await client.ontology.groups.create(ontology.ROOT_ID, name);
162
+ const g = await client.ontology.groups.create({ parent: ontology.ROOT_ID, name });
155
163
  const name2 = randomName();
156
- const g2 = await client.ontology.groups.create(ontology.ROOT_ID, name2);
157
- await client.ontology.addChildren(g.ontologyID, g2.ontologyID);
158
- const children = await client.ontology.retrieveChildren(g.ontologyID);
164
+ const g2 = await client.ontology.groups.create({
165
+ parent: ontology.ROOT_ID,
166
+ name: name2,
167
+ });
168
+ await client.ontology.addChildren(
169
+ group.ontologyID(g.key),
170
+ group.ontologyID(g2.key),
171
+ );
172
+ const children = await client.ontology.retrieveChildren(group.ontologyID(g.key));
159
173
  expect(children.length).toEqual(1);
160
174
  expect(children[0].name).toEqual(name2);
161
175
  });
162
176
  test("remove children", async () => {
163
177
  const name = randomName();
164
- const g = await client.ontology.groups.create(ontology.ROOT_ID, name);
178
+ const g = await client.ontology.groups.create({ parent: ontology.ROOT_ID, name });
165
179
  const name2 = randomName();
166
- const g2 = await client.ontology.groups.create(ontology.ROOT_ID, name2);
167
- await client.ontology.addChildren(g.ontologyID, g2.ontologyID);
168
- await client.ontology.removeChildren(g.ontologyID, g2.ontologyID);
169
- const children = await client.ontology.retrieveChildren(g.ontologyID);
180
+ const g2 = await client.ontology.groups.create({
181
+ parent: ontology.ROOT_ID,
182
+ name: name2,
183
+ });
184
+ await client.ontology.addChildren(
185
+ group.ontologyID(g.key),
186
+ group.ontologyID(g2.key),
187
+ );
188
+ await client.ontology.removeChildren(
189
+ group.ontologyID(g.key),
190
+ group.ontologyID(g2.key),
191
+ );
192
+ const children = await client.ontology.retrieveChildren(group.ontologyID(g.key));
170
193
  expect(children.length).toEqual(0);
171
194
  });
172
195
  test("move children", async () => {
173
196
  const name = randomName();
174
- const g = await client.ontology.groups.create(ontology.ROOT_ID, name);
197
+ const g = await client.ontology.groups.create({ parent: ontology.ROOT_ID, name });
175
198
  const name2 = randomName();
176
- const g2 = await client.ontology.groups.create(ontology.ROOT_ID, name2);
199
+ const g2 = await client.ontology.groups.create({
200
+ parent: ontology.ROOT_ID,
201
+ name: name2,
202
+ });
177
203
  const oldRootLength = (await client.ontology.retrieveChildren(ontology.ROOT_ID))
178
204
  .length;
179
- await client.ontology.moveChildren(ontology.ROOT_ID, g.ontologyID, g2.ontologyID);
180
- const children = await client.ontology.retrieveChildren(g.ontologyID);
205
+ await client.ontology.moveChildren(
206
+ ontology.ROOT_ID,
207
+ group.ontologyID(g.key),
208
+ group.ontologyID(g2.key),
209
+ );
210
+ const children = await client.ontology.retrieveChildren(group.ontologyID(g.key));
181
211
  expect(children.length).toEqual(1);
182
212
  const newRootLength = (await client.ontology.retrieveChildren(ontology.ROOT_ID))
183
213
  .length;
@@ -439,4 +469,41 @@ describe("Ontology", () => {
439
469
  });
440
470
  });
441
471
  });
472
+
473
+ describe("idToString", () => {
474
+ it("should convert an ID to a string", () => {
475
+ const result = ontology.idToString({ type: "group", key: "one" });
476
+ expect(result).toEqual("group:one");
477
+ });
478
+
479
+ it("should convert an array of IDs to strings", () => {
480
+ const result = ontology.idToString([
481
+ { type: "group", key: "one" },
482
+ { type: "channel", key: "two" },
483
+ ]);
484
+ expect(result).toEqual(["group:one", "channel:two"]);
485
+ });
486
+
487
+ it("should pass through string IDs", () => {
488
+ const result = ontology.idToString("group:one");
489
+ expect(result).toEqual("group:one");
490
+ });
491
+
492
+ it("should validate string IDs that get passed", () => {
493
+ expect(() => {
494
+ ontology.idToString("dog");
495
+ }).toThrow();
496
+ });
497
+
498
+ it("should pass through an array of string IDs", () => {
499
+ const result = ontology.idToString(["group:one", "channel:two"]);
500
+ expect(result).toEqual(["group:one", "channel:two"]);
501
+ });
502
+
503
+ it("should validate an array of string IDs that get passed", () => {
504
+ expect(() => {
505
+ ontology.idToString(["group:one", "channel:two", "dog"]);
506
+ }).toThrow();
507
+ });
508
+ });
442
509
  });
@@ -17,9 +17,7 @@ export type RelationshipChange = change.Change<Relationship, undefined>;
17
17
  export interface RelationshipSet extends change.Set<Relationship, undefined> {}
18
18
  export interface RelationshipDelete extends change.Delete<Relationship, undefined> {}
19
19
 
20
- export const BUILTIN_TYPE = "builtin";
21
- export const CLUSTER_TYPE = "cluster";
22
- export const NODE_TYPE = "node";
20
+ export interface RelationshipDelete extends change.Delete<Relationship, undefined> {}
23
21
 
24
22
  export const resourceTypeZ = z.enum([
25
23
  "label",
@@ -42,7 +40,9 @@ export const resourceTypeZ = z.enum([
42
40
  "task",
43
41
  "policy",
44
42
  "table",
43
+ "arc",
45
44
  "schematic_symbol",
45
+ "status",
46
46
  ]);
47
47
  export type ResourceType = z.infer<typeof resourceTypeZ>;
48
48
 
@@ -55,14 +55,23 @@ export const idZ = z.object({ type: resourceTypeZ, key: z.string() }).or(stringI
55
55
 
56
56
  export type ID = z.infer<typeof idZ>;
57
57
 
58
- export const ROOT_ID: ID = { type: BUILTIN_TYPE, key: "root" };
58
+ export const ROOT_ID: ID = { type: "builtin", key: "root" };
59
+
60
+ export interface IDToString {
61
+ (id: ID | string): string;
62
+ (ids: (ID | string)[]): string[];
63
+ }
59
64
 
60
- export const idToString = (id: ID) => `${id.type}:${id.key}`;
65
+ export const idToString = ((id: ID | string | (ID | string)[]) => {
66
+ if (typeof id === "string") id = stringIDZ.parse(id);
67
+ if (Array.isArray(id)) return id.map((id) => idToString(id));
68
+ return `${id.type}:${id.key}`;
69
+ }) as IDToString;
61
70
 
62
71
  export const idsEqual = (a: ID, b: ID) => a.type === b.type && a.key === b.key;
63
72
 
64
73
  export const parseIDs = (
65
- ids: ID | ID[] | string | string[] | Resource | Resource[],
74
+ ids: ID | string | Resource | (ID | string | Resource)[],
66
75
  ): ID[] => {
67
76
  const arr = array.toArray(ids);
68
77
  if (arr.length === 0) return [];
@@ -16,11 +16,9 @@ const ADD_CHILDREN_ENDPOINT = "/ontology/add-children";
16
16
  const REMOVE_CHILDREN_ENDPOINT = "/ontology/remove-children";
17
17
  const MOVE_CHILDREN_ENDPOINT = "/ontology/move-children";
18
18
 
19
- const addRemoveChildrenReqZ = z.object({ id: idZ, children: idZ.array() });
20
-
21
- const moveChildrenReqZ = z.object({ from: idZ, to: idZ, children: idZ.array() });
22
-
23
- const emptyResZ = z.object({});
19
+ export const addRemoveChildrenReqZ = z.object({ id: idZ, children: idZ.array() });
20
+ export const moveChildrenReqZ = z.object({ from: idZ, to: idZ, children: idZ.array() });
21
+ export const emptyResZ = z.object({});
24
22
 
25
23
  export class Writer {
26
24
  client: UnaryClient;
@@ -128,11 +128,11 @@ export class Aliaser {
128
128
  return isSingle ? res.aliases[alias] : res.aliases;
129
129
  }
130
130
 
131
- async delete(aliases: channel.Key[]): Promise<void> {
131
+ async delete(aliases: channel.Key | channel.Key[]): Promise<void> {
132
132
  await sendRequired<typeof deleteReqZ, typeof deleteResZ>(
133
133
  this.client,
134
134
  Aliaser.DELETE_ENDPOINT,
135
- { range: this.rangeKey, channels: aliases },
135
+ { range: this.rangeKey, channels: array.toArray(aliases) },
136
136
  deleteReqZ,
137
137
  deleteResZ,
138
138
  );
@@ -32,7 +32,6 @@ import {
32
32
  } from "@/ranger/payload";
33
33
  import { type CreateOptions, type Writer } from "@/ranger/writer";
34
34
  import { checkForMultipleOrNoResults } from "@/util/retrieve";
35
- import { nullableArrayZ } from "@/util/zod";
36
35
 
37
36
  export const SET_CHANNEL_NAME = "sy_range_set";
38
37
  export const DELETE_CHANNEL_NAME = "sy_range_delete";
@@ -193,7 +192,7 @@ export type RetrieveArgs = z.input<typeof retrieveArgsZ>;
193
192
 
194
193
  const RETRIEVE_ENDPOINT = "/range/retrieve";
195
194
 
196
- const retrieveResZ = z.object({ ranges: nullableArrayZ(payloadZ) });
195
+ const retrieveResZ = z.object({ ranges: array.nullableZ(payloadZ) });
197
196
 
198
197
  export class Client {
199
198
  readonly type: string = "range";
@@ -240,7 +239,7 @@ export class Client {
240
239
 
241
240
  async retrieve(params: Key | Name): Promise<Range>;
242
241
  async retrieve(params: Keys | Names): Promise<Range[]>;
243
- async retrieve(params: TimeRange): Promise<Range[]>;
242
+ async retrieve(params: CrudeTimeRange): Promise<Range[]>;
244
243
  async retrieve(params: RetrieveRequest): Promise<Range[]>;
245
244
  async retrieve(params: RetrieveArgs): Promise<Range | Range[]> {
246
245
  const isSingle = typeof params === "string";
@@ -295,6 +294,11 @@ export class Client {
295
294
  await aliaser.set({ [channel]: alias });
296
295
  }
297
296
 
297
+ async deleteAlias(range: Key, channels: channel.Key | channel.Key[]): Promise<void> {
298
+ const aliaser = new Aliaser(range, this.frameClient, this.unaryClient);
299
+ await aliaser.delete(channels);
300
+ }
301
+
298
302
  sugarOne(payload: Payload): Range {
299
303
  return new Range(payload, {
300
304
  frameClient: this.frameClient,
package/src/ranger/kv.ts CHANGED
@@ -13,7 +13,6 @@ import { isObject } from "@synnaxlabs/x/identity";
13
13
  import { z } from "zod";
14
14
 
15
15
  import { type Key, keyZ } from "@/ranger/payload";
16
- import { nullableArrayZ } from "@/util/zod";
17
16
 
18
17
  export const KV_SET_CHANNEL = "sy_range_kv_set";
19
18
  export const KV_DELETE_CHANNEL = "sy_range_kv_delete";
@@ -27,7 +26,7 @@ export const kvPairKey = ({ range, key }: Omit<KVPair, "value">) =>
27
26
  const getReqZ = z.object({ range: keyZ, keys: z.string().array() });
28
27
  export interface GetRequest extends z.infer<typeof getReqZ> {}
29
28
 
30
- const getResZ = z.object({ pairs: nullableArrayZ(kvPairZ) });
29
+ const getResZ = z.object({ pairs: array.nullableZ(kvPairZ) });
31
30
 
32
31
  const setReqZ = z.object({ range: keyZ, pairs: kvPairZ.array() });
33
32
  export interface SetRequest extends z.infer<typeof setReqZ> {}