@synnaxlabs/client 0.44.1 → 0.44.2

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 (67) hide show
  1. package/.turbo/turbo-build.log +5 -5
  2. package/dist/channel/client.d.ts +11 -4
  3. package/dist/channel/client.d.ts.map +1 -1
  4. package/dist/channel/payload.d.ts +86 -14
  5. package/dist/channel/payload.d.ts.map +1 -1
  6. package/dist/channel/writer.d.ts.map +1 -1
  7. package/dist/client.cjs +20 -20
  8. package/dist/client.js +1803 -1764
  9. package/dist/framer/streamer.d.ts +96 -0
  10. package/dist/framer/streamer.d.ts.map +1 -1
  11. package/dist/framer/writer.d.ts +80 -0
  12. package/dist/framer/writer.d.ts.map +1 -1
  13. package/dist/hardware/device/payload.d.ts +4 -4
  14. package/dist/hardware/rack/payload.d.ts +4 -4
  15. package/dist/index.d.ts +1 -1
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/ontology/payload.d.ts +1 -0
  18. package/dist/ontology/payload.d.ts.map +1 -1
  19. package/dist/ranger/alias.d.ts +5 -1
  20. package/dist/ranger/alias.d.ts.map +1 -1
  21. package/dist/ranger/client.d.ts +5 -1
  22. package/dist/ranger/client.d.ts.map +1 -1
  23. package/dist/ranger/external.d.ts +1 -1
  24. package/dist/ranger/external.d.ts.map +1 -1
  25. package/dist/ranger/kv.d.ts +1 -0
  26. package/dist/ranger/kv.d.ts.map +1 -1
  27. package/dist/ranger/payload.d.ts +3 -7
  28. package/dist/ranger/payload.d.ts.map +1 -1
  29. package/dist/ranger/writer.d.ts +1 -1
  30. package/dist/testutil/client.d.ts +1 -1
  31. package/dist/testutil/client.d.ts.map +1 -1
  32. package/dist/workspace/payload.d.ts +1 -1
  33. package/package.json +2 -2
  34. package/src/access/policy/policy.spec.ts +3 -3
  35. package/src/channel/channel.spec.ts +2 -2
  36. package/src/channel/client.ts +21 -5
  37. package/src/channel/payload.ts +4 -4
  38. package/src/channel/writer.ts +4 -1
  39. package/src/control/state.spec.ts +2 -2
  40. package/src/errors.spec.ts +2 -2
  41. package/src/framer/adapter.spec.ts +2 -2
  42. package/src/framer/client.spec.ts +2 -2
  43. package/src/framer/deleter.spec.ts +2 -2
  44. package/src/framer/iterator.spec.ts +2 -2
  45. package/src/framer/streamer.spec.ts +2 -2
  46. package/src/framer/writer.spec.ts +3 -2
  47. package/src/hardware/device/device.spec.ts +2 -2
  48. package/src/hardware/rack/rack.spec.ts +2 -2
  49. package/src/hardware/task/task.spec.ts +2 -2
  50. package/src/index.ts +1 -1
  51. package/src/label/label.spec.ts +2 -2
  52. package/src/ontology/group/group.spec.ts +2 -2
  53. package/src/ontology/ontology.spec.ts +2 -2
  54. package/src/ontology/payload.ts +3 -0
  55. package/src/ranger/alias.ts +27 -1
  56. package/src/ranger/client.ts +30 -3
  57. package/src/ranger/external.ts +1 -9
  58. package/src/ranger/kv.ts +3 -0
  59. package/src/ranger/payload.ts +4 -2
  60. package/src/ranger/ranger.spec.ts +3 -3
  61. package/src/testutil/client.ts +1 -1
  62. package/src/user/user.spec.ts +2 -2
  63. package/src/workspace/lineplot/lineplot.spec.ts +2 -2
  64. package/src/workspace/log/log.spec.ts +2 -2
  65. package/src/workspace/schematic/schematic.spec.ts +2 -2
  66. package/src/workspace/table/table.spec.ts +2 -2
  67. package/src/workspace/workspace.spec.ts +2 -2
@@ -1,4 +1,4 @@
1
1
  import { default as Synnax, SynnaxProps } from '../client';
2
2
  export declare const TEST_CLIENT_PROPS: SynnaxProps;
3
- export declare const newTestClient: (props?: Partial<SynnaxProps>) => Synnax;
3
+ export declare const createTestClient: (props?: Partial<SynnaxProps>) => Synnax;
4
4
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/testutil/client.ts"],"names":[],"mappings":"AASA,OAAO,MAAM,EAAE,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AAEpD,eAAO,MAAM,iBAAiB,EAAE,WAK/B,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,QAAQ,OAAO,CAAC,WAAW,CAAC,KAAG,MACb,CAAC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/testutil/client.ts"],"names":[],"mappings":"AASA,OAAO,MAAM,EAAE,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AAEpD,eAAO,MAAM,iBAAiB,EAAE,WAK/B,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,OAAO,CAAC,WAAW,CAAC,KAAG,MAChB,CAAC"}
@@ -26,8 +26,8 @@ export declare const newZ: z.ZodPipe<z.ZodObject<{
26
26
  export interface New extends z.input<typeof newZ> {
27
27
  }
28
28
  export declare const remoteZ: z.ZodObject<{
29
- name: z.ZodString;
30
29
  key: z.ZodUUID;
30
+ name: z.ZodString;
31
31
  layout: z.ZodPipe<z.ZodString, z.ZodTransform<record.Unknown, string>>;
32
32
  }, z.core.$strip>;
33
33
  //# sourceMappingURL=payload.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synnaxlabs/client",
3
- "version": "0.44.1",
3
+ "version": "0.44.2",
4
4
  "description": "The Synnax Client Library",
5
5
  "keywords": [
6
6
  "synnax",
@@ -27,7 +27,7 @@
27
27
  "async-mutex": "^0.5.0",
28
28
  "zod": "^4.0.2",
29
29
  "@synnaxlabs/freighter": "^0.44.0",
30
- "@synnaxlabs/x": "^0.44.0"
30
+ "@synnaxlabs/x": "^0.44.2"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@vitest/coverage-v8": "^3.2.4",
@@ -12,10 +12,10 @@ import { describe, expect, test } from "vitest";
12
12
 
13
13
  import { type policy } from "@/access/policy";
14
14
  import { AuthError } from "@/errors";
15
- import { newTestClient } from "@/testutil/client";
15
+ import { createTestClient } from "@/testutil/client";
16
16
  import { user } from "@/user";
17
17
 
18
- const client = newTestClient();
18
+ const client = createTestClient();
19
19
 
20
20
  describe("Policy", () => {
21
21
  describe("create", () => {
@@ -299,7 +299,7 @@ describe("privilege", async () => {
299
299
  const username = id.create();
300
300
  const user2 = await client.user.create({ username, password: "pwd1" });
301
301
  expect(user2).toBeDefined();
302
- const client2 = newTestClient({ username: user2.username, password: "pwd1" });
302
+ const client2 = createTestClient({ username: user2.username, password: "pwd1" });
303
303
  await expect(
304
304
  client2.user.create({ username: id.create(), password: id.create() }),
305
305
  ).rejects.toThrow(AuthError);
@@ -12,9 +12,9 @@ import { beforeAll, describe, expect, it, test } from "vitest";
12
12
 
13
13
  import { Channel } from "@/channel/client";
14
14
  import { NotFoundError, PathError } from "@/errors";
15
- import { newTestClient } from "@/testutil/client";
15
+ import { createTestClient } from "@/testutil/client";
16
16
 
17
- const client = newTestClient();
17
+ const client = createTestClient();
18
18
 
19
19
  describe("Channel", () => {
20
20
  describe("create", () => {
@@ -8,7 +8,7 @@
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
10
  import { sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
11
- import { array } from "@synnaxlabs/x";
11
+ import { array, status } from "@synnaxlabs/x";
12
12
  import {
13
13
  type CrudeDensity,
14
14
  type CrudeTimeStamp,
@@ -27,6 +27,7 @@ import {
27
27
  type Params,
28
28
  type Payload,
29
29
  payloadZ,
30
+ type Status,
30
31
  } from "@/channel/payload";
31
32
  import {
32
33
  analyzeParams,
@@ -99,7 +100,7 @@ export class Channel {
99
100
  * An alias for the channel under a specific range. This parameter is unstable and
100
101
  * should not be relied upon in the current version of Synnax.
101
102
  */
102
- readonly alias: string | undefined;
103
+ alias: string | undefined;
103
104
  /**
104
105
  * Whether the channel is virtual. Virtual channels do not store any data in the
105
106
  * database, but can still be used for streaming purposes.
@@ -114,6 +115,10 @@ export class Channel {
114
115
  * Only used for calculated channels. Specifies the channels required for calculation
115
116
  */
116
117
  readonly requires: Key[];
118
+ /**
119
+ * The status of the channel.
120
+ */
121
+ readonly status?: Status;
117
122
 
118
123
  constructor({
119
124
  dataType,
@@ -126,9 +131,14 @@ export class Channel {
126
131
  virtual = false,
127
132
  frameClient,
128
133
  alias,
134
+ status: argsStatus,
129
135
  expression = "",
130
136
  requires = [],
131
- }: New & { frameClient?: framer.Client; density?: CrudeDensity }) {
137
+ }: New & {
138
+ frameClient?: framer.Client;
139
+ density?: CrudeDensity;
140
+ status?: status.Crude;
141
+ }) {
132
142
  this.key = key;
133
143
  this.name = name;
134
144
  this.dataType = new DataType(dataType);
@@ -140,6 +150,7 @@ export class Channel {
140
150
  this.virtual = virtual;
141
151
  this.expression = expression;
142
152
  this.requires = requires ?? [];
153
+ if (argsStatus != null) this.status = status.create(argsStatus);
143
154
  this._frameClient = frameClient ?? null;
144
155
  }
145
156
 
@@ -166,6 +177,7 @@ export class Channel {
166
177
  virtual: this.virtual,
167
178
  expression: this.expression,
168
179
  requires: this.requires,
180
+ status: this.status,
169
181
  });
170
182
  }
171
183
 
@@ -397,9 +409,13 @@ export class Client {
397
409
  );
398
410
  }
399
411
 
400
- private sugar(payloads: Payload[]): Channel[] {
412
+ sugar(payload: Payload): Channel;
413
+ sugar(payloads: Payload[]): Channel[];
414
+ sugar(payloads: Payload | Payload[]): Channel | Channel[] {
401
415
  const { frameClient } = this;
402
- return payloads.map((p) => new Channel({ ...p, frameClient }));
416
+ if (Array.isArray(payloads))
417
+ return payloads.map((p) => new Channel({ ...p, frameClient }));
418
+ return new Channel({ ...payloads, frameClient });
403
419
  }
404
420
 
405
421
  async retrieveGroup(): Promise<group.Group> {
@@ -22,6 +22,8 @@ export type KeyOrName = Key | Name;
22
22
  export type KeysOrNames = Keys | Names;
23
23
  export type PrimitiveParams = Key | Name | Keys | Names;
24
24
 
25
+ export const statusZ = status.statusZ();
26
+ export type Status = z.infer<typeof statusZ>;
25
27
  export const payloadZ = z.object({
26
28
  name: nameZ,
27
29
  key: keyZ,
@@ -34,6 +36,7 @@ export const payloadZ = z.object({
34
36
  alias: z.string().optional(),
35
37
  expression: z.string().default(""),
36
38
  requires: nullableArrayZ(keyZ),
39
+ status: statusZ.optional(),
37
40
  });
38
41
  export interface Payload extends z.infer<typeof payloadZ> {}
39
42
 
@@ -48,13 +51,10 @@ export const newZ = payloadZ.extend({
48
51
  requires: nullableArrayZ(keyZ).optional().default([]),
49
52
  });
50
53
 
51
- export interface New extends Omit<z.input<typeof newZ>, "dataType"> {
54
+ export interface New extends Omit<z.input<typeof newZ>, "dataType" | "status"> {
52
55
  dataType: CrudeDataType;
53
56
  }
54
57
 
55
- export const calculationStatusZ = status.statusZ();
56
- export type CalculationStatus = z.infer<typeof calculationStatusZ>;
57
-
58
58
  export const paramsZ = z.union([
59
59
  zod.toArray(keyZ),
60
60
  zod.toArray(nameZ),
@@ -58,7 +58,10 @@ export class Writer {
58
58
  this.client,
59
59
  CREATE_ENDPOINT,
60
60
  {
61
- channels: channels.map((c) => ({ ...c, dataType: c.dataType as DataType })),
61
+ channels: channels.map((c) => ({
62
+ ...c,
63
+ dataType: c.dataType as DataType,
64
+ })),
62
65
  },
63
66
  createReqZ,
64
67
  createResZ,
@@ -9,9 +9,9 @@
9
9
 
10
10
  import { describe, expect, it } from "vitest";
11
11
 
12
- import { newTestClient } from "@/testutil/client";
12
+ import { createTestClient } from "@/testutil/client";
13
13
 
14
- const client = newTestClient();
14
+ const client = createTestClient();
15
15
 
16
16
  describe("state", () => {
17
17
  it("should receive the initial control state from the cluster", async () => {
@@ -24,7 +24,7 @@ import {
24
24
  UnexpectedError,
25
25
  ValidationError,
26
26
  } from "@/errors";
27
- import { newTestClient } from "@/testutil/client";
27
+ import { createTestClient } from "@/testutil/client";
28
28
 
29
29
  describe("error", () => {
30
30
  describe("type matching", () => {
@@ -54,7 +54,7 @@ describe("error", () => {
54
54
  });
55
55
  });
56
56
 
57
- const client = newTestClient();
57
+ const client = createTestClient();
58
58
 
59
59
  test("client", async () => {
60
60
  expect.assertions(2);
@@ -13,9 +13,9 @@ import { beforeAll, describe, expect, it } from "vitest";
13
13
  import { type channel } from "@/channel";
14
14
  import { ReadAdapter, WriteAdapter } from "@/framer/adapter";
15
15
  import { Frame } from "@/index";
16
- import { newTestClient } from "@/testutil/client";
16
+ import { createTestClient } from "@/testutil/client";
17
17
 
18
- const client = newTestClient();
18
+ const client = createTestClient();
19
19
 
20
20
  describe("WriteFrameAdapter", () => {
21
21
  let timeCh: channel.Channel;
@@ -10,9 +10,9 @@
10
10
  import { TimeSpan, TimeStamp } from "@synnaxlabs/x";
11
11
  import { describe, expect, it } from "vitest";
12
12
 
13
- import { newTestClient } from "@/testutil/client";
13
+ import { createTestClient } from "@/testutil/client";
14
14
 
15
- const client = newTestClient();
15
+ const client = createTestClient();
16
16
 
17
17
  describe("Client", () => {
18
18
  describe("read + write", () => {
@@ -12,11 +12,11 @@ import { describe, expect, test } from "vitest";
12
12
 
13
13
  import { NotFoundError, UnauthorizedError } from "@/errors";
14
14
  import { newIndexedPair } from "@/testutil/channels";
15
- import { newTestClient } from "@/testutil/client";
15
+ import { createTestClient } from "@/testutil/client";
16
16
  import { secondsLinspace } from "@/testutil/telem";
17
17
  import { randomSeries } from "@/util/telem";
18
18
 
19
- const client = newTestClient();
19
+ const client = createTestClient();
20
20
 
21
21
  describe("Deleter", () => {
22
22
  test("Client - basic delete", async () => {
@@ -12,11 +12,11 @@ import { describe, expect, test } from "vitest";
12
12
 
13
13
  import { AUTO_SPAN } from "@/framer/iterator";
14
14
  import { newIndexedPair } from "@/testutil/channels";
15
- import { newTestClient } from "@/testutil/client";
15
+ import { createTestClient } from "@/testutil/client";
16
16
  import { secondsLinspace } from "@/testutil/telem";
17
17
  import { randomSeries } from "@/util/telem";
18
18
 
19
- const client = newTestClient();
19
+ const client = createTestClient();
20
20
 
21
21
  describe("Iterator", () => {
22
22
  test("happy path", async () => {
@@ -20,9 +20,9 @@ import {
20
20
  streamerConfigZ,
21
21
  } from "@/framer/streamer";
22
22
  import { newVirtualChannel } from "@/testutil/channels";
23
- import { newTestClient } from "@/testutil/client";
23
+ import { createTestClient } from "@/testutil/client";
24
24
 
25
- const client = newTestClient();
25
+ const client = createTestClient();
26
26
 
27
27
  describe("Streamer", () => {
28
28
  describe("standard", () => {
@@ -13,11 +13,12 @@ import { describe, expect, it, test } from "vitest";
13
13
  import { UnauthorizedError, ValidationError } from "@/errors";
14
14
  import { ALWAYS_INDEX_PERSIST_ON_AUTO_COMMIT, WriterMode } from "@/framer/writer";
15
15
  import { newIndexedPair } from "@/testutil/channels";
16
- import { newTestClient } from "@/testutil/client";
16
+ import { createTestClient } from "@/testutil/client";
17
17
  import { secondsLinspace } from "@/testutil/telem";
18
18
  import { randomSeries } from "@/util/telem";
19
19
 
20
- const client = newTestClient();
20
+ const client = createTestClient();
21
+
21
22
  describe("Writer", () => {
22
23
  describe("Writer", () => {
23
24
  test("basic write", async () => {
@@ -10,9 +10,9 @@
10
10
  import { id, unique } from "@synnaxlabs/x";
11
11
  import { beforeAll, describe, expect, it } from "vitest";
12
12
 
13
- import { newTestClient } from "@/testutil/client";
13
+ import { createTestClient } from "@/testutil/client";
14
14
 
15
- const client = newTestClient();
15
+ const client = createTestClient();
16
16
 
17
17
  describe("Device", async () => {
18
18
  const testRack = await client.hardware.racks.create({ name: "test" });
@@ -11,9 +11,9 @@ import { describe, expect, it } from "vitest";
11
11
  import { ZodError } from "zod";
12
12
 
13
13
  import { type rack } from "@/hardware/rack";
14
- import { newTestClient } from "@/testutil/client";
14
+ import { createTestClient } from "@/testutil/client";
15
15
 
16
- const client = newTestClient();
16
+ const client = createTestClient();
17
17
 
18
18
  describe("Rack", () => {
19
19
  describe("create", () => {
@@ -11,9 +11,9 @@ import { id, TimeStamp } from "@synnaxlabs/x";
11
11
  import { beforeAll, describe, expect, it } from "vitest";
12
12
 
13
13
  import { task } from "@/hardware/task";
14
- import { newTestClient } from "@/testutil/client";
14
+ import { createTestClient } from "@/testutil/client";
15
15
 
16
- const client = newTestClient();
16
+ const client = createTestClient();
17
17
 
18
18
  describe("Task", async () => {
19
19
  const testRack = await client.hardware.racks.create({ name: "test" });
package/src/index.ts CHANGED
@@ -35,7 +35,7 @@ export { label } from "@/label";
35
35
  export { ontology } from "@/ontology";
36
36
  export { group } from "@/ontology/group";
37
37
  export { ranger } from "@/ranger";
38
- export { newTestClient, TEST_CLIENT_PROPS } from "@/testutil/client";
38
+ export { createTestClient, TEST_CLIENT_PROPS } from "@/testutil/client";
39
39
  export { user } from "@/user";
40
40
  export { workspace } from "@/workspace";
41
41
  export { linePlot } from "@/workspace/lineplot";
@@ -10,9 +10,9 @@
10
10
  import { describe, expect, it } from "vitest";
11
11
 
12
12
  import { label } from "@/label";
13
- import { newTestClient } from "@/testutil/client";
13
+ import { createTestClient } from "@/testutil/client";
14
14
 
15
- const client = newTestClient();
15
+ const client = createTestClient();
16
16
 
17
17
  describe("Label", () => {
18
18
  describe("create", () => {
@@ -11,9 +11,9 @@ import { describe, expect, it } from "vitest";
11
11
 
12
12
  import { NotFoundError } from "@/errors";
13
13
  import { ontology } from "@/ontology";
14
- import { newTestClient } from "@/testutil/client";
14
+ import { createTestClient } from "@/testutil/client";
15
15
 
16
- const client = newTestClient();
16
+ const client = createTestClient();
17
17
 
18
18
  describe("Group", () => {
19
19
  describe("create", () => {
@@ -10,9 +10,9 @@
10
10
  import { describe, expect, it, test } from "vitest";
11
11
 
12
12
  import { ontology } from "@/ontology";
13
- import { newTestClient } from "@/testutil/client";
13
+ import { createTestClient } from "@/testutil/client";
14
14
 
15
- const client = newTestClient();
15
+ const client = createTestClient();
16
16
 
17
17
  const randomName = (): string => `group-${Math.random()}`;
18
18
 
@@ -96,6 +96,9 @@ export const relationshipZ = z.object({ from: idZ, type: z.string(), to: idZ }).
96
96
  );
97
97
  export type Relationship = z.infer<typeof relationshipZ>;
98
98
 
99
+ export const relationshipToString = (relationship: Relationship) =>
100
+ `${idToString(relationship.from)}->${relationship.type}->${idToString(relationship.to)}`;
101
+
99
102
  export const PARENT_OF_RELATIONSHIP_TYPE = "parent";
100
103
 
101
104
  export interface MatchRelationshipArgs {
@@ -8,6 +8,7 @@
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
10
  import { sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
11
+ import { array } from "@synnaxlabs/x";
11
12
  import { type change } from "@synnaxlabs/x/change";
12
13
  import { z } from "zod";
13
14
 
@@ -37,10 +38,15 @@ const listReqZ = z.object({ range: keyZ });
37
38
 
38
39
  const listResZ = z.object({ aliases: z.record(z.string(), z.string()) });
39
40
 
41
+ const retrieveReqZ = z.object({ range: keyZ, channels: channel.keyZ.array() });
42
+
43
+ const retrieveResZ = z.object({ aliases: z.record(z.string(), z.string()) });
44
+
40
45
  export class Aliaser {
41
46
  private static readonly SET_ENDPOINT = "/range/alias/set";
42
47
  private static readonly RESOLVE_ENDPOINT = "/range/alias/resolve";
43
48
  private static readonly LIST_ENDPOINT = "/range/alias/list";
49
+ private static readonly RETRIEVE_ENDPOINT = "/range/alias/retrieve";
44
50
  private static readonly DELETE_ENDPOINT = "/range/alias/delete";
45
51
  private readonly frameClient: framer.Client;
46
52
  private readonly cache = new Map<string, channel.Key>();
@@ -108,6 +114,23 @@ export class Aliaser {
108
114
  ).aliases;
109
115
  }
110
116
 
117
+ async retrieve(alias: channel.Key): Promise<string>;
118
+ async retrieve(aliases: channel.Key[]): Promise<Record<channel.Key, string>>;
119
+
120
+ async retrieve(
121
+ alias: channel.Key | channel.Key[],
122
+ ): Promise<string | Record<channel.Key, string>> {
123
+ const isSingle = typeof alias === "number";
124
+ const res = await sendRequired<typeof retrieveReqZ, typeof retrieveResZ>(
125
+ this.client,
126
+ Aliaser.RETRIEVE_ENDPOINT,
127
+ { range: this.rangeKey, channels: array.toArray(alias) },
128
+ retrieveReqZ,
129
+ retrieveResZ,
130
+ );
131
+ return isSingle ? res.aliases[alias] : res.aliases;
132
+ }
133
+
111
134
  async delete(aliases: channel.Key[]): Promise<void> {
112
135
  await sendRequired<typeof deleteReqZ, typeof deleteResZ>(
113
136
  this.client,
@@ -120,7 +143,7 @@ export class Aliaser {
120
143
  }
121
144
 
122
145
  export const aliasZ = z.object({
123
- alias: z.string(),
146
+ alias: z.string().optional(),
124
147
  channel: channel.keyZ,
125
148
  range: keyZ,
126
149
  });
@@ -130,6 +153,9 @@ export type AliasChange = change.Change<string, Alias>;
130
153
 
131
154
  const SEPARATOR = "---";
132
155
 
156
+ export const aliasKey = (alias: Pick<Alias, "range" | "channel">): string =>
157
+ `${alias.range}${SEPARATOR}${alias.channel}`;
158
+
133
159
  export interface DecodedDeleteAliasChange {
134
160
  range: Key;
135
161
  channel: channel.Key;
@@ -54,7 +54,7 @@ export class Range {
54
54
  readonly timeRange: TimeRange;
55
55
  readonly color: string | undefined;
56
56
  readonly parent: Payload | null;
57
- readonly labels: label.Label[];
57
+ readonly labels?: label.Label[];
58
58
  readonly channels: channel.Retriever;
59
59
  private readonly aliaser: Aliaser;
60
60
  private readonly frameClient: framer.Client;
@@ -63,7 +63,7 @@ export class Range {
63
63
  private readonly rangeClient: Client;
64
64
 
65
65
  constructor(
66
- { name, timeRange = TimeRange.ZERO, key, color, parent, labels = [] }: Payload,
66
+ { name, timeRange = TimeRange.ZERO, key, color, parent, labels }: Payload,
67
67
  {
68
68
  frameClient,
69
69
  kv,
@@ -94,13 +94,17 @@ export class Range {
94
94
  }
95
95
 
96
96
  get payload(): Payload {
97
+ let parent: Payload | null = null;
98
+ if (this.parent != null)
99
+ if ("payload" in this.parent) parent = (this.parent as Range).payload;
100
+ else parent = this.parent;
97
101
  return {
98
102
  key: this.key,
99
103
  name: this.name,
100
104
  timeRange: this.timeRange,
101
105
  color: this.color,
102
106
  labels: this.labels,
103
- parent: this.parent,
107
+ parent,
104
108
  };
105
109
  }
106
110
 
@@ -268,6 +272,29 @@ export class Client {
268
272
  return this.sugarOne(convertOntologyResourceToPayload(resource));
269
273
  }
270
274
 
275
+ async retrieveAlias(range: Key, channel: channel.Key): Promise<string> {
276
+ const aliaser = new Aliaser(range, this.frameClient, this.unaryClient);
277
+ return await aliaser.retrieve(channel);
278
+ }
279
+
280
+ async retrieveAliases(
281
+ range: Key,
282
+ channels: channel.Key[],
283
+ ): Promise<Record<channel.Key, string>> {
284
+ const aliaser = new Aliaser(range, this.frameClient, this.unaryClient);
285
+ return await aliaser.retrieve(channels);
286
+ }
287
+
288
+ async listAliases(range: Key): Promise<Record<channel.Key, string>> {
289
+ const aliaser = new Aliaser(range, this.frameClient, this.unaryClient);
290
+ return await aliaser.list();
291
+ }
292
+
293
+ async setAlias(range: Key, channel: channel.Key, alias: string): Promise<void> {
294
+ const aliaser = new Aliaser(range, this.frameClient, this.unaryClient);
295
+ await aliaser.set({ [channel]: alias });
296
+ }
297
+
271
298
  sugarOne(payload: Payload): Range {
272
299
  return new Range(payload, {
273
300
  frameClient: this.frameClient,
@@ -7,15 +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
- export {
11
- type Alias,
12
- type AliasChange,
13
- aliasZ,
14
- type DecodedDeleteAliasChange,
15
- decodeDeleteAliasChange,
16
- DELETE_ALIAS_CHANNEL_NAME,
17
- SET_ALIAS_CHANNEL_NAME,
18
- } from "@/ranger/alias";
10
+ export * from "@/ranger/alias";
19
11
  export * from "@/ranger/client";
20
12
  export * from "@/ranger/kv";
21
13
  export * from "@/ranger/payload";
package/src/ranger/kv.ts CHANGED
@@ -21,6 +21,9 @@ export const KV_DELETE_CHANNEL = "sy_range_kv_delete";
21
21
  export const kvPairZ = z.object({ range: keyZ, key: z.string(), value: z.string() });
22
22
  export interface KVPair extends z.infer<typeof kvPairZ> {}
23
23
 
24
+ export const kvPairKey = ({ range, key }: Omit<KVPair, "value">) =>
25
+ `${range}<--->${key}`;
26
+
24
27
  const getReqZ = z.object({ range: keyZ, keys: z.string().array() });
25
28
  export interface GetRequest extends z.infer<typeof getReqZ> {}
26
29
 
@@ -11,7 +11,6 @@ import { TimeRange } from "@synnaxlabs/x/telem";
11
11
  import { z } from "zod";
12
12
 
13
13
  import { label } from "@/label";
14
- import { nullableArrayZ } from "@/util/zod";
15
14
 
16
15
  export const keyZ = z.uuid();
17
16
  export type Key = z.infer<typeof keyZ>;
@@ -26,7 +25,10 @@ export const payloadZ = z.object({
26
25
  name: nameZ,
27
26
  timeRange: TimeRange.z,
28
27
  color: z.string().optional(),
29
- labels: nullableArrayZ(label.labelZ),
28
+ labels: label.labelZ
29
+ .array()
30
+ .or(z.null().transform(() => undefined))
31
+ .optional(),
30
32
  get parent(): z.ZodUnion<readonly [z.ZodNull, typeof payloadZ]> {
31
33
  // Using as unknown is bad, but unfortunately resolving the output type of this
32
34
  // transform is nearly impossible.
@@ -12,9 +12,9 @@ import { describe, expect, it } from "vitest";
12
12
 
13
13
  import { NotFoundError } from "@/errors";
14
14
  import { type ranger } from "@/ranger";
15
- import { newTestClient } from "@/testutil/client";
15
+ import { createTestClient } from "@/testutil/client";
16
16
 
17
- const client = newTestClient();
17
+ const client = createTestClient();
18
18
 
19
19
  describe("Ranger", () => {
20
20
  describe("create", () => {
@@ -194,7 +194,7 @@ describe("Ranger", () => {
194
194
  includeLabels: true,
195
195
  });
196
196
  expect(newRange[0].labels).toHaveLength(1);
197
- expect(newRange[0].labels[0]).toEqual(label);
197
+ expect(newRange[0].labels?.[0]).toEqual(label);
198
198
  });
199
199
  });
200
200
 
@@ -16,5 +16,5 @@ export const TEST_CLIENT_PROPS: SynnaxProps = {
16
16
  password: "seldon",
17
17
  };
18
18
 
19
- export const newTestClient = (props?: Partial<SynnaxProps>): Synnax =>
19
+ export const createTestClient = (props?: Partial<SynnaxProps>): Synnax =>
20
20
  new Synnax({ ...TEST_CLIENT_PROPS, ...props });
@@ -11,7 +11,7 @@ import { id } from "@synnaxlabs/x";
11
11
  import { describe, expect, test } from "vitest";
12
12
 
13
13
  import { AuthError, NotFoundError } from "@/errors";
14
- import { newTestClient } from "@/testutil/client";
14
+ import { createTestClient } from "@/testutil/client";
15
15
  import { type user } from "@/user";
16
16
 
17
17
  interface SortType {
@@ -20,7 +20,7 @@ interface SortType {
20
20
 
21
21
  const sort = (a: SortType, b: SortType) => a.username.localeCompare(b.username);
22
22
 
23
- const client = newTestClient();
23
+ const client = createTestClient();
24
24
 
25
25
  const userOne: user.New = {
26
26
  username: id.create(),