@synnaxlabs/client 0.2.1 → 0.13.6

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 (299) hide show
  1. package/.eslintrc.cjs +18 -0
  2. package/.pytest_cache/README.md +8 -0
  3. package/.turbo/turbo-build.log +16 -0
  4. package/LICENSE +4 -21
  5. package/{build/module/lib → dist/auth}/auth.d.ts +16 -19
  6. package/dist/auth/index.d.ts +1 -0
  7. package/dist/cdc/external.d.ts +1 -0
  8. package/dist/cdc/index.d.ts +1 -0
  9. package/dist/cdc/observable.d.ts +17 -0
  10. package/dist/channel/client.d.ts +58 -0
  11. package/dist/channel/creator.d.ts +8 -0
  12. package/dist/channel/external.d.ts +4 -0
  13. package/dist/channel/index.d.ts +1 -0
  14. package/dist/channel/payload.d.ts +63 -0
  15. package/dist/channel/retriever.d.ts +49 -0
  16. package/dist/client.cjs.js +23050 -0
  17. package/dist/client.cjs.js.map +1 -0
  18. package/dist/client.d.ts +73 -0
  19. package/dist/client.es.js +23050 -0
  20. package/dist/client.es.js.map +1 -0
  21. package/dist/connection/checker.d.ts +66 -0
  22. package/dist/connection/index.d.ts +1 -0
  23. package/dist/control/authority.d.ts +6 -0
  24. package/dist/control/external.d.ts +2 -0
  25. package/dist/control/index.d.ts +1 -0
  26. package/dist/control/state.d.ts +81 -0
  27. package/{build/main/lib → dist}/errors.d.ts +6 -3
  28. package/dist/framer/adapter.d.ts +21 -0
  29. package/dist/framer/client.d.ts +44 -0
  30. package/dist/framer/external.d.ts +5 -0
  31. package/dist/framer/frame.d.ts +251 -0
  32. package/dist/framer/index.d.ts +1 -0
  33. package/{build/module/lib/segment → dist/framer}/iterator.d.ts +32 -64
  34. package/dist/framer/streamProxy.d.ts +12 -0
  35. package/dist/framer/streamer.d.ts +17 -0
  36. package/dist/framer/writer.d.ts +257 -0
  37. package/dist/index.d.ts +16 -0
  38. package/dist/label/client.d.ts +25 -0
  39. package/dist/label/external.d.ts +4 -0
  40. package/dist/label/index.d.ts +1 -0
  41. package/dist/label/payload.d.ts +20 -0
  42. package/dist/label/retriever.d.ts +13 -0
  43. package/dist/label/writer.d.ts +26 -0
  44. package/dist/ontology/cdc.d.ts +25 -0
  45. package/dist/ontology/client.d.ts +25 -0
  46. package/dist/ontology/external.d.ts +3 -0
  47. package/dist/ontology/group/client.d.ts +11 -0
  48. package/dist/ontology/group/external.d.ts +2 -0
  49. package/dist/ontology/group/group.d.ts +7 -0
  50. package/dist/ontology/group/index.d.ts +1 -0
  51. package/dist/ontology/group/payload.d.ts +40 -0
  52. package/dist/ontology/group/writer.d.ts +13 -0
  53. package/dist/ontology/index.d.ts +1 -0
  54. package/dist/ontology/ontology.spec.d.ts +1 -0
  55. package/dist/ontology/payload.d.ts +235 -0
  56. package/dist/ontology/retriever.d.ts +12 -0
  57. package/dist/ontology/signals.d.ts +25 -0
  58. package/dist/ontology/writer.d.ts +9 -0
  59. package/dist/ranger/active.d.ts +9 -0
  60. package/dist/ranger/alias.d.ts +32 -0
  61. package/dist/ranger/client.d.ts +31 -0
  62. package/dist/ranger/external.d.ts +6 -0
  63. package/dist/ranger/index.d.ts +1 -0
  64. package/dist/ranger/kv.d.ts +50 -0
  65. package/dist/ranger/payload.d.ts +94 -0
  66. package/dist/ranger/range.d.ts +29 -0
  67. package/dist/ranger/ranger.spec.d.ts +1 -0
  68. package/dist/ranger/retriever.d.ts +10 -0
  69. package/dist/ranger/writer.d.ts +9 -0
  70. package/{build/main → dist}/setupspecs.d.ts +2 -2
  71. package/dist/signals/external.d.ts +1 -0
  72. package/dist/signals/index.d.ts +1 -0
  73. package/dist/signals/observable.d.ts +17 -0
  74. package/dist/transport.d.ts +10 -0
  75. package/dist/user/index.d.ts +1 -0
  76. package/{build/main/lib → dist}/user/payload.d.ts +3 -3
  77. package/dist/util/telem.d.ts +2 -0
  78. package/dist/workspace/client.d.ts +22 -0
  79. package/dist/workspace/external.d.ts +2 -0
  80. package/dist/workspace/index.d.ts +1 -0
  81. package/dist/workspace/lineplot/client.d.ts +15 -0
  82. package/dist/workspace/lineplot/external.d.ts +2 -0
  83. package/dist/workspace/lineplot/index.d.ts +1 -0
  84. package/dist/workspace/lineplot/linePlot.spec.d.ts +1 -0
  85. package/dist/workspace/lineplot/payload.d.ts +31 -0
  86. package/dist/workspace/lineplot/retriever.d.ts +9 -0
  87. package/dist/workspace/lineplot/writer.d.ts +39 -0
  88. package/dist/workspace/payload.d.ts +31 -0
  89. package/dist/workspace/pid/client.d.ts +16 -0
  90. package/dist/workspace/pid/external.d.ts +2 -0
  91. package/dist/workspace/pid/index.d.ts +1 -0
  92. package/dist/workspace/pid/payload.d.ts +37 -0
  93. package/dist/workspace/pid/pid.spec.d.ts +1 -0
  94. package/dist/workspace/pid/retriever.d.ts +9 -0
  95. package/dist/workspace/pid/writer.d.ts +46 -0
  96. package/dist/workspace/retriever.d.ts +12 -0
  97. package/dist/workspace/workspace.spec.d.ts +1 -0
  98. package/dist/workspace/writer.d.ts +55 -0
  99. package/package.json +27 -98
  100. package/src/auth/auth.spec.ts +46 -0
  101. package/src/auth/auth.ts +83 -0
  102. package/src/auth/index.ts +10 -0
  103. package/src/channel/channel.spec.ts +82 -0
  104. package/src/channel/client.ts +209 -0
  105. package/src/channel/creator.ts +43 -0
  106. package/src/channel/external.ts +13 -0
  107. package/src/channel/index.ts +10 -0
  108. package/src/channel/payload.ts +52 -0
  109. package/src/channel/retriever.ts +160 -0
  110. package/src/client.ts +116 -0
  111. package/src/connection/checker.ts +104 -0
  112. package/src/connection/connection.spec.ts +35 -0
  113. package/src/connection/index.ts +10 -0
  114. package/src/control/authority.ts +26 -0
  115. package/src/control/external.ts +11 -0
  116. package/src/control/index.ts +10 -0
  117. package/src/control/state.spec.ts +24 -0
  118. package/src/control/state.ts +133 -0
  119. package/src/errors.ts +163 -0
  120. package/src/framer/adapter.ts +116 -0
  121. package/src/framer/client.ts +116 -0
  122. package/src/framer/external.ts +14 -0
  123. package/src/framer/frame.spec.ts +317 -0
  124. package/src/framer/frame.ts +412 -0
  125. package/src/framer/index.ts +10 -0
  126. package/src/framer/iterator.spec.ts +62 -0
  127. package/src/framer/iterator.ts +240 -0
  128. package/src/framer/streamProxy.ts +59 -0
  129. package/src/framer/streamer.spec.ts +42 -0
  130. package/src/framer/streamer.ts +86 -0
  131. package/src/framer/writer.spec.ts +52 -0
  132. package/src/framer/writer.ts +236 -0
  133. package/src/index.ts +53 -0
  134. package/src/label/client.ts +103 -0
  135. package/src/label/external.ts +13 -0
  136. package/src/label/index.ts +10 -0
  137. package/src/label/label.spec.ts +51 -0
  138. package/src/label/payload.ts +29 -0
  139. package/src/label/retriever.ts +65 -0
  140. package/src/label/writer.ts +90 -0
  141. package/src/ontology/client.ts +104 -0
  142. package/src/ontology/external.ts +12 -0
  143. package/src/ontology/group/client.ts +40 -0
  144. package/src/ontology/group/external.ts +11 -0
  145. package/src/ontology/group/group.spec.ts +46 -0
  146. package/src/ontology/group/group.ts +27 -0
  147. package/src/ontology/group/index.ts +10 -0
  148. package/src/ontology/group/payload.ts +65 -0
  149. package/src/ontology/group/writer.ts +48 -0
  150. package/src/ontology/index.ts +10 -0
  151. package/src/ontology/ontology.spec.ts +114 -0
  152. package/src/ontology/payload.ts +118 -0
  153. package/src/ontology/retriever.ts +91 -0
  154. package/src/ontology/signals.ts +135 -0
  155. package/src/ontology/writer.ts +49 -0
  156. package/src/ranger/active.ts +56 -0
  157. package/src/ranger/alias.ts +183 -0
  158. package/src/ranger/client.ts +129 -0
  159. package/src/ranger/external.ts +15 -0
  160. package/src/ranger/index.ts +10 -0
  161. package/src/ranger/kv.ts +91 -0
  162. package/src/ranger/payload.ts +70 -0
  163. package/src/ranger/range.ts +95 -0
  164. package/src/ranger/ranger.spec.ts +201 -0
  165. package/src/ranger/retriever.ts +50 -0
  166. package/src/ranger/writer.ts +80 -0
  167. package/src/setupspecs.ts +25 -0
  168. package/src/signals/external.ts +10 -0
  169. package/src/signals/index.ts +10 -0
  170. package/src/signals/observable.ts +80 -0
  171. package/src/transport.ts +39 -0
  172. package/src/user/index.ts +10 -0
  173. package/src/user/payload.ts +17 -0
  174. package/src/util/telem.ts +19 -0
  175. package/src/vite-env.d.ts +11 -0
  176. package/src/workspace/client.ts +75 -0
  177. package/src/workspace/external.ts +11 -0
  178. package/src/workspace/index.ts +10 -0
  179. package/src/workspace/lineplot/client.ts +51 -0
  180. package/src/workspace/lineplot/external.ts +11 -0
  181. package/src/workspace/lineplot/index.ts +10 -0
  182. package/src/workspace/lineplot/linePlot.spec.ts +78 -0
  183. package/src/workspace/lineplot/payload.ts +29 -0
  184. package/src/workspace/lineplot/retriever.ts +49 -0
  185. package/src/workspace/lineplot/writer.ts +109 -0
  186. package/src/workspace/payload.ts +29 -0
  187. package/src/workspace/pid/client.ts +55 -0
  188. package/src/workspace/pid/external.ts +11 -0
  189. package/src/workspace/pid/index.ts +10 -0
  190. package/src/workspace/pid/payload.ts +31 -0
  191. package/src/workspace/pid/pid.spec.ts +111 -0
  192. package/src/workspace/pid/retriever.ts +45 -0
  193. package/src/workspace/pid/writer.ts +130 -0
  194. package/src/workspace/retriever.ts +66 -0
  195. package/src/workspace/workspace.spec.ts +62 -0
  196. package/src/workspace/writer.ts +103 -0
  197. package/tsconfig.json +7 -0
  198. package/tsconfig.vite.json +4 -0
  199. package/vite.config.ts +25 -0
  200. package/CHANGELOG.md +0 -5
  201. package/build/main/index.d.ts +0 -4
  202. package/build/main/index.js +0 -35
  203. package/build/main/lib/auth.d.ts +0 -54
  204. package/build/main/lib/auth.js +0 -62
  205. package/build/main/lib/auth.spec.js +0 -39
  206. package/build/main/lib/channel/channel.spec.js +0 -49
  207. package/build/main/lib/channel/client.d.ts +0 -94
  208. package/build/main/lib/channel/client.js +0 -134
  209. package/build/main/lib/channel/creator.d.ts +0 -19
  210. package/build/main/lib/channel/creator.js +0 -44
  211. package/build/main/lib/channel/payload.d.ts +0 -25
  212. package/build/main/lib/channel/payload.js +0 -18
  213. package/build/main/lib/channel/registry.d.ts +0 -9
  214. package/build/main/lib/channel/registry.js +0 -37
  215. package/build/main/lib/channel/retriever.d.ts +0 -11
  216. package/build/main/lib/channel/retriever.js +0 -39
  217. package/build/main/lib/client.d.ts +0 -30
  218. package/build/main/lib/client.js +0 -46
  219. package/build/main/lib/errors.js +0 -122
  220. package/build/main/lib/segment/client.d.ts +0 -62
  221. package/build/main/lib/segment/client.js +0 -95
  222. package/build/main/lib/segment/iterator.d.ts +0 -134
  223. package/build/main/lib/segment/iterator.js +0 -253
  224. package/build/main/lib/segment/iterator.spec.js +0 -73
  225. package/build/main/lib/segment/payload.d.ts +0 -16
  226. package/build/main/lib/segment/payload.js +0 -13
  227. package/build/main/lib/segment/splitter.d.ts +0 -7
  228. package/build/main/lib/segment/splitter.js +0 -25
  229. package/build/main/lib/segment/typed.d.ts +0 -15
  230. package/build/main/lib/segment/typed.js +0 -49
  231. package/build/main/lib/segment/validator.d.ts +0 -22
  232. package/build/main/lib/segment/validator.js +0 -64
  233. package/build/main/lib/segment/writer.d.ts +0 -98
  234. package/build/main/lib/segment/writer.js +0 -183
  235. package/build/main/lib/segment/writer.spec.js +0 -90
  236. package/build/main/lib/telem.d.ts +0 -395
  237. package/build/main/lib/telem.js +0 -553
  238. package/build/main/lib/telem.spec.js +0 -152
  239. package/build/main/lib/transport.d.ts +0 -10
  240. package/build/main/lib/transport.js +0 -22
  241. package/build/main/lib/user/payload.js +0 -9
  242. package/build/main/lib/util/telem.d.ts +0 -2
  243. package/build/main/lib/util/telem.js +0 -13
  244. package/build/main/setupspecs.js +0 -17
  245. package/build/module/index.d.ts +0 -4
  246. package/build/module/index.js +0 -5
  247. package/build/module/lib/auth.js +0 -63
  248. package/build/module/lib/auth.spec.js +0 -34
  249. package/build/module/lib/channel/channel.spec.js +0 -44
  250. package/build/module/lib/channel/client.d.ts +0 -94
  251. package/build/module/lib/channel/client.js +0 -134
  252. package/build/module/lib/channel/creator.d.ts +0 -19
  253. package/build/module/lib/channel/creator.js +0 -42
  254. package/build/module/lib/channel/payload.d.ts +0 -25
  255. package/build/module/lib/channel/payload.js +0 -15
  256. package/build/module/lib/channel/registry.d.ts +0 -9
  257. package/build/module/lib/channel/registry.js +0 -36
  258. package/build/module/lib/channel/retriever.d.ts +0 -11
  259. package/build/module/lib/channel/retriever.js +0 -37
  260. package/build/module/lib/client.d.ts +0 -30
  261. package/build/module/lib/client.js +0 -44
  262. package/build/module/lib/errors.d.ts +0 -53
  263. package/build/module/lib/errors.js +0 -113
  264. package/build/module/lib/segment/client.d.ts +0 -62
  265. package/build/module/lib/segment/client.js +0 -94
  266. package/build/module/lib/segment/iterator.js +0 -248
  267. package/build/module/lib/segment/iterator.spec.js +0 -68
  268. package/build/module/lib/segment/payload.d.ts +0 -16
  269. package/build/module/lib/segment/payload.js +0 -10
  270. package/build/module/lib/segment/splitter.d.ts +0 -7
  271. package/build/module/lib/segment/splitter.js +0 -26
  272. package/build/module/lib/segment/typed.d.ts +0 -15
  273. package/build/module/lib/segment/typed.js +0 -49
  274. package/build/module/lib/segment/validator.d.ts +0 -22
  275. package/build/module/lib/segment/validator.js +0 -60
  276. package/build/module/lib/segment/writer.d.ts +0 -98
  277. package/build/module/lib/segment/writer.js +0 -183
  278. package/build/module/lib/segment/writer.spec.js +0 -85
  279. package/build/module/lib/telem.d.ts +0 -395
  280. package/build/module/lib/telem.js +0 -545
  281. package/build/module/lib/telem.spec.js +0 -147
  282. package/build/module/lib/transport.d.ts +0 -10
  283. package/build/module/lib/transport.js +0 -22
  284. package/build/module/lib/user/payload.d.ts +0 -12
  285. package/build/module/lib/user/payload.js +0 -6
  286. package/build/module/lib/util/telem.d.ts +0 -2
  287. package/build/module/lib/util/telem.js +0 -9
  288. package/build/module/setupspecs.d.ts +0 -4
  289. package/build/module/setupspecs.js +0 -16
  290. /package/{build/main/lib → dist/auth}/auth.spec.d.ts +0 -0
  291. /package/{build/main/lib → dist}/channel/channel.spec.d.ts +0 -0
  292. /package/{build/main/lib/segment/iterator.spec.d.ts → dist/connection/connection.spec.d.ts} +0 -0
  293. /package/{build/main/lib/segment/writer.spec.d.ts → dist/control/state.spec.d.ts} +0 -0
  294. /package/{build/main/lib/telem.spec.d.ts → dist/framer/frame.spec.d.ts} +0 -0
  295. /package/{build/module/lib/segment → dist/framer}/iterator.spec.d.ts +0 -0
  296. /package/{build/module/lib/auth.spec.d.ts → dist/framer/streamer.spec.d.ts} +0 -0
  297. /package/{build/module/lib/segment → dist/framer}/writer.spec.d.ts +0 -0
  298. /package/{build/module/lib/channel/channel.spec.d.ts → dist/label/label.spec.d.ts} +0 -0
  299. /package/{build/module/lib/telem.spec.d.ts → dist/ontology/group/group.spec.d.ts} +0 -0
@@ -0,0 +1,91 @@
1
+ // Copyright 2023 Synnax Labs, Inc.
2
+ //
3
+ // Use of this software is governed by the Business Source License included in the file
4
+ // licenses/BSL.txt.
5
+ //
6
+ // As of the Change Date specified in that file, in accordance with the Business Source
7
+ // License, use of this software will be governed by the Apache License, Version 2.0,
8
+ // included in the file licenses/APL.txt.
9
+
10
+ import type { UnaryClient } from "@synnaxlabs/freighter";
11
+ import { toArray } from "@synnaxlabs/x";
12
+ import { z } from "zod";
13
+
14
+ import { ID, type Resource, idZ, resourceSchemaZ } from "@/ontology/payload";
15
+
16
+ const requestSchema = z.object({
17
+ ids: idZ.array().optional(),
18
+ children: z.boolean().optional(),
19
+ parents: z.boolean().optional(),
20
+ includeSchema: z.boolean().optional(),
21
+ includeFieldData: z.boolean().optional(),
22
+ term: z.string().optional(),
23
+ });
24
+
25
+ type Request = z.infer<typeof requestSchema>;
26
+
27
+ const responseSchema = z.object({
28
+ resources: resourceSchemaZ.array(),
29
+ });
30
+
31
+ export class Retriever {
32
+ private static readonly ENDPOINT = "/ontology/retrieve";
33
+ private readonly client: UnaryClient;
34
+
35
+ constructor(unary: UnaryClient) {
36
+ this.client = unary;
37
+ }
38
+
39
+ async search(term: string): Promise<Resource[]> {
40
+ const resources = await this.execute({ term });
41
+ return resources;
42
+ }
43
+
44
+ async retrieve(
45
+ ids: ID | ID[] | string | string[],
46
+ includeSchema: boolean = true,
47
+ includeFieldData: boolean = true,
48
+ ): Promise<Resource[]> {
49
+ return await this.execute({
50
+ ids: toArray(ids).map((id) => new ID(id).payload),
51
+ includeFieldData,
52
+ includeSchema,
53
+ });
54
+ }
55
+
56
+ async retrieveChildren(
57
+ ids: ID | ID[],
58
+ includeSchema: boolean = true,
59
+ includeFieldData: boolean = true,
60
+ ): Promise<Resource[]> {
61
+ return await this.execute({
62
+ ids: toArray(ids).map((id) => new ID(id).payload),
63
+ children: true,
64
+ includeSchema,
65
+ includeFieldData,
66
+ });
67
+ }
68
+
69
+ async retrieveParents(
70
+ ids: ID | ID[],
71
+ includeSchema: boolean = true,
72
+ includeFieldData: boolean = true,
73
+ ): Promise<Resource[]> {
74
+ return await this.execute({
75
+ ids: toArray(ids).map((id) => new ID(id).payload),
76
+ parents: true,
77
+ includeSchema,
78
+ includeFieldData,
79
+ });
80
+ }
81
+
82
+ private async execute(request: Request): Promise<Resource[]> {
83
+ const [res, err] = await this.client.send(
84
+ Retriever.ENDPOINT,
85
+ request,
86
+ responseSchema,
87
+ );
88
+ if (err != null) throw err;
89
+ return res.resources;
90
+ }
91
+ }
@@ -0,0 +1,135 @@
1
+ // Copyright 2023 Synnax Labs, Inc.
2
+ //
3
+ // Use of this software is governed by the Business Source License included in the file
4
+ // licenses/BSL.txt.
5
+ //
6
+ // As of the Change Date specified in that file, in accordance with the Business Source
7
+ // License, use of this software will be governed by the Apache License, Version 2.0,
8
+ // included in the file licenses/APL.txt.
9
+
10
+ import { observe, type change } from "@synnaxlabs/x";
11
+
12
+ import { QueryError } from "@/errors";
13
+ import { type Client as FrameClient } from "@/framer/client";
14
+ import { type Frame } from "@/framer/frame";
15
+ import { type Streamer as FrameStreamer } from "@/framer/streamer";
16
+ import {
17
+ ID,
18
+ parseRelationship,
19
+ type Relationship,
20
+ type Resource,
21
+ } from "@/ontology/payload";
22
+ import { type Retriever } from "@/ontology/retriever";
23
+
24
+ export type ResourceChange = change.Change<ID, Resource>;
25
+ export type RelationshipChange = change.Change<Relationship, undefined>;
26
+
27
+ const RESOURCE_SET_NAME = "sy_ontology_resource_set";
28
+ const RESOURCE_DELETE_NAME = "sy_ontology_resource_delete";
29
+ const RELATIONSHIP_SET_NAME = "sy_ontology_relationship_set";
30
+ const RELATIONSHIP_DELETE_NAME = "sy_ontology_relationship_delete";
31
+
32
+ export class ChangeTracker {
33
+ private readonly resourceObs: observe.Observer<ResourceChange[]>;
34
+ private readonly relationshipObs: observe.Observer<RelationshipChange[]>;
35
+
36
+ readonly relationships: observe.Observable<RelationshipChange[]>;
37
+ readonly resources: observe.Observable<ResourceChange[]>;
38
+
39
+ private readonly streamer: FrameStreamer;
40
+ private readonly retriever: Retriever;
41
+ private readonly closePromise: Promise<void>;
42
+
43
+ constructor(streamer: FrameStreamer, retriever: Retriever) {
44
+ this.relationshipObs = new observe.Observer<RelationshipChange[]>();
45
+ this.relationships = this.relationshipObs;
46
+ this.resourceObs = new observe.Observer<ResourceChange[]>();
47
+ this.resources = this.resourceObs;
48
+ this.retriever = retriever;
49
+ this.streamer = streamer;
50
+ this.closePromise = this.start();
51
+ }
52
+
53
+ async close(): Promise<void> {
54
+ this.streamer.close();
55
+ await this.closePromise;
56
+ }
57
+
58
+ private async start(): Promise<void> {
59
+ for await (const frame of this.streamer) {
60
+ await this.update(frame);
61
+ }
62
+ }
63
+
64
+ private async update(frame: Frame): Promise<void> {
65
+ const resSets = await this.parseResourceSets(frame);
66
+ const resDeletes = this.parseResourceDeletes(frame);
67
+ const allResources = resSets.concat(resDeletes);
68
+ if (allResources.length > 0) this.resourceObs.notify(resSets.concat(resDeletes));
69
+ const relSets = this.parseRelationshipSets(frame);
70
+ const relDeletes = this.parseRelationshipDeletes(frame);
71
+ const allRels = relSets.concat(relDeletes);
72
+ if (allRels.length > 0) this.relationshipObs.notify(relSets.concat(relDeletes));
73
+ }
74
+
75
+ private parseRelationshipSets(frame: Frame): RelationshipChange[] {
76
+ const relationships = frame.get(RELATIONSHIP_SET_NAME);
77
+ if (relationships.length === 0) return [];
78
+ // We should only ever get one series of relationships
79
+ return relationships[0].toStrings().map((rel) => ({
80
+ variant: "set",
81
+ key: parseRelationship(rel),
82
+ value: undefined,
83
+ }));
84
+ }
85
+
86
+ private parseRelationshipDeletes(frame: Frame): RelationshipChange[] {
87
+ const relationships = frame.get(RELATIONSHIP_DELETE_NAME);
88
+ if (relationships.length === 0) return [];
89
+ // We should only ever get one series of relationships
90
+ return relationships[0].toStrings().map((rel) => ({
91
+ variant: "delete",
92
+ key: parseRelationship(rel),
93
+ }));
94
+ }
95
+
96
+ private async parseResourceSets(frame: Frame): Promise<ResourceChange[]> {
97
+ const sets = frame.get(RESOURCE_SET_NAME);
98
+ if (sets.length === 0) return [];
99
+ // We should only ever get one series of sets
100
+ const ids = sets[0].toStrings().map((id) => new ID(id));
101
+ try {
102
+ const resources = await this.retriever.retrieve(ids);
103
+ return resources.map((resource) => ({
104
+ variant: "set",
105
+ key: resource.id,
106
+ value: resource,
107
+ }));
108
+ } catch (e) {
109
+ if (e instanceof QueryError) {
110
+ console.warn(e);
111
+ return [];
112
+ }
113
+ throw e;
114
+ }
115
+ }
116
+
117
+ private parseResourceDeletes(frame: Frame): ResourceChange[] {
118
+ const deletes = frame.get(RESOURCE_DELETE_NAME);
119
+ if (deletes.length === 0) return [];
120
+ // We should only ever get one series of deletes
121
+ return deletes[0]
122
+ .toStrings()
123
+ .map((str) => ({ variant: "delete", key: new ID(str) }));
124
+ }
125
+
126
+ static async open(client: FrameClient, retriever: Retriever): Promise<ChangeTracker> {
127
+ const streamer = await client.newStreamer([
128
+ RESOURCE_SET_NAME,
129
+ RESOURCE_DELETE_NAME,
130
+ RELATIONSHIP_SET_NAME,
131
+ RELATIONSHIP_DELETE_NAME,
132
+ ]);
133
+ return new ChangeTracker(streamer, retriever);
134
+ }
135
+ }
@@ -0,0 +1,49 @@
1
+ // Copyright 2023 Synnax Labs, Inc.
2
+ //
3
+ // Use of this software is governed by the Business Source License included in the file
4
+ // licenses/BSL.txt.
5
+ //
6
+ // As of the Change Date specified in that file, in accordance with the Business Source
7
+ // License, use of this software will be governed by the Apache License, Version 2.0,
8
+ // included in the file licenses/APL.txt.
9
+
10
+ import { type UnaryClient } from "@synnaxlabs/freighter";
11
+ import { z } from "zod";
12
+
13
+ import { type ID } from "@/ontology/payload";
14
+
15
+ const ENDPOINTS = {
16
+ ADD_CHILDREN: "/ontology/add-children",
17
+ REMOVE_CHILDREN: "/ontology/remove-children",
18
+ MOVE_CHILDREN: "/ontology/move-children",
19
+ };
20
+
21
+ export class Writer {
22
+ client: UnaryClient;
23
+
24
+ constructor(client: UnaryClient) {
25
+ this.client = client;
26
+ }
27
+
28
+ async addChildren(id: ID, ...children: ID[]): Promise<void> {
29
+ const req = { id, children };
30
+ const [, err] = await this.client.send(ENDPOINTS.ADD_CHILDREN, req, z.object({}));
31
+ if (err != null) throw err;
32
+ }
33
+
34
+ async removeChildren(id: ID, ...children: ID[]): Promise<void> {
35
+ const req = { id, children };
36
+ const [, err] = await this.client.send(
37
+ ENDPOINTS.REMOVE_CHILDREN,
38
+ req,
39
+ z.object({}),
40
+ );
41
+ if (err != null) throw err;
42
+ }
43
+
44
+ async moveChildren(from: ID, to: ID, ...children: ID[]): Promise<void> {
45
+ const req = { from, to, children };
46
+ const [, err] = await this.client.send(ENDPOINTS.MOVE_CHILDREN, req, z.object({}));
47
+ if (err != null) throw err;
48
+ }
49
+ }
@@ -0,0 +1,56 @@
1
+ // Copyright 2023 Synnax Labs, Inc.
2
+ //
3
+ // Use of this software is governed by the Business Source License included in the file
4
+ // licenses/BSL.txt.
5
+ //
6
+ // As of the Change Date specified in that file, in accordance with the Business Source
7
+ // License, use of this software will be governed by the Apache License, Version 2.0,
8
+ // included in the file licenses/APL.txt.
9
+
10
+ import { type UnaryClient } from "@synnaxlabs/freighter";
11
+ import { z } from "zod";
12
+
13
+ import { QueryError } from "..";
14
+
15
+ import { type Payload, payloadZ, type Key } from "./payload";
16
+
17
+ const setActiveResZ = z.object({});
18
+
19
+ const retrieveActiveResZ = z.object({
20
+ range: payloadZ,
21
+ });
22
+
23
+ const clearActiveResZ = z.object({});
24
+
25
+ const SET_ENDPOINT = "/range/set-active";
26
+ const RETRIEVE_ENDPOINT = "/range/retrieve-active";
27
+ const CLEAR_ENDPOINT = "/range/clear-active";
28
+
29
+ export class Active {
30
+ private readonly client: UnaryClient;
31
+
32
+ constructor(client: UnaryClient) {
33
+ this.client = client;
34
+ }
35
+
36
+ async setActive(range: Key): Promise<void> {
37
+ const [, err] = await this.client.send(SET_ENDPOINT, { range }, setActiveResZ);
38
+ if (err != null) throw err;
39
+ }
40
+
41
+ async retrieveActive(): Promise<Payload | null> {
42
+ const [res, err] = await this.client.send(
43
+ RETRIEVE_ENDPOINT,
44
+ {},
45
+ retrieveActiveResZ,
46
+ );
47
+ if (err instanceof QueryError) return null;
48
+ if (err != null) throw err;
49
+ return res.range;
50
+ }
51
+
52
+ async clearActive(range: Key): Promise<void> {
53
+ const [, err] = await this.client.send(CLEAR_ENDPOINT, { range }, clearActiveResZ);
54
+ if (err != null) throw err;
55
+ }
56
+ }
@@ -0,0 +1,183 @@
1
+ // Copyright 2023 Synnax Labs, Inc.
2
+ //
3
+ // Use of this software is governed by the Business Source License included in the file
4
+ // licenses/BSL.txt.
5
+ //
6
+ // As of the Change Date specified in that file, in accordance with the Business Source
7
+ // License, use of this software will be governed by the Apache License, Version 2.0,
8
+ // included in the file licenses/APL.txt.
9
+
10
+ import { sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
11
+ import { type change } from "@synnaxlabs/x";
12
+ import { z } from "zod";
13
+
14
+ import { type channel } from "@/channel";
15
+ import { keyZ as channelKeyZ, type Key as ChannelKey } from "@/channel/payload";
16
+ import { type Client as FrameClient } from "@/framer/client";
17
+ import { type Key, keyZ } from "@/ranger/payload";
18
+ import { signals } from "@/signals";
19
+
20
+ export const ALIAS_SET_NAME = "sy_range_alias_set";
21
+ export const ALIAS_DELETE_NAME = "sy_range_alias_delete";
22
+
23
+ const resolveReqZ = z.object({
24
+ range: keyZ,
25
+ aliases: z.string().array(),
26
+ });
27
+
28
+ const resolveResZ = z.object({
29
+ aliases: z.record(z.string(), channelKeyZ),
30
+ });
31
+
32
+ const setReqZ = z.object({
33
+ range: keyZ,
34
+ aliases: z.record(channelKeyZ, z.string()),
35
+ });
36
+
37
+ const setResZ = z.unknown();
38
+
39
+ const deleteReqZ = z.object({
40
+ range: keyZ,
41
+ channels: channelKeyZ.array(),
42
+ });
43
+
44
+ const deleteResZ = z.unknown();
45
+
46
+ const listReqZ = z.object({
47
+ range: keyZ,
48
+ });
49
+
50
+ const listResZ = z.object({
51
+ aliases: z.record(z.string(), z.string()),
52
+ });
53
+
54
+ export class Aliaser {
55
+ private static readonly SET_ENDPOINT = "/range/alias/set";
56
+ private static readonly RESOLVE_ENDPOINT = "/range/alias/resolve";
57
+ private static readonly LIST_ENDPOINT = "/range/alias/list";
58
+ private static readonly DELETE_ENDPOINT = "/range/alias/delete";
59
+ private readonly frameClient: FrameClient;
60
+ private readonly cache = new Map<string, ChannelKey>();
61
+ private readonly client: UnaryClient;
62
+ private readonly rangeKey: Key;
63
+
64
+ constructor(rangeKey: Key, frameClient: FrameClient, client: UnaryClient) {
65
+ this.rangeKey = rangeKey;
66
+ this.cache = new Map();
67
+ this.client = client;
68
+ this.frameClient = frameClient;
69
+ }
70
+
71
+ resolve(aliases: string): Promise<ChannelKey>;
72
+
73
+ resolve(aliases: string[]): Promise<Record<string, ChannelKey>>;
74
+
75
+ async resolve(
76
+ aliases: string | string[],
77
+ ): Promise<ChannelKey | Record<string, ChannelKey>> {
78
+ const toFetch: string[] = [];
79
+ const isSingle = typeof aliases === "string";
80
+ const cached: Record<string, ChannelKey> = {};
81
+ if (isSingle) {
82
+ const c = this.cache.get(aliases);
83
+ if (c != null) return c;
84
+ toFetch.push(aliases);
85
+ } else
86
+ aliases.forEach((alias) => {
87
+ const c = this.cache.get(alias);
88
+ if (c != null) cached[alias] = c;
89
+ else toFetch.push(alias);
90
+ });
91
+ if (toFetch.length === 0) return cached;
92
+ const res = await sendRequired<typeof resolveReqZ, typeof resolveResZ>(
93
+ this.client,
94
+ Aliaser.RESOLVE_ENDPOINT,
95
+ { range: this.rangeKey, aliases: toFetch },
96
+ resolveResZ,
97
+ );
98
+ Object.entries(res.aliases).forEach(([alias, key]) => this.cache.set(alias, key));
99
+ return isSingle ? res.aliases[toFetch[0]] : { ...cached, ...res.aliases };
100
+ }
101
+
102
+ async set(aliases: Record<ChannelKey, string>): Promise<void> {
103
+ await sendRequired<typeof setReqZ, typeof setResZ>(
104
+ this.client,
105
+ Aliaser.SET_ENDPOINT,
106
+ {
107
+ range: this.rangeKey,
108
+ aliases,
109
+ },
110
+ z.unknown(),
111
+ );
112
+ }
113
+
114
+ async list(): Promise<Record<ChannelKey, string>> {
115
+ return (
116
+ await sendRequired<typeof listReqZ, typeof listResZ>(
117
+ this.client,
118
+ Aliaser.LIST_ENDPOINT,
119
+ {
120
+ range: this.rangeKey,
121
+ },
122
+ listResZ,
123
+ )
124
+ ).aliases;
125
+ }
126
+
127
+ async delete(aliases: ChannelKey[]): Promise<void> {
128
+ await sendRequired<typeof deleteReqZ, typeof deleteResZ>(
129
+ this.client,
130
+ Aliaser.DELETE_ENDPOINT,
131
+ {
132
+ range: this.rangeKey,
133
+ channels: aliases,
134
+ },
135
+ deleteResZ,
136
+ );
137
+ }
138
+
139
+ async openChangeTracker(): Promise<signals.Observable<string, Alias>> {
140
+ return await signals.Observable.open<string, Alias>(
141
+ this.frameClient,
142
+ ALIAS_SET_NAME,
143
+ ALIAS_DELETE_NAME,
144
+ decodeAliasChanges(this.rangeKey),
145
+ );
146
+ }
147
+ }
148
+
149
+ export interface Alias {
150
+ range: Key;
151
+ channel: channel.Key;
152
+ alias: string;
153
+ }
154
+
155
+ export type AliasChange = change.Change<string, Alias>;
156
+
157
+ const aliasZ = z.object({
158
+ range: keyZ,
159
+ channel: channelKeyZ,
160
+ alias: z.string(),
161
+ });
162
+
163
+ const aliasSeparator = "---";
164
+
165
+ const decodeAliasChanges =
166
+ (rangeKey: Key): signals.Decoder<string, Alias> =>
167
+ (variant, data) => {
168
+ if (variant === "delete") {
169
+ return data
170
+ .toStrings()
171
+ .filter((k) => k.split(aliasSeparator)[0] === rangeKey)
172
+ .map((alias) => ({
173
+ variant,
174
+ key: alias,
175
+ value: undefined,
176
+ }));
177
+ }
178
+ return data.parseJSON(aliasZ).map((alias) => ({
179
+ variant,
180
+ key: alias.alias,
181
+ value: alias,
182
+ }));
183
+ };
@@ -0,0 +1,129 @@
1
+ // Copyright 2023 Synnax Labs, Inc.
2
+ //
3
+ // Use of this software is governed by the Business Source License included in the file
4
+ // licenses/BSL.txt.
5
+ //
6
+ // As of the Change Date specified in that file, in accordance with the Business Source
7
+ // License, use of this software will be governed by the Apache License, Version 2.0,
8
+ // included in the file licenses/APL.txt.
9
+
10
+ import { type UnaryClient } from "@synnaxlabs/freighter";
11
+ import { type AsyncTermSearcher, toArray } from "@synnaxlabs/x";
12
+
13
+ import { type Retriever as ChannelRetriever } from "@/channel/retriever";
14
+ import { QueryError } from "@/errors";
15
+ import { type framer } from "@/framer";
16
+ import { type label } from "@/label";
17
+ import { type ontology } from "@/ontology";
18
+ import { Active } from "@/ranger/active";
19
+ import { Aliaser } from "@/ranger/alias";
20
+ import { KV } from "@/ranger/kv";
21
+ import {
22
+ type NewPayload,
23
+ type Key,
24
+ type Keys,
25
+ type Name,
26
+ type Names,
27
+ type Params,
28
+ type Payload,
29
+ analyzeParams,
30
+ } from "@/ranger/payload";
31
+ import { Range } from "@/ranger/range";
32
+ import { type Retriever } from "@/ranger/retriever";
33
+ import { type Writer } from "@/ranger/writer";
34
+
35
+ export class Client implements AsyncTermSearcher<string, Key, Range> {
36
+ private readonly frameClient: framer.Client;
37
+ private readonly retriever: Retriever;
38
+ private readonly writer: Writer;
39
+ private readonly unaryClient: UnaryClient;
40
+ private readonly channels: ChannelRetriever;
41
+ private readonly active: Active;
42
+ private readonly labelClient: label.Client;
43
+
44
+ constructor(
45
+ frameClient: framer.Client,
46
+ retriever: Retriever,
47
+ writer: Writer,
48
+ unary: UnaryClient,
49
+ channels: ChannelRetriever,
50
+ labelClient: label.Client,
51
+ ) {
52
+ this.frameClient = frameClient;
53
+ this.retriever = retriever;
54
+ this.writer = writer;
55
+ this.unaryClient = unary;
56
+ this.channels = channels;
57
+ this.active = new Active(unary);
58
+ this.labelClient = labelClient;
59
+ }
60
+
61
+ async create(range: NewPayload): Promise<Range>;
62
+
63
+ async create(ranges: NewPayload[]): Promise<Range[]>;
64
+
65
+ async create(ranges: NewPayload | NewPayload[]): Promise<Range | Range[]> {
66
+ const single = !Array.isArray(ranges);
67
+ const res = this.sugar(await this.writer.create(toArray(ranges)));
68
+ return single ? res[0] : res;
69
+ }
70
+
71
+ async rename(key: Key, name: Name): Promise<void> {
72
+ await this.writer.rename(key, name);
73
+ }
74
+
75
+ async delete(key: Key | Keys): Promise<void> {
76
+ await this.writer.delete(toArray(key));
77
+ }
78
+
79
+ async search(term: string): Promise<Range[]> {
80
+ return this.sugar(await this.retriever.search(term));
81
+ }
82
+
83
+ async page(offset: number, limit: number): Promise<Range[]> {
84
+ return [];
85
+ }
86
+
87
+ async retrieve(range: Key | Name): Promise<Range>;
88
+
89
+ async retrieve(params: Keys | Names): Promise<Range[]>;
90
+
91
+ async retrieve(params: Params): Promise<Range | Range[]> {
92
+ const { single, actual } = analyzeParams(params);
93
+ const res = this.sugar(await this.retriever.retrieve(params));
94
+ if (!single) return res;
95
+ if (res.length === 0) throw new QueryError(`range matching ${actual} not found`);
96
+ if (res.length > 1)
97
+ throw new QueryError(`multiple ranges matching ${actual} found`);
98
+ return res[0];
99
+ }
100
+
101
+ async setActive(range: Key): Promise<void> {
102
+ await this.active.setActive(range);
103
+ }
104
+
105
+ async retrieveActive(): Promise<Range | null> {
106
+ const res = await this.active.retrieveActive();
107
+ if (res == null) return null;
108
+ return this.sugar([res])[0];
109
+ }
110
+
111
+ async clearActive(range: Key): Promise<void> {
112
+ await this.active.clearActive(range);
113
+ }
114
+
115
+ private sugar(payloads: Payload[]): Range[] {
116
+ return payloads.map((payload) => {
117
+ return new Range(
118
+ payload.name,
119
+ payload.timeRange,
120
+ payload.key,
121
+ this.frameClient,
122
+ new KV(payload.key, this.unaryClient),
123
+ new Aliaser(payload.key, this.frameClient, this.unaryClient),
124
+ this.channels,
125
+ this.labelClient,
126
+ );
127
+ });
128
+ }
129
+ }
@@ -0,0 +1,15 @@
1
+ // Copyright 2023 Synnax Labs, Inc.
2
+ //
3
+ // Use of this software is governed by the Business Source License included in the file
4
+ // licenses/BSL.txt.
5
+ //
6
+ // As of the Change Date specified in that file, in accordance with the Business Source
7
+ // License, use of this software will be governed by the Apache License, Version 2.0,
8
+ // included in the file licenses/APL.txt.
9
+
10
+ export * from "@/ranger/client";
11
+ export * from "@/ranger/writer";
12
+ export * from "@/ranger/payload";
13
+ export * from "@/ranger/range";
14
+ export * from "@/ranger/retriever";
15
+ export type { Alias, AliasChange } from "@/ranger/alias";
@@ -0,0 +1,10 @@
1
+ // Copyright 2023 Synnax Labs, Inc.
2
+ //
3
+ // Use of this software is governed by the Business Source License included in the file
4
+ // licenses/BSL.txt.
5
+ //
6
+ // As of the Change Date specified in that file, in accordance with the Business Source
7
+ // License, use of this software will be governed by the Apache License, Version 2.0,
8
+ // included in the file licenses/APL.txt.
9
+
10
+ export * as ranger from "@/ranger/external";