@synnaxlabs/client 0.43.0 → 0.44.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/.turbo/turbo-build.log +7 -7
  2. package/dist/access/payload.d.ts +1 -1
  3. package/dist/access/payload.d.ts.map +1 -1
  4. package/dist/access/policy/client.d.ts +263 -6
  5. package/dist/access/policy/client.d.ts.map +1 -1
  6. package/dist/access/policy/external.d.ts +0 -1
  7. package/dist/access/policy/external.d.ts.map +1 -1
  8. package/dist/access/policy/payload.d.ts +105 -93
  9. package/dist/access/policy/payload.d.ts.map +1 -1
  10. package/dist/auth/auth.d.ts +1 -1
  11. package/dist/auth/auth.d.ts.map +1 -1
  12. package/dist/channel/client.d.ts +12 -13
  13. package/dist/channel/client.d.ts.map +1 -1
  14. package/dist/channel/payload.d.ts +77 -19
  15. package/dist/channel/payload.d.ts.map +1 -1
  16. package/dist/channel/retriever.d.ts +9 -16
  17. package/dist/channel/retriever.d.ts.map +1 -1
  18. package/dist/channel/writer.d.ts +1 -1
  19. package/dist/channel/writer.d.ts.map +1 -1
  20. package/dist/client.cjs +27 -135
  21. package/dist/client.d.ts +3 -3
  22. package/dist/client.d.ts.map +1 -1
  23. package/dist/client.js +8619 -28938
  24. package/dist/connection/checker.d.ts +1 -1
  25. package/dist/connection/checker.d.ts.map +1 -1
  26. package/dist/control/client.d.ts +1 -0
  27. package/dist/control/client.d.ts.map +1 -1
  28. package/dist/control/state.d.ts +6 -6
  29. package/dist/control/state.d.ts.map +1 -1
  30. package/dist/errors.d.ts +18 -5
  31. package/dist/errors.d.ts.map +1 -1
  32. package/dist/framer/adapter.d.ts +3 -3
  33. package/dist/framer/adapter.d.ts.map +1 -1
  34. package/dist/framer/client.d.ts +4 -13
  35. package/dist/framer/client.d.ts.map +1 -1
  36. package/dist/framer/codec.d.ts +1 -1
  37. package/dist/framer/codec.d.ts.map +1 -1
  38. package/dist/framer/deleter.d.ts +5 -5
  39. package/dist/framer/deleter.d.ts.map +1 -1
  40. package/dist/framer/frame.d.ts +5 -7
  41. package/dist/framer/frame.d.ts.map +1 -1
  42. package/dist/framer/streamProxy.d.ts +1 -1
  43. package/dist/framer/streamProxy.d.ts.map +1 -1
  44. package/dist/framer/streamer.d.ts +139 -20
  45. package/dist/framer/streamer.d.ts.map +1 -1
  46. package/dist/framer/writer.d.ts +222 -33
  47. package/dist/framer/writer.d.ts.map +1 -1
  48. package/dist/hardware/device/client.d.ts +49 -28
  49. package/dist/hardware/device/client.d.ts.map +1 -1
  50. package/dist/hardware/device/payload.d.ts +126 -46
  51. package/dist/hardware/device/payload.d.ts.map +1 -1
  52. package/dist/hardware/rack/client.d.ts +78 -22
  53. package/dist/hardware/rack/client.d.ts.map +1 -1
  54. package/dist/hardware/rack/payload.d.ts +99 -56
  55. package/dist/hardware/rack/payload.d.ts.map +1 -1
  56. package/dist/hardware/task/client.d.ts +100 -41
  57. package/dist/hardware/task/client.d.ts.map +1 -1
  58. package/dist/hardware/task/payload.d.ts +83 -61
  59. package/dist/hardware/task/payload.d.ts.map +1 -1
  60. package/dist/index.d.ts +2 -2
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/label/client.d.ts +138 -20
  63. package/dist/label/client.d.ts.map +1 -1
  64. package/dist/label/external.d.ts +0 -2
  65. package/dist/label/external.d.ts.map +1 -1
  66. package/dist/label/payload.d.ts +4 -5
  67. package/dist/label/payload.d.ts.map +1 -1
  68. package/dist/ontology/client.d.ts +45 -135
  69. package/dist/ontology/client.d.ts.map +1 -1
  70. package/dist/ontology/group/group.d.ts +3 -3
  71. package/dist/ontology/group/group.d.ts.map +1 -1
  72. package/dist/ontology/group/payload.d.ts +3 -27
  73. package/dist/ontology/group/payload.d.ts.map +1 -1
  74. package/dist/ontology/payload.d.ts +113 -243
  75. package/dist/ontology/payload.d.ts.map +1 -1
  76. package/dist/ontology/writer.d.ts +4 -4
  77. package/dist/ontology/writer.d.ts.map +1 -1
  78. package/dist/ranger/alias.d.ts +11 -5
  79. package/dist/ranger/alias.d.ts.map +1 -1
  80. package/dist/ranger/client.d.ts +87 -30
  81. package/dist/ranger/client.d.ts.map +1 -1
  82. package/dist/ranger/external.d.ts +1 -1
  83. package/dist/ranger/external.d.ts.map +1 -1
  84. package/dist/ranger/kv.d.ts +10 -12
  85. package/dist/ranger/kv.d.ts.map +1 -1
  86. package/dist/ranger/payload.d.ts +23 -44
  87. package/dist/ranger/payload.d.ts.map +1 -1
  88. package/dist/ranger/writer.d.ts +22 -19
  89. package/dist/ranger/writer.d.ts.map +1 -1
  90. package/dist/testutil/client.d.ts +4 -0
  91. package/dist/testutil/client.d.ts.map +1 -0
  92. package/dist/user/client.d.ts +59 -6
  93. package/dist/user/client.d.ts.map +1 -1
  94. package/dist/user/payload.d.ts +4 -6
  95. package/dist/user/payload.d.ts.map +1 -1
  96. package/dist/user/retriever.d.ts +2 -2
  97. package/dist/user/retriever.d.ts.map +1 -1
  98. package/dist/util/decodeJSONString.d.ts +2 -2
  99. package/dist/util/decodeJSONString.d.ts.map +1 -1
  100. package/dist/util/parseWithoutKeyConversion.d.ts +2 -2
  101. package/dist/util/parseWithoutKeyConversion.d.ts.map +1 -1
  102. package/dist/util/retrieve.d.ts +1 -1
  103. package/dist/util/retrieve.d.ts.map +1 -1
  104. package/dist/util/zod.d.ts +1 -1
  105. package/dist/util/zod.d.ts.map +1 -1
  106. package/dist/workspace/client.d.ts +17 -6
  107. package/dist/workspace/client.d.ts.map +1 -1
  108. package/dist/workspace/lineplot/client.d.ts +2 -2
  109. package/dist/workspace/lineplot/client.d.ts.map +1 -1
  110. package/dist/workspace/lineplot/payload.d.ts +8 -9
  111. package/dist/workspace/lineplot/payload.d.ts.map +1 -1
  112. package/dist/workspace/log/client.d.ts +2 -2
  113. package/dist/workspace/log/client.d.ts.map +1 -1
  114. package/dist/workspace/log/payload.d.ts +8 -9
  115. package/dist/workspace/log/payload.d.ts.map +1 -1
  116. package/dist/workspace/payload.d.ts +10 -11
  117. package/dist/workspace/payload.d.ts.map +1 -1
  118. package/dist/workspace/schematic/client.d.ts +2 -2
  119. package/dist/workspace/schematic/client.d.ts.map +1 -1
  120. package/dist/workspace/schematic/payload.d.ts +10 -11
  121. package/dist/workspace/schematic/payload.d.ts.map +1 -1
  122. package/dist/workspace/table/client.d.ts +2 -2
  123. package/dist/workspace/table/client.d.ts.map +1 -1
  124. package/dist/workspace/table/payload.d.ts +10 -11
  125. package/dist/workspace/table/payload.d.ts.map +1 -1
  126. package/examples/node/package-lock.json +47 -39
  127. package/examples/node/package.json +2 -1
  128. package/examples/node/streamWrite.js +5 -11
  129. package/package.json +14 -13
  130. package/src/access/payload.ts +1 -1
  131. package/src/access/policy/client.ts +87 -32
  132. package/src/access/policy/external.ts +0 -1
  133. package/src/access/policy/payload.ts +4 -4
  134. package/src/access/policy/policy.spec.ts +86 -83
  135. package/src/auth/auth.spec.ts +29 -18
  136. package/src/auth/auth.ts +1 -1
  137. package/src/channel/batchRetriever.spec.ts +4 -9
  138. package/src/channel/channel.spec.ts +24 -6
  139. package/src/channel/client.ts +31 -46
  140. package/src/channel/payload.ts +13 -14
  141. package/src/channel/retriever.ts +26 -41
  142. package/src/channel/writer.ts +3 -3
  143. package/src/client.ts +4 -4
  144. package/src/connection/checker.ts +1 -1
  145. package/src/connection/connection.spec.ts +31 -23
  146. package/src/control/client.ts +2 -2
  147. package/src/control/state.spec.ts +3 -3
  148. package/src/control/state.ts +1 -1
  149. package/src/errors.spec.ts +9 -5
  150. package/src/errors.ts +28 -15
  151. package/src/framer/adapter.spec.ts +118 -9
  152. package/src/framer/adapter.ts +24 -11
  153. package/src/framer/client.spec.ts +125 -2
  154. package/src/framer/client.ts +41 -47
  155. package/src/framer/codec.ts +1 -1
  156. package/src/framer/deleter.spec.ts +2 -2
  157. package/src/framer/deleter.ts +1 -1
  158. package/src/framer/frame.ts +1 -4
  159. package/src/framer/iterator.spec.ts +8 -8
  160. package/src/framer/iterator.ts +1 -1
  161. package/src/framer/streamProxy.ts +1 -1
  162. package/src/framer/streamer.spec.ts +185 -36
  163. package/src/framer/streamer.ts +28 -36
  164. package/src/framer/writer.spec.ts +6 -6
  165. package/src/framer/writer.ts +97 -111
  166. package/src/hardware/device/client.ts +45 -131
  167. package/src/hardware/device/device.spec.ts +163 -52
  168. package/src/hardware/device/payload.ts +10 -21
  169. package/src/hardware/rack/client.ts +87 -105
  170. package/src/hardware/rack/payload.ts +4 -13
  171. package/src/hardware/rack/rack.spec.ts +28 -35
  172. package/src/hardware/task/client.ts +335 -291
  173. package/src/hardware/task/payload.ts +86 -62
  174. package/src/hardware/task/task.spec.ts +208 -32
  175. package/src/index.ts +2 -1
  176. package/src/label/client.ts +100 -95
  177. package/src/label/external.ts +0 -2
  178. package/src/label/label.spec.ts +8 -6
  179. package/src/label/payload.ts +3 -4
  180. package/src/ontology/client.ts +41 -324
  181. package/src/ontology/group/group.spec.ts +2 -2
  182. package/src/ontology/group/group.ts +4 -5
  183. package/src/ontology/group/payload.ts +2 -25
  184. package/src/ontology/group/writer.ts +1 -1
  185. package/src/ontology/ontology.spec.ts +355 -41
  186. package/src/ontology/payload.ts +74 -112
  187. package/src/ontology/writer.ts +8 -17
  188. package/src/ranger/alias.ts +19 -37
  189. package/src/ranger/client.ts +118 -150
  190. package/src/ranger/external.ts +9 -1
  191. package/src/ranger/kv.ts +6 -27
  192. package/src/ranger/payload.ts +21 -37
  193. package/src/ranger/ranger.spec.ts +37 -56
  194. package/src/ranger/writer.ts +1 -1
  195. package/src/{signals/index.ts → testutil/client.ts} +11 -1
  196. package/src/user/client.ts +122 -47
  197. package/src/user/payload.ts +2 -5
  198. package/src/user/retriever.ts +1 -1
  199. package/src/user/user.spec.ts +31 -31
  200. package/src/user/writer.ts +1 -1
  201. package/src/util/decodeJSONString.ts +3 -3
  202. package/src/util/parseWithoutKeyConversion.ts +2 -2
  203. package/src/util/retrieve.ts +1 -1
  204. package/src/util/zod.ts +1 -1
  205. package/src/workspace/client.ts +20 -36
  206. package/src/workspace/lineplot/client.ts +5 -7
  207. package/src/workspace/lineplot/lineplot.spec.ts +2 -2
  208. package/src/workspace/lineplot/payload.ts +4 -7
  209. package/src/workspace/log/client.ts +5 -7
  210. package/src/workspace/log/log.spec.ts +2 -2
  211. package/src/workspace/log/payload.ts +4 -7
  212. package/src/workspace/payload.ts +4 -7
  213. package/src/workspace/schematic/client.ts +5 -7
  214. package/src/workspace/schematic/payload.ts +4 -7
  215. package/src/workspace/schematic/schematic.spec.ts +2 -2
  216. package/src/workspace/table/client.ts +5 -7
  217. package/src/workspace/table/payload.ts +4 -7
  218. package/src/workspace/table/table.spec.ts +2 -2
  219. package/src/workspace/workspace.spec.ts +2 -2
  220. package/dist/access/policy/ontology.d.ts +0 -5
  221. package/dist/access/policy/ontology.d.ts.map +0 -1
  222. package/dist/access/policy/retriever.d.ts +0 -40
  223. package/dist/access/policy/retriever.d.ts.map +0 -1
  224. package/dist/access/policy/writer.d.ts +0 -9
  225. package/dist/access/policy/writer.d.ts.map +0 -1
  226. package/dist/label/retriever.d.ts +0 -14
  227. package/dist/label/retriever.d.ts.map +0 -1
  228. package/dist/label/writer.d.ts +0 -54
  229. package/dist/label/writer.d.ts.map +0 -1
  230. package/dist/setupspecs.d.ts +0 -5
  231. package/dist/setupspecs.d.ts.map +0 -1
  232. package/dist/signals/external.d.ts +0 -2
  233. package/dist/signals/external.d.ts.map +0 -1
  234. package/dist/signals/index.d.ts +0 -2
  235. package/dist/signals/index.d.ts.map +0 -1
  236. package/dist/signals/observable.d.ts +0 -12
  237. package/dist/signals/observable.d.ts.map +0 -1
  238. package/src/access/policy/ontology.ts +0 -17
  239. package/src/access/policy/retriever.ts +0 -44
  240. package/src/access/policy/writer.ts +0 -65
  241. package/src/label/retriever.ts +0 -63
  242. package/src/label/writer.ts +0 -95
  243. package/src/setupspecs.ts +0 -27
  244. package/src/signals/external.ts +0 -10
  245. package/src/signals/observable.ts +0 -42
@@ -7,14 +7,8 @@
7
7
  // License, use of this software will be governed by the Apache License, Version 2.0,
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
- import {
11
- binary,
12
- type observe,
13
- status,
14
- type UnknownRecord,
15
- unknownRecordZ,
16
- } from "@synnaxlabs/x";
17
- import { z } from "zod/v4";
10
+ import { binary, type observe, record, status } from "@synnaxlabs/x";
11
+ import { z } from "zod";
18
12
 
19
13
  import { type Key as RackKey } from "@/hardware/rack/payload";
20
14
  import { decodeJSONString } from "@/util/decodeJSONString";
@@ -27,77 +21,107 @@ export const keyZ = z.union([
27
21
  ]);
28
22
  export type Key = z.infer<typeof keyZ>;
29
23
 
30
- export const stateZ = z.object({
31
- task: keyZ,
32
- variant: status.variantZ,
33
- key: z.string().optional(),
34
- details: unknownRecordZ
35
- .or(z.string().transform(parseWithoutKeyConversion))
36
- .or(z.array(z.unknown()))
37
- .or(z.null()) as z.ZodType<UnknownRecord | undefined>,
38
- });
24
+ export const statusDetailsZ = <D extends z.ZodType>(data: D) =>
25
+ z.object({ task: keyZ, running: z.boolean(), data });
39
26
 
40
- export interface State<Details extends {} = UnknownRecord>
41
- extends Omit<z.infer<typeof stateZ>, "details"> {
42
- details?: Details;
43
- }
27
+ export type StatusDetails<D extends z.ZodType> = z.infer<
28
+ ReturnType<typeof statusDetailsZ<D>>
29
+ >;
44
30
 
45
- export const taskZ = z.object({
46
- key: keyZ,
47
- name: z.string(),
48
- type: z.string(),
49
- internal: z.boolean().optional(),
50
- config: unknownRecordZ.or(z.string().transform(decodeJSONString)),
51
- state: stateZ.optional().nullable(),
52
- snapshot: z.boolean().optional(),
53
- });
31
+ export const statusZ = <D extends z.ZodType>(data: D) =>
32
+ status.statusZ(statusDetailsZ(data));
54
33
 
55
- export interface Payload<
56
- Config extends UnknownRecord = UnknownRecord,
57
- Details extends {} = UnknownRecord,
58
- Type extends string = string,
59
- > extends Omit<z.infer<typeof taskZ>, "config" | "type" | "state"> {
60
- type: Type;
61
- config: Config;
62
- state?: State<Details> | null;
63
- }
34
+ export type Status<StatusData extends z.ZodType = z.ZodUnknown> = z.infer<
35
+ ReturnType<typeof statusZ<StatusData>>
36
+ >;
64
37
 
65
- export const newZ = taskZ.omit({ key: true }).extend({
66
- key: keyZ.transform((k) => k.toString()).optional(),
67
- config: z.unknown().transform((c) => binary.JSON_CODEC.encodeString(c)),
68
- });
38
+ export const taskZ = <
39
+ Type extends z.ZodLiteral<string> = z.ZodLiteral<string>,
40
+ Config extends z.ZodType = z.ZodType,
41
+ StatusData extends z.ZodType = z.ZodUnknown,
42
+ >(
43
+ schemas: Schemas<Type, Config, StatusData> = {
44
+ typeSchema: z.string() as unknown as Type,
45
+ configSchema: z.unknown() as unknown as Config,
46
+ statusDataSchema: z.unknown() as unknown as StatusData,
47
+ },
48
+ ) =>
49
+ z.object({
50
+ key: keyZ,
51
+ name: z.string(),
52
+ type: schemas.typeSchema,
53
+ internal: z.boolean().optional(),
54
+ config: z.string().transform(decodeJSONString).or(schemas.configSchema),
55
+ status: statusZ(schemas.statusDataSchema).optional().nullable(),
56
+ snapshot: z.boolean().optional(),
57
+ });
69
58
 
70
- export interface New<
71
- Config extends UnknownRecord = UnknownRecord,
72
- Type extends string = string,
73
- > extends Omit<z.input<typeof newZ>, "config" | "state"> {
74
- type: Type;
75
- config: Config;
59
+ export interface Schemas<
60
+ Type extends z.ZodLiteral<string> = z.ZodLiteral<string>,
61
+ Config extends z.ZodType = z.ZodType,
62
+ StatusData extends z.ZodType = z.ZodType,
63
+ > {
64
+ typeSchema: Type;
65
+ configSchema: Config;
66
+ statusDataSchema: StatusData;
76
67
  }
77
68
 
69
+ export type Payload<
70
+ Type extends z.ZodLiteral<string> = z.ZodLiteral<string>,
71
+ Config extends z.ZodType = z.ZodType,
72
+ StatusData extends z.ZodType = z.ZodType,
73
+ > = {
74
+ key: Key;
75
+ name: string;
76
+ type: z.infer<Type>;
77
+ config: z.infer<Config>;
78
+ status?: Status<StatusData>;
79
+ snapshot?: boolean;
80
+ internal?: boolean;
81
+ };
82
+
83
+ export const newZ = <
84
+ Type extends z.ZodLiteral<string> = z.ZodLiteral<string>,
85
+ Config extends z.ZodType = z.ZodType,
86
+ StatusData extends z.ZodType = z.ZodUnknown,
87
+ >(
88
+ schemas?: Schemas<Type, Config, StatusData>,
89
+ ) =>
90
+ taskZ(schemas)
91
+ .omit({ key: true })
92
+ .extend({
93
+ key: keyZ.transform((k) => k.toString()).optional(),
94
+ config: z.unknown().transform((c) => binary.JSON_CODEC.encodeString(c)),
95
+ });
96
+
97
+ export type New<
98
+ Type extends z.ZodLiteral<string> = z.ZodLiteral<string>,
99
+ Config extends z.ZodType = z.ZodType,
100
+ > = {
101
+ key?: Key;
102
+ name: string;
103
+ type: z.infer<Type>;
104
+ config: z.infer<Config>;
105
+ };
106
+
78
107
  export const commandZ = z.object({
79
108
  task: keyZ,
80
109
  type: z.string(),
81
110
  key: z.string(),
82
- args: unknownRecordZ
111
+ args: record.unknownZ
83
112
  .or(z.string().transform(parseWithoutKeyConversion))
84
113
  .or(z.array(z.unknown()))
85
114
  .or(z.null())
86
- .optional() as z.ZodOptional<z.ZodType<UnknownRecord>>,
115
+ .optional() as z.ZodOptional<z.ZodType<record.Unknown>>,
87
116
  });
88
117
 
89
- export interface Command<Args extends {} = UnknownRecord>
90
- extends Omit<z.infer<typeof commandZ>, "args"> {
91
- args?: Args;
118
+ export interface Command extends Omit<z.infer<typeof commandZ>, "args"> {
119
+ args?: record.Unknown;
92
120
  }
93
121
 
94
- export interface StateObservable<Details extends {} = UnknownRecord>
95
- extends observe.ObservableAsyncCloseable<State<Details>> {}
96
-
97
- export interface CommandObservable<Args extends {} = UnknownRecord>
98
- extends observe.ObservableAsyncCloseable<Command<Args>> {}
122
+ export interface StateObservable<StatusData extends z.ZodType>
123
+ extends observe.ObservableAsyncCloseable<Status<StatusData>> {}
99
124
 
100
- export const ONTOLOGY_TYPE = "task";
101
- export type OntologyType = typeof ONTOLOGY_TYPE;
125
+ export interface CommandObservable extends observe.ObservableAsyncCloseable<Command> {}
102
126
 
103
- export const getRackKey = (key: Key): RackKey => Number(BigInt(key) >> 32n);
127
+ export const rackKey = (key: Key): RackKey => Number(BigInt(key) >> 32n);
@@ -7,13 +7,13 @@
7
7
  // License, use of this software will be governed by the Apache License, Version 2.0,
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
- import { id } from "@synnaxlabs/x";
11
- import { describe, expect, it } from "vitest";
10
+ import { id, TimeStamp } from "@synnaxlabs/x";
11
+ import { beforeAll, describe, expect, it } from "vitest";
12
12
 
13
- import { type task } from "@/hardware/task";
14
- import { newClient } from "@/setupspecs";
13
+ import { task } from "@/hardware/task";
14
+ import { newTestClient } from "@/testutil/client";
15
15
 
16
- const client = newClient();
16
+ const client = newTestClient();
17
17
 
18
18
  describe("Task", async () => {
19
19
  const testRack = await client.hardware.racks.create({ name: "test" });
@@ -57,7 +57,7 @@ describe("Task", async () => {
57
57
  name: "updated",
58
58
  });
59
59
  expect(updated.name).toBe("updated");
60
- const retrieved = await client.hardware.tasks.retrieve(m.key);
60
+ const retrieved = await client.hardware.tasks.retrieve({ key: m.key });
61
61
  expect(retrieved.name).toBe("updated");
62
62
  });
63
63
  });
@@ -68,46 +68,200 @@ describe("Task", async () => {
68
68
  config: { a: "dog" },
69
69
  type: "ni",
70
70
  });
71
- const retrieved = await client.hardware.tasks.retrieve(m.key);
71
+ const retrieved = await client.hardware.tasks.retrieve({ key: m.key });
72
72
  expect(retrieved.key).toBe(m.key);
73
73
  expect(retrieved.name).toBe("test");
74
74
  expect(retrieved.config).toStrictEqual({ a: "dog" });
75
75
  expect(retrieved.type).toBe("ni");
76
76
  });
77
- describe("retrieveByName", () => {
78
- it("should retrieve a task by its name", async () => {
79
- const name = `test-${Date.now()}-${Math.random()}`;
80
- const m = await testRack.createTask({ name, config: { a: "dog" }, type: "ni" });
81
- const retrieved = await client.hardware.tasks.retrieveByName(name);
82
- expect(retrieved.key).toBe(m.key);
83
- });
77
+
78
+ it("should retrieve a task by its name", async () => {
79
+ const name = `test-${Date.now()}-${Math.random()}`;
80
+ const m = await testRack.createTask({ name, config: { a: "dog" }, type: "ni" });
81
+ const retrieved = await client.hardware.tasks.retrieve({ name });
82
+ expect(retrieved.key).toBe(m.key);
84
83
  });
85
- describe("retrieve with state", () => {
86
- it("should also send the tasks state", async () => {
84
+
85
+ describe("state", () => {
86
+ it("should include task status when requested", async () => {
87
87
  const t = await testRack.createTask({
88
88
  name: "test",
89
89
  config: { a: "dog" },
90
90
  type: "ni",
91
91
  });
92
- const w = await client.openWriter(["sy_task_state"]);
93
- interface StateDetails {
94
- dog: string;
95
- }
96
- const state: task.State<StateDetails> = {
92
+ const w = await client.openWriter([task.STATUS_CHANNEL_NAME]);
93
+ const communicatedStatus: task.Status = {
97
94
  key: id.create(),
98
- task: t.key,
99
95
  variant: "success",
96
+ details: { task: t.key, running: false, data: {} },
97
+ message: "test",
98
+ time: TimeStamp.now(),
100
99
  };
101
- await w.write("sy_task_state", [state]);
100
+ await w.write(task.STATUS_CHANNEL_NAME, [communicatedStatus]);
102
101
  await w.close();
103
102
  await expect
104
103
  .poll(async () => {
105
- const retrieved = await client.hardware.tasks.retrieve(t.key, {
106
- includeState: true,
104
+ const retrieved = await client.hardware.tasks.retrieve({
105
+ key: t.key,
106
+ includeStatus: true,
107
+ });
108
+ return retrieved.status?.variant === communicatedStatus.variant;
109
+ })
110
+ .toBe(true);
111
+ });
112
+ });
113
+
114
+ describe("request object format", () => {
115
+ const testTasks: Array<{ key: string; name: string; type: string }> = [];
116
+ let secondRack: any;
117
+
118
+ beforeAll(async () => {
119
+ secondRack = await client.hardware.racks.create({ name: "test-rack-2" });
120
+
121
+ const taskConfigs = [
122
+ { name: "sensor_task1", type: "ni", rack: testRack },
123
+ { name: "sensor_task2", type: "ni", rack: testRack },
124
+ { name: "actuator_task1", type: "labjack", rack: testRack },
125
+ { name: "actuator_task2", type: "labjack", rack: secondRack },
126
+ { name: "controller_task", type: "opc", rack: secondRack },
127
+ ];
128
+
129
+ for (const config of taskConfigs) {
130
+ const task = await config.rack.createTask({
131
+ name: config.name,
132
+ type: config.type,
133
+ config: { test: true },
134
+ });
135
+ testTasks.push({ key: task.key, name: config.name, type: config.type });
136
+ }
137
+ });
138
+
139
+ it("should retrieve tasks by rack", async () => {
140
+ const result = await client.hardware.tasks.retrieve({
141
+ rack: testRack.key,
142
+ });
143
+ expect(result.length).toBeGreaterThanOrEqual(3);
144
+ expect(result.every((t) => task.rackKey(t.key) === testRack.key)).toBe(true);
145
+ });
146
+
147
+ it("should retrieve tasks by multiple keys", async () => {
148
+ const keysToQuery = testTasks.slice(0, 2).map((t) => t.key);
149
+ const result = await client.hardware.tasks.retrieve({
150
+ keys: keysToQuery,
151
+ });
152
+ expect(result).toHaveLength(2);
153
+ expect(result.map((t) => t.key).sort()).toEqual(keysToQuery.sort());
154
+ });
155
+
156
+ it("should retrieve tasks by multiple names", async () => {
157
+ const namesToQuery = ["sensor_task1", "actuator_task1"];
158
+ const result = await client.hardware.tasks.retrieve({
159
+ names: namesToQuery,
160
+ });
161
+ expect(result.length).toBeGreaterThanOrEqual(2);
162
+ expect(result.every((t) => namesToQuery.includes(t.name))).toBe(true);
163
+ });
164
+
165
+ it("should retrieve tasks by types", async () => {
166
+ const result = await client.hardware.tasks.retrieve({
167
+ types: ["ni"],
168
+ });
169
+ expect(result.length).toBeGreaterThanOrEqual(2);
170
+ expect(result.every((t) => t.type === "ni")).toBe(true);
171
+ });
172
+
173
+ it("should retrieve tasks by multiple types", async () => {
174
+ const typesToQuery = ["ni", "labjack"];
175
+ const result = await client.hardware.tasks.retrieve({
176
+ types: typesToQuery,
177
+ });
178
+ expect(result.length).toBeGreaterThanOrEqual(4);
179
+ expect(result.every((t) => typesToQuery.includes(t.type))).toBe(true);
180
+ });
181
+
182
+ it("should support pagination with limit and offset", async () => {
183
+ const firstPage = await client.hardware.tasks.retrieve({
184
+ rack: testRack.key,
185
+ limit: 2,
186
+ offset: 0,
187
+ });
188
+ expect(firstPage.length).toBeLessThanOrEqual(2);
189
+
190
+ if (firstPage.length === 2) {
191
+ const secondPage = await client.hardware.tasks.retrieve({
192
+ rack: testRack.key,
193
+ limit: 2,
194
+ offset: 2,
195
+ });
196
+
197
+ const firstPageKeys = firstPage.map((t) => t.key);
198
+ const secondPageKeys = secondPage.map((t) => t.key);
199
+ expect(firstPageKeys.every((key) => !secondPageKeys.includes(key))).toBe(
200
+ true,
201
+ );
202
+ }
203
+ });
204
+
205
+ it("should support combined filters", async () => {
206
+ const result = await client.hardware.tasks.retrieve({
207
+ rack: testRack.key,
208
+ types: ["ni"],
209
+ includeStatus: true,
210
+ });
211
+ expect(result.length).toBeGreaterThanOrEqual(1);
212
+ expect(result.every((t) => t.type === "ni")).toBe(true);
213
+
214
+ await expect
215
+ .poll(async () => {
216
+ const tasks = await client.hardware.tasks.retrieve({
217
+ rack: testRack.key,
218
+ types: ["ni"],
219
+ includeStatus: true,
107
220
  });
108
- return retrieved.state?.variant === state.variant;
221
+ return tasks.every((t) => t.status !== undefined);
109
222
  })
110
- .toBeTruthy();
223
+ .toBe(true);
224
+ });
225
+
226
+ it("should handle empty results gracefully", async () => {
227
+ const result = await client.hardware.tasks.retrieve({
228
+ types: ["nonexistent_type"],
229
+ });
230
+ expect(result).toEqual([]);
231
+ });
232
+
233
+ it("should combine rack and type filters", async () => {
234
+ const result = await client.hardware.tasks.retrieve({
235
+ rack: secondRack.key,
236
+ types: ["labjack"],
237
+ });
238
+ expect(result.length).toBeGreaterThanOrEqual(1);
239
+ expect(result.every((t) => t.type === "labjack")).toBe(true);
240
+ });
241
+
242
+ it("should handle limit without offset", async () => {
243
+ const result = await client.hardware.tasks.retrieve({
244
+ limit: 1,
245
+ });
246
+ expect(result).toHaveLength(1);
247
+ });
248
+
249
+ it("should retrieve tasks with includeStatus in request object", async () => {
250
+ const result = await client.hardware.tasks.retrieve({
251
+ rack: testRack.key,
252
+ includeStatus: true,
253
+ });
254
+ expect(result.length).toBeGreaterThanOrEqual(1);
255
+
256
+ await expect
257
+ .poll(async () => {
258
+ const tasks = await client.hardware.tasks.retrieve({
259
+ rack: testRack.key,
260
+ includeStatus: true,
261
+ });
262
+ return tasks.every((t) => t.status !== undefined);
263
+ })
264
+ .toBe(true);
111
265
  });
112
266
  });
113
267
  });
@@ -125,11 +279,33 @@ describe("Task", async () => {
125
279
  });
126
280
  });
127
281
 
128
- describe("list", () => {
129
- it("should list all tasks", async () => {
130
- await testRack.createTask({ name: "test", config: { a: "dog" }, type: "ni" });
131
- const tasks = await client.hardware.tasks.list();
132
- expect(tasks.length).toBeGreaterThan(0);
282
+ describe("executeCommand", () => {
283
+ it("should execute a command on a task", async () => {
284
+ const type = "testCmd";
285
+ const args = { a: "dog" };
286
+ const t = await testRack.createTask({
287
+ name: "test",
288
+ config: { a: "dog" },
289
+ type: "ni",
290
+ });
291
+ const streamer = await client.openStreamer(task.COMMAND_CHANNEL_NAME);
292
+ const key = await client.hardware.tasks.executeCommand(t.key, type, args);
293
+ await expect
294
+ .poll<Promise<task.Command>>(async () => {
295
+ const fr = await streamer.read();
296
+ const sample = fr.at(-1)[task.COMMAND_CHANNEL_NAME];
297
+ return task.commandZ.parse(sample);
298
+ })
299
+ .toMatchObject({ key, task: t.key, type, args });
300
+ streamer.close();
301
+ });
302
+ it("should timeout on a synchronously executed command", async () => {
303
+ const t = await testRack.createTask({
304
+ name: "test",
305
+ config: {},
306
+ type: "ni",
307
+ });
308
+ await expect(t.executeCommandSync("test", 0)).rejects.toThrow("timed out");
133
309
  });
134
310
  });
135
311
  });
package/src/index.ts CHANGED
@@ -17,6 +17,7 @@ export { control } from "@/control";
17
17
  export {
18
18
  AuthError,
19
19
  ContiguityError,
20
+ DisconnectedError,
20
21
  MultipleFoundError,
21
22
  NotFoundError,
22
23
  QueryError,
@@ -34,7 +35,7 @@ export { label } from "@/label";
34
35
  export { ontology } from "@/ontology";
35
36
  export { group } from "@/ontology/group";
36
37
  export { ranger } from "@/ranger";
37
- export { signals } from "@/signals";
38
+ export { newTestClient, TEST_CLIENT_PROPS } from "@/testutil/client";
38
39
  export { user } from "@/user";
39
40
  export { workspace } from "@/workspace";
40
41
  export { linePlot } from "@/workspace/lineplot";