@synnaxlabs/client 0.43.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 (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 +23 -17
  13. package/dist/channel/client.d.ts.map +1 -1
  14. package/dist/channel/payload.d.ts +151 -21
  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 +8657 -28963
  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 +235 -20
  45. package/dist/framer/streamer.d.ts.map +1 -1
  46. package/dist/framer/writer.d.ts +302 -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 +114 -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 +15 -5
  79. package/dist/ranger/alias.d.ts.map +1 -1
  80. package/dist/ranger/client.d.ts +91 -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 +11 -12
  85. package/dist/ranger/kv.d.ts.map +1 -1
  86. package/dist/ranger/payload.d.ts +19 -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 +52 -51
  140. package/src/channel/payload.ts +15 -16
  141. package/src/channel/retriever.ts +26 -41
  142. package/src/channel/writer.ts +7 -4
  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 +7 -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 +77 -112
  187. package/src/ontology/writer.ts +8 -17
  188. package/src/ranger/alias.ts +45 -37
  189. package/src/ranger/client.ts +144 -149
  190. package/src/ranger/external.ts +1 -1
  191. package/src/ranger/kv.ts +9 -27
  192. package/src/ranger/payload.ts +23 -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
  );
@@ -8,13 +8,13 @@
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
- import { z } from "zod/v4";
13
+ import { z } from "zod";
13
14
 
14
15
  import { channel } from "@/channel";
15
16
  import { type framer } from "@/framer";
16
17
  import { type Key, keyZ } from "@/ranger/payload";
17
- import { signals } from "@/signals";
18
18
 
19
19
  export const SET_ALIAS_CHANNEL_NAME = "sy_range_alias_set";
20
20
  export const DELETE_ALIAS_CHANNEL_NAME = "sy_range_alias_delete";
@@ -38,10 +38,15 @@ const listReqZ = z.object({ range: keyZ });
38
38
 
39
39
  const listResZ = z.object({ aliases: z.record(z.string(), z.string()) });
40
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
+
41
45
  export class Aliaser {
42
46
  private static readonly SET_ENDPOINT = "/range/alias/set";
43
47
  private static readonly RESOLVE_ENDPOINT = "/range/alias/resolve";
44
48
  private static readonly LIST_ENDPOINT = "/range/alias/list";
49
+ private static readonly RETRIEVE_ENDPOINT = "/range/alias/retrieve";
45
50
  private static readonly DELETE_ENDPOINT = "/range/alias/delete";
46
51
  private readonly frameClient: framer.Client;
47
52
  private readonly cache = new Map<string, channel.Key>();
@@ -109,6 +114,23 @@ export class Aliaser {
109
114
  ).aliases;
110
115
  }
111
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
+
112
134
  async delete(aliases: channel.Key[]): Promise<void> {
113
135
  await sendRequired<typeof deleteReqZ, typeof deleteResZ>(
114
136
  this.client,
@@ -118,44 +140,30 @@ export class Aliaser {
118
140
  deleteResZ,
119
141
  );
120
142
  }
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
143
  }
131
144
 
132
- export interface Alias {
145
+ export const aliasZ = z.object({
146
+ alias: z.string().optional(),
147
+ channel: channel.keyZ,
148
+ range: keyZ,
149
+ });
150
+ export interface Alias extends z.infer<typeof aliasZ> {}
151
+
152
+ export type AliasChange = change.Change<string, Alias>;
153
+
154
+ const SEPARATOR = "---";
155
+
156
+ export const aliasKey = (alias: Pick<Alias, "range" | "channel">): string =>
157
+ `${alias.range}${SEPARATOR}${alias.channel}`;
158
+
159
+ export interface DecodedDeleteAliasChange {
133
160
  range: Key;
134
161
  channel: channel.Key;
135
- alias: string;
136
162
  }
137
163
 
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
- };
164
+ export const decodeDeleteAliasChange = (
165
+ deletedAlias: string,
166
+ ): DecodedDeleteAliasChange => {
167
+ const [range, channel] = deletedAlias.split(SEPARATOR);
168
+ return { range, channel: Number(channel) };
169
+ };
@@ -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 {
@@ -83,11 +94,17 @@ export class Range {
83
94
  }
84
95
 
85
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;
86
101
  return {
87
102
  key: this.key,
88
103
  name: this.name,
89
104
  timeRange: this.timeRange,
90
105
  color: this.color,
106
+ labels: this.labels,
107
+ parent,
91
108
  };
92
109
  }
93
110
 
@@ -109,10 +126,6 @@ export class Range {
109
126
  return await this.aliaser.resolve(alias);
110
127
  }
111
128
 
112
- async openAliasTracker(): Promise<signals.Observable<string, Alias>> {
113
- return await this.aliaser.openChangeTracker();
114
- }
115
-
116
129
  async retrieveParent(): Promise<Range | null> {
117
130
  return this.rangeClient.retrieveParent(this.key);
118
131
  }
@@ -133,8 +146,8 @@ export class Range {
133
146
  return await this.frameClient.read(this.timeRange, channels);
134
147
  }
135
148
 
136
- async labels(): Promise<label.Label[]> {
137
- return await this.labelClient.retrieveFor(ontologyID(this.key));
149
+ async retrieveLabels(): Promise<label.Label[]> {
150
+ return await this.labelClient.retrieve({ for: ontologyID(this.key) });
138
151
  }
139
152
 
140
153
  async addLabel(...labels: label.Key[]): Promise<void> {
@@ -142,69 +155,47 @@ export class Range {
142
155
  }
143
156
 
144
157
  async removeLabel(...labels: label.Key[]): Promise<void> {
145
- await this.labelClient.removeLabels(ontologyID(this.key), labels);
146
- }
147
-
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;
158
+ await this.labelClient.remove(ontologyID(this.key), labels);
164
159
  }
165
160
 
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;
161
+ static sort(a: Range, b: Range): number {
162
+ return TimeRange.sort(a.timeRange, b.timeRange);
185
163
  }
186
164
  }
187
165
 
188
- export const sort = (a: Range, b: Range): -1 | 0 | 1 =>
189
- sortTimeRange(a.timeRange, b.timeRange);
190
-
191
- const retrieveReqZ = z.object({
166
+ const retrieveRequestZ = z.object({
192
167
  keys: keyZ.array().optional(),
193
168
  names: z.array(z.string()).optional(),
194
- term: z.string().optional(),
169
+ searchTerm: z.string().optional(),
195
170
  overlapsWith: TimeRange.z.optional(),
196
171
  limit: z.number().int().optional(),
197
172
  offset: z.number().int().optional(),
198
173
  hasLabels: label.keyZ.array().optional(),
174
+ includeLabels: z.boolean().optional(),
175
+ includeParent: z.boolean().optional(),
199
176
  });
200
177
 
201
- export interface RetrieveRequest extends z.infer<typeof retrieveReqZ> {}
178
+ export type RetrieveRequest = z.infer<typeof retrieveRequestZ>;
179
+
180
+ const retrieveArgsZ = retrieveRequestZ
181
+ .or(keyZ.array().transform((keys) => ({ keys })))
182
+ .or(keyZ.transform((key) => ({ keys: [key] })))
183
+ .or(z.string().transform((name) => ({ names: [name] })))
184
+ .or(
185
+ z
186
+ .string()
187
+ .array()
188
+ .transform((names) => ({ names })),
189
+ )
190
+ .or(TimeRange.z.transform((timeRange) => ({ overlapsWith: timeRange })));
191
+
192
+ export type RetrieveArgs = z.input<typeof retrieveArgsZ>;
202
193
 
203
194
  const RETRIEVE_ENDPOINT = "/range/retrieve";
204
195
 
205
196
  const retrieveResZ = z.object({ ranges: nullableArrayZ(payloadZ) });
206
197
 
207
- export class Client implements AsyncTermSearcher<string, Key, Range> {
198
+ export class Client {
208
199
  readonly type: string = "range";
209
200
  private readonly frameClient: framer.Client;
210
201
  private readonly writer: Writer;
@@ -247,48 +238,28 @@ export class Client implements AsyncTermSearcher<string, Key, Range> {
247
238
  await this.writer.delete(array.toArray(key));
248
239
  }
249
240
 
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>(
241
+ async retrieve(params: Key | Name): Promise<Range>;
242
+ async retrieve(params: Keys | Names): Promise<Range[]>;
243
+ async retrieve(params: TimeRange): Promise<Range[]>;
244
+ async retrieve(params: RetrieveRequest): Promise<Range[]>;
245
+ async retrieve(params: RetrieveArgs): Promise<Range | Range[]> {
246
+ const isSingle = typeof params === "string";
247
+ const { ranges } = await sendRequired(
283
248
  this.unaryClient,
284
249
  RETRIEVE_ENDPOINT,
285
- req,
286
- retrieveReqZ,
250
+ params,
251
+ retrieveArgsZ,
287
252
  retrieveResZ,
288
253
  );
254
+ checkForMultipleOrNoResults("Range", params, ranges, isSingle);
255
+ if (isSingle) return this.sugarMany(ranges)[0];
289
256
  return this.sugarMany(ranges);
290
257
  }
291
258
 
259
+ getKV(range: Key): KV {
260
+ return new KV(range, this.unaryClient);
261
+ }
262
+
292
263
  async retrieveParent(range: Key): Promise<Range | null> {
293
264
  const res = await this.ontologyClient.retrieveParents(ontologyID(range));
294
265
  if (res.length === 0) return null;
@@ -297,42 +268,47 @@ export class Client implements AsyncTermSearcher<string, Key, Range> {
297
268
  return await this.retrieve(first.id.key);
298
269
  }
299
270
 
300
- 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
- );
271
+ sugarOntologyResource(resource: ontology.Resource): Range {
272
+ return this.sugarOne(convertOntologyResourceToPayload(resource));
314
273
  }
315
274
 
316
- sugarMany(payloads: Payload[]): Range[] {
317
- return payloads.map((payload) => this.sugarOne(payload));
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);
318
278
  }
319
279
 
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
- );
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);
332
286
  }
333
287
 
334
- resourcesToRanges(resources: ontology.Resource[]): Range[] {
335
- return resources.map((r) => this.resourceToRange(r));
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
+
298
+ sugarOne(payload: Payload): Range {
299
+ return new Range(payload, {
300
+ frameClient: this.frameClient,
301
+ kv: new KV(payload.key, this.unaryClient),
302
+ aliaser: new Aliaser(payload.key, this.frameClient, this.unaryClient),
303
+ channels: this.channels,
304
+ labelClient: this.labelClient,
305
+ ontologyClient: this.ontologyClient,
306
+ rangeClient: this,
307
+ });
308
+ }
309
+
310
+ sugarMany(payloads: Payload[]): Range[] {
311
+ return payloads.map((payload) => this.sugarOne(payload));
336
312
  }
337
313
 
338
314
  resourceToRange(resource: ontology.Resource): Range {
@@ -341,12 +317,31 @@ export class Client implements AsyncTermSearcher<string, Key, Range> {
341
317
  name: resource.data?.name as string,
342
318
  timeRange: new TimeRange(resource.data?.timeRange as CrudeTimeRange),
343
319
  color: resource.data?.color as string,
320
+ labels: [],
321
+ parent: null,
344
322
  });
345
323
  }
346
324
  }
347
325
 
348
- export const ontologyID = (key: Key): ontology.ID =>
349
- new ontology.ID({ type: ONTOLOGY_TYPE, key });
326
+ export const ontologyID = (key: Key): ontology.ID => ({ type: "range", key });
327
+
328
+ export const aliasOntologyID = (key: Key): ontology.ID => ({
329
+ type: "range-alias",
330
+ key,
331
+ });
350
332
 
351
- export const aliasOntologyID = (key: Key): ontology.ID =>
352
- new ontology.ID({ type: ALIAS_ONTOLOGY_TYPE, key });
333
+ export const convertOntologyResourceToPayload = ({
334
+ data,
335
+ id: { key },
336
+ name,
337
+ }: ontology.Resource): Payload => {
338
+ const timeRange = TimeRange.z.parse(data?.timeRange);
339
+ return {
340
+ key,
341
+ name,
342
+ timeRange,
343
+ color: typeof data?.color === "string" ? data.color : undefined,
344
+ labels: [],
345
+ parent: null,
346
+ };
347
+ };
@@ -7,7 +7,7 @@
7
7
  // License, use of this software will be governed by the Apache License, Version 2.0,
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
- export { type Alias, type AliasChange } from "@/ranger/alias";
10
+ export * from "@/ranger/alias";
11
11
  export * from "@/ranger/client";
12
12
  export * from "@/ranger/kv";
13
13
  export * from "@/ranger/payload";
package/src/ranger/kv.ts CHANGED
@@ -10,16 +10,20 @@
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
 
24
+ export const kvPairKey = ({ range, key }: Omit<KVPair, "value">) =>
25
+ `${range}<--->${key}`;
26
+
23
27
  const getReqZ = z.object({ range: keyZ, keys: z.string().array() });
24
28
  export interface GetRequest extends z.infer<typeof getReqZ> {}
25
29
 
@@ -37,12 +41,10 @@ export class KV {
37
41
  private static readonly DELETE_ENDPOINT = "/range/kv/delete";
38
42
  private readonly rangeKey: Key;
39
43
  private readonly client: UnaryClient;
40
- private readonly frameClient: framer.Client;
41
44
 
42
- constructor(rng: Key, client: UnaryClient, frameClient: framer.Client) {
45
+ constructor(rng: Key, client: UnaryClient) {
43
46
  this.rangeKey = rng;
44
47
  this.client = client;
45
- this.frameClient = frameClient;
46
48
  }
47
49
 
48
50
  async get(key: string): Promise<string>;
@@ -92,24 +94,4 @@ export class KV {
92
94
  z.unknown(),
93
95
  );
94
96
  }
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
97
  }