@synnaxlabs/client 0.47.0 → 0.49.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 (311) hide show
  1. package/.turbo/turbo-build.log +7 -7
  2. package/dist/client.cjs +35 -35
  3. package/dist/client.js +6264 -5984
  4. package/dist/eslint.config.d.ts +3 -2
  5. package/dist/eslint.config.d.ts.map +1 -1
  6. package/dist/src/access/client.d.ts +3 -1
  7. package/dist/src/access/client.d.ts.map +1 -1
  8. package/dist/src/access/enforce.d.ts +35 -0
  9. package/dist/src/access/enforce.d.ts.map +1 -0
  10. package/dist/src/access/enforce.spec.d.ts +2 -0
  11. package/dist/src/access/enforce.spec.d.ts.map +1 -0
  12. package/dist/src/access/external.d.ts +3 -0
  13. package/dist/src/access/external.d.ts.map +1 -1
  14. package/dist/src/access/payload.d.ts +0 -6
  15. package/dist/src/access/payload.d.ts.map +1 -1
  16. package/dist/src/access/policy/access.spec.d.ts +2 -0
  17. package/dist/src/access/policy/access.spec.d.ts.map +1 -0
  18. package/dist/src/access/policy/client.d.ts +485 -31
  19. package/dist/src/access/policy/client.d.ts.map +1 -1
  20. package/dist/src/access/policy/payload.d.ts +36 -113
  21. package/dist/src/access/policy/payload.d.ts.map +1 -1
  22. package/dist/src/access/role/client.d.ts +135 -0
  23. package/dist/src/access/role/client.d.ts.map +1 -0
  24. package/dist/src/access/role/external.d.ts.map +1 -0
  25. package/dist/src/access/role/index.d.ts +2 -0
  26. package/dist/src/access/role/index.d.ts.map +1 -0
  27. package/dist/src/access/role/payload.d.ts +27 -0
  28. package/dist/src/access/role/payload.d.ts.map +1 -0
  29. package/dist/src/access/role/role.spec.d.ts +2 -0
  30. package/dist/src/access/role/role.spec.d.ts.map +1 -0
  31. package/dist/src/arc/access.spec.d.ts +2 -0
  32. package/dist/src/arc/access.spec.d.ts.map +1 -0
  33. package/dist/src/arc/client.d.ts +5 -14
  34. package/dist/src/arc/client.d.ts.map +1 -1
  35. package/dist/src/arc/payload.d.ts +11 -2
  36. package/dist/src/arc/payload.d.ts.map +1 -1
  37. package/dist/src/auth/auth.d.ts +5 -3
  38. package/dist/src/auth/auth.d.ts.map +1 -1
  39. package/dist/src/channel/access.spec.d.ts +2 -0
  40. package/dist/src/channel/access.spec.d.ts.map +1 -0
  41. package/dist/src/channel/client.d.ts +0 -1
  42. package/dist/src/channel/client.d.ts.map +1 -1
  43. package/dist/src/channel/payload.d.ts +19 -8
  44. package/dist/src/channel/payload.d.ts.map +1 -1
  45. package/dist/src/channel/payload.spec.d.ts +2 -0
  46. package/dist/src/channel/payload.spec.d.ts.map +1 -0
  47. package/dist/src/channel/retriever.d.ts +4 -6
  48. package/dist/src/channel/retriever.d.ts.map +1 -1
  49. package/dist/src/channel/writer.d.ts.map +1 -1
  50. package/dist/src/client.d.ts +18 -10
  51. package/dist/src/client.d.ts.map +1 -1
  52. package/dist/src/connection/checker.d.ts +2 -3
  53. package/dist/src/connection/checker.d.ts.map +1 -1
  54. package/dist/src/connection.spec.d.ts +2 -0
  55. package/dist/src/connection.spec.d.ts.map +1 -0
  56. package/dist/src/device/access.spec.d.ts +2 -0
  57. package/dist/src/device/access.spec.d.ts.map +1 -0
  58. package/dist/src/{hardware/device → device}/client.d.ts +14 -7
  59. package/dist/src/device/client.d.ts.map +1 -0
  60. package/dist/src/device/device.spec.d.ts.map +1 -0
  61. package/dist/src/device/external.d.ts.map +1 -0
  62. package/dist/src/device/index.d.ts.map +1 -0
  63. package/dist/src/{hardware/device → device}/payload.d.ts +1 -1
  64. package/dist/src/device/payload.d.ts.map +1 -0
  65. package/dist/src/errors.d.ts +3 -0
  66. package/dist/src/errors.d.ts.map +1 -1
  67. package/dist/src/framer/adapter.d.ts +2 -2
  68. package/dist/src/framer/adapter.d.ts.map +1 -1
  69. package/dist/src/framer/client.d.ts +8 -1
  70. package/dist/src/framer/client.d.ts.map +1 -1
  71. package/dist/src/framer/frame.d.ts +11 -5
  72. package/dist/src/framer/frame.d.ts.map +1 -1
  73. package/dist/src/framer/iterator.d.ts +3 -3
  74. package/dist/src/framer/streamer.d.ts +24 -21
  75. package/dist/src/framer/streamer.d.ts.map +1 -1
  76. package/dist/src/framer/writer.d.ts +13 -13
  77. package/dist/src/index.d.ts +6 -7
  78. package/dist/src/index.d.ts.map +1 -1
  79. package/dist/src/label/access.spec.d.ts +2 -0
  80. package/dist/src/label/access.spec.d.ts.map +1 -0
  81. package/dist/src/label/client.d.ts +20 -11
  82. package/dist/src/label/client.d.ts.map +1 -1
  83. package/dist/src/ontology/client.d.ts +6 -6
  84. package/dist/src/ontology/client.d.ts.map +1 -1
  85. package/dist/src/ontology/group/access.spec.d.ts +2 -0
  86. package/dist/src/ontology/group/access.spec.d.ts.map +1 -0
  87. package/dist/src/ontology/group/client.d.ts +2 -2
  88. package/dist/src/ontology/group/client.d.ts.map +1 -1
  89. package/dist/src/ontology/group/payload.d.ts +1 -2
  90. package/dist/src/ontology/group/payload.d.ts.map +1 -1
  91. package/dist/src/ontology/payload.d.ts +23 -17
  92. package/dist/src/ontology/payload.d.ts.map +1 -1
  93. package/dist/src/ontology/writer.d.ts +10 -10
  94. package/dist/src/ontology/writer.d.ts.map +1 -1
  95. package/dist/src/rack/access.spec.d.ts +2 -0
  96. package/dist/src/rack/access.spec.d.ts.map +1 -0
  97. package/dist/src/{hardware/rack → rack}/client.d.ts +15 -8
  98. package/dist/src/rack/client.d.ts.map +1 -0
  99. package/dist/src/rack/external.d.ts.map +1 -0
  100. package/dist/src/rack/index.d.ts.map +1 -0
  101. package/dist/src/{hardware/rack → rack}/payload.d.ts +1 -1
  102. package/dist/src/rack/payload.d.ts.map +1 -0
  103. package/dist/src/rack/rack.spec.d.ts.map +1 -0
  104. package/dist/src/ranger/access.spec.d.ts +2 -0
  105. package/dist/src/ranger/access.spec.d.ts.map +1 -0
  106. package/dist/src/ranger/alias.d.ts +1 -8
  107. package/dist/src/ranger/alias.d.ts.map +1 -1
  108. package/dist/src/ranger/client.d.ts +12 -5
  109. package/dist/src/ranger/client.d.ts.map +1 -1
  110. package/dist/src/ranger/kv.d.ts +0 -3
  111. package/dist/src/ranger/kv.d.ts.map +1 -1
  112. package/dist/src/ranger/writer.d.ts +2 -2
  113. package/dist/src/ranger/writer.d.ts.map +1 -1
  114. package/dist/src/status/access.spec.d.ts +2 -0
  115. package/dist/src/status/access.spec.d.ts.map +1 -0
  116. package/dist/src/status/client.d.ts +4 -4
  117. package/dist/src/status/client.d.ts.map +1 -1
  118. package/dist/src/status/payload.d.ts +9 -2
  119. package/dist/src/status/payload.d.ts.map +1 -1
  120. package/dist/src/task/access.spec.d.ts +2 -0
  121. package/dist/src/task/access.spec.d.ts.map +1 -0
  122. package/dist/src/{hardware/task → task}/client.d.ts +26 -15
  123. package/dist/src/task/client.d.ts.map +1 -0
  124. package/dist/src/task/external.d.ts +3 -0
  125. package/dist/src/task/external.d.ts.map +1 -0
  126. package/dist/src/task/index.d.ts.map +1 -0
  127. package/dist/src/{hardware/task → task}/payload.d.ts +45 -6
  128. package/dist/src/task/payload.d.ts.map +1 -0
  129. package/dist/src/task/task.spec.d.ts.map +1 -0
  130. package/dist/src/testutil/access.d.ts +4 -0
  131. package/dist/src/testutil/access.d.ts.map +1 -0
  132. package/dist/src/testutil/client.d.ts +3 -3
  133. package/dist/src/testutil/client.d.ts.map +1 -1
  134. package/dist/src/transport.d.ts.map +1 -1
  135. package/dist/src/user/access.spec.d.ts +2 -0
  136. package/dist/src/user/access.spec.d.ts.map +1 -0
  137. package/dist/src/user/client.d.ts +10 -1
  138. package/dist/src/user/client.d.ts.map +1 -1
  139. package/dist/src/user/external.d.ts +1 -1
  140. package/dist/src/user/external.d.ts.map +1 -1
  141. package/dist/src/user/payload.d.ts.map +1 -1
  142. package/dist/src/workspace/access.spec.d.ts +2 -0
  143. package/dist/src/workspace/access.spec.d.ts.map +1 -0
  144. package/dist/src/workspace/client.d.ts +10 -5
  145. package/dist/src/workspace/client.d.ts.map +1 -1
  146. package/dist/src/workspace/lineplot/access.spec.d.ts +2 -0
  147. package/dist/src/workspace/lineplot/access.spec.d.ts.map +1 -0
  148. package/dist/src/workspace/lineplot/client.d.ts +8 -1
  149. package/dist/src/workspace/lineplot/client.d.ts.map +1 -1
  150. package/dist/src/workspace/log/access.spec.d.ts +2 -0
  151. package/dist/src/workspace/log/access.spec.d.ts.map +1 -0
  152. package/dist/src/workspace/log/client.d.ts +8 -1
  153. package/dist/src/workspace/log/client.d.ts.map +1 -1
  154. package/dist/src/workspace/schematic/access.spec.d.ts +2 -0
  155. package/dist/src/workspace/schematic/access.spec.d.ts.map +1 -0
  156. package/dist/src/workspace/schematic/client.d.ts +8 -1
  157. package/dist/src/workspace/schematic/client.d.ts.map +1 -1
  158. package/dist/src/workspace/schematic/symbol/access.spec.d.ts +2 -0
  159. package/dist/src/workspace/schematic/symbol/access.spec.d.ts.map +1 -0
  160. package/dist/src/workspace/schematic/symbol/client.d.ts +1 -5
  161. package/dist/src/workspace/schematic/symbol/client.d.ts.map +1 -1
  162. package/dist/src/workspace/schematic/symbol/payload.d.ts +2 -2
  163. package/dist/src/workspace/table/access.spec.d.ts +2 -0
  164. package/dist/src/workspace/table/access.spec.d.ts.map +1 -0
  165. package/dist/src/workspace/table/client.d.ts +8 -1
  166. package/dist/src/workspace/table/client.d.ts.map +1 -1
  167. package/eslint.config.ts +3 -1
  168. package/package.json +8 -8
  169. package/src/access/client.ts +5 -2
  170. package/src/access/enforce.spec.ts +189 -0
  171. package/src/access/enforce.ts +84 -0
  172. package/src/access/external.ts +3 -0
  173. package/src/access/payload.ts +1 -13
  174. package/src/access/policy/access.spec.ts +147 -0
  175. package/src/access/policy/client.ts +21 -25
  176. package/src/access/policy/payload.ts +9 -5
  177. package/src/access/role/client.ts +135 -0
  178. package/src/access/role/external.ts +11 -0
  179. package/src/{hardware → access/role}/index.ts +1 -1
  180. package/src/access/role/payload.ts +32 -0
  181. package/src/access/role/role.spec.ts +95 -0
  182. package/src/arc/access.spec.ts +143 -0
  183. package/src/arc/client.ts +7 -31
  184. package/src/arc/payload.ts +4 -0
  185. package/src/auth/auth.spec.ts +13 -13
  186. package/src/auth/auth.ts +33 -11
  187. package/src/channel/access.spec.ts +116 -0
  188. package/src/channel/channel.spec.ts +63 -73
  189. package/src/channel/client.ts +2 -8
  190. package/src/channel/payload.spec.ts +171 -0
  191. package/src/channel/payload.ts +37 -8
  192. package/src/channel/retriever.ts +10 -11
  193. package/src/channel/writer.ts +3 -7
  194. package/src/client.ts +38 -28
  195. package/src/connection/checker.ts +10 -10
  196. package/src/connection/connection.spec.ts +13 -13
  197. package/src/connection.spec.ts +145 -0
  198. package/src/device/access.spec.ts +159 -0
  199. package/src/{hardware/device → device}/client.ts +12 -21
  200. package/src/{hardware/device → device}/device.spec.ts +70 -34
  201. package/src/device/external.ts +11 -0
  202. package/src/{hardware/rack → device}/index.ts +1 -1
  203. package/src/{hardware/device → device}/payload.ts +3 -3
  204. package/src/errors.ts +2 -0
  205. package/src/framer/adapter.spec.ts +351 -13
  206. package/src/framer/adapter.ts +23 -13
  207. package/src/framer/client.spec.ts +14 -20
  208. package/src/framer/client.ts +3 -5
  209. package/src/framer/deleter.spec.ts +1 -1
  210. package/src/framer/frame.spec.ts +427 -0
  211. package/src/framer/frame.ts +30 -3
  212. package/src/framer/iterator.ts +4 -4
  213. package/src/framer/streamer.spec.ts +155 -10
  214. package/src/framer/streamer.ts +35 -12
  215. package/src/framer/writer.spec.ts +5 -5
  216. package/src/index.ts +13 -7
  217. package/src/label/access.spec.ts +109 -0
  218. package/src/label/client.ts +10 -14
  219. package/src/ontology/client.ts +4 -6
  220. package/src/ontology/group/access.spec.ts +77 -0
  221. package/src/ontology/group/client.ts +3 -7
  222. package/src/ontology/group/group.spec.ts +18 -0
  223. package/src/ontology/group/payload.ts +2 -2
  224. package/src/ontology/ontology.spec.ts +2 -0
  225. package/src/ontology/payload.ts +18 -2
  226. package/src/ontology/writer.ts +3 -7
  227. package/src/rack/access.spec.ts +102 -0
  228. package/src/{hardware/rack → rack}/client.ts +14 -19
  229. package/src/{hardware/device/index.ts → rack/external.ts} +2 -1
  230. package/src/{hardware/external.ts → rack/index.ts} +1 -1
  231. package/src/{hardware/rack → rack}/payload.ts +2 -2
  232. package/src/{hardware/rack → rack}/rack.spec.ts +43 -17
  233. package/src/ranger/access.spec.ts +115 -0
  234. package/src/ranger/alias.ts +6 -14
  235. package/src/ranger/client.ts +13 -14
  236. package/src/ranger/kv.ts +7 -9
  237. package/src/ranger/ranger.spec.ts +4 -4
  238. package/src/ranger/writer.ts +3 -7
  239. package/src/status/access.spec.ts +129 -0
  240. package/src/status/client.ts +5 -9
  241. package/src/status/payload.ts +3 -2
  242. package/src/task/access.spec.ts +131 -0
  243. package/src/{hardware/task → task}/client.ts +50 -25
  244. package/src/task/external.ts +11 -0
  245. package/src/{hardware/task → task}/index.ts +1 -1
  246. package/src/{hardware/task → task}/payload.ts +22 -3
  247. package/src/{hardware/task → task}/task.spec.ts +197 -34
  248. package/src/testutil/access.ts +34 -0
  249. package/src/testutil/channels.ts +3 -3
  250. package/src/testutil/client.ts +4 -4
  251. package/src/transport.ts +1 -3
  252. package/src/user/access.spec.ts +107 -0
  253. package/src/user/client.ts +10 -12
  254. package/src/user/external.ts +12 -1
  255. package/src/user/payload.ts +3 -5
  256. package/src/workspace/access.spec.ts +108 -0
  257. package/src/workspace/client.ts +11 -27
  258. package/src/workspace/lineplot/access.spec.ts +134 -0
  259. package/src/workspace/lineplot/client.ts +8 -13
  260. package/src/workspace/log/access.spec.ts +134 -0
  261. package/src/workspace/log/client.ts +8 -13
  262. package/src/workspace/schematic/access.spec.ts +134 -0
  263. package/src/workspace/schematic/client.ts +9 -18
  264. package/src/workspace/schematic/symbol/access.spec.ts +172 -0
  265. package/src/workspace/schematic/symbol/client.ts +6 -17
  266. package/src/workspace/schematic/symbol/payload.ts +1 -1
  267. package/src/workspace/table/access.spec.ts +134 -0
  268. package/src/workspace/table/client.ts +8 -13
  269. package/dist/src/access/policy/policy.spec.d.ts +0 -2
  270. package/dist/src/access/policy/policy.spec.d.ts.map +0 -1
  271. package/dist/src/hardware/client.d.ts +0 -10
  272. package/dist/src/hardware/client.d.ts.map +0 -1
  273. package/dist/src/hardware/device/client.d.ts.map +0 -1
  274. package/dist/src/hardware/device/device.spec.d.ts.map +0 -1
  275. package/dist/src/hardware/device/external.d.ts.map +0 -1
  276. package/dist/src/hardware/device/index.d.ts.map +0 -1
  277. package/dist/src/hardware/device/payload.d.ts.map +0 -1
  278. package/dist/src/hardware/external.d.ts +0 -2
  279. package/dist/src/hardware/external.d.ts.map +0 -1
  280. package/dist/src/hardware/index.d.ts +0 -2
  281. package/dist/src/hardware/index.d.ts.map +0 -1
  282. package/dist/src/hardware/rack/client.d.ts.map +0 -1
  283. package/dist/src/hardware/rack/external.d.ts.map +0 -1
  284. package/dist/src/hardware/rack/index.d.ts.map +0 -1
  285. package/dist/src/hardware/rack/payload.d.ts.map +0 -1
  286. package/dist/src/hardware/rack/rack.spec.d.ts.map +0 -1
  287. package/dist/src/hardware/task/client.d.ts.map +0 -1
  288. package/dist/src/hardware/task/external.d.ts.map +0 -1
  289. package/dist/src/hardware/task/index.d.ts.map +0 -1
  290. package/dist/src/hardware/task/payload.d.ts.map +0 -1
  291. package/dist/src/hardware/task/task.spec.d.ts.map +0 -1
  292. package/dist/src/user/retriever.d.ts +0 -16
  293. package/dist/src/user/retriever.d.ts.map +0 -1
  294. package/dist/src/user/writer.d.ts +0 -11
  295. package/dist/src/user/writer.d.ts.map +0 -1
  296. package/src/access/policy/policy.spec.ts +0 -329
  297. package/src/hardware/client.ts +0 -24
  298. package/src/hardware/device/external.ts +0 -11
  299. package/src/hardware/rack/external.ts +0 -11
  300. package/src/hardware/task/external.ts +0 -11
  301. package/src/user/retriever.ts +0 -41
  302. package/src/user/writer.ts +0 -84
  303. /package/dist/src/{hardware/device → access/role}/external.d.ts +0 -0
  304. /package/dist/src/{hardware/device → device}/device.spec.d.ts +0 -0
  305. /package/dist/src/{hardware/rack → device}/external.d.ts +0 -0
  306. /package/dist/src/{hardware/device → device}/index.d.ts +0 -0
  307. /package/dist/src/{hardware/task → rack}/external.d.ts +0 -0
  308. /package/dist/src/{hardware/rack → rack}/index.d.ts +0 -0
  309. /package/dist/src/{hardware/rack → rack}/rack.spec.d.ts +0 -0
  310. /package/dist/src/{hardware/task → task}/index.d.ts +0 -0
  311. /package/dist/src/{hardware/task → task}/task.spec.d.ts +0 -0
@@ -0,0 +1,131 @@
1
+ // Copyright 2025 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 { describe, expect, it } from "vitest";
11
+
12
+ import { AuthError, NotFoundError } from "@/errors";
13
+ import { rack } from "@/rack";
14
+ import { task } from "@/task";
15
+ import { createTestClientWithPolicy } from "@/testutil/access";
16
+ import { createTestClient } from "@/testutil/client";
17
+
18
+ const client = createTestClient();
19
+
20
+ describe("task", () => {
21
+ describe("access control", () => {
22
+ it("should deny access when no retrieve policy exists", async () => {
23
+ const userClient = await createTestClientWithPolicy(client, {
24
+ name: "test",
25
+ objects: [],
26
+ actions: [],
27
+ });
28
+ const rack = await client.racks.create({
29
+ name: "test",
30
+ });
31
+ const randomTask = await rack.createTask({
32
+ name: "test",
33
+ type: "ni",
34
+ config: {},
35
+ });
36
+ await expect(userClient.tasks.retrieve({ key: randomTask.key })).rejects.toThrow(
37
+ AuthError,
38
+ );
39
+ });
40
+
41
+ it("should allow the caller to retrieve tasks with the correct policy", async () => {
42
+ const userClient = await createTestClientWithPolicy(client, {
43
+ name: "test",
44
+ objects: [task.ontologyID("")],
45
+ actions: ["retrieve"],
46
+ });
47
+ const rack = await client.racks.create({
48
+ name: "test",
49
+ });
50
+ const randomTask = await rack.createTask({
51
+ name: "test",
52
+ type: "ni",
53
+ config: {},
54
+ });
55
+ const retrieved = await userClient.tasks.retrieve({
56
+ key: randomTask.key,
57
+ });
58
+ expect(retrieved.key).toBe(randomTask.key);
59
+ expect(retrieved.name).toBe(randomTask.name);
60
+ });
61
+
62
+ it("should allow the caller to create tasks with the correct policy", async () => {
63
+ const userClient = await createTestClientWithPolicy(client, {
64
+ name: "test",
65
+ objects: [task.ontologyID(""), rack.ontologyID(0)],
66
+ actions: ["create", "retrieve"],
67
+ });
68
+ const rck = await client.racks.create({
69
+ name: "test",
70
+ });
71
+ const userRack = await userClient.racks.retrieve({ key: rck.key });
72
+ await userRack.createTask({
73
+ name: "test",
74
+ type: "ni",
75
+ config: {},
76
+ });
77
+ });
78
+
79
+ it("should deny access when no create policy exists", async () => {
80
+ const userClient = await createTestClientWithPolicy(client, {
81
+ name: "test",
82
+ objects: [task.ontologyID("")],
83
+ actions: [],
84
+ });
85
+ await expect(
86
+ userClient.tasks.create({
87
+ name: "test",
88
+ type: "ni",
89
+ config: {},
90
+ }),
91
+ ).rejects.toThrow(AuthError);
92
+ });
93
+
94
+ it("should allow the caller to delete tasks with the correct policy", async () => {
95
+ const userClient = await createTestClientWithPolicy(client, {
96
+ name: "test",
97
+ objects: [task.ontologyID("")],
98
+ actions: ["delete", "retrieve"],
99
+ });
100
+ const rack = await client.racks.create({
101
+ name: "test",
102
+ });
103
+ const randomTask = await rack.createTask({
104
+ name: "test",
105
+ type: "ni",
106
+ config: {},
107
+ });
108
+ await userClient.tasks.delete(randomTask.key);
109
+ await expect(userClient.tasks.retrieve({ key: randomTask.key })).rejects.toThrow(
110
+ NotFoundError,
111
+ );
112
+ });
113
+
114
+ it("should deny access when no delete policy exists", async () => {
115
+ const userClient = await createTestClientWithPolicy(client, {
116
+ name: "test",
117
+ objects: [task.ontologyID("")],
118
+ actions: [],
119
+ });
120
+ const rack = await client.racks.create({
121
+ name: "test",
122
+ });
123
+ const randomTask = await rack.createTask({
124
+ name: "test",
125
+ type: "ni",
126
+ config: {},
127
+ });
128
+ await expect(userClient.tasks.delete(randomTask.key)).rejects.toThrow(AuthError);
129
+ });
130
+ });
131
+ });
@@ -20,7 +20,10 @@ import {
20
20
  import { z } from "zod";
21
21
 
22
22
  import { type framer } from "@/framer";
23
- import { keyZ as rackKeyZ } from "@/hardware/rack/payload";
23
+ import { ontology } from "@/ontology";
24
+ import { keyZ as rackKeyZ } from "@/rack/payload";
25
+ import { type ranger } from "@/ranger";
26
+ import { status } from "@/status";
24
27
  import {
25
28
  type Key,
26
29
  keyZ,
@@ -31,12 +34,9 @@ import {
31
34
  type Status,
32
35
  statusZ,
33
36
  taskZ,
34
- } from "@/hardware/task/payload";
35
- import { type ontology } from "@/ontology";
36
- import { type ranger } from "@/ranger";
37
+ } from "@/task/payload";
37
38
  import { checkForMultipleOrNoResults } from "@/util/retrieve";
38
39
 
39
- export const STATUS_CHANNEL_NAME = "sy_task_status";
40
40
  export const COMMAND_CHANNEL_NAME = "sy_task_cmd";
41
41
  export const SET_CHANNEL_NAME = "sy_task_set";
42
42
  export const DELETE_CHANNEL_NAME = "sy_task_delete";
@@ -172,6 +172,23 @@ export class Task<
172
172
  });
173
173
  }
174
174
 
175
+ async start(): Promise<void> {
176
+ await this.executeCommand({ type: "start" });
177
+ }
178
+
179
+ async stop(): Promise<void> {
180
+ await this.executeCommand({ type: "stop" });
181
+ }
182
+
183
+ async run<T>(fn: () => Promise<T>): Promise<T> {
184
+ await this.start();
185
+ try {
186
+ return await fn();
187
+ } finally {
188
+ await this.stop();
189
+ }
190
+ }
191
+
175
192
  async snapshottedTo(): Promise<ontology.Resource | null> {
176
193
  if (this.ontologyClient == null || this.rangeClient == null)
177
194
  throw NOT_CREATED_ERROR;
@@ -189,8 +206,8 @@ const retrieveReqZ = z.object({
189
206
  internal: z.boolean().optional(),
190
207
  snapshot: z.boolean().optional(),
191
208
  searchTerm: z.string().optional(),
192
- offset: z.number().optional(),
193
- limit: z.number().optional(),
209
+ offset: z.int().optional(),
210
+ limit: z.int().optional(),
194
211
  });
195
212
 
196
213
  const singleRetrieveArgsZ = z.union([
@@ -236,11 +253,6 @@ const retrieveResZ = <
236
253
 
237
254
  export interface RetrieveRequest extends z.infer<typeof retrieveReqZ> {}
238
255
 
239
- const RETRIEVE_ENDPOINT = "/hardware/task/retrieve";
240
- const CREATE_ENDPOINT = "/hardware/task/create";
241
- const DELETE_ENDPOINT = "/hardware/task/delete";
242
- const COPY_ENDPOINT = "/hardware/task/copy";
243
-
244
256
  const createReqZ = <
245
257
  Type extends z.ZodLiteral<string> = z.ZodLiteral<string>,
246
258
  Config extends z.ZodType = z.ZodType,
@@ -294,7 +306,7 @@ export class Client {
294
306
  Config extends z.ZodType = z.ZodType,
295
307
  StatusData extends z.ZodType = z.ZodType,
296
308
  >(
297
- task: New<Type, Config>,
309
+ task: New<Type, Config, StatusData>,
298
310
  schemas: Schemas<Type, Config, StatusData>,
299
311
  ): Promise<Task<Type, Config, StatusData>>;
300
312
  async create<
@@ -302,7 +314,7 @@ export class Client {
302
314
  Config extends z.ZodType = z.ZodType,
303
315
  StatusData extends z.ZodType = z.ZodType,
304
316
  >(
305
- tasks: New<Type, Config>[],
317
+ tasks: New<Type, Config, StatusData>[],
306
318
  schemas: Schemas<Type, Config, StatusData>,
307
319
  ): Promise<Task<Type, Config, StatusData>[]>;
308
320
 
@@ -311,7 +323,7 @@ export class Client {
311
323
  Config extends z.ZodType = z.ZodType,
312
324
  StatusData extends z.ZodType = z.ZodType,
313
325
  >(
314
- task: New<Type, Config> | Array<New<Type, Config>>,
326
+ task: New<Type, Config, StatusData> | Array<New<Type, Config, StatusData>>,
315
327
  schemas?: Schemas<Type, Config, StatusData>,
316
328
  ): Promise<Task<Type, Config, StatusData> | Array<Task<Type, Config, StatusData>>> {
317
329
  const isSingle = !Array.isArray(task);
@@ -319,7 +331,7 @@ export class Client {
319
331
  const createRes = createResZ(schemas);
320
332
  const res = await sendRequired(
321
333
  this.client,
322
- CREATE_ENDPOINT,
334
+ "/task/create",
323
335
  { tasks: array.toArray(task) } as z.infer<typeof createReq>,
324
336
  createReq,
325
337
  createRes,
@@ -334,7 +346,7 @@ export class Client {
334
346
  async delete(keys: Key | Key[]): Promise<void> {
335
347
  await sendRequired<typeof deleteReqZ, typeof deleteResZ>(
336
348
  this.client,
337
- DELETE_ENDPOINT,
349
+ "/task/delete",
338
350
  { keys: array.toArray(keys) },
339
351
  deleteReqZ,
340
352
  deleteResZ,
@@ -370,7 +382,7 @@ export class Client {
370
382
  const isSingle = singleRetrieveArgsZ.safeParse(args).success;
371
383
  const res = await sendRequired(
372
384
  this.client,
373
- RETRIEVE_ENDPOINT,
385
+ "/task/retrieve",
374
386
  args,
375
387
  retrieveArgsZ,
376
388
  retrieveResZ(schemas),
@@ -385,7 +397,7 @@ export class Client {
385
397
  const copyRes = copyResZ();
386
398
  const response = await sendRequired(
387
399
  this.client,
388
- COPY_ENDPOINT,
400
+ "/task/copy",
389
401
  { key, name, snapshot },
390
402
  copyReqZ,
391
403
  copyRes,
@@ -393,6 +405,12 @@ export class Client {
393
405
  return this.sugar(response.task as Payload);
394
406
  }
395
407
 
408
+ async list(rack?: number): Promise<Task[]> {
409
+ const params: RetrieveMultipleParams = { internal: false };
410
+ if (rack !== undefined) params.rack = rack;
411
+ return await this.retrieve(params);
412
+ }
413
+
396
414
  async retrieveSnapshottedTo(taskKey: Key): Promise<ontology.Resource | null> {
397
415
  if (this.ontologyClient == null) throw NOT_CREATED_ERROR;
398
416
  return await retrieveSnapshottedTo(taskKey, this.ontologyClient);
@@ -459,11 +477,11 @@ export class Client {
459
477
  }
460
478
 
461
479
  async executeCommandSync<StatusData extends z.ZodType = z.ZodType>(
462
- parms: ExecuteCommandsSyncParams<StatusData>,
480
+ params: ExecuteCommandsSyncParams<StatusData>,
463
481
  ): Promise<Status<StatusData>[]>;
464
482
 
465
483
  async executeCommandSync<StatusData extends z.ZodType = z.ZodType>(
466
- parms: ExecuteCommandSyncParams<StatusData>,
484
+ params: ExecuteCommandSyncParams<StatusData>,
467
485
  ): Promise<Status<StatusData>>;
468
486
 
469
487
  async executeCommandSync<StatusData extends z.ZodType = z.ZodType>(
@@ -496,7 +514,10 @@ export class Client {
496
514
  }
497
515
  }
498
516
 
499
- export const ontologyID = (key: Key): ontology.ID => ({ type: "task", key });
517
+ export const ontologyID = ontology.createIDFactory<Key>("task");
518
+ export const TYPE_ONTOLOGY_ID = ontologyID("");
519
+
520
+ export const statusKey = (key: Key): string => ontology.idToString(ontologyID(key));
500
521
 
501
522
  interface ExecuteCommandInternalParams {
502
523
  frameClient: framer.Client | null;
@@ -577,7 +598,7 @@ const executeCommandsSync = async <StatusData extends z.ZodType = z.ZodType>({
577
598
  name: taskName,
578
599
  }: ExecuteCommandsSyncInternalParams<StatusData>): Promise<Status<StatusData>[]> => {
579
600
  if (frameClient == null) throw NOT_CREATED_ERROR;
580
- const streamer = await frameClient.openStreamer(STATUS_CHANNEL_NAME);
601
+ const streamer = await frameClient.openStreamer(status.SET_CHANNEL_NAME);
581
602
  const cmdKeys = await executeCommands({ frameClient, commands });
582
603
  const parsedTimeout = new TimeSpan(timeout);
583
604
  let states: Status<StatusData>[] = [];
@@ -593,8 +614,12 @@ const executeCommandsSync = async <StatusData extends z.ZodType = z.ZodType>({
593
614
  try {
594
615
  while (true) {
595
616
  const frame = await Promise.race([streamer.read(), timeoutPromise]);
596
- const state = statusZ(statusDataZ).parse(frame.at(-1)[STATUS_CHANNEL_NAME]);
597
- if (!cmdKeys.includes(state.key)) continue;
617
+ const parseResult = statusZ(statusDataZ).safeParse(
618
+ frame.at(-1)[status.SET_CHANNEL_NAME],
619
+ );
620
+ if (!parseResult.success) continue;
621
+ const state = parseResult.data;
622
+ if (state.details.cmd == null || !cmdKeys.includes(state.details.cmd)) continue;
598
623
  states = [...states.filter((s) => s.key !== state.key), state];
599
624
  if (states.length === cmdKeys.length) return states;
600
625
  }
@@ -0,0 +1,11 @@
1
+ // Copyright 2025 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 "@/task/client";
11
+ export * from "@/task/payload";
@@ -7,4 +7,4 @@
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 * as task from "@/hardware/task/external";
10
+ export * as task from "@/task/external";
@@ -10,7 +10,7 @@
10
10
  import { binary, type observe, record, status } from "@synnaxlabs/x";
11
11
  import { z } from "zod";
12
12
 
13
- import { type Key as RackKey } from "@/hardware/rack/payload";
13
+ import { type Key as RackKey } from "@/rack/payload";
14
14
  import { decodeJSONString } from "@/util/decodeJSONString";
15
15
  import { parseWithoutKeyConversion } from "@/util/parseWithoutKeyConversion";
16
16
 
@@ -22,7 +22,12 @@ export const keyZ = z.union([
22
22
  export type Key = z.infer<typeof keyZ>;
23
23
 
24
24
  export const statusDetailsZ = <DataSchema extends z.ZodType>(data: DataSchema) =>
25
- z.object({ task: keyZ, running: z.boolean(), data });
25
+ z.object({
26
+ task: keyZ,
27
+ running: z.boolean(),
28
+ data,
29
+ cmd: z.string().optional(),
30
+ });
26
31
 
27
32
  export type StatusDetails<DataSchema extends z.ZodType> = z.infer<
28
33
  ReturnType<typeof statusDetailsZ<DataSchema>>
@@ -35,6 +40,15 @@ export type Status<StatusData extends z.ZodType = z.ZodUnknown> = z.infer<
35
40
  ReturnType<typeof statusZ<StatusData>>
36
41
  >;
37
42
 
43
+ const newStatusDetailsZ = <DataSchema extends z.ZodType>(data: DataSchema) =>
44
+ statusDetailsZ(data).partial({ task: true });
45
+
46
+ export const newStatusZ = <DataSchema extends z.ZodType>(data: DataSchema) =>
47
+ status.statusZ(newStatusDetailsZ(data)).partial({ key: true, name: true });
48
+
49
+ export interface NewStatus<DataSchema extends z.ZodType = z.ZodUnknown>
50
+ extends z.infer<ReturnType<typeof newStatusZ<DataSchema>>> {}
51
+
38
52
  export const taskZ = <
39
53
  Type extends z.ZodLiteral<string> = z.ZodLiteral<string>,
40
54
  Config extends z.ZodType = z.ZodType,
@@ -88,20 +102,25 @@ export const newZ = <
88
102
  schemas?: Schemas<Type, Config, StatusData>,
89
103
  ) =>
90
104
  taskZ(schemas)
91
- .omit({ key: true })
105
+ .omit({ key: true, status: true })
92
106
  .extend({
93
107
  key: keyZ.transform((k) => k.toString()).optional(),
94
108
  config: z.unknown().transform((c) => binary.JSON_CODEC.encodeString(c)),
109
+ status: newStatusZ(schemas?.statusDataSchema ?? z.unknown())
110
+ .optional()
111
+ .nullable(),
95
112
  });
96
113
 
97
114
  export type New<
98
115
  Type extends z.ZodLiteral<string> = z.ZodLiteral<string>,
99
116
  Config extends z.ZodType = z.ZodType,
117
+ StatusData extends z.ZodType = z.ZodUnknown,
100
118
  > = {
101
119
  key?: Key;
102
120
  name: string;
103
121
  type: z.infer<Type>;
104
122
  config: z.infer<Config>;
123
+ status?: NewStatus<StatusData>;
105
124
  };
106
125
 
107
126
  export const commandZ = z.object({