@synnaxlabs/client 0.38.1 → 0.39.0

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 (257) hide show
  1. package/.turbo/turbo-build.log +7 -7
  2. package/dist/access/payload.d.ts +6 -6
  3. package/dist/access/payload.d.ts.map +1 -1
  4. package/dist/access/policy/client.d.ts +5 -3
  5. package/dist/access/policy/client.d.ts.map +1 -1
  6. package/dist/access/policy/external.d.ts +1 -0
  7. package/dist/access/policy/external.d.ts.map +1 -1
  8. package/dist/access/policy/ontology.d.ts +5 -0
  9. package/dist/access/policy/ontology.d.ts.map +1 -0
  10. package/dist/access/policy/payload.d.ts +86 -89
  11. package/dist/access/policy/payload.d.ts.map +1 -1
  12. package/dist/access/policy/retriever.d.ts +7 -6
  13. package/dist/access/policy/retriever.d.ts.map +1 -1
  14. package/dist/access/policy/writer.d.ts +2 -2
  15. package/dist/access/policy/writer.d.ts.map +1 -1
  16. package/dist/auth/auth.d.ts +2 -1
  17. package/dist/auth/auth.d.ts.map +1 -1
  18. package/dist/channel/client.d.ts +6 -5
  19. package/dist/channel/client.d.ts.map +1 -1
  20. package/dist/channel/payload.d.ts +13 -11
  21. package/dist/channel/payload.d.ts.map +1 -1
  22. package/dist/channel/retriever.d.ts +9 -6
  23. package/dist/channel/retriever.d.ts.map +1 -1
  24. package/dist/channel/writer.d.ts +6 -4
  25. package/dist/channel/writer.d.ts.map +1 -1
  26. package/dist/client.cjs +30 -30
  27. package/dist/client.d.ts +4 -2
  28. package/dist/client.d.ts.map +1 -1
  29. package/dist/client.js +3376 -3423
  30. package/dist/connection/checker.d.ts +5 -4
  31. package/dist/connection/checker.d.ts.map +1 -1
  32. package/dist/control/state.d.ts +10 -8
  33. package/dist/control/state.d.ts.map +1 -1
  34. package/dist/errors.d.ts +5 -0
  35. package/dist/errors.d.ts.map +1 -1
  36. package/dist/framer/adapter.d.ts +14 -15
  37. package/dist/framer/adapter.d.ts.map +1 -1
  38. package/dist/framer/client.d.ts +13 -15
  39. package/dist/framer/client.d.ts.map +1 -1
  40. package/dist/framer/deleter.d.ts +3 -2
  41. package/dist/framer/deleter.d.ts.map +1 -1
  42. package/dist/framer/frame.d.ts +31 -27
  43. package/dist/framer/frame.d.ts.map +1 -1
  44. package/dist/framer/iterator.d.ts +4 -5
  45. package/dist/framer/iterator.d.ts.map +1 -1
  46. package/dist/framer/streamer.d.ts +5 -6
  47. package/dist/framer/streamer.d.ts.map +1 -1
  48. package/dist/framer/writer.d.ts +42 -39
  49. package/dist/framer/writer.d.ts.map +1 -1
  50. package/dist/hardware/device/client.d.ts +17 -12
  51. package/dist/hardware/device/client.d.ts.map +1 -1
  52. package/dist/hardware/device/payload.d.ts +19 -16
  53. package/dist/hardware/device/payload.d.ts.map +1 -1
  54. package/dist/hardware/rack/client.d.ts +15 -15
  55. package/dist/hardware/rack/client.d.ts.map +1 -1
  56. package/dist/hardware/rack/payload.d.ts +9 -8
  57. package/dist/hardware/rack/payload.d.ts.map +1 -1
  58. package/dist/hardware/task/client.d.ts +38 -29
  59. package/dist/hardware/task/client.d.ts.map +1 -1
  60. package/dist/hardware/task/payload.d.ts +58 -53
  61. package/dist/hardware/task/payload.d.ts.map +1 -1
  62. package/dist/label/client.d.ts +4 -3
  63. package/dist/label/client.d.ts.map +1 -1
  64. package/dist/label/payload.d.ts +4 -4
  65. package/dist/label/payload.d.ts.map +1 -1
  66. package/dist/label/retriever.d.ts.map +1 -1
  67. package/dist/label/writer.d.ts +13 -10
  68. package/dist/label/writer.d.ts.map +1 -1
  69. package/dist/ontology/client.d.ts +12 -10
  70. package/dist/ontology/client.d.ts.map +1 -1
  71. package/dist/ontology/group/client.d.ts +5 -4
  72. package/dist/ontology/group/client.d.ts.map +1 -1
  73. package/dist/ontology/group/group.d.ts +7 -5
  74. package/dist/ontology/group/group.d.ts.map +1 -1
  75. package/dist/ontology/group/payload.d.ts +6 -5
  76. package/dist/ontology/group/payload.d.ts.map +1 -1
  77. package/dist/ontology/group/writer.d.ts +8 -8
  78. package/dist/ontology/group/writer.d.ts.map +1 -1
  79. package/dist/ontology/payload.d.ts +72 -62
  80. package/dist/ontology/payload.d.ts.map +1 -1
  81. package/dist/ontology/writer.d.ts.map +1 -1
  82. package/dist/ranger/alias.d.ts +9 -10
  83. package/dist/ranger/alias.d.ts.map +1 -1
  84. package/dist/ranger/client.d.ts +18 -18
  85. package/dist/ranger/client.d.ts.map +1 -1
  86. package/dist/ranger/external.d.ts +1 -1
  87. package/dist/ranger/external.d.ts.map +1 -1
  88. package/dist/ranger/kv.d.ts +18 -14
  89. package/dist/ranger/kv.d.ts.map +1 -1
  90. package/dist/ranger/payload.d.ts +13 -13
  91. package/dist/ranger/payload.d.ts.map +1 -1
  92. package/dist/ranger/writer.d.ts +14 -14
  93. package/dist/ranger/writer.d.ts.map +1 -1
  94. package/dist/setupspecs.d.ts.map +1 -1
  95. package/dist/signals/observable.d.ts +3 -1
  96. package/dist/signals/observable.d.ts.map +1 -1
  97. package/dist/user/client.d.ts +5 -3
  98. package/dist/user/client.d.ts.map +1 -1
  99. package/dist/user/payload.d.ts +7 -6
  100. package/dist/user/payload.d.ts.map +1 -1
  101. package/dist/user/retriever.d.ts +2 -1
  102. package/dist/user/retriever.d.ts.map +1 -1
  103. package/dist/user/writer.d.ts +2 -2
  104. package/dist/user/writer.d.ts.map +1 -1
  105. package/dist/util/decodeJSONString.d.ts +3 -0
  106. package/dist/util/decodeJSONString.d.ts.map +1 -0
  107. package/dist/util/parseWithoutKeyConversion.d.ts +3 -0
  108. package/dist/util/parseWithoutKeyConversion.d.ts.map +1 -0
  109. package/dist/util/retrieve.d.ts +1 -1
  110. package/dist/util/retrieve.d.ts.map +1 -1
  111. package/dist/util/telem.d.ts.map +1 -1
  112. package/dist/util/zod.d.ts.map +1 -1
  113. package/dist/workspace/client.d.ts +6 -60
  114. package/dist/workspace/client.d.ts.map +1 -1
  115. package/dist/workspace/external.d.ts +3 -0
  116. package/dist/workspace/external.d.ts.map +1 -0
  117. package/dist/workspace/index.d.ts +1 -1
  118. package/dist/workspace/index.d.ts.map +1 -1
  119. package/dist/workspace/lineplot/client.d.ts +5 -44
  120. package/dist/workspace/lineplot/client.d.ts.map +1 -1
  121. package/dist/workspace/lineplot/external.d.ts +3 -0
  122. package/dist/workspace/lineplot/external.d.ts.map +1 -0
  123. package/dist/workspace/lineplot/index.d.ts +1 -1
  124. package/dist/workspace/lineplot/index.d.ts.map +1 -1
  125. package/dist/workspace/lineplot/payload.d.ts +45 -0
  126. package/dist/workspace/lineplot/payload.d.ts.map +1 -0
  127. package/dist/workspace/log/client.d.ts +5 -44
  128. package/dist/workspace/log/client.d.ts.map +1 -1
  129. package/dist/workspace/log/external.d.ts +3 -0
  130. package/dist/workspace/log/external.d.ts.map +1 -0
  131. package/dist/workspace/log/index.d.ts +1 -1
  132. package/dist/workspace/log/index.d.ts.map +1 -1
  133. package/dist/workspace/log/payload.d.ts +45 -0
  134. package/dist/workspace/log/payload.d.ts.map +1 -0
  135. package/dist/workspace/payload.d.ts +60 -0
  136. package/dist/workspace/payload.d.ts.map +1 -0
  137. package/dist/workspace/schematic/client.d.ts +5 -68
  138. package/dist/workspace/schematic/client.d.ts.map +1 -1
  139. package/dist/workspace/schematic/external.d.ts +3 -0
  140. package/dist/workspace/schematic/external.d.ts.map +1 -0
  141. package/dist/workspace/schematic/index.d.ts +1 -1
  142. package/dist/workspace/schematic/index.d.ts.map +1 -1
  143. package/dist/workspace/schematic/payload.d.ts +71 -0
  144. package/dist/workspace/schematic/payload.d.ts.map +1 -0
  145. package/dist/workspace/table/client.d.ts +5 -57
  146. package/dist/workspace/table/client.d.ts.map +1 -1
  147. package/dist/workspace/table/external.d.ts +3 -0
  148. package/dist/workspace/table/external.d.ts.map +1 -0
  149. package/dist/workspace/table/index.d.ts +1 -1
  150. package/dist/workspace/table/index.d.ts.map +1 -1
  151. package/dist/workspace/table/payload.d.ts +60 -0
  152. package/dist/workspace/table/payload.d.ts.map +1 -0
  153. package/examples/node/basicReadWrite.js +26 -26
  154. package/examples/node/liveStream.js +15 -15
  155. package/examples/node/seriesAndFrames.js +38 -38
  156. package/examples/node/streamWrite.js +47 -45
  157. package/package.json +15 -13
  158. package/src/access/payload.ts +12 -12
  159. package/src/access/policy/client.ts +13 -12
  160. package/src/access/policy/external.ts +1 -0
  161. package/src/access/policy/ontology.ts +17 -0
  162. package/src/access/policy/payload.ts +7 -19
  163. package/src/access/policy/policy.spec.ts +16 -16
  164. package/src/access/policy/retriever.ts +2 -1
  165. package/src/access/policy/writer.ts +4 -4
  166. package/src/auth/auth.spec.ts +27 -23
  167. package/src/auth/auth.ts +7 -11
  168. package/src/channel/batchRetriever.spec.ts +25 -22
  169. package/src/channel/client.ts +19 -21
  170. package/src/channel/payload.ts +16 -20
  171. package/src/channel/retriever.ts +20 -21
  172. package/src/channel/writer.ts +11 -13
  173. package/src/client.ts +6 -16
  174. package/src/connection/checker.ts +9 -11
  175. package/src/connection/connection.spec.ts +17 -5
  176. package/src/control/state.ts +8 -9
  177. package/src/errors.spec.ts +1 -1
  178. package/src/errors.ts +8 -0
  179. package/src/framer/adapter.spec.ts +28 -23
  180. package/src/framer/adapter.ts +37 -41
  181. package/src/framer/client.spec.ts +5 -11
  182. package/src/framer/client.ts +34 -38
  183. package/src/framer/deleter.ts +5 -6
  184. package/src/framer/frame.ts +62 -50
  185. package/src/framer/iterator.ts +11 -16
  186. package/src/framer/streamer.spec.ts +2 -10
  187. package/src/framer/streamer.ts +15 -19
  188. package/src/framer/writer.spec.ts +48 -7
  189. package/src/framer/writer.ts +39 -31
  190. package/src/hardware/device/client.ts +64 -39
  191. package/src/hardware/device/device.spec.ts +49 -33
  192. package/src/hardware/device/payload.ts +29 -29
  193. package/src/hardware/rack/client.ts +52 -65
  194. package/src/hardware/rack/payload.ts +9 -18
  195. package/src/hardware/rack/rack.spec.ts +12 -0
  196. package/src/hardware/task/client.ts +160 -131
  197. package/src/hardware/task/payload.ts +49 -68
  198. package/src/hardware/task/task.spec.ts +98 -81
  199. package/src/label/client.ts +12 -15
  200. package/src/label/payload.ts +3 -9
  201. package/src/label/retriever.ts +3 -7
  202. package/src/label/writer.ts +8 -15
  203. package/src/ontology/client.ts +17 -22
  204. package/src/ontology/group/client.ts +5 -5
  205. package/src/ontology/group/group.spec.ts +4 -4
  206. package/src/ontology/group/group.ts +10 -7
  207. package/src/ontology/group/payload.ts +11 -35
  208. package/src/ontology/group/writer.ts +22 -26
  209. package/src/ontology/ontology.spec.ts +15 -15
  210. package/src/ontology/payload.ts +67 -43
  211. package/src/ontology/writer.ts +16 -23
  212. package/src/ranger/alias.ts +25 -42
  213. package/src/ranger/client.ts +29 -38
  214. package/src/ranger/external.ts +1 -1
  215. package/src/ranger/kv.ts +9 -32
  216. package/src/ranger/payload.ts +14 -36
  217. package/src/ranger/ranger.spec.ts +1 -2
  218. package/src/ranger/writer.ts +8 -26
  219. package/src/signals/observable.ts +3 -4
  220. package/src/user/client.ts +8 -4
  221. package/src/user/payload.ts +5 -9
  222. package/src/user/retriever.ts +1 -1
  223. package/src/user/user.spec.ts +17 -15
  224. package/src/user/writer.ts +3 -10
  225. package/src/util/decodeJSONString.ts +13 -0
  226. package/src/util/parseWithoutKeyConversion.ts +19 -0
  227. package/src/util/retrieve.spec.ts +3 -13
  228. package/src/util/retrieve.ts +2 -12
  229. package/src/util/telem.ts +1 -1
  230. package/src/vite-env.d.ts +1 -0
  231. package/src/workspace/client.ts +30 -57
  232. package/src/workspace/external.ts +11 -0
  233. package/src/workspace/index.ts +1 -1
  234. package/src/workspace/lineplot/client.ts +22 -36
  235. package/src/workspace/lineplot/external.ts +11 -0
  236. package/src/workspace/lineplot/index.ts +1 -1
  237. package/src/workspace/lineplot/linePlot.spec.ts +1 -2
  238. package/src/workspace/lineplot/payload.ts +32 -0
  239. package/src/workspace/log/client.ts +25 -39
  240. package/src/workspace/log/external.ts +11 -0
  241. package/src/workspace/log/index.ts +1 -1
  242. package/src/workspace/log/log.spec.ts +5 -18
  243. package/src/workspace/log/payload.ts +32 -0
  244. package/src/workspace/payload.ts +36 -0
  245. package/src/workspace/schematic/client.ts +30 -56
  246. package/src/workspace/schematic/external.ts +11 -0
  247. package/src/workspace/schematic/index.ts +1 -1
  248. package/src/workspace/schematic/payload.ts +37 -0
  249. package/src/workspace/schematic/schematic.spec.ts +15 -6
  250. package/src/workspace/table/client.ts +27 -50
  251. package/src/workspace/table/external.ts +11 -0
  252. package/src/workspace/table/index.ts +1 -1
  253. package/src/workspace/table/payload.ts +36 -0
  254. package/src/workspace/workspace.spec.ts +1 -2
  255. package/dist/channel/creator.d.ts +0 -9
  256. package/dist/channel/creator.d.ts.map +0 -1
  257. package/src/channel/creator.ts +0 -37
@@ -94,7 +94,7 @@ describe("Policy", () => {
94
94
  });
95
95
  describe("many", () => {
96
96
  test("with keys", async () => {
97
- const policiesToCreate: policy.NewPolicy[] = [
97
+ const policiesToCreate: policy.New[] = [
98
98
  {
99
99
  subjects: [{ type: user.ONTOLOGY_TYPE, key: "10" }],
100
100
  objects: [
@@ -185,8 +185,8 @@ describe("Policy", () => {
185
185
  await client.access.policy.delete([policies[0].key, policies[1].key]);
186
186
  });
187
187
  test("by subject", async () => {
188
- const key1 = id.id();
189
- const key2 = id.id();
188
+ const key1 = id.create();
189
+ const key2 = id.create();
190
190
  const created = await client.access.policy.create([
191
191
  {
192
192
  subjects: [
@@ -216,10 +216,10 @@ describe("Policy", () => {
216
216
  });
217
217
  describe("delete", async () => {
218
218
  test("one", async () => {
219
- const id1 = id.id();
220
- const id2 = id.id();
221
- const id3 = id.id();
222
- const policies: policy.NewPolicy[] = [
219
+ const id1 = id.create();
220
+ const id2 = id.create();
221
+ const id3 = id.create();
222
+ const policies: policy.New[] = [
223
223
  {
224
224
  subjects: [
225
225
  { type: user.ONTOLOGY_TYPE, key: id1 },
@@ -250,10 +250,10 @@ describe("Policy", () => {
250
250
  await client.access.policy.delete(created[1].key);
251
251
  });
252
252
  test("many", async () => {
253
- const id1 = id.id();
254
- const id2 = id.id();
255
- const id3 = id.id();
256
- const policies: policy.NewPolicy[] = [
253
+ const id1 = id.create();
254
+ const id2 = id.create();
255
+ const id3 = id.create();
256
+ const policies: policy.New[] = [
257
257
  {
258
258
  subjects: [
259
259
  { type: user.ONTOLOGY_TYPE, key: id1 },
@@ -288,7 +288,7 @@ describe("Policy", () => {
288
288
 
289
289
  describe("privilege", async () => {
290
290
  test("new user", async () => {
291
- const username = id.id();
291
+ const username = id.create();
292
292
  const user2 = await client.user.create({ username, password: "pwd1" });
293
293
  expect(user2).toBeDefined();
294
294
  const client2 = new Synnax({
@@ -298,7 +298,7 @@ describe("privilege", async () => {
298
298
  password: "pwd1",
299
299
  });
300
300
  await expect(
301
- client2.user.create({ username: id.id(), password: id.id() }),
301
+ client2.user.create({ username: id.create(), password: id.create() }),
302
302
  ).rejects.toThrow(AuthError);
303
303
 
304
304
  const policy = await client.access.policy.create({
@@ -307,11 +307,11 @@ describe("privilege", async () => {
307
307
  actions: ["create"],
308
308
  });
309
309
 
310
- const newUsername = id.id();
310
+ const newUsername = id.create();
311
311
 
312
312
  const newUser = await client2.user.create({
313
313
  username: newUsername,
314
- password: id.id(),
314
+ password: id.create(),
315
315
  });
316
316
 
317
317
  expect(newUser.username).toEqual(newUsername);
@@ -320,7 +320,7 @@ describe("privilege", async () => {
320
320
  await client.access.policy.delete(policy.key);
321
321
 
322
322
  await expect(
323
- client2.user.create({ username: id.id(), password: id.id() }),
323
+ client2.user.create({ username: id.create(), password: id.create() }),
324
324
  ).rejects.toThrow(AuthError);
325
325
  });
326
326
  });
@@ -18,7 +18,8 @@ const reqZ = z.object({
18
18
  keys: keyZ.array().optional(),
19
19
  subjects: ontology.idZ.array().optional(),
20
20
  });
21
- type Request = z.infer<typeof reqZ>;
21
+ interface Request extends z.infer<typeof reqZ> {}
22
+
22
23
  const resZ = z.object({ policies: nullableArrayZ(policyZ) });
23
24
 
24
25
  const ENDPOINT = "/access/policy/retrieve";
@@ -14,8 +14,8 @@ import { z } from "zod";
14
14
  import {
15
15
  type Key,
16
16
  keyZ,
17
- type NewPolicy,
18
- newPolicyZ,
17
+ type New,
18
+ newZ,
19
19
  type Policy,
20
20
  policyZ,
21
21
  } from "@/access/policy/payload";
@@ -36,8 +36,8 @@ export class Writer {
36
36
  this.client = client;
37
37
  }
38
38
 
39
- async create(policies: NewPolicy | NewPolicy[]): Promise<Policy[]> {
40
- const parsedPolicies = newPolicyZ.array().parse(toArray(policies));
39
+ async create(policies: New | New[]): Promise<Policy[]> {
40
+ const parsedPolicies = newZ.array().parse(toArray(policies));
41
41
  const req = parsedPolicies.map((policy) => ({
42
42
  objects: toArray(policy.objects),
43
43
  actions: toArray(policy.actions),
@@ -12,7 +12,7 @@ import { URL } from "@synnaxlabs/x/url";
12
12
  import { describe, expect, it, test } from "vitest";
13
13
 
14
14
  import { auth } from "@/auth";
15
- import { AuthError, InvalidTokenError } from "@/errors";
15
+ import { AuthError, ExpiredTokenError, InvalidTokenError } from "@/errors";
16
16
  import { HOST, PORT } from "@/setupspecs";
17
17
  import { Transport } from "@/transport";
18
18
 
@@ -46,30 +46,34 @@ describe("auth", () => {
46
46
  expect(err).toBeInstanceOf(AuthError);
47
47
  });
48
48
 
49
- describe("invalid token retry", async () => {
50
- it("should re-authenticate and retry the request", async () => {
51
- const transport = new Transport(new URL({ host: HOST, port: PORT }));
52
- const client = new auth.Client(transport.unary, {
53
- username: "synnax",
54
- password: "seldon",
49
+ describe("token retry", () => {
50
+ const ERROR_TYPES = [InvalidTokenError, ExpiredTokenError];
51
+ ERROR_TYPES.forEach((ErrorType) => {
52
+ it(`should re-authenticate and retry the request for ${ErrorType.name}`, async () => {
53
+ const transport = new Transport(new URL({ host: HOST, port: PORT }));
54
+ const client = new auth.Client(transport.unary, {
55
+ username: "synnax",
56
+ password: "seldon",
57
+ });
58
+ const mw = client.middleware();
59
+ let isFirst = true;
60
+ let tkOne: string | undefined;
61
+ let tkTwo: string | undefined;
62
+ const [, err] = await mw(DUMMY_CTX, async () => {
63
+ if (isFirst) {
64
+ isFirst = false;
65
+ tkOne = client.token;
66
+ return [DUMMY_CTX, new ErrorType()];
67
+ }
68
+ tkTwo = client.token;
69
+ return [DUMMY_CTX, null];
70
+ });
71
+ expect(err).toBeNull();
72
+ expect(tkOne).toBeDefined();
73
+ expect(tkTwo).toBeDefined();
55
74
  });
56
- const mw = client.middleware();
57
- let isFirst = true;
58
- let tkOne: string | undefined;
59
- let tkTwo: string | undefined;
60
- const [, err] = await mw(DUMMY_CTX, async () => {
61
- if (isFirst) {
62
- isFirst = false;
63
- tkOne = client.token;
64
- return [DUMMY_CTX, new InvalidTokenError()];
65
- }
66
- tkTwo = client.token;
67
- return [DUMMY_CTX, null];
68
- });
69
- expect(err).toBeNull();
70
- expect(tkOne).toBeDefined();
71
- expect(tkTwo).toBeDefined();
72
75
  });
76
+
73
77
  it("should fail after MAX_RETRIES", async () => {
74
78
  const transport = new Transport(new URL({ host: HOST, port: PORT }));
75
79
  const client = new auth.Client(transport.unary, {
package/src/auth/auth.ts CHANGED
@@ -10,19 +10,13 @@
10
10
  import { type Middleware, sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
11
11
  import { z } from "zod";
12
12
 
13
- import { InvalidTokenError } from "@/errors";
13
+ import { ExpiredTokenError, InvalidTokenError } from "@/errors";
14
14
  import { user } from "@/user";
15
15
 
16
- const insecureCredentialsZ = z.object({
17
- username: z.string(),
18
- password: z.string(),
19
- });
20
- type InsecureCredentials = z.infer<typeof insecureCredentialsZ>;
16
+ const insecureCredentialsZ = z.object({ username: z.string(), password: z.string() });
17
+ interface InsecureCredentials extends z.infer<typeof insecureCredentialsZ> {}
21
18
 
22
- const tokenResponseZ = z.object({
23
- token: z.string(),
24
- user: user.userZ,
25
- });
19
+ const tokenResponseZ = z.object({ token: z.string(), user: user.userZ });
26
20
 
27
21
  const LOGIN_ENDPOINT = "/auth/login";
28
22
 
@@ -37,6 +31,8 @@ const changePasswordReqZ = z.object({
37
31
  });
38
32
  const changePasswordResZ = z.object({});
39
33
 
34
+ const RETRY_ON = [InvalidTokenError, ExpiredTokenError] as const;
35
+
40
36
  export class Client {
41
37
  token: string | undefined;
42
38
  private readonly client: UnaryClient;
@@ -94,7 +90,7 @@ export class Client {
94
90
  }
95
91
  reqCtx.params.Authorization = `Bearer ${this.token}`;
96
92
  const [resCtx, err] = await next(reqCtx);
97
- if (InvalidTokenError.matches(err) && this.retryCount < MAX_RETRIES) {
93
+ if (RETRY_ON.some((e) => e.matches(err)) && this.retryCount < MAX_RETRIES) {
98
94
  this.authenticated = false;
99
95
  this.authenticating = undefined;
100
96
  this.retryCount += 1;
@@ -10,42 +10,45 @@
10
10
  import { DataType, Rate } from "@synnaxlabs/x/telem";
11
11
  import { describe, expect, it, vi } from "vitest";
12
12
 
13
- import { type Params, type Payload } from "@/channel/payload";
14
- import {
15
- analyzeChannelParams,
16
- DebouncedBatchRetriever,
17
- type RetrieveOptions,
18
- type Retriever,
19
- } from "@/channel/retriever";
13
+ import { channel } from "@/channel";
20
14
 
21
- class MockRetriever implements Retriever {
22
- func: (channels: Params, options?: RetrieveOptions) => Promise<Payload[]>;
15
+ class MockRetriever implements channel.Retriever {
16
+ func: (
17
+ channels: channel.Params,
18
+ options?: channel.RetrieveOptions,
19
+ ) => Promise<channel.Payload[]>;
23
20
 
24
21
  constructor(
25
- func: (channels: Params, options?: RetrieveOptions) => Promise<Payload[]>,
22
+ func: (
23
+ channels: channel.Params,
24
+ options?: channel.RetrieveOptions,
25
+ ) => Promise<channel.Payload[]>,
26
26
  ) {
27
27
  this.func = func;
28
28
  }
29
29
 
30
- async search(): Promise<Payload[]> {
30
+ async search(): Promise<channel.Payload[]> {
31
31
  throw new Error("Method not implemented.");
32
32
  }
33
33
 
34
- async page(): Promise<Payload[]> {
34
+ async page(): Promise<channel.Payload[]> {
35
35
  throw new Error("Method not implemented.");
36
36
  }
37
37
 
38
- async retrieve(channels: Params, options?: RetrieveOptions): Promise<Payload[]> {
38
+ async retrieve(
39
+ channels: channel.Params,
40
+ options?: channel.RetrieveOptions,
41
+ ): Promise<channel.Payload[]> {
39
42
  return await this.func(channels, options);
40
43
  }
41
44
  }
42
45
 
43
- describe("channelRetriever", () => {
46
+ describe("channelchannel.Retriever", () => {
44
47
  it("should batch multiple retrieve requests", async () => {
45
48
  const called = vi.fn();
46
- const base = new MockRetriever(async (batch): Promise<Payload[]> => {
49
+ const base = new MockRetriever(async (batch): Promise<channel.Payload[]> => {
47
50
  called(batch);
48
- const { normalized } = analyzeChannelParams(batch);
51
+ const { normalized } = channel.analyzeParams(batch);
49
52
  return normalized.map((key) => ({
50
53
  key: key as number,
51
54
  name: `channel-${key}`,
@@ -60,7 +63,7 @@ describe("channelRetriever", () => {
60
63
  requires: [],
61
64
  }));
62
65
  });
63
- const retriever = new DebouncedBatchRetriever(base, 10);
66
+ const retriever = new channel.DebouncedBatchRetriever(base, 10);
64
67
  const res = await Promise.all([
65
68
  retriever.retrieve([1]),
66
69
  retriever.retrieve([2]),
@@ -72,9 +75,9 @@ describe("channelRetriever", () => {
72
75
  });
73
76
  it("should only fetch duplicate keys once", async () => {
74
77
  const called = vi.fn();
75
- const base = new MockRetriever(async (batch): Promise<Payload[]> => {
78
+ const base = new MockRetriever(async (batch): Promise<channel.Payload[]> => {
76
79
  called(batch);
77
- const { normalized } = analyzeChannelParams(batch);
80
+ const { normalized } = channel.analyzeParams(batch);
78
81
  return normalized.map((key) => ({
79
82
  key: key as number,
80
83
  name: `channel-${key}`,
@@ -89,7 +92,7 @@ describe("channelRetriever", () => {
89
92
  requires: [],
90
93
  }));
91
94
  });
92
- const retriever = new DebouncedBatchRetriever(base, 10);
95
+ const retriever = new channel.DebouncedBatchRetriever(base, 10);
93
96
  const res = await Promise.all([
94
97
  retriever.retrieve([1]),
95
98
  retriever.retrieve([2]),
@@ -100,10 +103,10 @@ describe("channelRetriever", () => {
100
103
  expect(res.map((r) => r.map((c) => c.key))).toEqual([[1], [2], [1, 2]]);
101
104
  });
102
105
  it("should throw an error if the fetch fails", async () => {
103
- const base = new MockRetriever(async (): Promise<Payload[]> => {
106
+ const base = new MockRetriever(async (): Promise<channel.Payload[]> => {
104
107
  throw new Error("failed to fetch");
105
108
  });
106
- const retriever = new DebouncedBatchRetriever(base, 10);
109
+ const retriever = new channel.DebouncedBatchRetriever(base, 10);
107
110
  await expect(retriever.retrieve([1])).rejects.toThrow("failed to fetch");
108
111
  });
109
112
  });
@@ -22,16 +22,17 @@ import { toArray } from "@synnaxlabs/x/toArray";
22
22
  import { z } from "zod";
23
23
 
24
24
  import {
25
+ channelZ,
25
26
  type Key,
26
27
  type KeyOrName,
27
- type NewPayload,
28
- ontologyID as payloadOntologyID,
28
+ type Name,
29
+ type New,
30
+ ONTOLOGY_TYPE,
29
31
  type Params,
30
32
  type Payload,
31
- payload,
32
33
  } from "@/channel/payload";
33
34
  import {
34
- analyzeChannelParams,
35
+ analyzeParams,
35
36
  CacheRetriever,
36
37
  ClusterRetriever,
37
38
  DebouncedBatchRetriever,
@@ -41,7 +42,7 @@ import {
41
42
  import { type Writer } from "@/channel/writer";
42
43
  import { ValidationError } from "@/errors";
43
44
  import { type framer } from "@/framer";
44
- import { type ontology } from "@/ontology";
45
+ import { ontology } from "@/ontology";
45
46
  import { group } from "@/ontology/group";
46
47
  import { checkForMultipleOrNoResults } from "@/util/retrieve";
47
48
 
@@ -69,7 +70,7 @@ export class Channel {
69
70
  * A human-readable name for the channel. This name is not guaranteed to be
70
71
  * unique.
71
72
  */
72
- readonly name: string;
73
+ readonly name: Name;
73
74
  /**
74
75
  * The rate at which the channel samples telemetry. This only applies to fixed rate
75
76
  * channels, and will be 0 if the channel is indexed.
@@ -132,10 +133,7 @@ export class Channel {
132
133
  alias,
133
134
  expression = "",
134
135
  requires = [],
135
- }: NewPayload & {
136
- frameClient?: framer.Client;
137
- density?: CrudeDensity;
138
- }) {
136
+ }: New & { frameClient?: framer.Client; density?: CrudeDensity }) {
139
137
  this.key = key;
140
138
  this.name = name;
141
139
  this.rate = new Rate(rate ?? 0);
@@ -163,7 +161,7 @@ export class Channel {
163
161
  * network transportation, but also provided to you as a convenience.
164
162
  */
165
163
  get payload(): Payload {
166
- return payload.parse({
164
+ return channelZ.parse({
167
165
  key: this.key,
168
166
  name: this.name,
169
167
  rate: this.rate.valueOf(),
@@ -186,7 +184,7 @@ export class Channel {
186
184
  * @returns the ontology ID of the channel
187
185
  */
188
186
  get ontologyID(): ontology.ID {
189
- return payloadOntologyID(this.key);
187
+ return ontologyID(this.key);
190
188
  }
191
189
 
192
190
  /**
@@ -215,9 +213,7 @@ const RETRIEVE_GROUP_ENDPOINT = "/channel/retrieve-group";
215
213
 
216
214
  const retrieveGroupReqZ = z.object({});
217
215
 
218
- const retrieveGroupResZ = z.object({
219
- group: group.groupZ,
220
- });
216
+ const retrieveGroupResZ = z.object({ group: group.groupZ });
221
217
 
222
218
  /**
223
219
  * The core client class for executing channel operations against a Synnax
@@ -225,7 +221,7 @@ const retrieveGroupResZ = z.object({
225
221
  * through the `channels` property of an {@link Synnax} client.
226
222
  */
227
223
  export class Client implements AsyncTermSearcher<string, Key, Channel> {
228
- readonly type = "channel";
224
+ readonly type = ONTOLOGY_TYPE;
229
225
  private readonly frameClient: framer.Client;
230
226
  private readonly client: UnaryClient;
231
227
  readonly retriever: Retriever;
@@ -278,7 +274,7 @@ export class Client implements AsyncTermSearcher<string, Key, Channel> {
278
274
  * });
279
275
  * ```
280
276
  */
281
- async create(channel: NewPayload, options?: CreateOptions): Promise<Channel>;
277
+ async create(channel: New, options?: CreateOptions): Promise<Channel>;
282
278
 
283
279
  /**
284
280
  * Creates multiple channels with the given properties. The order of the channels
@@ -303,10 +299,10 @@ export class Client implements AsyncTermSearcher<string, Key, Channel> {
303
299
  *
304
300
  * @param channels
305
301
  */
306
- async create(channels: NewPayload[], options?: CreateOptions): Promise<Channel[]>;
302
+ async create(channels: New[], options?: CreateOptions): Promise<Channel[]>;
307
303
 
308
304
  async create(
309
- channels: NewPayload | NewPayload[],
305
+ channels: New | New[],
310
306
  options: CreateOptions = {},
311
307
  ): Promise<Channel | Channel[]> {
312
308
  const { retrieveIfNameExists = false } = options;
@@ -387,7 +383,7 @@ export class Client implements AsyncTermSearcher<string, Key, Channel> {
387
383
  * @param channels - The keys or names of the channels to delete.
388
384
  */
389
385
  async delete(channels: Params): Promise<void> {
390
- const { normalized, variant } = analyzeChannelParams(channels);
386
+ const { normalized, variant } = analyzeParams(channels);
391
387
  if (variant === "keys")
392
388
  return await this.writer.delete({ keys: normalized as Key[] });
393
389
  return await this.writer.delete({ names: normalized as string[] });
@@ -395,7 +391,6 @@ export class Client implements AsyncTermSearcher<string, Key, Channel> {
395
391
 
396
392
  async rename(key: Key, name: string): Promise<void>;
397
393
  async rename(keys: Key[], names: string[]): Promise<void>;
398
-
399
394
  async rename(keys: Key | Key[], names: string | string[]): Promise<void> {
400
395
  return await this.writer.rename(toArray(keys), toArray(names));
401
396
  }
@@ -466,3 +461,6 @@ export const resolveCalculatedIndex = async (
466
461
  }
467
462
  return null;
468
463
  };
464
+
465
+ export const ontologyID = (key: Key): ontology.ID =>
466
+ new ontology.ID({ type: ONTOLOGY_TYPE, key: key.toString() });
@@ -10,25 +10,25 @@
10
10
  import { DataType, Rate } from "@synnaxlabs/x/telem";
11
11
  import { z } from "zod";
12
12
 
13
- import { ontology } from "@/ontology";
14
13
  import { nullableArrayZ } from "@/util/zod";
15
14
 
16
15
  export const keyZ = z.number();
17
- export type Key = number;
18
- export type Keys = number[];
19
- export type Name = string;
20
- export type Names = string[];
16
+ export type Key = z.infer<typeof keyZ>;
17
+ export type Keys = Key[];
18
+ export const nameZ = z.string();
19
+ export type Name = z.infer<typeof nameZ>;
20
+ export type Names = Name[];
21
21
  export type KeyOrName = Key | Name;
22
22
  export type KeysOrNames = Keys | Names;
23
23
  export type Params = Key | Name | Keys | Names;
24
24
 
25
- export const payload = z.object({
26
- name: z.string(),
27
- key: z.number(),
25
+ export const channelZ = z.object({
26
+ name: nameZ,
27
+ key: keyZ,
28
28
  rate: Rate.z,
29
29
  dataType: DataType.z,
30
30
  leaseholder: z.number(),
31
- index: z.number(),
31
+ index: keyZ,
32
32
  isIndex: z.boolean(),
33
33
  internal: z.boolean(),
34
34
  virtual: z.boolean(),
@@ -36,13 +36,12 @@ export const payload = z.object({
36
36
  expression: z.string().default(""),
37
37
  requires: nullableArrayZ(keyZ),
38
38
  });
39
+ export interface Payload extends z.infer<typeof channelZ> {}
39
40
 
40
- export type Payload = z.infer<typeof payload>;
41
-
42
- export const newPayload = payload.extend({
43
- key: z.number().optional(),
41
+ export const newZ = channelZ.extend({
42
+ key: keyZ.optional(),
44
43
  leaseholder: z.number().optional(),
45
- index: z.number().optional(),
44
+ index: keyZ.optional(),
46
45
  rate: Rate.z.optional().default(0),
47
46
  isIndex: z.boolean().optional(),
48
47
  internal: z.boolean().optional().default(false),
@@ -50,10 +49,7 @@ export const newPayload = payload.extend({
50
49
  expression: z.string().optional().default(""),
51
50
  requires: nullableArrayZ(keyZ).optional().default([]),
52
51
  });
52
+ export interface New extends z.input<typeof newZ> {}
53
53
 
54
- export type NewPayload = z.input<typeof newPayload>;
55
-
56
- export const ONTOLOGY_TYPE: ontology.ResourceType = "channel";
57
-
58
- export const ontologyID = (key: Key): ontology.ID =>
59
- new ontology.ID({ type: ONTOLOGY_TYPE, key: key.toString() });
54
+ export const ONTOLOGY_TYPE = "channel";
55
+ export type OntologyType = typeof ONTOLOGY_TYPE;
@@ -6,28 +6,33 @@
6
6
  // As of the Change Date specified in that file, in accordance with the Business Source
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
- import type { UnaryClient } from "@synnaxlabs/freighter";
9
+
10
+ import { type UnaryClient } from "@synnaxlabs/freighter";
10
11
  import { debounce } from "@synnaxlabs/x/debounce";
11
12
  import { DataType } from "@synnaxlabs/x/telem";
12
13
  import { Mutex } from "async-mutex";
13
14
  import { z } from "zod";
14
15
 
15
16
  import {
17
+ channelZ,
16
18
  type Key,
17
19
  type KeyOrName,
18
20
  type Keys,
19
21
  type KeysOrNames,
22
+ keyZ,
20
23
  type Params,
21
24
  type Payload,
22
- payload,
23
25
  } from "@/channel/payload";
24
26
  import { QueryError } from "@/errors";
25
- import { analyzeParams, type ParamAnalysisResult } from "@/util/retrieve";
27
+ import {
28
+ analyzeParams as analyzeParameters,
29
+ type ParamAnalysisResult,
30
+ } from "@/util/retrieve";
26
31
  import { nullableArrayZ } from "@/util/zod";
27
32
 
28
33
  const reqZ = z.object({
29
34
  leaseholder: z.number().optional(),
30
- keys: z.number().array().optional(),
35
+ keys: keyZ.array().optional(),
31
36
  names: z.string().array().optional(),
32
37
  search: z.string().optional(),
33
38
  rangeKey: z.string().optional(),
@@ -39,23 +44,17 @@ const reqZ = z.object({
39
44
  isIndex: z.boolean().optional(),
40
45
  internal: z.boolean().optional(),
41
46
  });
47
+ interface Request extends z.input<typeof reqZ> {}
42
48
 
43
- type Request = z.input<typeof reqZ>;
49
+ export interface RetrieveOptions extends Omit<Request, "keys" | "names" | "search"> {}
50
+ export interface PageOptions extends Omit<RetrieveOptions, "offset" | "limit"> {}
44
51
 
45
- export type RetrieveOptions = Omit<Request, "keys" | "names" | "search">;
46
- export type PageOptions = Omit<RetrieveOptions, "offset" | "limit">;
52
+ const resZ = z.object({ channels: nullableArrayZ(channelZ) });
47
53
 
48
- const resZ = z.object({
49
- channels: nullableArrayZ(payload),
50
- });
51
-
52
- export const analyzeChannelParams = (
54
+ export const analyzeParams = (
53
55
  channels: Params,
54
56
  ): ParamAnalysisResult<KeyOrName, { number: "keys"; string: "names" }> =>
55
- analyzeParams(channels, {
56
- number: "keys",
57
- string: "names",
58
- });
57
+ analyzeParameters(channels, { number: "keys", string: "names" });
59
58
 
60
59
  export interface Retriever {
61
60
  retrieve: (channels: Params, opts?: RetrieveOptions) => Promise<Payload[]>;
@@ -76,7 +75,7 @@ export class ClusterRetriever implements Retriever {
76
75
  }
77
76
 
78
77
  async retrieve(channels: Params, options?: RetrieveOptions): Promise<Payload[]> {
79
- const res = analyzeChannelParams(channels);
78
+ const res = analyzeParams(channels);
80
79
  const { variant } = res;
81
80
  let { normalized } = res;
82
81
  if (variant === "keys" && (normalized as Key[]).indexOf(0) !== -1)
@@ -121,7 +120,7 @@ export class CacheRetriever implements Retriever {
121
120
  }
122
121
 
123
122
  async retrieve(channels: Params, options?: RetrieveOptions): Promise<Payload[]> {
124
- const { normalized } = analyzeParams<string | number>(channels, {
123
+ const { normalized } = analyzeParameters<string | number>(channels, {
125
124
  string: "names",
126
125
  number: "keys",
127
126
  });
@@ -139,7 +138,7 @@ export class CacheRetriever implements Retriever {
139
138
  }
140
139
 
141
140
  delete(channels: Params): void {
142
- const { variant, normalized } = analyzeChannelParams(channels);
141
+ const { variant, normalized } = analyzeParams(channels);
143
142
  if (variant === "names")
144
143
  (normalized as string[]).forEach((name) => {
145
144
  const keys = this.namesToKeys.get(name);
@@ -234,7 +233,7 @@ export class DebouncedBatchRetriever implements Retriever {
234
233
  }
235
234
 
236
235
  async retrieve(channels: Params): Promise<Payload[]> {
237
- const { normalized, variant } = analyzeChannelParams(channels);
236
+ const { normalized, variant } = analyzeParams(channels);
238
237
  // Bypass on name fetches for now.
239
238
  if (variant === "names") return await this.wrapped.retrieve(normalized);
240
239
 
@@ -269,7 +268,7 @@ export const retrieveRequired = async (
269
268
  r: Retriever,
270
269
  channels: Params,
271
270
  ): Promise<Payload[]> => {
272
- const { normalized } = analyzeChannelParams(channels);
271
+ const { normalized } = analyzeParams(channels);
273
272
  const results = await r.retrieve(normalized);
274
273
  const notFound: KeyOrName[] = [];
275
274
  normalized.forEach((v) => {