@synnaxlabs/client 0.40.0 → 0.42.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 +7 -7
- package/dist/access/payload.d.ts +7 -1
- package/dist/access/payload.d.ts.map +1 -1
- package/dist/access/policy/payload.d.ts +182 -142
- package/dist/access/policy/payload.d.ts.map +1 -1
- package/dist/access/policy/retriever.d.ts +25 -22
- package/dist/access/policy/retriever.d.ts.map +1 -1
- package/dist/auth/auth.d.ts +1 -7
- package/dist/auth/auth.d.ts.map +1 -1
- package/dist/channel/client.d.ts +2 -7
- package/dist/channel/client.d.ts.map +1 -1
- package/dist/channel/payload.d.ts +13 -74
- package/dist/channel/payload.d.ts.map +1 -1
- package/dist/channel/retriever.d.ts +5 -31
- package/dist/channel/retriever.d.ts.map +1 -1
- package/dist/channel/writer.d.ts +6 -18
- package/dist/channel/writer.d.ts.map +1 -1
- package/dist/client.cjs +35 -30
- package/dist/client.d.ts +8 -56
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +6391 -3850
- package/dist/connection/checker.d.ts +22 -39
- package/dist/connection/checker.d.ts.map +1 -1
- package/dist/control/client.d.ts.map +1 -1
- package/dist/control/state.d.ts +6 -26
- package/dist/control/state.d.ts.map +1 -1
- package/dist/errors.d.ts +31 -56
- package/dist/errors.d.ts.map +1 -1
- package/dist/framer/adapter.d.ts +4 -0
- package/dist/framer/adapter.d.ts.map +1 -1
- package/dist/framer/client.d.ts +2 -2
- package/dist/framer/client.d.ts.map +1 -1
- package/dist/framer/codec.d.ts +34 -0
- package/dist/framer/codec.d.ts.map +1 -0
- package/dist/framer/codec.spec.d.ts +2 -0
- package/dist/framer/codec.spec.d.ts.map +1 -0
- package/dist/framer/deleter.d.ts +12 -49
- package/dist/framer/deleter.d.ts.map +1 -1
- package/dist/framer/frame.d.ts +26 -88
- package/dist/framer/frame.d.ts.map +1 -1
- package/dist/framer/iterator.d.ts.map +1 -1
- package/dist/framer/streamer.d.ts +69 -11
- package/dist/framer/streamer.d.ts.map +1 -1
- package/dist/framer/writer.d.ts +60 -257
- package/dist/framer/writer.d.ts.map +1 -1
- package/dist/hardware/device/client.d.ts +13 -24
- package/dist/hardware/device/client.d.ts.map +1 -1
- package/dist/hardware/device/payload.d.ts +25 -44
- package/dist/hardware/device/payload.d.ts.map +1 -1
- package/dist/hardware/rack/client.d.ts +12 -5
- package/dist/hardware/rack/client.d.ts.map +1 -1
- package/dist/hardware/rack/payload.d.ts +36 -15
- package/dist/hardware/rack/payload.d.ts.map +1 -1
- package/dist/hardware/task/client.d.ts +4 -20
- package/dist/hardware/task/client.d.ts.map +1 -1
- package/dist/hardware/task/payload.d.ts +41 -116
- package/dist/hardware/task/payload.d.ts.map +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/label/payload.d.ts +1 -9
- package/dist/label/payload.d.ts.map +1 -1
- package/dist/label/writer.d.ts +27 -36
- package/dist/label/writer.d.ts.map +1 -1
- package/dist/ontology/client.d.ts +46 -36
- package/dist/ontology/client.d.ts.map +1 -1
- package/dist/ontology/group/payload.d.ts +1 -7
- package/dist/ontology/group/payload.d.ts.map +1 -1
- package/dist/ontology/payload.d.ts +239 -146
- package/dist/ontology/payload.d.ts.map +1 -1
- package/dist/ranger/client.d.ts +13 -55
- package/dist/ranger/client.d.ts.map +1 -1
- package/dist/ranger/kv.d.ts +7 -49
- package/dist/ranger/kv.d.ts.map +1 -1
- package/dist/ranger/payload.d.ts +21 -99
- package/dist/ranger/payload.d.ts.map +1 -1
- package/dist/ranger/writer.d.ts +35 -88
- package/dist/ranger/writer.d.ts.map +1 -1
- package/dist/testutil/indexedPair.d.ts +5 -0
- package/dist/testutil/indexedPair.d.ts.map +1 -0
- package/dist/testutil/telem.d.ts +3 -0
- package/dist/testutil/telem.d.ts.map +1 -0
- package/dist/transport.d.ts +2 -2
- package/dist/transport.d.ts.map +1 -1
- package/dist/user/payload.d.ts +3 -29
- package/dist/user/payload.d.ts.map +1 -1
- package/dist/user/retriever.d.ts +3 -9
- package/dist/user/retriever.d.ts.map +1 -1
- package/dist/util/decodeJSONString.d.ts.map +1 -1
- package/dist/util/zod.d.ts +1 -1
- package/dist/util/zod.d.ts.map +1 -1
- package/dist/workspace/lineplot/payload.d.ts +10 -26
- package/dist/workspace/lineplot/payload.d.ts.map +1 -1
- package/dist/workspace/log/payload.d.ts +10 -26
- package/dist/workspace/log/payload.d.ts.map +1 -1
- package/dist/workspace/payload.d.ts +14 -40
- package/dist/workspace/payload.d.ts.map +1 -1
- package/dist/workspace/schematic/payload.d.ts +13 -45
- package/dist/workspace/schematic/payload.d.ts.map +1 -1
- package/dist/workspace/table/payload.d.ts +13 -39
- package/dist/workspace/table/payload.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/channel/channel.spec.ts +26 -27
- package/src/channel/client.ts +0 -9
- package/src/channel/payload.ts +22 -5
- package/src/channel/retriever.ts +12 -6
- package/src/client.ts +4 -4
- package/src/control/client.ts +5 -2
- package/src/control/state.spec.ts +1 -2
- package/src/control/state.ts +8 -3
- package/src/errors.spec.ts +5 -4
- package/src/errors.ts +21 -82
- package/src/framer/adapter.ts +22 -3
- package/src/framer/client.ts +38 -21
- package/src/framer/codec.spec.ts +303 -0
- package/src/framer/codec.ts +396 -0
- package/src/framer/deleter.spec.ts +51 -63
- package/src/framer/frame.ts +16 -5
- package/src/framer/iterator.spec.ts +45 -28
- package/src/framer/iterator.ts +6 -5
- package/src/framer/streamProxy.ts +1 -1
- package/src/framer/streamer.spec.ts +10 -27
- package/src/framer/streamer.ts +138 -22
- package/src/framer/writer.spec.ts +125 -150
- package/src/framer/writer.ts +74 -68
- package/src/hardware/device/client.ts +42 -10
- package/src/hardware/device/device.spec.ts +109 -1
- package/src/hardware/device/payload.ts +17 -3
- package/src/hardware/rack/client.ts +48 -8
- package/src/hardware/rack/payload.ts +16 -1
- package/src/hardware/rack/rack.spec.ts +36 -0
- package/src/hardware/task/payload.ts +9 -6
- package/src/hardware/task/task.spec.ts +9 -6
- package/src/index.ts +0 -2
- package/src/ontology/group/group.spec.ts +2 -2
- package/src/ontology/payload.ts +3 -3
- package/src/ranger/client.ts +3 -2
- package/src/ranger/ranger.spec.ts +9 -7
- package/src/testutil/indexedPair.ts +40 -0
- package/src/testutil/telem.ts +13 -0
- package/src/transport.ts +1 -2
- package/src/util/decodeJSONString.ts +2 -2
- package/src/util/retrieve.spec.ts +1 -1
|
@@ -13,6 +13,7 @@ import { type AsyncTermSearcher } from "@synnaxlabs/x/search";
|
|
|
13
13
|
import { toArray } from "@synnaxlabs/x/toArray";
|
|
14
14
|
import { z } from "zod";
|
|
15
15
|
|
|
16
|
+
import { framer } from "@/framer";
|
|
16
17
|
import {
|
|
17
18
|
type Key,
|
|
18
19
|
keyZ,
|
|
@@ -21,6 +22,8 @@ import {
|
|
|
21
22
|
ONTOLOGY_TYPE,
|
|
22
23
|
type Payload,
|
|
23
24
|
rackZ,
|
|
25
|
+
type State,
|
|
26
|
+
stateZ,
|
|
24
27
|
} from "@/hardware/rack/payload";
|
|
25
28
|
import { type task } from "@/hardware/task";
|
|
26
29
|
import { ontology } from "@/ontology";
|
|
@@ -31,12 +34,17 @@ const RETRIEVE_ENDPOINT = "/hardware/rack/retrieve";
|
|
|
31
34
|
const CREATE_ENDPOINT = "/hardware/rack/create";
|
|
32
35
|
const DELETE_ENDPOINT = "/hardware/rack/delete";
|
|
33
36
|
|
|
37
|
+
const STATE_CHANNEL_NAME = "sy_rack_state";
|
|
38
|
+
|
|
34
39
|
const retrieveReqZ = z.object({
|
|
35
40
|
keys: keyZ.array().optional(),
|
|
36
41
|
names: z.string().array().optional(),
|
|
37
42
|
search: z.string().optional(),
|
|
38
|
-
|
|
43
|
+
embedded: z.boolean().optional(),
|
|
44
|
+
hostIsNode: z.boolean().optional(),
|
|
39
45
|
limit: z.number().optional(),
|
|
46
|
+
offset: z.number().optional(),
|
|
47
|
+
includeState: z.boolean().optional(),
|
|
40
48
|
});
|
|
41
49
|
|
|
42
50
|
const retrieveResZ = z.object({ racks: nullableArrayZ(rackZ) });
|
|
@@ -49,14 +57,24 @@ const deleteReqZ = z.object({ keys: keyZ.array() });
|
|
|
49
57
|
|
|
50
58
|
const deleteResZ = z.object({});
|
|
51
59
|
|
|
60
|
+
export interface RetrieveOptions {
|
|
61
|
+
includeState?: boolean;
|
|
62
|
+
}
|
|
63
|
+
|
|
52
64
|
export class Client implements AsyncTermSearcher<string, Key, Payload> {
|
|
53
65
|
readonly type = ONTOLOGY_TYPE;
|
|
54
66
|
private readonly client: UnaryClient;
|
|
55
67
|
private readonly tasks: task.Client;
|
|
68
|
+
private readonly frameClient: framer.Client;
|
|
56
69
|
|
|
57
|
-
constructor(
|
|
70
|
+
constructor(
|
|
71
|
+
client: UnaryClient,
|
|
72
|
+
taskClient: task.Client,
|
|
73
|
+
frameClient: framer.Client,
|
|
74
|
+
) {
|
|
58
75
|
this.client = client;
|
|
59
76
|
this.tasks = taskClient;
|
|
77
|
+
this.frameClient = frameClient;
|
|
60
78
|
}
|
|
61
79
|
|
|
62
80
|
async delete(keys: Key | Key[]): Promise<void> {
|
|
@@ -107,9 +125,12 @@ export class Client implements AsyncTermSearcher<string, Key, Payload> {
|
|
|
107
125
|
return this.sugar(res.racks);
|
|
108
126
|
}
|
|
109
127
|
|
|
110
|
-
async retrieve(key: string | Key): Promise<Rack>;
|
|
111
|
-
async retrieve(keys: Key[]): Promise<Rack[]>;
|
|
112
|
-
async retrieve(
|
|
128
|
+
async retrieve(key: string | Key, options?: RetrieveOptions): Promise<Rack>;
|
|
129
|
+
async retrieve(keys: Key[], options?: RetrieveOptions): Promise<Rack[]>;
|
|
130
|
+
async retrieve(
|
|
131
|
+
racks: string | Key | Key[],
|
|
132
|
+
options?: RetrieveOptions,
|
|
133
|
+
): Promise<Rack | Rack[]> {
|
|
113
134
|
const { variant, normalized, single } = analyzeParams(racks, {
|
|
114
135
|
string: "names",
|
|
115
136
|
number: "keys",
|
|
@@ -117,7 +138,10 @@ export class Client implements AsyncTermSearcher<string, Key, Payload> {
|
|
|
117
138
|
const res = await sendRequired<typeof retrieveReqZ, typeof retrieveResZ>(
|
|
118
139
|
this.client,
|
|
119
140
|
RETRIEVE_ENDPOINT,
|
|
120
|
-
{
|
|
141
|
+
{
|
|
142
|
+
[variant]: normalized,
|
|
143
|
+
includeState: options?.includeState,
|
|
144
|
+
},
|
|
121
145
|
retrieveReqZ,
|
|
122
146
|
retrieveResZ,
|
|
123
147
|
);
|
|
@@ -126,20 +150,36 @@ export class Client implements AsyncTermSearcher<string, Key, Payload> {
|
|
|
126
150
|
return single ? sugared[0] : sugared;
|
|
127
151
|
}
|
|
128
152
|
|
|
153
|
+
async openStateObserver(): Promise<framer.ObservableStreamer<State[]>> {
|
|
154
|
+
return new framer.ObservableStreamer<State[]>(
|
|
155
|
+
await this.frameClient.openStreamer(STATE_CHANNEL_NAME),
|
|
156
|
+
(fr) => {
|
|
157
|
+
const data = fr.get(STATE_CHANNEL_NAME);
|
|
158
|
+
if (data.length === 0) return [[], false];
|
|
159
|
+
const states = data.parseJSON(stateZ);
|
|
160
|
+
return [states, true];
|
|
161
|
+
},
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
129
165
|
private sugar(payloads: Payload[]): Rack[] {
|
|
130
|
-
return payloads.map(
|
|
166
|
+
return payloads.map(
|
|
167
|
+
({ key, name, state }) => new Rack(key, name, this.tasks, state),
|
|
168
|
+
);
|
|
131
169
|
}
|
|
132
170
|
}
|
|
133
171
|
|
|
134
172
|
export class Rack {
|
|
135
173
|
key: Key;
|
|
136
174
|
name: string;
|
|
175
|
+
state?: State;
|
|
137
176
|
private readonly tasks: task.Client;
|
|
138
177
|
|
|
139
|
-
constructor(key: Key, name: string, taskClient: task.Client) {
|
|
178
|
+
constructor(key: Key, name: string, taskClient: task.Client, state?: State) {
|
|
140
179
|
this.key = key;
|
|
141
180
|
this.name = name;
|
|
142
181
|
this.tasks = taskClient;
|
|
182
|
+
this.state = state;
|
|
143
183
|
}
|
|
144
184
|
|
|
145
185
|
async listTasks(): Promise<task.Task[]> {
|
|
@@ -8,12 +8,27 @@
|
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
10
|
import { zod } from "@synnaxlabs/x";
|
|
11
|
+
import { TimeStamp } from "@synnaxlabs/x/telem";
|
|
11
12
|
import { z } from "zod";
|
|
12
13
|
|
|
13
14
|
export const keyZ = zod.uint32;
|
|
14
15
|
export type Key = z.infer<typeof keyZ>;
|
|
15
16
|
|
|
16
|
-
export const
|
|
17
|
+
export const stateZ = z.object({
|
|
18
|
+
key: keyZ,
|
|
19
|
+
variant: z.string(),
|
|
20
|
+
message: z.string(),
|
|
21
|
+
lastReceived: TimeStamp.z.optional(),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export interface State extends z.infer<typeof stateZ> {}
|
|
25
|
+
|
|
26
|
+
export const rackZ = z.object({
|
|
27
|
+
key: keyZ,
|
|
28
|
+
name: z.string(),
|
|
29
|
+
state: stateZ.optional(),
|
|
30
|
+
});
|
|
31
|
+
|
|
17
32
|
export interface Payload extends z.infer<typeof rackZ> {}
|
|
18
33
|
|
|
19
34
|
export const newZ = rackZ.partial({ key: true });
|
|
@@ -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 { TimeStamp } from "@synnaxlabs/x";
|
|
10
11
|
import { describe, expect, it } from "vitest";
|
|
11
12
|
import { ZodError } from "zod";
|
|
12
13
|
|
|
@@ -66,4 +67,39 @@ describe("Rack", () => {
|
|
|
66
67
|
).rejects.toThrow(NotFoundError);
|
|
67
68
|
});
|
|
68
69
|
});
|
|
70
|
+
describe("state", () => {
|
|
71
|
+
it("should include state when includeState is true", async () => {
|
|
72
|
+
const r = await client.hardware.racks.create({ name: "test" });
|
|
73
|
+
await expect
|
|
74
|
+
.poll(async () => {
|
|
75
|
+
const retrieved = await client.hardware.racks.retrieve(r.key, {
|
|
76
|
+
includeState: true,
|
|
77
|
+
});
|
|
78
|
+
return (
|
|
79
|
+
retrieved.state !== undefined &&
|
|
80
|
+
retrieved.state.lastReceived instanceof TimeStamp &&
|
|
81
|
+
retrieved.state.key === r.key
|
|
82
|
+
);
|
|
83
|
+
})
|
|
84
|
+
.toBeTruthy();
|
|
85
|
+
});
|
|
86
|
+
it("should include state for multiple racks", async () => {
|
|
87
|
+
const r1 = await client.hardware.racks.create({ name: "test1" });
|
|
88
|
+
const r2 = await client.hardware.racks.create({ name: "test2" });
|
|
89
|
+
|
|
90
|
+
await expect
|
|
91
|
+
.poll(async () => {
|
|
92
|
+
const retrieved = await client.hardware.racks.retrieve([r1.key, r2.key], {
|
|
93
|
+
includeState: true,
|
|
94
|
+
});
|
|
95
|
+
return retrieved.every(
|
|
96
|
+
(rack) =>
|
|
97
|
+
rack.state !== undefined &&
|
|
98
|
+
rack.state.lastReceived instanceof TimeStamp &&
|
|
99
|
+
rack.state.key === rack.key,
|
|
100
|
+
);
|
|
101
|
+
})
|
|
102
|
+
.toBeTruthy();
|
|
103
|
+
});
|
|
104
|
+
});
|
|
69
105
|
});
|
|
@@ -7,7 +7,12 @@
|
|
|
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 {
|
|
10
|
+
import {
|
|
11
|
+
binary,
|
|
12
|
+
type observe,
|
|
13
|
+
type UnknownRecord,
|
|
14
|
+
unknownRecordZ,
|
|
15
|
+
} from "@synnaxlabs/x";
|
|
11
16
|
import { z } from "zod";
|
|
12
17
|
|
|
13
18
|
import { type Key as RackKey } from "@/hardware/rack/payload";
|
|
@@ -28,8 +33,7 @@ export const stateZ = z.object({
|
|
|
28
33
|
task: keyZ,
|
|
29
34
|
variant: statusZ,
|
|
30
35
|
key: z.string().optional(),
|
|
31
|
-
details:
|
|
32
|
-
.record(z.unknown())
|
|
36
|
+
details: unknownRecordZ
|
|
33
37
|
.or(z.string().transform(parseWithoutKeyConversion))
|
|
34
38
|
.or(z.array(z.unknown()))
|
|
35
39
|
.or(z.null()) as z.ZodType<UnknownRecord | undefined>,
|
|
@@ -44,7 +48,7 @@ export const taskZ = z.object({
|
|
|
44
48
|
name: z.string(),
|
|
45
49
|
type: z.string(),
|
|
46
50
|
internal: z.boolean().optional(),
|
|
47
|
-
config:
|
|
51
|
+
config: unknownRecordZ.or(z.string().transform(decodeJSONString)),
|
|
48
52
|
state: stateZ.optional().nullable(),
|
|
49
53
|
snapshot: z.boolean().optional(),
|
|
50
54
|
});
|
|
@@ -74,8 +78,7 @@ export const commandZ = z.object({
|
|
|
74
78
|
task: keyZ,
|
|
75
79
|
type: z.string(),
|
|
76
80
|
key: z.string(),
|
|
77
|
-
args:
|
|
78
|
-
.record(z.unknown())
|
|
81
|
+
args: unknownRecordZ
|
|
79
82
|
.or(z.string().transform(parseWithoutKeyConversion))
|
|
80
83
|
.or(z.array(z.unknown()))
|
|
81
84
|
.or(z.null())
|
|
@@ -98,13 +98,16 @@ describe("Task", async () => {
|
|
|
98
98
|
task: t.key,
|
|
99
99
|
variant: "success",
|
|
100
100
|
};
|
|
101
|
-
|
|
101
|
+
await w.write("sy_task_state", [state]);
|
|
102
102
|
await w.close();
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
103
|
+
await expect
|
|
104
|
+
.poll(async () => {
|
|
105
|
+
const retrieved = await client.hardware.tasks.retrieve(t.key, {
|
|
106
|
+
includeState: true,
|
|
107
|
+
});
|
|
108
|
+
return retrieved.state?.variant === state.variant;
|
|
109
|
+
})
|
|
110
|
+
.toBeTruthy();
|
|
108
111
|
});
|
|
109
112
|
});
|
|
110
113
|
});
|
package/src/index.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import { describe, expect, it } from "vitest";
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import { NotFoundError } from "@/errors";
|
|
13
13
|
import { ontology } from "@/ontology";
|
|
14
14
|
import { newClient } from "@/setupspecs";
|
|
15
15
|
|
|
@@ -40,7 +40,7 @@ describe("Group", () => {
|
|
|
40
40
|
await client.ontology.groups.delete(g.key);
|
|
41
41
|
await expect(
|
|
42
42
|
async () => await client.ontology.retrieve(g.ontologyID),
|
|
43
|
-
).rejects.
|
|
43
|
+
).rejects.toThrowError(NotFoundError);
|
|
44
44
|
});
|
|
45
45
|
});
|
|
46
46
|
});
|
package/src/ontology/payload.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 { type change, type UnknownRecord } from "@synnaxlabs/x";
|
|
10
|
+
import { type change, type UnknownRecord, unknownRecordZ } from "@synnaxlabs/x";
|
|
11
11
|
import { z } from "zod";
|
|
12
12
|
|
|
13
13
|
import {
|
|
@@ -124,7 +124,7 @@ export interface SchemaField extends z.infer<typeof schemaFieldZ> {}
|
|
|
124
124
|
|
|
125
125
|
export const schemaZ = z.object({
|
|
126
126
|
type: resourceTypeZ,
|
|
127
|
-
fields: z.record(schemaFieldZ),
|
|
127
|
+
fields: z.record(z.string(), schemaFieldZ),
|
|
128
128
|
});
|
|
129
129
|
export interface Schema extends z.infer<typeof schemaZ> {}
|
|
130
130
|
|
|
@@ -133,7 +133,7 @@ export const resourceZ = z
|
|
|
133
133
|
id: ID.z,
|
|
134
134
|
name: z.string(),
|
|
135
135
|
schema: schemaZ.optional().nullable(),
|
|
136
|
-
data:
|
|
136
|
+
data: unknownRecordZ.optional().nullable(),
|
|
137
137
|
})
|
|
138
138
|
.transform((resource) => ({ key: resource.id.toString(), ...resource }));
|
|
139
139
|
export interface Resource<T extends UnknownRecord = UnknownRecord>
|
package/src/ranger/client.ts
CHANGED
|
@@ -17,7 +17,7 @@ import { z } from "zod";
|
|
|
17
17
|
import { type channel } from "@/channel";
|
|
18
18
|
import { MultipleFoundError, NotFoundError, QueryError } from "@/errors";
|
|
19
19
|
import { type framer } from "@/framer";
|
|
20
|
-
import {
|
|
20
|
+
import { label } from "@/label";
|
|
21
21
|
import { ontology } from "@/ontology";
|
|
22
22
|
import { type Alias, Aliaser } from "@/ranger/alias";
|
|
23
23
|
import { KV } from "@/ranger/kv";
|
|
@@ -195,6 +195,7 @@ const retrieveReqZ = z.object({
|
|
|
195
195
|
overlapsWith: TimeRange.z.optional(),
|
|
196
196
|
limit: z.number().int().optional(),
|
|
197
197
|
offset: z.number().int().optional(),
|
|
198
|
+
hasLabels: label.keyZ.array().optional(),
|
|
198
199
|
});
|
|
199
200
|
|
|
200
201
|
export interface RetrieveRequest extends z.infer<typeof retrieveReqZ> {}
|
|
@@ -321,7 +322,7 @@ export class Client implements AsyncTermSearcher<string, Key, Range> {
|
|
|
321
322
|
"sy_range_delete",
|
|
322
323
|
(variant, data) => {
|
|
323
324
|
if (variant === "delete")
|
|
324
|
-
return data.
|
|
325
|
+
return data.toUUIDs().map((k) => ({ variant, key: k, value: undefined }));
|
|
325
326
|
const sugared = this.sugarMany(data.parseJSON(payloadZ));
|
|
326
327
|
return sugared.map((r) => ({ variant, key: r.key, value: r }));
|
|
327
328
|
},
|
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
10
|
import { type change } from "@synnaxlabs/x";
|
|
11
|
-
import { DataType,
|
|
11
|
+
import { DataType, TimeSpan, TimeStamp } from "@synnaxlabs/x/telem";
|
|
12
12
|
import { describe, expect, it } from "vitest";
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import { NotFoundError } from "@/errors";
|
|
15
15
|
import { type ranger } from "@/ranger";
|
|
16
16
|
import { newClient } from "@/setupspecs";
|
|
17
17
|
|
|
@@ -74,7 +74,7 @@ describe("Ranger", () => {
|
|
|
74
74
|
});
|
|
75
75
|
await client.ranges.delete(range.key);
|
|
76
76
|
await expect(async () => await client.ranges.retrieve(range.key)).rejects.toThrow(
|
|
77
|
-
|
|
77
|
+
NotFoundError,
|
|
78
78
|
);
|
|
79
79
|
});
|
|
80
80
|
});
|
|
@@ -172,7 +172,9 @@ describe("Ranger", () => {
|
|
|
172
172
|
const val = await rng.kv.get("foo");
|
|
173
173
|
expect(val).toEqual("bar");
|
|
174
174
|
await rng.kv.delete("foo");
|
|
175
|
-
await expect(async () => await rng.kv.get("foo")).rejects.
|
|
175
|
+
await expect(async () => await rng.kv.get("foo")).rejects.toThrowError(
|
|
176
|
+
NotFoundError,
|
|
177
|
+
);
|
|
176
178
|
});
|
|
177
179
|
|
|
178
180
|
it("should set and get multiple keys", async () => {
|
|
@@ -240,7 +242,7 @@ describe("Ranger", () => {
|
|
|
240
242
|
const ch = await client.channels.create({
|
|
241
243
|
name: "My New Channel",
|
|
242
244
|
dataType: DataType.FLOAT32,
|
|
243
|
-
|
|
245
|
+
virtual: true,
|
|
244
246
|
});
|
|
245
247
|
const rng = await client.ranges.create({
|
|
246
248
|
name: "My New One Second Range",
|
|
@@ -256,7 +258,7 @@ describe("Ranger", () => {
|
|
|
256
258
|
const ch = await client.channels.create({
|
|
257
259
|
name: "My New Channel",
|
|
258
260
|
dataType: DataType.FLOAT32,
|
|
259
|
-
|
|
261
|
+
virtual: true,
|
|
260
262
|
});
|
|
261
263
|
const rng = await client.ranges.create({
|
|
262
264
|
name: "My New One Second Range",
|
|
@@ -272,7 +274,7 @@ describe("Ranger", () => {
|
|
|
272
274
|
const ch = await client.channels.create({
|
|
273
275
|
name: "My New Channel",
|
|
274
276
|
dataType: DataType.FLOAT32,
|
|
275
|
-
|
|
277
|
+
virtual: true,
|
|
276
278
|
});
|
|
277
279
|
const rng = await client.ranges.create({
|
|
278
280
|
name: "My New One Second Range",
|
|
@@ -0,0 +1,40 @@
|
|
|
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 { DataType, id } from "@synnaxlabs/x";
|
|
11
|
+
|
|
12
|
+
import { type channel } from "@/channel";
|
|
13
|
+
import type Synnax from "@/client";
|
|
14
|
+
|
|
15
|
+
export const newIndexedPair = async (
|
|
16
|
+
client: Synnax,
|
|
17
|
+
): Promise<[channel.Channel, channel.Channel]> => {
|
|
18
|
+
const index = await client.channels.create({
|
|
19
|
+
leaseholder: 1,
|
|
20
|
+
name: `test-${id.create()}`,
|
|
21
|
+
dataType: DataType.TIMESTAMP,
|
|
22
|
+
isIndex: true,
|
|
23
|
+
});
|
|
24
|
+
const data = await client.channels.create({
|
|
25
|
+
leaseholder: 1,
|
|
26
|
+
name: `test-${id.create()}`,
|
|
27
|
+
dataType: DataType.FLOAT64,
|
|
28
|
+
index: index.key,
|
|
29
|
+
});
|
|
30
|
+
return [index, data];
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const newVirtualChannel = async (client: Synnax): Promise<channel.Channel> => {
|
|
34
|
+
const ch = await client.channels.create({
|
|
35
|
+
name: `test-${id.create()}`,
|
|
36
|
+
dataType: DataType.FLOAT64,
|
|
37
|
+
virtual: true,
|
|
38
|
+
});
|
|
39
|
+
return ch;
|
|
40
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
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 { TimeStamp } from "@synnaxlabs/x";
|
|
11
|
+
|
|
12
|
+
export const secondsLinspace = (start: number, n: number): TimeStamp[] =>
|
|
13
|
+
Array.from({ length: n }, (_, i) => start + i).map((n) => TimeStamp.seconds(n));
|
package/src/transport.ts
CHANGED
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
import {
|
|
11
11
|
HTTPClient,
|
|
12
12
|
type Middleware,
|
|
13
|
-
type StreamClient,
|
|
14
13
|
type UnaryClient,
|
|
15
14
|
unaryWithBreaker,
|
|
16
15
|
WebSocketClient,
|
|
@@ -24,7 +23,7 @@ const baseAPIEndpoint = "/api/v1/";
|
|
|
24
23
|
export class Transport {
|
|
25
24
|
readonly url: URL;
|
|
26
25
|
readonly unary: UnaryClient;
|
|
27
|
-
readonly stream:
|
|
26
|
+
readonly stream: WebSocketClient;
|
|
28
27
|
readonly secure: boolean;
|
|
29
28
|
|
|
30
29
|
constructor(url: URL, breakerCfg: breaker.Config = {}, secure: boolean = false) {
|
|
@@ -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 { binary, type UnknownRecord } from "@synnaxlabs/x";
|
|
10
|
+
import { binary, type UnknownRecord, unknownRecordZ } from "@synnaxlabs/x";
|
|
11
11
|
|
|
12
12
|
export const decodeJSONString = (s: string): UnknownRecord =>
|
|
13
|
-
s ? binary.JSON_CODEC.decodeString(s) : {};
|
|
13
|
+
s ? binary.JSON_CODEC.decodeString(s, unknownRecordZ) : {};
|
|
@@ -7,8 +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 { type Primitive } from "@synnaxlabs/x";
|
|
10
11
|
import { describe, expect, it } from "vitest";
|
|
11
|
-
import { type Primitive } from "zod";
|
|
12
12
|
|
|
13
13
|
import {
|
|
14
14
|
analyzeParams,
|