@synnaxlabs/client 0.54.1 → 0.55.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.
- package/.turbo/turbo-build.log +6 -6
- package/dist/client.cjs +39 -28
- package/dist/client.js +6205 -5448
- package/dist/src/arc/arc.spec.d.ts +2 -0
- package/dist/src/arc/arc.spec.d.ts.map +1 -0
- package/dist/src/arc/graph/types.gen.d.ts +20 -20
- package/dist/src/arc/ir/types.gen.d.ts +145 -176
- package/dist/src/arc/ir/types.gen.d.ts.map +1 -1
- package/dist/src/arc/module/types.gen.d.ts +46 -65
- package/dist/src/arc/module/types.gen.d.ts.map +1 -1
- package/dist/src/arc/program/types.gen.d.ts +46 -65
- package/dist/src/arc/program/types.gen.d.ts.map +1 -1
- package/dist/src/arc/types.gen.d.ts +86 -105
- package/dist/src/arc/types.gen.d.ts.map +1 -1
- package/dist/src/auth/auth.d.ts.map +1 -1
- package/dist/src/channel/types.gen.d.ts.map +1 -1
- package/dist/src/client.d.ts +5 -0
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/connection/checker.d.ts +17 -2
- package/dist/src/connection/checker.d.ts.map +1 -1
- package/dist/src/control/state.d.ts.map +1 -1
- package/dist/src/framer/client.d.ts.map +1 -1
- package/dist/src/framer/deleter.d.ts +2 -2
- package/dist/src/framer/frame.d.ts +2 -2
- package/dist/src/framer/streamer.d.ts +2 -2
- package/dist/src/framer/writer.d.ts +5 -5
- package/dist/src/framer/writer.d.ts.map +1 -1
- package/dist/src/label/payload.d.ts +2 -2
- package/dist/src/ranger/client.d.ts +6 -6
- package/dist/src/ranger/types.gen.d.ts +10 -10
- package/dist/src/ranger/writer.d.ts +2 -2
- package/dist/src/status/payload.d.ts +1 -1
- package/dist/src/task/client.d.ts.map +1 -1
- package/dist/src/task/types.gen.d.ts +2 -2
- package/package.json +9 -9
- package/src/arc/arc.spec.ts +44 -0
- package/src/arc/ir/types.gen.ts +101 -47
- package/src/auth/auth.ts +13 -1
- package/src/channel/channel.spec.ts +13 -0
- package/src/channel/types.gen.ts +1 -2
- package/src/client.ts +6 -3
- package/src/connection/checker.ts +44 -5
- package/src/connection/connection.spec.ts +67 -2
- package/src/control/state.ts +5 -4
- package/src/device/device.spec.ts +7 -5
- package/src/framer/client.ts +12 -0
- package/src/framer/writer.spec.ts +144 -1
- package/src/framer/writer.ts +9 -2
- package/src/label/label.spec.ts +12 -0
- package/src/ontology/ontology.spec.ts +10 -0
- package/src/rack/rack.spec.ts +13 -3
- package/src/ranger/ranger.spec.ts +12 -0
- package/src/schematic/symbol/client.spec.ts +33 -9
- package/src/status/status.spec.ts +7 -6
- package/src/task/client.ts +7 -9
- package/src/task/task.spec.ts +15 -1
- package/src/view/view.spec.ts +9 -5
- package/src/workspace/workspace.spec.ts +14 -1
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
|
-
import { DataType, id, TimeRange, TimeSpan, TimeStamp } from "@synnaxlabs/x";
|
|
10
|
+
import { DataType, id, Series, TimeRange, TimeSpan, TimeStamp } from "@synnaxlabs/x";
|
|
11
11
|
import { describe, expect, it, test } from "vitest";
|
|
12
12
|
|
|
13
13
|
import { UnauthorizedError, ValidationError } from "@/errors";
|
|
@@ -263,4 +263,147 @@ describe("Writer", () => {
|
|
|
263
263
|
expect(f.length).toEqual(10);
|
|
264
264
|
});
|
|
265
265
|
});
|
|
266
|
+
|
|
267
|
+
describe("Variable Channels", () => {
|
|
268
|
+
test("write and read string data", async () => {
|
|
269
|
+
const index = await client.channels.create({
|
|
270
|
+
name: id.create(),
|
|
271
|
+
isIndex: true,
|
|
272
|
+
dataType: DataType.TIMESTAMP,
|
|
273
|
+
leaseholder: 1,
|
|
274
|
+
});
|
|
275
|
+
const data = await client.channels.create({
|
|
276
|
+
name: id.create(),
|
|
277
|
+
index: index.key,
|
|
278
|
+
dataType: DataType.STRING,
|
|
279
|
+
leaseholder: 1,
|
|
280
|
+
});
|
|
281
|
+
const writer = await client.openWriter({
|
|
282
|
+
start: TimeStamp.seconds(1),
|
|
283
|
+
channels: [index, data],
|
|
284
|
+
});
|
|
285
|
+
try {
|
|
286
|
+
await writer.write({
|
|
287
|
+
[index.key]: secondsLinspace(1, 3),
|
|
288
|
+
[data.key]: new Series({
|
|
289
|
+
data: ["hello", "world", "foo"],
|
|
290
|
+
dataType: DataType.STRING,
|
|
291
|
+
}),
|
|
292
|
+
});
|
|
293
|
+
await writer.commit();
|
|
294
|
+
} finally {
|
|
295
|
+
await writer.close();
|
|
296
|
+
}
|
|
297
|
+
const f = await data.read(TimeRange.MAX);
|
|
298
|
+
expect(f.toStrings()).toEqual(["hello", "world", "foo"]);
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
test("write and read JSON data", async () => {
|
|
302
|
+
const index = await client.channels.create({
|
|
303
|
+
name: id.create(),
|
|
304
|
+
isIndex: true,
|
|
305
|
+
dataType: DataType.TIMESTAMP,
|
|
306
|
+
leaseholder: 1,
|
|
307
|
+
});
|
|
308
|
+
const data = await client.channels.create({
|
|
309
|
+
name: id.create(),
|
|
310
|
+
index: index.key,
|
|
311
|
+
dataType: DataType.JSON,
|
|
312
|
+
leaseholder: 1,
|
|
313
|
+
});
|
|
314
|
+
const writer = await client.openWriter({
|
|
315
|
+
start: TimeStamp.seconds(1),
|
|
316
|
+
channels: [index, data],
|
|
317
|
+
});
|
|
318
|
+
try {
|
|
319
|
+
await writer.write({
|
|
320
|
+
[index.key]: secondsLinspace(1, 2),
|
|
321
|
+
[data.key]: new Series({
|
|
322
|
+
data: [{ key: "value" }, { num: 42 }],
|
|
323
|
+
dataType: DataType.JSON,
|
|
324
|
+
}),
|
|
325
|
+
});
|
|
326
|
+
await writer.commit();
|
|
327
|
+
} finally {
|
|
328
|
+
await writer.close();
|
|
329
|
+
}
|
|
330
|
+
const f = await data.read(TimeRange.MAX);
|
|
331
|
+
expect(f.length).toEqual(2);
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
test("write mixed fixed and variable channels", async () => {
|
|
335
|
+
const index = await client.channels.create({
|
|
336
|
+
name: id.create(),
|
|
337
|
+
isIndex: true,
|
|
338
|
+
dataType: DataType.TIMESTAMP,
|
|
339
|
+
leaseholder: 1,
|
|
340
|
+
});
|
|
341
|
+
const floatCh = await client.channels.create({
|
|
342
|
+
name: id.create(),
|
|
343
|
+
index: index.key,
|
|
344
|
+
dataType: DataType.FLOAT64,
|
|
345
|
+
leaseholder: 1,
|
|
346
|
+
});
|
|
347
|
+
const strCh = await client.channels.create({
|
|
348
|
+
name: id.create(),
|
|
349
|
+
index: index.key,
|
|
350
|
+
dataType: DataType.STRING,
|
|
351
|
+
leaseholder: 1,
|
|
352
|
+
});
|
|
353
|
+
const writer = await client.openWriter({
|
|
354
|
+
start: TimeStamp.seconds(1),
|
|
355
|
+
channels: [index, floatCh, strCh],
|
|
356
|
+
});
|
|
357
|
+
try {
|
|
358
|
+
await writer.write({
|
|
359
|
+
[index.key]: secondsLinspace(1, 3),
|
|
360
|
+
[floatCh.key]: new Float64Array([1.1, 2.2, 3.3]),
|
|
361
|
+
[strCh.key]: new Series({
|
|
362
|
+
data: ["a", "b", "c"],
|
|
363
|
+
dataType: DataType.STRING,
|
|
364
|
+
}),
|
|
365
|
+
});
|
|
366
|
+
await writer.commit();
|
|
367
|
+
} finally {
|
|
368
|
+
await writer.close();
|
|
369
|
+
}
|
|
370
|
+
const floatData = await floatCh.read(TimeRange.MAX);
|
|
371
|
+
expect(floatData.length).toEqual(3);
|
|
372
|
+
const strData = await strCh.read(TimeRange.MAX);
|
|
373
|
+
expect(strData.toStrings()).toEqual(["a", "b", "c"]);
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
test("write strings with embedded newlines", async () => {
|
|
377
|
+
const index = await client.channels.create({
|
|
378
|
+
name: id.create(),
|
|
379
|
+
isIndex: true,
|
|
380
|
+
dataType: DataType.TIMESTAMP,
|
|
381
|
+
leaseholder: 1,
|
|
382
|
+
});
|
|
383
|
+
const data = await client.channels.create({
|
|
384
|
+
name: id.create(),
|
|
385
|
+
index: index.key,
|
|
386
|
+
dataType: DataType.STRING,
|
|
387
|
+
leaseholder: 1,
|
|
388
|
+
});
|
|
389
|
+
const writer = await client.openWriter({
|
|
390
|
+
start: TimeStamp.seconds(1),
|
|
391
|
+
channels: [index, data],
|
|
392
|
+
});
|
|
393
|
+
try {
|
|
394
|
+
await writer.write({
|
|
395
|
+
[index.key]: secondsLinspace(1, 2),
|
|
396
|
+
[data.key]: new Series({
|
|
397
|
+
data: ["line1\nline2", "no newline"],
|
|
398
|
+
dataType: DataType.STRING,
|
|
399
|
+
}),
|
|
400
|
+
});
|
|
401
|
+
await writer.commit();
|
|
402
|
+
} finally {
|
|
403
|
+
await writer.close();
|
|
404
|
+
}
|
|
405
|
+
const f = await data.read(TimeRange.MAX);
|
|
406
|
+
expect(f.toStrings()).toEqual(["line1\nline2", "no newline"]);
|
|
407
|
+
});
|
|
408
|
+
});
|
|
266
409
|
});
|
package/src/framer/writer.ts
CHANGED
|
@@ -8,7 +8,14 @@
|
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
10
|
import { EOF, type Stream, type WebSocketClient } from "@synnaxlabs/freighter";
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
control,
|
|
13
|
+
type CrudeSeries,
|
|
14
|
+
errors,
|
|
15
|
+
TimeSpan,
|
|
16
|
+
TimeStamp,
|
|
17
|
+
zod,
|
|
18
|
+
} from "@synnaxlabs/x";
|
|
12
19
|
import { z } from "zod";
|
|
13
20
|
|
|
14
21
|
import { channel } from "@/channel";
|
|
@@ -203,7 +210,7 @@ export class Writer {
|
|
|
203
210
|
client: WebSocketClient,
|
|
204
211
|
config: WriterConfig,
|
|
205
212
|
): Promise<Writer> {
|
|
206
|
-
const cfg =
|
|
213
|
+
const cfg = zod.parse(writerConfigZ, config);
|
|
207
214
|
const adapter = await WriteAdapter.open(retriever, cfg.channels);
|
|
208
215
|
if (cfg.useHighPerformanceCodec)
|
|
209
216
|
client = client.withCodec(new WSWriterCodec(adapter.codec));
|
package/src/label/label.spec.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
|
+
import { id } from "@synnaxlabs/x";
|
|
10
11
|
import { describe, expect, it } from "vitest";
|
|
11
12
|
|
|
12
13
|
import { label } from "@/label";
|
|
@@ -34,6 +35,17 @@ describe("Label", () => {
|
|
|
34
35
|
const retrieved = await client.labels.retrieve({ key: v.key });
|
|
35
36
|
expect(retrieved).toEqual(v);
|
|
36
37
|
});
|
|
38
|
+
it("should retrieve labels by search term", async () => {
|
|
39
|
+
const prefix = `searchable-label-${id.create()}`;
|
|
40
|
+
const names = [`${prefix}-1`, `${prefix}-2`];
|
|
41
|
+
await client.labels.create(names.map((name) => ({ name, color: "#E774D0" })));
|
|
42
|
+
await expect
|
|
43
|
+
.poll(async () => {
|
|
44
|
+
const results = await client.labels.retrieve({ searchTerm: prefix });
|
|
45
|
+
return results.map((l) => l.name).sort();
|
|
46
|
+
})
|
|
47
|
+
.toEqual(names);
|
|
48
|
+
});
|
|
37
49
|
});
|
|
38
50
|
|
|
39
51
|
describe("delete", () => {
|
|
@@ -154,6 +154,16 @@ describe("Ontology", () => {
|
|
|
154
154
|
expect(parents.length).toEqual(1);
|
|
155
155
|
expect(parents[0].name).toEqual(name);
|
|
156
156
|
});
|
|
157
|
+
test("retrieve by search term", async () => {
|
|
158
|
+
const name = randomName();
|
|
159
|
+
const g = await client.groups.create({ parent: ontology.ROOT_ID, name });
|
|
160
|
+
await expect
|
|
161
|
+
.poll(async () => {
|
|
162
|
+
const results = await client.ontology.retrieve({ searchTerm: name });
|
|
163
|
+
return results.find((r) => r.id.key === g.key);
|
|
164
|
+
})
|
|
165
|
+
.toMatchObject({ name, id: { type: "group", key: g.key } });
|
|
166
|
+
});
|
|
157
167
|
});
|
|
158
168
|
|
|
159
169
|
describe("write", () => {
|
package/src/rack/rack.spec.ts
CHANGED
|
@@ -7,9 +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 { TimeStamp } from "@synnaxlabs/x";
|
|
10
|
+
import { id, TimeStamp, zod } from "@synnaxlabs/x";
|
|
11
11
|
import { describe, expect, it } from "vitest";
|
|
12
|
-
import { ZodError } from "zod";
|
|
13
12
|
|
|
14
13
|
import { type rack } from "@/rack";
|
|
15
14
|
import { createTestClient } from "@/testutil/client";
|
|
@@ -24,7 +23,7 @@ describe("Rack", () => {
|
|
|
24
23
|
});
|
|
25
24
|
it("should return an error if the rack doesn't have a name", async () => {
|
|
26
25
|
// @ts-expect-error - Testing for error
|
|
27
|
-
await expect(client.racks.create({})).rejects.toThrow(
|
|
26
|
+
await expect(client.racks.create({})).rejects.toThrow(zod.ParseError);
|
|
28
27
|
});
|
|
29
28
|
it("should create a rack with a custom status", async () => {
|
|
30
29
|
const customStatus: rack.Status = {
|
|
@@ -78,6 +77,17 @@ describe("Rack", () => {
|
|
|
78
77
|
expect(retrieved.key).toBe(r.key);
|
|
79
78
|
expect(retrieved.name).toEqual(name);
|
|
80
79
|
});
|
|
80
|
+
it("should retrieve racks by search term", async () => {
|
|
81
|
+
const prefix = `searchable-rack-${id.create()}`;
|
|
82
|
+
const names = [`${prefix}-1`, `${prefix}-2`];
|
|
83
|
+
await client.racks.create(names.map((name) => ({ name })));
|
|
84
|
+
await expect
|
|
85
|
+
.poll(async () => {
|
|
86
|
+
const results = await client.racks.retrieve({ searchTerm: prefix });
|
|
87
|
+
return results.map((r) => r.name).sort();
|
|
88
|
+
})
|
|
89
|
+
.toEqual(names);
|
|
90
|
+
});
|
|
81
91
|
});
|
|
82
92
|
describe("integrations", () => {
|
|
83
93
|
it("should create a rack with integrations and retrieve them", async () => {
|
|
@@ -185,6 +185,18 @@ describe("range", () => {
|
|
|
185
185
|
expect(retrieved.length).toBeGreaterThan(0);
|
|
186
186
|
expect(retrieved.map((r) => r.key)).toContain(range.key);
|
|
187
187
|
});
|
|
188
|
+
it("should retrieve ranges by search term", async () => {
|
|
189
|
+
const prefix = `searchable-range-${id.create()}`;
|
|
190
|
+
const timeRange = TimeStamp.now().spanRange(TimeSpan.seconds(1));
|
|
191
|
+
const names = [`${prefix}-1`, `${prefix}-2`];
|
|
192
|
+
await client.ranges.create(names.map((name) => ({ name, timeRange })));
|
|
193
|
+
await expect
|
|
194
|
+
.poll(async () => {
|
|
195
|
+
const results = await client.ranges.retrieve({ searchTerm: prefix });
|
|
196
|
+
return results.map((r) => r.name).sort();
|
|
197
|
+
})
|
|
198
|
+
.toEqual(names);
|
|
199
|
+
});
|
|
188
200
|
});
|
|
189
201
|
|
|
190
202
|
describe("retrieveParent", () => {
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
|
+
import { id } from "@synnaxlabs/x";
|
|
10
11
|
import { beforeAll, describe, expect, it } from "vitest";
|
|
11
12
|
|
|
12
13
|
import { group } from "@/group";
|
|
@@ -75,22 +76,45 @@ describe("Symbol Client", () => {
|
|
|
75
76
|
});
|
|
76
77
|
|
|
77
78
|
it("should retrieve multiple symbols by keys", async () => {
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
79
|
+
const created = await client.schematics.symbols.create({
|
|
80
|
+
symbols: [
|
|
81
|
+
{
|
|
82
|
+
name: "Multi Test 1",
|
|
83
|
+
data: { svg: "<svg></svg>", states: [], handles: [], variant: "sensor" },
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: "Multi Test 2",
|
|
87
|
+
data: { svg: "<svg></svg>", states: [], handles: [], variant: "sensor" },
|
|
88
|
+
},
|
|
89
|
+
],
|
|
86
90
|
parent: group.ontologyID(symbolGroup.key),
|
|
87
91
|
});
|
|
88
92
|
|
|
89
93
|
const retrieved = await client.schematics.symbols.retrieve({
|
|
90
|
-
keys:
|
|
94
|
+
keys: created.map((s) => s.key),
|
|
91
95
|
});
|
|
92
96
|
expect(retrieved).toHaveLength(2);
|
|
93
97
|
});
|
|
98
|
+
|
|
99
|
+
it("should retrieve symbols by search term", async () => {
|
|
100
|
+
const prefix = `searchable-symbol-${id.create()}`;
|
|
101
|
+
const names = [`${prefix}-1`, `${prefix}-2`];
|
|
102
|
+
await client.schematics.symbols.create({
|
|
103
|
+
symbols: names.map((name) => ({
|
|
104
|
+
name,
|
|
105
|
+
data: { svg: "<svg></svg>", states: [], handles: [], variant: "sensor" },
|
|
106
|
+
})),
|
|
107
|
+
parent: group.ontologyID(symbolGroup.key),
|
|
108
|
+
});
|
|
109
|
+
await expect
|
|
110
|
+
.poll(async () => {
|
|
111
|
+
const results = await client.schematics.symbols.retrieve({
|
|
112
|
+
searchTerm: prefix,
|
|
113
|
+
});
|
|
114
|
+
return results.map((s) => s.name).sort();
|
|
115
|
+
})
|
|
116
|
+
.toEqual(names);
|
|
117
|
+
});
|
|
94
118
|
});
|
|
95
119
|
|
|
96
120
|
describe("rename", () => {
|
|
@@ -161,12 +161,13 @@ describe("Status", () => {
|
|
|
161
161
|
time: TimeStamp.now(),
|
|
162
162
|
});
|
|
163
163
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
164
|
+
await expect
|
|
165
|
+
.poll(async () =>
|
|
166
|
+
(await client.statuses.retrieve({ searchTerm: uniqueName })).some(
|
|
167
|
+
(s) => s.name === uniqueName,
|
|
168
|
+
),
|
|
169
|
+
)
|
|
170
|
+
.toBe(true);
|
|
170
171
|
});
|
|
171
172
|
|
|
172
173
|
it("should paginate results", async () => {
|
package/src/task/client.ts
CHANGED
|
@@ -44,8 +44,6 @@ export const COMMAND_CHANNEL_NAME = "sy_task_cmd";
|
|
|
44
44
|
export const SET_CHANNEL_NAME = "sy_task_set";
|
|
45
45
|
export const DELETE_CHANNEL_NAME = "sy_task_delete";
|
|
46
46
|
|
|
47
|
-
const NOT_CREATED_ERROR = new Error("Task not created");
|
|
48
|
-
|
|
49
47
|
export const rackKey = (key: Key): RackKey => Number(BigInt(key) >> 32n);
|
|
50
48
|
|
|
51
49
|
export const newKey = (rackKey: RackKey, taskKey: number = 0): Key =>
|
|
@@ -99,17 +97,17 @@ export class Task<S extends Schemas = Schemas> {
|
|
|
99
97
|
private readonly rangeClient_?: ranger.Client;
|
|
100
98
|
|
|
101
99
|
get frameClient(): framer.Client {
|
|
102
|
-
if (this.frameClient_ == null) throw
|
|
100
|
+
if (this.frameClient_ == null) throw new Error("Task not created");
|
|
103
101
|
return this.frameClient_;
|
|
104
102
|
}
|
|
105
103
|
|
|
106
104
|
get ontologyClient(): ontology.Client {
|
|
107
|
-
if (this.ontologyClient_ == null) throw
|
|
105
|
+
if (this.ontologyClient_ == null) throw new Error("Task not created");
|
|
108
106
|
return this.ontologyClient_;
|
|
109
107
|
}
|
|
110
108
|
|
|
111
109
|
get rangeClient(): ranger.Client {
|
|
112
|
-
if (this.rangeClient_ == null) throw
|
|
110
|
+
if (this.rangeClient_ == null) throw new Error("Task not created");
|
|
113
111
|
return this.rangeClient_;
|
|
114
112
|
}
|
|
115
113
|
|
|
@@ -193,7 +191,7 @@ export class Task<S extends Schemas = Schemas> {
|
|
|
193
191
|
|
|
194
192
|
async snapshottedTo(): Promise<ontology.Resource | null> {
|
|
195
193
|
if (this.ontologyClient == null || this.rangeClient == null)
|
|
196
|
-
throw
|
|
194
|
+
throw new Error("Task not created");
|
|
197
195
|
if (!this.snapshot) return null;
|
|
198
196
|
return await retrieveSnapshottedTo(this.key, this.ontologyClient);
|
|
199
197
|
}
|
|
@@ -347,7 +345,7 @@ export class Client {
|
|
|
347
345
|
}
|
|
348
346
|
|
|
349
347
|
async retrieveSnapshottedTo(taskKey: Key): Promise<ontology.Resource | null> {
|
|
350
|
-
if (this.ontologyClient == null) throw
|
|
348
|
+
if (this.ontologyClient == null) throw new Error("Task not created");
|
|
351
349
|
return await retrieveSnapshottedTo(taskKey, this.ontologyClient);
|
|
352
350
|
}
|
|
353
351
|
|
|
@@ -463,7 +461,7 @@ const executeCommands = async ({
|
|
|
463
461
|
frameClient,
|
|
464
462
|
commands,
|
|
465
463
|
}: ExecuteCommandsInternalParams): Promise<string[]> => {
|
|
466
|
-
if (frameClient == null) throw
|
|
464
|
+
if (frameClient == null) throw new Error("Task not created");
|
|
467
465
|
const w = await frameClient.openWriter(COMMAND_CHANNEL_NAME);
|
|
468
466
|
const cmds = commands.map((c) => ({ ...c, key: id.create() }));
|
|
469
467
|
await w.write(COMMAND_CHANNEL_NAME, cmds);
|
|
@@ -512,7 +510,7 @@ const executeCommandsSync = async <StatusData extends z.ZodType = z.ZodNever>({
|
|
|
512
510
|
statusDataZ,
|
|
513
511
|
name: taskName,
|
|
514
512
|
}: ExecuteCommandsSyncInternalParams<StatusData>): Promise<Status<StatusData>[]> => {
|
|
515
|
-
if (frameClient == null) throw
|
|
513
|
+
if (frameClient == null) throw new Error("Task not created");
|
|
516
514
|
const streamer = await frameClient.openStreamer(status.SET_CHANNEL_NAME);
|
|
517
515
|
const cmdKeys = await executeCommands({ frameClient, commands });
|
|
518
516
|
const parsedTimeout = new TimeSpan(timeout);
|
package/src/task/task.spec.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
|
-
import { TimeStamp } from "@synnaxlabs/x";
|
|
10
|
+
import { id, TimeStamp } from "@synnaxlabs/x";
|
|
11
11
|
import { beforeAll, describe, expect, it } from "vitest";
|
|
12
12
|
import { z } from "zod";
|
|
13
13
|
|
|
@@ -114,6 +114,20 @@ describe("Task", async () => {
|
|
|
114
114
|
expect(retrieved.key).toBe(m.key);
|
|
115
115
|
});
|
|
116
116
|
|
|
117
|
+
it("should retrieve tasks by search term", async () => {
|
|
118
|
+
const prefix = `searchable-task-${id.create()}`;
|
|
119
|
+
const names = [`${prefix}-1`, `${prefix}-2`];
|
|
120
|
+
await Promise.all(
|
|
121
|
+
names.map((name) => testRack.createTask({ name, config: {}, type: "ni" })),
|
|
122
|
+
);
|
|
123
|
+
await expect
|
|
124
|
+
.poll(async () => {
|
|
125
|
+
const results = await client.tasks.retrieve({ searchTerm: prefix });
|
|
126
|
+
return results.map((t) => t.name).sort();
|
|
127
|
+
})
|
|
128
|
+
.toEqual(names);
|
|
129
|
+
});
|
|
130
|
+
|
|
117
131
|
describe("status", () => {
|
|
118
132
|
it("should include task status when requested", async () => {
|
|
119
133
|
const t = await testRack.createTask({
|
package/src/view/view.spec.ts
CHANGED
|
@@ -113,15 +113,19 @@ describe("View", () => {
|
|
|
113
113
|
|
|
114
114
|
it("should search for views by name", async () => {
|
|
115
115
|
const client = createTestClient();
|
|
116
|
+
const prefix = id.create();
|
|
117
|
+
const name = `${prefix} View`;
|
|
116
118
|
await client.views.create({
|
|
117
|
-
name
|
|
119
|
+
name,
|
|
118
120
|
type: "lineplot",
|
|
119
121
|
query: { channels: ["search"] },
|
|
120
122
|
});
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
await expect
|
|
124
|
+
.poll(async () => {
|
|
125
|
+
const results = await client.views.retrieve({ searchTerm: prefix });
|
|
126
|
+
return results.find((v) => v.name === name);
|
|
127
|
+
})
|
|
128
|
+
.toMatchObject({ query: { channels: ["search"] } });
|
|
125
129
|
});
|
|
126
130
|
});
|
|
127
131
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
|
-
import { uuid } from "@synnaxlabs/x";
|
|
10
|
+
import { id, uuid } from "@synnaxlabs/x";
|
|
11
11
|
import { describe, expect, test } from "vitest";
|
|
12
12
|
|
|
13
13
|
import { createTestClient } from "@/testutil/client";
|
|
@@ -58,6 +58,19 @@ describe("Workspace", () => {
|
|
|
58
58
|
await expect(client.workspaces.retrieve(ws.key)).rejects.toThrow();
|
|
59
59
|
});
|
|
60
60
|
});
|
|
61
|
+
describe("retrieve", () => {
|
|
62
|
+
test("retrieve workspaces by search term", async () => {
|
|
63
|
+
const prefix = `searchable-workspace-${id.create()}`;
|
|
64
|
+
const names = [`${prefix}-1`, `${prefix}-2`];
|
|
65
|
+
await client.workspaces.create(names.map((name) => ({ name, layout: {} })));
|
|
66
|
+
await expect
|
|
67
|
+
.poll(async () => {
|
|
68
|
+
const results = await client.workspaces.retrieve({ searchTerm: prefix });
|
|
69
|
+
return results.map((w) => w.name).sort();
|
|
70
|
+
})
|
|
71
|
+
.toEqual(names);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
61
74
|
describe("case preservation", () => {
|
|
62
75
|
test("should preserve key casing in layout field on create/retrieve cycle", async () => {
|
|
63
76
|
const ws = await client.workspaces.create({
|