@synnaxlabs/client 0.43.0 → 0.44.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 (245) hide show
  1. package/.turbo/turbo-build.log +7 -7
  2. package/dist/access/payload.d.ts +1 -1
  3. package/dist/access/payload.d.ts.map +1 -1
  4. package/dist/access/policy/client.d.ts +263 -6
  5. package/dist/access/policy/client.d.ts.map +1 -1
  6. package/dist/access/policy/external.d.ts +0 -1
  7. package/dist/access/policy/external.d.ts.map +1 -1
  8. package/dist/access/policy/payload.d.ts +105 -93
  9. package/dist/access/policy/payload.d.ts.map +1 -1
  10. package/dist/auth/auth.d.ts +1 -1
  11. package/dist/auth/auth.d.ts.map +1 -1
  12. package/dist/channel/client.d.ts +12 -13
  13. package/dist/channel/client.d.ts.map +1 -1
  14. package/dist/channel/payload.d.ts +77 -19
  15. package/dist/channel/payload.d.ts.map +1 -1
  16. package/dist/channel/retriever.d.ts +9 -16
  17. package/dist/channel/retriever.d.ts.map +1 -1
  18. package/dist/channel/writer.d.ts +1 -1
  19. package/dist/channel/writer.d.ts.map +1 -1
  20. package/dist/client.cjs +27 -135
  21. package/dist/client.d.ts +3 -3
  22. package/dist/client.d.ts.map +1 -1
  23. package/dist/client.js +8619 -28938
  24. package/dist/connection/checker.d.ts +1 -1
  25. package/dist/connection/checker.d.ts.map +1 -1
  26. package/dist/control/client.d.ts +1 -0
  27. package/dist/control/client.d.ts.map +1 -1
  28. package/dist/control/state.d.ts +6 -6
  29. package/dist/control/state.d.ts.map +1 -1
  30. package/dist/errors.d.ts +18 -5
  31. package/dist/errors.d.ts.map +1 -1
  32. package/dist/framer/adapter.d.ts +3 -3
  33. package/dist/framer/adapter.d.ts.map +1 -1
  34. package/dist/framer/client.d.ts +4 -13
  35. package/dist/framer/client.d.ts.map +1 -1
  36. package/dist/framer/codec.d.ts +1 -1
  37. package/dist/framer/codec.d.ts.map +1 -1
  38. package/dist/framer/deleter.d.ts +5 -5
  39. package/dist/framer/deleter.d.ts.map +1 -1
  40. package/dist/framer/frame.d.ts +5 -7
  41. package/dist/framer/frame.d.ts.map +1 -1
  42. package/dist/framer/streamProxy.d.ts +1 -1
  43. package/dist/framer/streamProxy.d.ts.map +1 -1
  44. package/dist/framer/streamer.d.ts +139 -20
  45. package/dist/framer/streamer.d.ts.map +1 -1
  46. package/dist/framer/writer.d.ts +222 -33
  47. package/dist/framer/writer.d.ts.map +1 -1
  48. package/dist/hardware/device/client.d.ts +49 -28
  49. package/dist/hardware/device/client.d.ts.map +1 -1
  50. package/dist/hardware/device/payload.d.ts +126 -46
  51. package/dist/hardware/device/payload.d.ts.map +1 -1
  52. package/dist/hardware/rack/client.d.ts +78 -22
  53. package/dist/hardware/rack/client.d.ts.map +1 -1
  54. package/dist/hardware/rack/payload.d.ts +99 -56
  55. package/dist/hardware/rack/payload.d.ts.map +1 -1
  56. package/dist/hardware/task/client.d.ts +100 -41
  57. package/dist/hardware/task/client.d.ts.map +1 -1
  58. package/dist/hardware/task/payload.d.ts +83 -61
  59. package/dist/hardware/task/payload.d.ts.map +1 -1
  60. package/dist/index.d.ts +2 -2
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/label/client.d.ts +138 -20
  63. package/dist/label/client.d.ts.map +1 -1
  64. package/dist/label/external.d.ts +0 -2
  65. package/dist/label/external.d.ts.map +1 -1
  66. package/dist/label/payload.d.ts +4 -5
  67. package/dist/label/payload.d.ts.map +1 -1
  68. package/dist/ontology/client.d.ts +45 -135
  69. package/dist/ontology/client.d.ts.map +1 -1
  70. package/dist/ontology/group/group.d.ts +3 -3
  71. package/dist/ontology/group/group.d.ts.map +1 -1
  72. package/dist/ontology/group/payload.d.ts +3 -27
  73. package/dist/ontology/group/payload.d.ts.map +1 -1
  74. package/dist/ontology/payload.d.ts +113 -243
  75. package/dist/ontology/payload.d.ts.map +1 -1
  76. package/dist/ontology/writer.d.ts +4 -4
  77. package/dist/ontology/writer.d.ts.map +1 -1
  78. package/dist/ranger/alias.d.ts +11 -5
  79. package/dist/ranger/alias.d.ts.map +1 -1
  80. package/dist/ranger/client.d.ts +87 -30
  81. package/dist/ranger/client.d.ts.map +1 -1
  82. package/dist/ranger/external.d.ts +1 -1
  83. package/dist/ranger/external.d.ts.map +1 -1
  84. package/dist/ranger/kv.d.ts +10 -12
  85. package/dist/ranger/kv.d.ts.map +1 -1
  86. package/dist/ranger/payload.d.ts +23 -44
  87. package/dist/ranger/payload.d.ts.map +1 -1
  88. package/dist/ranger/writer.d.ts +22 -19
  89. package/dist/ranger/writer.d.ts.map +1 -1
  90. package/dist/testutil/client.d.ts +4 -0
  91. package/dist/testutil/client.d.ts.map +1 -0
  92. package/dist/user/client.d.ts +59 -6
  93. package/dist/user/client.d.ts.map +1 -1
  94. package/dist/user/payload.d.ts +4 -6
  95. package/dist/user/payload.d.ts.map +1 -1
  96. package/dist/user/retriever.d.ts +2 -2
  97. package/dist/user/retriever.d.ts.map +1 -1
  98. package/dist/util/decodeJSONString.d.ts +2 -2
  99. package/dist/util/decodeJSONString.d.ts.map +1 -1
  100. package/dist/util/parseWithoutKeyConversion.d.ts +2 -2
  101. package/dist/util/parseWithoutKeyConversion.d.ts.map +1 -1
  102. package/dist/util/retrieve.d.ts +1 -1
  103. package/dist/util/retrieve.d.ts.map +1 -1
  104. package/dist/util/zod.d.ts +1 -1
  105. package/dist/util/zod.d.ts.map +1 -1
  106. package/dist/workspace/client.d.ts +17 -6
  107. package/dist/workspace/client.d.ts.map +1 -1
  108. package/dist/workspace/lineplot/client.d.ts +2 -2
  109. package/dist/workspace/lineplot/client.d.ts.map +1 -1
  110. package/dist/workspace/lineplot/payload.d.ts +8 -9
  111. package/dist/workspace/lineplot/payload.d.ts.map +1 -1
  112. package/dist/workspace/log/client.d.ts +2 -2
  113. package/dist/workspace/log/client.d.ts.map +1 -1
  114. package/dist/workspace/log/payload.d.ts +8 -9
  115. package/dist/workspace/log/payload.d.ts.map +1 -1
  116. package/dist/workspace/payload.d.ts +10 -11
  117. package/dist/workspace/payload.d.ts.map +1 -1
  118. package/dist/workspace/schematic/client.d.ts +2 -2
  119. package/dist/workspace/schematic/client.d.ts.map +1 -1
  120. package/dist/workspace/schematic/payload.d.ts +10 -11
  121. package/dist/workspace/schematic/payload.d.ts.map +1 -1
  122. package/dist/workspace/table/client.d.ts +2 -2
  123. package/dist/workspace/table/client.d.ts.map +1 -1
  124. package/dist/workspace/table/payload.d.ts +10 -11
  125. package/dist/workspace/table/payload.d.ts.map +1 -1
  126. package/examples/node/package-lock.json +47 -39
  127. package/examples/node/package.json +2 -1
  128. package/examples/node/streamWrite.js +5 -11
  129. package/package.json +14 -13
  130. package/src/access/payload.ts +1 -1
  131. package/src/access/policy/client.ts +87 -32
  132. package/src/access/policy/external.ts +0 -1
  133. package/src/access/policy/payload.ts +4 -4
  134. package/src/access/policy/policy.spec.ts +86 -83
  135. package/src/auth/auth.spec.ts +29 -18
  136. package/src/auth/auth.ts +1 -1
  137. package/src/channel/batchRetriever.spec.ts +4 -9
  138. package/src/channel/channel.spec.ts +24 -6
  139. package/src/channel/client.ts +31 -46
  140. package/src/channel/payload.ts +13 -14
  141. package/src/channel/retriever.ts +26 -41
  142. package/src/channel/writer.ts +3 -3
  143. package/src/client.ts +4 -4
  144. package/src/connection/checker.ts +1 -1
  145. package/src/connection/connection.spec.ts +31 -23
  146. package/src/control/client.ts +2 -2
  147. package/src/control/state.spec.ts +3 -3
  148. package/src/control/state.ts +1 -1
  149. package/src/errors.spec.ts +9 -5
  150. package/src/errors.ts +28 -15
  151. package/src/framer/adapter.spec.ts +118 -9
  152. package/src/framer/adapter.ts +24 -11
  153. package/src/framer/client.spec.ts +125 -2
  154. package/src/framer/client.ts +41 -47
  155. package/src/framer/codec.ts +1 -1
  156. package/src/framer/deleter.spec.ts +2 -2
  157. package/src/framer/deleter.ts +1 -1
  158. package/src/framer/frame.ts +1 -4
  159. package/src/framer/iterator.spec.ts +8 -8
  160. package/src/framer/iterator.ts +1 -1
  161. package/src/framer/streamProxy.ts +1 -1
  162. package/src/framer/streamer.spec.ts +185 -36
  163. package/src/framer/streamer.ts +28 -36
  164. package/src/framer/writer.spec.ts +6 -6
  165. package/src/framer/writer.ts +97 -111
  166. package/src/hardware/device/client.ts +45 -131
  167. package/src/hardware/device/device.spec.ts +163 -52
  168. package/src/hardware/device/payload.ts +10 -21
  169. package/src/hardware/rack/client.ts +87 -105
  170. package/src/hardware/rack/payload.ts +4 -13
  171. package/src/hardware/rack/rack.spec.ts +28 -35
  172. package/src/hardware/task/client.ts +335 -291
  173. package/src/hardware/task/payload.ts +86 -62
  174. package/src/hardware/task/task.spec.ts +208 -32
  175. package/src/index.ts +2 -1
  176. package/src/label/client.ts +100 -95
  177. package/src/label/external.ts +0 -2
  178. package/src/label/label.spec.ts +8 -6
  179. package/src/label/payload.ts +3 -4
  180. package/src/ontology/client.ts +41 -324
  181. package/src/ontology/group/group.spec.ts +2 -2
  182. package/src/ontology/group/group.ts +4 -5
  183. package/src/ontology/group/payload.ts +2 -25
  184. package/src/ontology/group/writer.ts +1 -1
  185. package/src/ontology/ontology.spec.ts +355 -41
  186. package/src/ontology/payload.ts +74 -112
  187. package/src/ontology/writer.ts +8 -17
  188. package/src/ranger/alias.ts +19 -37
  189. package/src/ranger/client.ts +118 -150
  190. package/src/ranger/external.ts +9 -1
  191. package/src/ranger/kv.ts +6 -27
  192. package/src/ranger/payload.ts +21 -37
  193. package/src/ranger/ranger.spec.ts +37 -56
  194. package/src/ranger/writer.ts +1 -1
  195. package/src/{signals/index.ts → testutil/client.ts} +11 -1
  196. package/src/user/client.ts +122 -47
  197. package/src/user/payload.ts +2 -5
  198. package/src/user/retriever.ts +1 -1
  199. package/src/user/user.spec.ts +31 -31
  200. package/src/user/writer.ts +1 -1
  201. package/src/util/decodeJSONString.ts +3 -3
  202. package/src/util/parseWithoutKeyConversion.ts +2 -2
  203. package/src/util/retrieve.ts +1 -1
  204. package/src/util/zod.ts +1 -1
  205. package/src/workspace/client.ts +20 -36
  206. package/src/workspace/lineplot/client.ts +5 -7
  207. package/src/workspace/lineplot/lineplot.spec.ts +2 -2
  208. package/src/workspace/lineplot/payload.ts +4 -7
  209. package/src/workspace/log/client.ts +5 -7
  210. package/src/workspace/log/log.spec.ts +2 -2
  211. package/src/workspace/log/payload.ts +4 -7
  212. package/src/workspace/payload.ts +4 -7
  213. package/src/workspace/schematic/client.ts +5 -7
  214. package/src/workspace/schematic/payload.ts +4 -7
  215. package/src/workspace/schematic/schematic.spec.ts +2 -2
  216. package/src/workspace/table/client.ts +5 -7
  217. package/src/workspace/table/payload.ts +4 -7
  218. package/src/workspace/table/table.spec.ts +2 -2
  219. package/src/workspace/workspace.spec.ts +2 -2
  220. package/dist/access/policy/ontology.d.ts +0 -5
  221. package/dist/access/policy/ontology.d.ts.map +0 -1
  222. package/dist/access/policy/retriever.d.ts +0 -40
  223. package/dist/access/policy/retriever.d.ts.map +0 -1
  224. package/dist/access/policy/writer.d.ts +0 -9
  225. package/dist/access/policy/writer.d.ts.map +0 -1
  226. package/dist/label/retriever.d.ts +0 -14
  227. package/dist/label/retriever.d.ts.map +0 -1
  228. package/dist/label/writer.d.ts +0 -54
  229. package/dist/label/writer.d.ts.map +0 -1
  230. package/dist/setupspecs.d.ts +0 -5
  231. package/dist/setupspecs.d.ts.map +0 -1
  232. package/dist/signals/external.d.ts +0 -2
  233. package/dist/signals/external.d.ts.map +0 -1
  234. package/dist/signals/index.d.ts +0 -2
  235. package/dist/signals/index.d.ts.map +0 -1
  236. package/dist/signals/observable.d.ts +0 -12
  237. package/dist/signals/observable.d.ts.map +0 -1
  238. package/src/access/policy/ontology.ts +0 -17
  239. package/src/access/policy/retriever.ts +0 -44
  240. package/src/access/policy/writer.ts +0 -65
  241. package/src/label/retriever.ts +0 -63
  242. package/src/label/writer.ts +0 -95
  243. package/src/setupspecs.ts +0 -27
  244. package/src/signals/external.ts +0 -10
  245. package/src/signals/observable.ts +0 -42
@@ -8,9 +8,9 @@
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
10
  import { sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
11
- import { z } from "zod/v4";
11
+ import { z } from "zod";
12
12
 
13
- import { type CrudeID, ID, idZ } from "@/ontology/payload";
13
+ import { type ID, idZ } from "@/ontology/payload";
14
14
 
15
15
  const ADD_CHILDREN_ENDPOINT = "/ontology/add-children";
16
16
  const REMOVE_CHILDREN_ENDPOINT = "/ontology/remove-children";
@@ -29,40 +29,31 @@ export class Writer {
29
29
  this.client = client;
30
30
  }
31
31
 
32
- async addChildren(id: CrudeID, ...children: CrudeID[]): Promise<void> {
32
+ async addChildren(id: ID, ...children: ID[]): Promise<void> {
33
33
  await sendRequired<typeof addRemoveChildrenReqZ, typeof emptyResZ>(
34
34
  this.client,
35
35
  ADD_CHILDREN_ENDPOINT,
36
- { id: new ID(id).payload, children: children.map((c) => new ID(c).payload) },
36
+ { id, children },
37
37
  addRemoveChildrenReqZ,
38
38
  emptyResZ,
39
39
  );
40
40
  }
41
41
 
42
- async removeChildren(id: CrudeID, ...children: CrudeID[]): Promise<void> {
42
+ async removeChildren(id: ID, ...children: ID[]): Promise<void> {
43
43
  await sendRequired<typeof addRemoveChildrenReqZ, typeof emptyResZ>(
44
44
  this.client,
45
45
  REMOVE_CHILDREN_ENDPOINT,
46
- { id: new ID(id).payload, children: children.map((c) => new ID(c).payload) },
46
+ { id, children },
47
47
  addRemoveChildrenReqZ,
48
48
  emptyResZ,
49
49
  );
50
50
  }
51
51
 
52
- async moveChildren(
53
- from: CrudeID,
54
- to: CrudeID,
55
- ...children: CrudeID[]
56
- ): Promise<void> {
57
- const req = {
58
- from: new ID(from).payload,
59
- to: new ID(to).payload,
60
- children: children.map((c) => new ID(c).payload),
61
- };
52
+ async moveChildren(from: ID, to: ID, ...children: ID[]): Promise<void> {
62
53
  await sendRequired<typeof moveChildrenReqZ, typeof emptyResZ>(
63
54
  this.client,
64
55
  MOVE_CHILDREN_ENDPOINT,
65
- req,
56
+ { from, to, children },
66
57
  moveChildrenReqZ,
67
58
  emptyResZ,
68
59
  );
@@ -9,12 +9,11 @@
9
9
 
10
10
  import { sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
11
11
  import { type change } from "@synnaxlabs/x/change";
12
- import { z } from "zod/v4";
12
+ import { z } from "zod";
13
13
 
14
14
  import { channel } from "@/channel";
15
15
  import { type framer } from "@/framer";
16
16
  import { type Key, keyZ } from "@/ranger/payload";
17
- import { signals } from "@/signals";
18
17
 
19
18
  export const SET_ALIAS_CHANNEL_NAME = "sy_range_alias_set";
20
19
  export const DELETE_ALIAS_CHANNEL_NAME = "sy_range_alias_delete";
@@ -118,44 +117,27 @@ export class Aliaser {
118
117
  deleteResZ,
119
118
  );
120
119
  }
121
-
122
- async openChangeTracker(): Promise<signals.Observable<string, Alias>> {
123
- return await signals.openObservable<string, Alias>(
124
- this.frameClient,
125
- SET_ALIAS_CHANNEL_NAME,
126
- DELETE_ALIAS_CHANNEL_NAME,
127
- decodeAliasChanges(this.rangeKey),
128
- );
129
- }
130
120
  }
131
121
 
132
- export interface Alias {
122
+ export const aliasZ = z.object({
123
+ alias: z.string(),
124
+ channel: channel.keyZ,
125
+ range: keyZ,
126
+ });
127
+ export interface Alias extends z.infer<typeof aliasZ> {}
128
+
129
+ export type AliasChange = change.Change<string, Alias>;
130
+
131
+ const SEPARATOR = "---";
132
+
133
+ export interface DecodedDeleteAliasChange {
133
134
  range: Key;
134
135
  channel: channel.Key;
135
- alias: string;
136
136
  }
137
137
 
138
- export type AliasChange = change.Change<string, Alias>;
139
-
140
- const aliasZ = z.object({ range: keyZ, channel: channel.keyZ, alias: z.string() });
141
-
142
- const separator = "---";
143
-
144
- const decodeAliasChanges =
145
- (rangeKey: Key): signals.Decoder<string, Alias> =>
146
- (variant, data) => {
147
- if (variant === "delete")
148
- return data
149
- .toStrings()
150
- .filter((k) => k.split(separator)[0] === rangeKey)
151
- .map((alias) => ({
152
- variant,
153
- key: alias,
154
- value: undefined,
155
- }));
156
- return data.parseJSON(aliasZ).map((alias) => ({
157
- variant,
158
- key: alias.alias,
159
- value: alias,
160
- }));
161
- };
138
+ export const decodeDeleteAliasChange = (
139
+ deletedAlias: string,
140
+ ): DecodedDeleteAliasChange => {
141
+ const [range, channel] = deletedAlias.split(SEPARATOR);
142
+ return { range, channel: Number(channel) };
143
+ };
@@ -8,43 +8,53 @@
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
10
  import { sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
11
- import { type CrudeTimeRange, observe, sortTimeRange, TimeRange } from "@synnaxlabs/x";
12
- import { array } from "@synnaxlabs/x/array";
13
- import { type AsyncTermSearcher } from "@synnaxlabs/x/search";
11
+ import { array, type CrudeTimeRange, TimeRange } from "@synnaxlabs/x";
14
12
  import { type Series } from "@synnaxlabs/x/telem";
15
- import { z } from "zod/v4";
13
+ import { z } from "zod";
16
14
 
17
15
  import { type channel } from "@/channel";
18
- import { MultipleFoundError, NotFoundError, QueryError } from "@/errors";
16
+ import { QueryError } from "@/errors";
19
17
  import { type framer } from "@/framer";
20
18
  import { label } from "@/label";
21
- import { ontology } from "@/ontology";
22
- import { type Alias, Aliaser } from "@/ranger/alias";
19
+ import { type ontology } from "@/ontology";
20
+ import { Aliaser } from "@/ranger/alias";
23
21
  import { KV } from "@/ranger/kv";
24
22
  import {
25
- ALIAS_ONTOLOGY_TYPE,
26
- analyzeParams,
27
23
  type Key,
28
24
  type Keys,
29
25
  keyZ,
30
26
  type Name,
31
27
  type Names,
32
28
  type New,
33
- ONTOLOGY_TYPE,
34
29
  type Params,
35
30
  type Payload,
36
31
  payloadZ,
37
32
  } from "@/ranger/payload";
38
33
  import { type CreateOptions, type Writer } from "@/ranger/writer";
39
- import { signals } from "@/signals";
34
+ import { checkForMultipleOrNoResults } from "@/util/retrieve";
40
35
  import { nullableArrayZ } from "@/util/zod";
41
36
 
37
+ export const SET_CHANNEL_NAME = "sy_range_set";
38
+ export const DELETE_CHANNEL_NAME = "sy_range_delete";
39
+
40
+ interface RangeConstructionOptions {
41
+ frameClient: framer.Client;
42
+ kv: KV;
43
+ aliaser: Aliaser;
44
+ channels: channel.Retriever;
45
+ labelClient: label.Client;
46
+ ontologyClient: ontology.Client;
47
+ rangeClient: Client;
48
+ }
49
+
42
50
  export class Range {
43
51
  key: string;
44
52
  name: string;
45
53
  readonly kv: KV;
46
54
  readonly timeRange: TimeRange;
47
55
  readonly color: string | undefined;
56
+ readonly parent: Payload | null;
57
+ readonly labels: label.Label[];
48
58
  readonly channels: channel.Retriever;
49
59
  private readonly aliaser: Aliaser;
50
60
  private readonly frameClient: framer.Client;
@@ -53,29 +63,30 @@ export class Range {
53
63
  private readonly rangeClient: Client;
54
64
 
55
65
  constructor(
56
- name: string,
57
- timeRange: TimeRange = TimeRange.ZERO,
58
- key: string,
59
- color: string | undefined,
60
- _frameClient: framer.Client,
61
- _kv: KV,
62
- _aliaser: Aliaser,
63
- _channels: channel.Retriever,
64
- _labelClient: label.Client,
65
- _ontologyClient: ontology.Client,
66
- _rangeClient: Client,
66
+ { name, timeRange = TimeRange.ZERO, key, color, parent, labels = [] }: Payload,
67
+ {
68
+ frameClient,
69
+ kv,
70
+ aliaser,
71
+ channels,
72
+ labelClient,
73
+ ontologyClient,
74
+ rangeClient,
75
+ }: RangeConstructionOptions,
67
76
  ) {
68
77
  this.key = key;
69
78
  this.name = name;
70
79
  this.timeRange = timeRange;
71
- this.frameClient = _frameClient;
80
+ this.parent = parent;
81
+ this.labels = labels;
82
+ this.frameClient = frameClient;
72
83
  this.color = color;
73
- this.kv = _kv;
74
- this.aliaser = _aliaser;
75
- this.channels = _channels;
76
- this.labelClient = _labelClient;
77
- this.ontologyClient = _ontologyClient;
78
- this.rangeClient = _rangeClient;
84
+ this.kv = kv;
85
+ this.aliaser = aliaser;
86
+ this.channels = channels;
87
+ this.labelClient = labelClient;
88
+ this.ontologyClient = ontologyClient;
89
+ this.rangeClient = rangeClient;
79
90
  }
80
91
 
81
92
  get ontologyID(): ontology.ID {
@@ -88,6 +99,8 @@ export class Range {
88
99
  name: this.name,
89
100
  timeRange: this.timeRange,
90
101
  color: this.color,
102
+ labels: this.labels,
103
+ parent: this.parent,
91
104
  };
92
105
  }
93
106
 
@@ -109,10 +122,6 @@ export class Range {
109
122
  return await this.aliaser.resolve(alias);
110
123
  }
111
124
 
112
- async openAliasTracker(): Promise<signals.Observable<string, Alias>> {
113
- return await this.aliaser.openChangeTracker();
114
- }
115
-
116
125
  async retrieveParent(): Promise<Range | null> {
117
126
  return this.rangeClient.retrieveParent(this.key);
118
127
  }
@@ -133,8 +142,8 @@ export class Range {
133
142
  return await this.frameClient.read(this.timeRange, channels);
134
143
  }
135
144
 
136
- async labels(): Promise<label.Label[]> {
137
- return await this.labelClient.retrieveFor(ontologyID(this.key));
145
+ async retrieveLabels(): Promise<label.Label[]> {
146
+ return await this.labelClient.retrieve({ for: ontologyID(this.key) });
138
147
  }
139
148
 
140
149
  async addLabel(...labels: label.Key[]): Promise<void> {
@@ -142,69 +151,47 @@ export class Range {
142
151
  }
143
152
 
144
153
  async removeLabel(...labels: label.Key[]): Promise<void> {
145
- await this.labelClient.removeLabels(ontologyID(this.key), labels);
154
+ await this.labelClient.remove(ontologyID(this.key), labels);
146
155
  }
147
156
 
148
- async openChildRangeTracker(): Promise<observe.ObservableAsyncCloseable<Range[]>> {
149
- const wrapper = new observe.Observer<Range[]>();
150
- const initial: ontology.Resource[] = (await this.retrieveChildren()).map((r) => {
151
- const id = ontologyID(r.key);
152
- return { id, key: id.toString(), name: r.name, data: r.payload };
153
- });
154
- const base = await this.ontologyClient.openDependentTracker({
155
- target: this.ontologyID,
156
- dependents: initial,
157
- resourceType: "range",
158
- });
159
- base.onChange((r: ontology.Resource[]) =>
160
- wrapper.notify(this.rangeClient.resourcesToRanges(r)),
161
- );
162
- wrapper.setCloser(async () => await base.close());
163
- return wrapper;
164
- }
165
-
166
- async openParentRangeTracker(): Promise<observe.ObservableAsyncCloseable<Range> | null> {
167
- const wrapper = new observe.Observer<Range>();
168
- const p = await this.retrieveParent();
169
- if (p == null) return null;
170
- const id = ontologyID(p.key);
171
- const resourceP = { id, key: id.toString(), name: p.name, data: p.payload };
172
- const base = await this.ontologyClient.openDependentTracker({
173
- target: this.ontologyID,
174
- dependents: [resourceP],
175
- relationshipDirection: "to",
176
- });
177
- base.onChange((resources: ontology.Resource[]) => {
178
- const ranges = this.rangeClient.resourcesToRanges(resources);
179
- if (ranges.length === 0) return;
180
- const p = ranges[0];
181
- wrapper.notify(p);
182
- });
183
- wrapper.setCloser(async () => await base.close());
184
- return wrapper;
157
+ static sort(a: Range, b: Range): number {
158
+ return TimeRange.sort(a.timeRange, b.timeRange);
185
159
  }
186
160
  }
187
161
 
188
- export const sort = (a: Range, b: Range): -1 | 0 | 1 =>
189
- sortTimeRange(a.timeRange, b.timeRange);
190
-
191
- const retrieveReqZ = z.object({
162
+ const retrieveRequestZ = z.object({
192
163
  keys: keyZ.array().optional(),
193
164
  names: z.array(z.string()).optional(),
194
- term: z.string().optional(),
165
+ searchTerm: z.string().optional(),
195
166
  overlapsWith: TimeRange.z.optional(),
196
167
  limit: z.number().int().optional(),
197
168
  offset: z.number().int().optional(),
198
169
  hasLabels: label.keyZ.array().optional(),
170
+ includeLabels: z.boolean().optional(),
171
+ includeParent: z.boolean().optional(),
199
172
  });
200
173
 
201
- export interface RetrieveRequest extends z.infer<typeof retrieveReqZ> {}
174
+ export type RetrieveRequest = z.infer<typeof retrieveRequestZ>;
175
+
176
+ const retrieveArgsZ = retrieveRequestZ
177
+ .or(keyZ.array().transform((keys) => ({ keys })))
178
+ .or(keyZ.transform((key) => ({ keys: [key] })))
179
+ .or(z.string().transform((name) => ({ names: [name] })))
180
+ .or(
181
+ z
182
+ .string()
183
+ .array()
184
+ .transform((names) => ({ names })),
185
+ )
186
+ .or(TimeRange.z.transform((timeRange) => ({ overlapsWith: timeRange })));
187
+
188
+ export type RetrieveArgs = z.input<typeof retrieveArgsZ>;
202
189
 
203
190
  const RETRIEVE_ENDPOINT = "/range/retrieve";
204
191
 
205
192
  const retrieveResZ = z.object({ ranges: nullableArrayZ(payloadZ) });
206
193
 
207
- export class Client implements AsyncTermSearcher<string, Key, Range> {
194
+ export class Client {
208
195
  readonly type: string = "range";
209
196
  private readonly frameClient: framer.Client;
210
197
  private readonly writer: Writer;
@@ -247,48 +234,28 @@ export class Client implements AsyncTermSearcher<string, Key, Range> {
247
234
  await this.writer.delete(array.toArray(key));
248
235
  }
249
236
 
250
- async search(term: string): Promise<Range[]> {
251
- return this.sugarMany(await this.execRetrieve({ term }));
252
- }
253
-
254
- async page(offset: number, limit: number): Promise<Range[]> {
255
- return this.sugarMany(await this.execRetrieve({ offset, limit }));
256
- }
257
-
258
- async retrieve(range: CrudeTimeRange): Promise<Range[]>;
259
- async retrieve(range: Key | Name): Promise<Range>;
260
- async retrieve(range: Keys | Names): Promise<Range[]>;
261
- async retrieve(ranges: Params | CrudeTimeRange): Promise<Range | Range[]> {
262
- if (typeof ranges === "object" && "start" in ranges)
263
- return await this.execRetrieve({ overlapsWith: new TimeRange(ranges) });
264
- const { single, actual, variant, normalized, empty } = analyzeParams(ranges);
265
- if (empty) return [];
266
- const retrieved = await this.execRetrieve({ [variant]: normalized });
267
- if (!single) return retrieved;
268
- if (retrieved.length === 0)
269
- throw new NotFoundError(`range matching ${actual as string} not found`);
270
- if (retrieved.length > 1)
271
- throw new MultipleFoundError(
272
- `multiple ranges matching ${actual as string} found`,
273
- );
274
- return retrieved[0];
275
- }
276
-
277
- getKV(range: Key): KV {
278
- return new KV(range, this.unaryClient, this.frameClient);
279
- }
280
-
281
- private async execRetrieve(req: RetrieveRequest): Promise<Range[]> {
282
- const { ranges } = await sendRequired<typeof retrieveReqZ, typeof retrieveResZ>(
237
+ async retrieve(params: Key | Name): Promise<Range>;
238
+ async retrieve(params: Keys | Names): Promise<Range[]>;
239
+ async retrieve(params: TimeRange): Promise<Range[]>;
240
+ async retrieve(params: RetrieveRequest): Promise<Range[]>;
241
+ async retrieve(params: RetrieveArgs): Promise<Range | Range[]> {
242
+ const isSingle = typeof params === "string";
243
+ const { ranges } = await sendRequired(
283
244
  this.unaryClient,
284
245
  RETRIEVE_ENDPOINT,
285
- req,
286
- retrieveReqZ,
246
+ params,
247
+ retrieveArgsZ,
287
248
  retrieveResZ,
288
249
  );
250
+ checkForMultipleOrNoResults("Range", params, ranges, isSingle);
251
+ if (isSingle) return this.sugarMany(ranges)[0];
289
252
  return this.sugarMany(ranges);
290
253
  }
291
254
 
255
+ getKV(range: Key): KV {
256
+ return new KV(range, this.unaryClient);
257
+ }
258
+
292
259
  async retrieveParent(range: Key): Promise<Range | null> {
293
260
  const res = await this.ontologyClient.retrieveParents(ontologyID(range));
294
261
  if (res.length === 0) return null;
@@ -297,56 +264,57 @@ export class Client implements AsyncTermSearcher<string, Key, Range> {
297
264
  return await this.retrieve(first.id.key);
298
265
  }
299
266
 
267
+ sugarOntologyResource(resource: ontology.Resource): Range {
268
+ return this.sugarOne(convertOntologyResourceToPayload(resource));
269
+ }
270
+
300
271
  sugarOne(payload: Payload): Range {
301
- return new Range(
302
- payload.name,
303
- payload.timeRange,
304
- payload.key,
305
- payload.color,
306
- this.frameClient,
307
- new KV(payload.key, this.unaryClient, this.frameClient),
308
- new Aliaser(payload.key, this.frameClient, this.unaryClient),
309
- this.channels,
310
- this.labelClient,
311
- this.ontologyClient,
312
- this,
313
- );
272
+ return new Range(payload, {
273
+ frameClient: this.frameClient,
274
+ kv: new KV(payload.key, this.unaryClient),
275
+ aliaser: new Aliaser(payload.key, this.frameClient, this.unaryClient),
276
+ channels: this.channels,
277
+ labelClient: this.labelClient,
278
+ ontologyClient: this.ontologyClient,
279
+ rangeClient: this,
280
+ });
314
281
  }
315
282
 
316
283
  sugarMany(payloads: Payload[]): Range[] {
317
284
  return payloads.map((payload) => this.sugarOne(payload));
318
285
  }
319
286
 
320
- async openTracker(): Promise<signals.Observable<string, Range>> {
321
- return await signals.openObservable<string, Range>(
322
- this.frameClient,
323
- "sy_range_set",
324
- "sy_range_delete",
325
- (variant, data) => {
326
- if (variant === "delete")
327
- return data.toUUIDs().map((k) => ({ variant, key: k, value: undefined }));
328
- const sugared = this.sugarMany(data.parseJSON(payloadZ));
329
- return sugared.map((r) => ({ variant, key: r.key, value: r }));
330
- },
331
- );
332
- }
333
-
334
- resourcesToRanges(resources: ontology.Resource[]): Range[] {
335
- return resources.map((r) => this.resourceToRange(r));
336
- }
337
-
338
287
  resourceToRange(resource: ontology.Resource): Range {
339
288
  return this.sugarOne({
340
289
  key: resource.id.key,
341
290
  name: resource.data?.name as string,
342
291
  timeRange: new TimeRange(resource.data?.timeRange as CrudeTimeRange),
343
292
  color: resource.data?.color as string,
293
+ labels: [],
294
+ parent: null,
344
295
  });
345
296
  }
346
297
  }
347
298
 
348
- export const ontologyID = (key: Key): ontology.ID =>
349
- new ontology.ID({ type: ONTOLOGY_TYPE, key });
299
+ export const ontologyID = (key: Key): ontology.ID => ({ type: "range", key });
300
+
301
+ export const aliasOntologyID = (key: Key): ontology.ID => ({
302
+ type: "range-alias",
303
+ key,
304
+ });
350
305
 
351
- export const aliasOntologyID = (key: Key): ontology.ID =>
352
- new ontology.ID({ type: ALIAS_ONTOLOGY_TYPE, key });
306
+ export const convertOntologyResourceToPayload = ({
307
+ data,
308
+ id: { key },
309
+ name,
310
+ }: ontology.Resource): Payload => {
311
+ const timeRange = TimeRange.z.parse(data?.timeRange);
312
+ return {
313
+ key,
314
+ name,
315
+ timeRange,
316
+ color: typeof data?.color === "string" ? data.color : undefined,
317
+ labels: [],
318
+ parent: null,
319
+ };
320
+ };
@@ -7,7 +7,15 @@
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 { type Alias, type AliasChange } from "@/ranger/alias";
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";
11
19
  export * from "@/ranger/client";
12
20
  export * from "@/ranger/kv";
13
21
  export * from "@/ranger/payload";
package/src/ranger/kv.ts CHANGED
@@ -10,14 +10,15 @@
10
10
  import { sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
11
11
  import { array } from "@synnaxlabs/x/array";
12
12
  import { isObject } from "@synnaxlabs/x/identity";
13
- import { z } from "zod/v4";
13
+ import { z } from "zod";
14
14
 
15
- import { type framer } from "@/framer";
16
15
  import { type Key, keyZ } from "@/ranger/payload";
17
- import { signals } from "@/signals";
18
16
  import { nullableArrayZ } from "@/util/zod";
19
17
 
20
- const kvPairZ = z.object({ range: keyZ, key: z.string(), value: z.string() });
18
+ export const KV_SET_CHANNEL = "sy_range_kv_set";
19
+ export const KV_DELETE_CHANNEL = "sy_range_kv_delete";
20
+
21
+ export const kvPairZ = z.object({ range: keyZ, key: z.string(), value: z.string() });
21
22
  export interface KVPair extends z.infer<typeof kvPairZ> {}
22
23
 
23
24
  const getReqZ = z.object({ range: keyZ, keys: z.string().array() });
@@ -37,12 +38,10 @@ export class KV {
37
38
  private static readonly DELETE_ENDPOINT = "/range/kv/delete";
38
39
  private readonly rangeKey: Key;
39
40
  private readonly client: UnaryClient;
40
- private readonly frameClient: framer.Client;
41
41
 
42
- constructor(rng: Key, client: UnaryClient, frameClient: framer.Client) {
42
+ constructor(rng: Key, client: UnaryClient) {
43
43
  this.rangeKey = rng;
44
44
  this.client = client;
45
- this.frameClient = frameClient;
46
45
  }
47
46
 
48
47
  async get(key: string): Promise<string>;
@@ -92,24 +91,4 @@ export class KV {
92
91
  z.unknown(),
93
92
  );
94
93
  }
95
-
96
- async openTracker(): Promise<signals.Observable<string, KVPair>> {
97
- return await signals.openObservable<string, KVPair>(
98
- this.frameClient,
99
- "sy_range_kv_set",
100
- "sy_range_kv_delete",
101
- (variant, data) => {
102
- if (variant === "delete")
103
- return data.toStrings().map((combinedKey) => {
104
- const [range, key] = combinedKey.split("<--->", 2);
105
- return { variant, key: combinedKey, value: { range, key, value: "" } };
106
- });
107
- return data.parseJSON(kvPairZ).map((pair) => ({
108
- variant,
109
- key: `${pair.range}${pair.key}`,
110
- value: pair,
111
- }));
112
- },
113
- );
114
- }
115
94
  }
@@ -7,11 +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 { array } from "@synnaxlabs/x/array";
11
10
  import { TimeRange } from "@synnaxlabs/x/telem";
12
- import { z } from "zod/v4";
11
+ import { z } from "zod";
13
12
 
14
- export const keyZ = z.string().uuid();
13
+ import { label } from "@/label";
14
+ import { nullableArrayZ } from "@/util/zod";
15
+
16
+ export const keyZ = z.uuid();
15
17
  export type Key = z.infer<typeof keyZ>;
16
18
  export const nameZ = z.string().min(1);
17
19
  export type Name = z.infer<typeof nameZ>;
@@ -24,40 +26,22 @@ export const payloadZ = z.object({
24
26
  name: nameZ,
25
27
  timeRange: TimeRange.z,
26
28
  color: z.string().optional(),
29
+ labels: nullableArrayZ(label.labelZ),
30
+ get parent(): z.ZodUnion<readonly [z.ZodNull, typeof payloadZ]> {
31
+ // Using as unknown is bad, but unfortunately resolving the output type of this
32
+ // transform is nearly impossible.
33
+ return payloadZ
34
+ .optional()
35
+ .nullable()
36
+ .transform((p) => (p === undefined ? null : p)) as unknown as z.ZodUnion<
37
+ readonly [z.ZodNull, typeof payloadZ]
38
+ >;
39
+ },
27
40
  });
28
- export interface Payload extends z.infer<typeof payloadZ> {}
29
-
30
- export const newZ = payloadZ.partial({ key: true });
31
- export interface New extends z.input<typeof newZ> {}
32
41
 
33
- export type ParamAnalysisResult =
34
- | { single: true; variant: "keys"; normalized: Keys; actual: Key; empty: never }
35
- | { single: true; variant: "names"; normalized: Names; actual: Name; empty: never }
36
- | { single: false; variant: "keys"; normalized: Keys; actual: Keys; empty: boolean }
37
- | {
38
- single: false;
39
- variant: "names";
40
- normalized: Names;
41
- actual: Names;
42
- empty: boolean;
43
- };
42
+ export type Payload = z.infer<typeof payloadZ>;
44
43
 
45
- export const analyzeParams = (ranges: Params): ParamAnalysisResult => {
46
- const normal = array.toArray(ranges) as Keys | Names;
47
- const empty = normal.length === 0;
48
- let isKey = false;
49
- if (!empty) isKey = keyZ.safeParse(normal[0]).success;
50
- return {
51
- single: !Array.isArray(ranges),
52
- variant: isKey ? "keys" : "names",
53
- normalized: normal,
54
- actual: ranges,
55
- empty,
56
- } as ParamAnalysisResult;
57
- };
58
-
59
- export const ONTOLOGY_TYPE = "range";
60
- export type OntologyType = typeof ONTOLOGY_TYPE;
61
-
62
- export const ALIAS_ONTOLOGY_TYPE = "range-alias";
63
- export type AliasOntologyType = typeof ALIAS_ONTOLOGY_TYPE;
44
+ export const newZ = payloadZ
45
+ .omit({ parent: true, labels: true })
46
+ .partial({ key: true });
47
+ export interface New extends z.input<typeof newZ> {}