@synnaxlabs/client 0.20.0 → 0.22.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/.vscode/settings.json +3 -0
- package/README.md +13 -0
- package/dist/auth/auth.d.ts +7 -6
- package/dist/auth/auth.d.ts.map +1 -1
- package/dist/channel/client.d.ts +14 -11
- package/dist/channel/client.d.ts.map +1 -1
- package/dist/channel/creator.d.ts +10 -0
- package/dist/channel/creator.d.ts.map +1 -0
- package/dist/channel/payload.d.ts +6 -2
- package/dist/channel/payload.d.ts.map +1 -1
- package/dist/channel/retriever.d.ts +65 -35
- package/dist/channel/retriever.d.ts.map +1 -1
- package/dist/channel/writer.d.ts +4 -3
- package/dist/client.cjs +19 -22
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.ts +12 -10
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +6781 -6675
- package/dist/client.js.map +1 -1
- package/dist/connection/checker.d.ts +4 -3
- package/dist/connection/checker.d.ts.map +1 -1
- package/dist/control/authority.d.ts +2 -1
- package/dist/control/state.d.ts +6 -4
- package/dist/control/state.d.ts.map +1 -1
- package/dist/errors.d.ts +24 -20
- package/dist/errors.d.ts.map +1 -1
- package/dist/framer/adapter.d.ts +5 -4
- package/dist/framer/adapter.d.ts.map +1 -1
- package/dist/framer/client.d.ts +12 -12
- package/dist/framer/client.d.ts.map +1 -1
- package/dist/framer/frame.d.ts +13 -12
- package/dist/framer/frame.d.ts.map +1 -1
- package/dist/framer/iterator.d.ts +5 -4
- package/dist/framer/iterator.d.ts.map +1 -1
- package/dist/framer/streamProxy.d.ts +3 -2
- package/dist/framer/streamProxy.d.ts.map +1 -1
- package/dist/framer/streamer.d.ts +13 -4
- package/dist/framer/streamer.d.ts.map +1 -1
- package/dist/framer/writer.d.ts +67 -33
- package/dist/framer/writer.d.ts.map +1 -1
- package/dist/hardware/client.d.ts +4 -3
- package/dist/hardware/device/client.d.ts +107 -14
- package/dist/hardware/device/client.d.ts.map +1 -1
- package/dist/hardware/device/external.d.ts +0 -2
- package/dist/hardware/device/external.d.ts.map +1 -1
- package/dist/hardware/device/index.d.ts +1 -1
- package/dist/hardware/device/index.d.ts.map +1 -1
- package/dist/hardware/rack/client.d.ts +43 -20
- package/dist/hardware/rack/client.d.ts.map +1 -1
- package/dist/hardware/rack/external.d.ts +0 -2
- package/dist/hardware/rack/external.d.ts.map +1 -1
- package/dist/hardware/task/client.d.ts +197 -14
- package/dist/hardware/task/client.d.ts.map +1 -1
- package/dist/hardware/task/index.d.ts +1 -1
- package/dist/hardware/task/index.d.ts.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/label/client.d.ts +8 -6
- package/dist/label/client.d.ts.map +1 -1
- package/dist/label/payload.d.ts +2 -1
- package/dist/label/retriever.d.ts +3 -2
- package/dist/label/writer.d.ts +4 -3
- package/dist/ontology/client.d.ts +82 -14
- package/dist/ontology/client.d.ts.map +1 -1
- package/dist/ontology/external.d.ts +0 -1
- package/dist/ontology/external.d.ts.map +1 -1
- package/dist/ontology/group/client.d.ts +3 -2
- package/dist/ontology/group/client.d.ts.map +1 -1
- package/dist/ontology/group/group.d.ts +1 -0
- package/dist/ontology/group/payload.d.ts +2 -1
- package/dist/ontology/group/writer.d.ts +4 -3
- package/dist/ontology/payload.d.ts +71 -60
- package/dist/ontology/payload.d.ts.map +1 -1
- package/dist/ontology/writer.d.ts +3 -2
- package/dist/ranger/active.d.ts +3 -2
- package/dist/ranger/alias.d.ts +7 -6
- package/dist/ranger/alias.d.ts.map +1 -1
- package/dist/ranger/client.d.ts +162 -11
- package/dist/ranger/client.d.ts.map +1 -1
- package/dist/ranger/external.d.ts +0 -1
- package/dist/ranger/external.d.ts.map +1 -1
- package/dist/ranger/kv.d.ts +5 -3
- package/dist/ranger/kv.d.ts.map +1 -1
- package/dist/ranger/payload.d.ts +57 -50
- package/dist/ranger/payload.d.ts.map +1 -1
- package/dist/ranger/range.d.ts +12 -10
- package/dist/ranger/range.d.ts.map +1 -1
- package/dist/ranger/writer.d.ts +3 -2
- package/dist/setupspecs.d.ts +2 -1
- package/dist/signals/observable.d.ts +8 -15
- package/dist/signals/observable.d.ts.map +1 -1
- package/dist/transport.d.ts +3 -2
- package/dist/transport.d.ts.map +1 -1
- package/dist/user/payload.d.ts +2 -1
- package/dist/util/retrieve.d.ts +24 -0
- package/dist/util/retrieve.d.ts.map +1 -0
- package/dist/util/retrieve.spec.d.ts +2 -0
- package/dist/util/retrieve.spec.d.ts.map +1 -0
- package/dist/util/telem.d.ts +2 -1
- package/dist/util/telem.d.ts.map +1 -1
- package/dist/util/zod.d.ts +4 -0
- package/dist/util/zod.d.ts.map +1 -0
- package/dist/workspace/client.d.ts +9 -6
- package/dist/workspace/client.d.ts.map +1 -1
- package/dist/workspace/lineplot/client.d.ts +6 -5
- package/dist/workspace/lineplot/client.d.ts.map +1 -1
- package/dist/workspace/lineplot/payload.d.ts +3 -2
- package/dist/workspace/lineplot/payload.d.ts.map +1 -1
- package/dist/workspace/lineplot/retriever.d.ts +3 -2
- package/dist/workspace/lineplot/retriever.d.ts.map +1 -1
- package/dist/workspace/lineplot/writer.d.ts +7 -6
- package/dist/workspace/lineplot/writer.d.ts.map +1 -1
- package/dist/workspace/payload.d.ts +3 -2
- package/dist/workspace/payload.d.ts.map +1 -1
- package/dist/workspace/retriever.d.ts +3 -2
- package/dist/workspace/schematic/client.d.ts +18 -0
- package/dist/workspace/schematic/client.d.ts.map +1 -0
- package/dist/workspace/schematic/external.d.ts.map +1 -0
- package/dist/workspace/schematic/index.d.ts +2 -0
- package/dist/workspace/schematic/index.d.ts.map +1 -0
- package/dist/workspace/{pid → schematic}/payload.d.ts +6 -5
- package/dist/workspace/schematic/payload.d.ts.map +1 -0
- package/dist/workspace/schematic/retriever.d.ts +10 -0
- package/dist/workspace/schematic/retriever.d.ts.map +1 -0
- package/dist/workspace/schematic/schematic.spec.d.ts +2 -0
- package/dist/workspace/schematic/schematic.spec.d.ts.map +1 -0
- package/dist/workspace/{pid → schematic}/writer.d.ts +11 -10
- package/dist/workspace/schematic/writer.d.ts.map +1 -0
- package/dist/workspace/writer.d.ts +5 -4
- package/dist/workspace/writer.d.ts.map +1 -1
- package/examples/node/package-lock.json +29 -12
- package/examples/node/package.json +2 -2
- package/examples/node/streamWrite.js +8 -11
- package/package.json +10 -9
- package/src/auth/auth.spec.ts +55 -15
- package/src/auth/auth.ts +41 -42
- package/src/channel/batchRetriever.spec.ts +37 -40
- package/src/channel/channel.spec.ts +4 -4
- package/src/channel/client.ts +42 -49
- package/src/channel/creator.ts +37 -0
- package/src/channel/payload.ts +2 -1
- package/src/channel/retriever.ts +55 -71
- package/src/client.ts +23 -20
- package/src/connection/checker.ts +1 -1
- package/src/connection/connection.spec.ts +1 -6
- package/src/control/state.ts +3 -1
- package/src/errors.ts +71 -67
- package/src/framer/adapter.spec.ts +33 -1
- package/src/framer/adapter.ts +10 -6
- package/src/framer/client.ts +13 -12
- package/src/framer/frame.spec.ts +1 -1
- package/src/framer/frame.ts +9 -6
- package/src/framer/iterator.spec.ts +1 -1
- package/src/framer/iterator.ts +1 -1
- package/src/framer/streamProxy.ts +12 -13
- package/src/framer/streamer.spec.ts +1 -1
- package/src/framer/streamer.ts +25 -1
- package/src/framer/writer.spec.ts +49 -2
- package/src/framer/writer.ts +27 -2
- package/src/hardware/device/client.ts +155 -28
- package/src/hardware/device/device.spec.ts +2 -2
- package/src/hardware/device/external.ts +0 -2
- package/src/hardware/device/index.ts +2 -2
- package/src/hardware/rack/client.ts +139 -56
- package/src/hardware/rack/external.ts +0 -2
- package/src/hardware/rack/rack.spec.ts +20 -1
- package/src/hardware/task/client.ts +324 -31
- package/src/hardware/task/index.ts +1 -1
- package/src/hardware/task/task.spec.ts +41 -0
- package/src/index.ts +3 -4
- package/src/label/client.ts +3 -2
- package/src/label/retriever.ts +1 -1
- package/src/label/writer.ts +1 -1
- package/src/ontology/client.ts +195 -41
- package/src/ontology/external.ts +0 -1
- package/src/ontology/group/client.ts +1 -2
- package/src/ontology/group/payload.ts +1 -1
- package/src/ontology/ontology.spec.ts +16 -0
- package/src/ontology/payload.ts +22 -13
- package/src/ranger/active.ts +5 -5
- package/src/ranger/alias.ts +2 -2
- package/src/ranger/client.ts +68 -17
- package/src/ranger/external.ts +0 -1
- package/src/ranger/kv.ts +6 -1
- package/src/ranger/payload.ts +6 -4
- package/src/ranger/range.ts +4 -1
- package/src/ranger/ranger.spec.ts +24 -2
- package/src/signals/observable.ts +24 -63
- package/src/transport.ts +2 -1
- package/src/util/retrieve.spec.ts +56 -0
- package/src/util/retrieve.ts +103 -0
- package/src/util/telem.ts +1 -1
- package/src/util/zod.ts +4 -0
- package/src/workspace/client.ts +6 -4
- package/src/workspace/lineplot/client.ts +3 -3
- package/src/workspace/lineplot/linePlot.spec.ts +11 -11
- package/src/workspace/lineplot/payload.ts +1 -1
- package/src/workspace/lineplot/retriever.ts +5 -13
- package/src/workspace/lineplot/writer.ts +8 -7
- package/src/workspace/payload.ts +6 -3
- package/src/workspace/retriever.ts +1 -1
- package/src/workspace/{pid → schematic}/client.ts +10 -10
- package/src/workspace/{pid → schematic}/external.ts +2 -2
- package/src/workspace/{pid → schematic}/index.ts +1 -1
- package/src/workspace/{pid → schematic}/payload.ts +4 -4
- package/src/workspace/{pid → schematic}/retriever.ts +10 -10
- package/src/workspace/{pid/pid.spec.ts → schematic/schematic.spec.ts} +35 -35
- package/src/workspace/{pid → schematic}/writer.ts +26 -25
- package/src/workspace/workspace.spec.ts +7 -7
- package/src/workspace/writer.ts +8 -2
- package/dist/hardware/device/payload.d.ts +0 -30
- package/dist/hardware/device/payload.d.ts.map +0 -1
- package/dist/hardware/device/retriever.d.ts +0 -10
- package/dist/hardware/device/retriever.d.ts.map +0 -1
- package/dist/hardware/device/writer.d.ts +0 -9
- package/dist/hardware/device/writer.d.ts.map +0 -1
- package/dist/hardware/rack/payload.d.ts +0 -26
- package/dist/hardware/rack/payload.d.ts.map +0 -1
- package/dist/hardware/rack/retriever.d.ts +0 -10
- package/dist/hardware/rack/retriever.d.ts.map +0 -1
- package/dist/hardware/rack/writer.d.ts +0 -9
- package/dist/hardware/rack/writer.d.ts.map +0 -1
- package/dist/hardware/task/external.d.ts +0 -4
- package/dist/hardware/task/external.d.ts.map +0 -1
- package/dist/hardware/task/payload.d.ts +0 -42
- package/dist/hardware/task/payload.d.ts.map +0 -1
- package/dist/hardware/task/retriever.d.ts +0 -29
- package/dist/hardware/task/retriever.d.ts.map +0 -1
- package/dist/hardware/task/writer.d.ts +0 -9
- package/dist/hardware/task/writer.d.ts.map +0 -1
- package/dist/ontology/retriever.d.ts +0 -13
- package/dist/ontology/retriever.d.ts.map +0 -1
- package/dist/ontology/signals.d.ts +0 -30
- package/dist/ontology/signals.d.ts.map +0 -1
- package/dist/ranger/retriever.d.ts +0 -11
- package/dist/ranger/retriever.d.ts.map +0 -1
- package/dist/workspace/pid/client.d.ts +0 -17
- package/dist/workspace/pid/client.d.ts.map +0 -1
- package/dist/workspace/pid/external.d.ts.map +0 -1
- package/dist/workspace/pid/index.d.ts +0 -2
- package/dist/workspace/pid/index.d.ts.map +0 -1
- package/dist/workspace/pid/payload.d.ts.map +0 -1
- package/dist/workspace/pid/pid.spec.d.ts +0 -2
- package/dist/workspace/pid/pid.spec.d.ts.map +0 -1
- package/dist/workspace/pid/retriever.d.ts +0 -9
- package/dist/workspace/pid/retriever.d.ts.map +0 -1
- package/dist/workspace/pid/writer.d.ts.map +0 -1
- package/src/hardware/device/payload.ts +0 -27
- package/src/hardware/device/retriever.ts +0 -60
- package/src/hardware/device/writer.ts +0 -59
- package/src/hardware/rack/payload.ts +0 -26
- package/src/hardware/rack/retriever.ts +0 -68
- package/src/hardware/rack/writer.ts +0 -59
- package/src/hardware/task/external.ts +0 -12
- package/src/hardware/task/payload.ts +0 -40
- package/src/hardware/task/retriever.ts +0 -70
- package/src/hardware/task/writer.ts +0 -65
- package/src/ontology/retriever.ts +0 -91
- package/src/ontology/signals.ts +0 -139
- package/src/ranger/retriever.ts +0 -50
- /package/dist/workspace/{pid → schematic}/external.d.ts +0 -0
package/src/client.ts
CHANGED
|
@@ -7,7 +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 { TimeSpan, TimeStamp
|
|
10
|
+
import { TimeSpan, TimeStamp } from "@synnaxlabs/x/telem";
|
|
11
|
+
import { URL } from "@synnaxlabs/x/url";
|
|
11
12
|
import { z } from "zod";
|
|
12
13
|
|
|
13
14
|
import { auth } from "@/auth";
|
|
@@ -26,8 +27,20 @@ import { Transport } from "@/transport";
|
|
|
26
27
|
import { workspace } from "@/workspace";
|
|
27
28
|
|
|
28
29
|
export const synnaxPropsZ = z.object({
|
|
29
|
-
host: z
|
|
30
|
-
|
|
30
|
+
host: z
|
|
31
|
+
.string({
|
|
32
|
+
required_error: "Host is required",
|
|
33
|
+
})
|
|
34
|
+
.min(1, "Host is required"),
|
|
35
|
+
port: z
|
|
36
|
+
.number({
|
|
37
|
+
required_error: "Port is required",
|
|
38
|
+
})
|
|
39
|
+
.or(
|
|
40
|
+
z.string({
|
|
41
|
+
required_error: "Port is required",
|
|
42
|
+
}),
|
|
43
|
+
),
|
|
31
44
|
username: z.string().optional(),
|
|
32
45
|
password: z.string().optional(),
|
|
33
46
|
connectivityPollFrequency: TimeSpan.z.default(TimeSpan.seconds(30)),
|
|
@@ -105,36 +118,26 @@ export default class Synnax extends framer.Client {
|
|
|
105
118
|
props.name,
|
|
106
119
|
);
|
|
107
120
|
this.ontology = new ontology.Client(transport.unary, this);
|
|
108
|
-
const rangeRetriever = new ranger.Retriever(transport.unary);
|
|
109
121
|
const rangeWriter = new ranger.Writer(this.transport.unary);
|
|
110
122
|
this.labels = new label.Client(this.transport.unary, this);
|
|
111
123
|
this.ranges = new ranger.Client(
|
|
112
124
|
this,
|
|
113
|
-
rangeRetriever,
|
|
114
125
|
rangeWriter,
|
|
115
126
|
this.transport.unary,
|
|
116
127
|
chRetriever,
|
|
117
128
|
this.labels,
|
|
118
129
|
);
|
|
119
130
|
this.workspaces = new workspace.Client(this.transport.unary);
|
|
120
|
-
const devices = new device.Client(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
this,
|
|
124
|
-
);
|
|
125
|
-
const taskRetriever = new task.Retriever(this.transport.unary);
|
|
126
|
-
const taskWriter = new task.Writer(this.transport.unary);
|
|
127
|
-
const tasks = new task.Client(taskRetriever, taskWriter);
|
|
128
|
-
const racks = new rack.Client(
|
|
129
|
-
new rack.Retriever(this.transport.unary),
|
|
130
|
-
new rack.Writer(this.transport.unary),
|
|
131
|
-
this,
|
|
132
|
-
taskWriter,
|
|
133
|
-
taskRetriever,
|
|
134
|
-
);
|
|
131
|
+
const devices = new device.Client(this.transport.unary, this);
|
|
132
|
+
const tasks = new task.Client(this.transport.unary, this);
|
|
133
|
+
const racks = new rack.Client(this.transport.unary, this, tasks);
|
|
135
134
|
this.hardware = new hardware.Client(tasks, racks, devices);
|
|
136
135
|
}
|
|
137
136
|
|
|
137
|
+
get key(): string {
|
|
138
|
+
return this.createdAt.valueOf().toString();
|
|
139
|
+
}
|
|
140
|
+
|
|
138
141
|
close(): void {
|
|
139
142
|
this.connectivity.stopChecking();
|
|
140
143
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
10
|
import type { UnaryClient } from "@synnaxlabs/freighter";
|
|
11
|
-
import { TimeSpan } from "@synnaxlabs/x";
|
|
11
|
+
import { TimeSpan } from "@synnaxlabs/x/telem";
|
|
12
12
|
import { z } from "zod";
|
|
13
13
|
|
|
14
14
|
const STATUSES = ["disconnected", "connecting", "connected", "failed"] as const;
|
|
@@ -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 { URL } from "@synnaxlabs/x";
|
|
10
|
+
import { URL } from "@synnaxlabs/x/url";
|
|
11
11
|
import { describe, expect, it } from "vitest";
|
|
12
12
|
|
|
13
13
|
import { auth } from "@/auth";
|
|
@@ -22,13 +22,8 @@ describe("connectivity", () => {
|
|
|
22
22
|
username: "synnax",
|
|
23
23
|
password: "seldon",
|
|
24
24
|
});
|
|
25
|
-
await client.authenticating;
|
|
26
|
-
expect(client.authenticated).toBeTruthy();
|
|
27
|
-
|
|
28
25
|
transport.use(client.middleware());
|
|
29
|
-
|
|
30
26
|
const connectivity = new Checker(transport.unary);
|
|
31
|
-
|
|
32
27
|
await connectivity.check();
|
|
33
28
|
expect(connectivity.state.status).toEqual("connected");
|
|
34
29
|
});
|
package/src/control/state.ts
CHANGED
|
@@ -7,7 +7,9 @@
|
|
|
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 { binary } from "@synnaxlabs/x/binary";
|
|
11
|
+
import { type Destructor } from "@synnaxlabs/x/destructor";
|
|
12
|
+
import { observe } from "@synnaxlabs/x/observe";
|
|
11
13
|
import { z } from "zod";
|
|
12
14
|
|
|
13
15
|
import { type Key as ChannelKey } from "@/channel/payload";
|
package/src/errors.ts
CHANGED
|
@@ -8,77 +8,58 @@
|
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
|
-
BaseTypedError,
|
|
12
11
|
type Middleware,
|
|
13
12
|
registerError,
|
|
14
13
|
Unreachable,
|
|
15
14
|
type ErrorPayload,
|
|
16
15
|
} from "@synnaxlabs/freighter";
|
|
17
16
|
|
|
18
|
-
const _FREIGHTER_EXCEPTION_PREFIX = "sy.
|
|
19
|
-
|
|
20
|
-
enum APIErrorType {
|
|
21
|
-
General = _FREIGHTER_EXCEPTION_PREFIX + "general",
|
|
22
|
-
Parse = _FREIGHTER_EXCEPTION_PREFIX + "parse",
|
|
23
|
-
Auth = _FREIGHTER_EXCEPTION_PREFIX + "auth",
|
|
24
|
-
Unexpected = _FREIGHTER_EXCEPTION_PREFIX + "unexpected",
|
|
25
|
-
Validation = _FREIGHTER_EXCEPTION_PREFIX + "validation",
|
|
26
|
-
Query = _FREIGHTER_EXCEPTION_PREFIX + "query",
|
|
27
|
-
Route = _FREIGHTER_EXCEPTION_PREFIX + "route",
|
|
28
|
-
}
|
|
17
|
+
const _FREIGHTER_EXCEPTION_PREFIX = "sy.";
|
|
29
18
|
|
|
30
19
|
export interface Field {
|
|
31
20
|
field: string;
|
|
32
21
|
message: string;
|
|
33
22
|
}
|
|
34
23
|
|
|
35
|
-
class BaseError extends BaseTypedError {
|
|
36
|
-
constructor(message: string) {
|
|
37
|
-
super(message, _FREIGHTER_EXCEPTION_PREFIX);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
24
|
/**
|
|
42
25
|
* Raised when a validation error occurs.
|
|
43
26
|
*/
|
|
44
|
-
export class ValidationError extends
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
constructor(fieldsOrMessage: string | Field[] | Field) {
|
|
48
|
-
if (typeof fieldsOrMessage === "string") {
|
|
49
|
-
super(fieldsOrMessage);
|
|
50
|
-
this.fields = [];
|
|
51
|
-
} else if (Array.isArray(fieldsOrMessage)) {
|
|
52
|
-
super(
|
|
53
|
-
fieldsOrMessage.map((field) => `${field.field}: ${field.message}`).join("\n"),
|
|
54
|
-
);
|
|
55
|
-
this.fields = fieldsOrMessage;
|
|
56
|
-
} else {
|
|
57
|
-
super(`${fieldsOrMessage.field}: ${fieldsOrMessage.message}`);
|
|
58
|
-
this.fields = [fieldsOrMessage];
|
|
59
|
-
}
|
|
60
|
-
}
|
|
27
|
+
export class ValidationError extends Error {
|
|
28
|
+
static readonly TYPE = _FREIGHTER_EXCEPTION_PREFIX + "validation";
|
|
61
29
|
}
|
|
62
30
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
31
|
+
export class FieldError extends ValidationError {
|
|
32
|
+
static readonly TYPE = ValidationError.TYPE + ".field";
|
|
33
|
+
readonly field: string;
|
|
34
|
+
readonly message: string;
|
|
35
|
+
|
|
36
|
+
constructor(field: string, message: string) {
|
|
37
|
+
super(field + ": " + message);
|
|
38
|
+
this.field = field;
|
|
39
|
+
this.message = message;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
67
42
|
|
|
68
43
|
/**
|
|
69
|
-
*
|
|
44
|
+
* AuthError is raised when an authentication error occurs.
|
|
70
45
|
*/
|
|
71
|
-
export class
|
|
46
|
+
export class AuthError extends Error {
|
|
47
|
+
static readonly TYPE = _FREIGHTER_EXCEPTION_PREFIX + "auth";
|
|
48
|
+
}
|
|
72
49
|
|
|
73
50
|
/**
|
|
74
|
-
*
|
|
51
|
+
* InvalidTokenError is raised when an authentication token is invalid.
|
|
75
52
|
*/
|
|
76
|
-
export class
|
|
53
|
+
export class InvalidTokenError extends AuthError {
|
|
54
|
+
static readonly TYPE = AuthError.TYPE + ".invalid-token";
|
|
55
|
+
}
|
|
77
56
|
|
|
78
57
|
/**
|
|
79
58
|
* UnexpectedError is raised when an unexpected error occurs.
|
|
80
59
|
*/
|
|
81
|
-
export class UnexpectedError extends
|
|
60
|
+
export class UnexpectedError extends Error {
|
|
61
|
+
static readonly TYPE = _FREIGHTER_EXCEPTION_PREFIX + "unexpected";
|
|
62
|
+
|
|
82
63
|
constructor(message: string) {
|
|
83
64
|
super(`
|
|
84
65
|
Unexpected error encountered:
|
|
@@ -93,16 +74,23 @@ export class UnexpectedError extends BaseError {
|
|
|
93
74
|
/**
|
|
94
75
|
* QueryError is raised when a query error occurs.
|
|
95
76
|
*/
|
|
96
|
-
export class QueryError extends
|
|
77
|
+
export class QueryError extends Error {
|
|
78
|
+
static readonly TYPE = _FREIGHTER_EXCEPTION_PREFIX + "query";
|
|
79
|
+
}
|
|
97
80
|
|
|
98
|
-
export class NotFoundError extends QueryError {
|
|
81
|
+
export class NotFoundError extends QueryError {
|
|
82
|
+
static readonly TYPE = QueryError.TYPE + ".not_found";
|
|
83
|
+
}
|
|
99
84
|
|
|
100
|
-
export class MultipleFoundError extends QueryError {
|
|
85
|
+
export class MultipleFoundError extends QueryError {
|
|
86
|
+
static readonly TYPE = QueryError.TYPE + ".multiple_results";
|
|
87
|
+
}
|
|
101
88
|
|
|
102
89
|
/**
|
|
103
90
|
* RouteError is raised when a routing error occurs.
|
|
104
91
|
*/
|
|
105
|
-
export class RouteError extends
|
|
92
|
+
export class RouteError extends Error {
|
|
93
|
+
static readonly TYPE = _FREIGHTER_EXCEPTION_PREFIX + "route";
|
|
106
94
|
path: string;
|
|
107
95
|
|
|
108
96
|
constructor(message: string, path: string) {
|
|
@@ -114,28 +102,44 @@ export class RouteError extends BaseError {
|
|
|
114
102
|
/**
|
|
115
103
|
* Raised when time-series data is not contiguous.
|
|
116
104
|
*/
|
|
117
|
-
export class ContiguityError extends
|
|
105
|
+
export class ContiguityError extends Error {}
|
|
118
106
|
|
|
119
107
|
const decode = (payload: ErrorPayload): Error | null => {
|
|
120
108
|
if (!payload.type.startsWith(_FREIGHTER_EXCEPTION_PREFIX)) return null;
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
return new
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
default:
|
|
137
|
-
return new UnexpectedError(payload.data);
|
|
109
|
+
if (payload.type.startsWith(ValidationError.TYPE)) {
|
|
110
|
+
if (payload.type === FieldError.TYPE) {
|
|
111
|
+
const values = payload.data.split(": ");
|
|
112
|
+
if (values.length < 2) {
|
|
113
|
+
return new ValidationError(payload.data);
|
|
114
|
+
}
|
|
115
|
+
return new FieldError(values[0], values[1]);
|
|
116
|
+
}
|
|
117
|
+
return new ValidationError(payload.data);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (payload.type.startsWith(AuthError.TYPE)) {
|
|
121
|
+
if (payload.type.startsWith(InvalidTokenError.TYPE))
|
|
122
|
+
return new InvalidTokenError(payload.data);
|
|
123
|
+
return new AuthError(payload.data);
|
|
138
124
|
}
|
|
125
|
+
|
|
126
|
+
if (payload.type.startsWith(UnexpectedError.TYPE)) {
|
|
127
|
+
return new UnexpectedError(payload.data);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (payload.type.startsWith(QueryError.TYPE)) {
|
|
131
|
+
if (payload.type.startsWith(NotFoundError.TYPE))
|
|
132
|
+
return new NotFoundError(payload.data);
|
|
133
|
+
if (payload.type.startsWith(MultipleFoundError.TYPE))
|
|
134
|
+
return new MultipleFoundError(payload.data);
|
|
135
|
+
return new QueryError(payload.data);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (payload.type.startsWith(RouteError.TYPE)) {
|
|
139
|
+
return new RouteError(payload.data, payload.data);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return new UnexpectedError(payload.data);
|
|
139
143
|
};
|
|
140
144
|
|
|
141
145
|
const encode = (): ErrorPayload => {
|
|
@@ -149,7 +153,7 @@ export const validateFieldNotNull = (
|
|
|
149
153
|
value: unknown,
|
|
150
154
|
message: string = "must be provided",
|
|
151
155
|
): void => {
|
|
152
|
-
if (value == null) throw new
|
|
156
|
+
if (value == null) throw new FieldError(key, message);
|
|
153
157
|
};
|
|
154
158
|
|
|
155
159
|
export const errorsMiddleware: Middleware = async (ctx, next) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DataType, Series, TimeStamp } from "@synnaxlabs/x";
|
|
1
|
+
import { DataType, Series, TimeStamp } from "@synnaxlabs/x/telem";
|
|
2
2
|
import { beforeAll, describe, expect, it } from "vitest";
|
|
3
3
|
|
|
4
4
|
import { type channel } from "@/channel";
|
|
@@ -115,4 +115,36 @@ describe("WriteFrameAdapter", () => {
|
|
|
115
115
|
expect(res.get(timeCh.key)).toHaveLength(1);
|
|
116
116
|
expect(res.get(timeCh.key).at(0)).toEqual(ts);
|
|
117
117
|
});
|
|
118
|
+
|
|
119
|
+
it("should correctly adapt a name and JSON value", async () => {
|
|
120
|
+
const jsonChannel = await client.channels.create({
|
|
121
|
+
name: `json-${Math.random()}-${TimeStamp.now().toString()}`,
|
|
122
|
+
dataType: DataType.JSON,
|
|
123
|
+
virtual: true,
|
|
124
|
+
});
|
|
125
|
+
const adapter = await WriteFrameAdapter.open(client.channels.retriever, [
|
|
126
|
+
jsonChannel.key,
|
|
127
|
+
]);
|
|
128
|
+
const res = await adapter.adapt(jsonChannel.name, [{ dog: "blue" }]);
|
|
129
|
+
expect(res.columns).toHaveLength(1);
|
|
130
|
+
expect(res.series).toHaveLength(1);
|
|
131
|
+
expect(res.get(jsonChannel.key)).toHaveLength(1);
|
|
132
|
+
expect(res.get(jsonChannel.key).at(0)).toEqual({ dog: "blue" });
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("should correctly adapt a name and a json typed series", async () => {
|
|
136
|
+
const jsonChannel = await client.channels.create({
|
|
137
|
+
name: `json-${Math.random()}-${TimeStamp.now().toString()}`,
|
|
138
|
+
dataType: DataType.JSON,
|
|
139
|
+
virtual: true,
|
|
140
|
+
});
|
|
141
|
+
const adapter = await WriteFrameAdapter.open(client.channels.retriever, [
|
|
142
|
+
jsonChannel.key,
|
|
143
|
+
]);
|
|
144
|
+
const res = await adapter.adapt(jsonChannel.name, new Series([{ dog: "blue" }]));
|
|
145
|
+
expect(res.columns).toHaveLength(1);
|
|
146
|
+
expect(res.series).toHaveLength(1);
|
|
147
|
+
expect(res.get(jsonChannel.key)).toHaveLength(1);
|
|
148
|
+
expect(res.get(jsonChannel.key).at(0)).toEqual({ dog: "blue" });
|
|
149
|
+
});
|
|
118
150
|
});
|
package/src/framer/adapter.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 CrudeSeries, Series } from "@synnaxlabs/x";
|
|
10
|
+
import { type CrudeSeries, Series } from "@synnaxlabs/x/telem";
|
|
11
11
|
|
|
12
12
|
import {
|
|
13
13
|
type Key,
|
|
@@ -16,7 +16,11 @@ import {
|
|
|
16
16
|
type KeyOrName,
|
|
17
17
|
type Payload,
|
|
18
18
|
} from "@/channel/payload";
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
type Retriever,
|
|
21
|
+
analyzeChannelParams,
|
|
22
|
+
retrieveRequired,
|
|
23
|
+
} from "@/channel/retriever";
|
|
20
24
|
import { ValidationError } from "@/errors";
|
|
21
25
|
import { type CrudeFrame, Frame } from "@/framer/frame";
|
|
22
26
|
|
|
@@ -38,10 +42,10 @@ export class ReadFrameAdapter {
|
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
async update(channels: Params): Promise<void> {
|
|
41
|
-
const { variant, normalized } =
|
|
45
|
+
const { variant, normalized } = analyzeChannelParams(channels);
|
|
42
46
|
if (variant === "keys") {
|
|
43
47
|
this.adapter = null;
|
|
44
|
-
this.keys = normalized;
|
|
48
|
+
this.keys = normalized as Key[];
|
|
45
49
|
return;
|
|
46
50
|
}
|
|
47
51
|
const fetched = await this.retriever.retrieve(normalized);
|
|
@@ -111,12 +115,12 @@ export class WriteFrameAdapter {
|
|
|
111
115
|
Received a single channel name or key but no series.
|
|
112
116
|
`);
|
|
113
117
|
if (Array.isArray(series)) {
|
|
114
|
-
if (series.
|
|
118
|
+
if (series.some((s) => s instanceof Series || Array.isArray(s))) {
|
|
115
119
|
throw new ValidationError(`
|
|
116
120
|
Received a single channel name or key but multiple series.
|
|
117
121
|
`);
|
|
118
122
|
}
|
|
119
|
-
series = series
|
|
123
|
+
series = series as CrudeSeries;
|
|
120
124
|
}
|
|
121
125
|
const pld = await this.fetchChannel(columnsOrData);
|
|
122
126
|
const s = new Series({ data: series as CrudeSeries, dataType: pld.dataType });
|
package/src/framer/client.ts
CHANGED
|
@@ -13,10 +13,10 @@ import {
|
|
|
13
13
|
type CrudeSeries,
|
|
14
14
|
type CrudeTimeRange,
|
|
15
15
|
type MultiSeries,
|
|
16
|
-
} from "@synnaxlabs/x";
|
|
16
|
+
} from "@synnaxlabs/x/telem";
|
|
17
17
|
|
|
18
|
-
import {
|
|
19
|
-
import { type Retriever,
|
|
18
|
+
import { KeysOrNames, type KeyOrName, type Params } from "@/channel/payload";
|
|
19
|
+
import { type Retriever, analyzeChannelParams } from "@/channel/retriever";
|
|
20
20
|
import { Frame } from "@/framer/frame";
|
|
21
21
|
import { Iterator } from "@/framer/iterator";
|
|
22
22
|
import { Streamer, type StreamerConfig } from "@/framer/streamer";
|
|
@@ -45,12 +45,13 @@ export class Client {
|
|
|
45
45
|
/**
|
|
46
46
|
* Opens a new writer on the given channels.
|
|
47
47
|
*
|
|
48
|
-
* @param
|
|
49
|
-
*
|
|
50
|
-
* for more information.
|
|
48
|
+
* @param config - The configuration for the created writer, see documentation for
|
|
49
|
+
* writerConfig for more detail.
|
|
51
50
|
* @returns a new {@link RecordWriter}.
|
|
52
51
|
*/
|
|
53
|
-
async openWriter(config: WriterConfig): Promise<Writer> {
|
|
52
|
+
async openWriter(config: WriterConfig | Params): Promise<Writer> {
|
|
53
|
+
if (Array.isArray(config) || typeof config !== "object")
|
|
54
|
+
config = { channels: config as Params };
|
|
54
55
|
return await Writer._open(this.retriever, this.stream, config);
|
|
55
56
|
}
|
|
56
57
|
|
|
@@ -76,12 +77,12 @@ export class Client {
|
|
|
76
77
|
* and then will start reading new values.
|
|
77
78
|
*
|
|
78
79
|
*/
|
|
79
|
-
async openStreamer(config: StreamerConfig): Promise<Streamer>;
|
|
80
|
+
async openStreamer(config: StreamerConfig | Params): Promise<Streamer>;
|
|
80
81
|
|
|
81
82
|
async openStreamer(config: StreamerConfig | Params): Promise<Streamer> {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return await Streamer._open(this.retriever, this.stream, config
|
|
83
|
+
if (Array.isArray(config) || typeof config !== "object")
|
|
84
|
+
config = { channels: config as Params };
|
|
85
|
+
return await Streamer._open(this.retriever, this.stream, config);
|
|
85
86
|
}
|
|
86
87
|
|
|
87
88
|
async write(
|
|
@@ -148,7 +149,7 @@ export class Client {
|
|
|
148
149
|
async read(tr: CrudeTimeRange, channels: Params): Promise<Frame>;
|
|
149
150
|
|
|
150
151
|
async read(tr: CrudeTimeRange, channels: Params): Promise<MultiSeries | Frame> {
|
|
151
|
-
const { single } =
|
|
152
|
+
const { single } = analyzeChannelParams(channels);
|
|
152
153
|
const fr = await this.readFrame(tr, channels);
|
|
153
154
|
if (single) return fr.get(channels as KeyOrName);
|
|
154
155
|
return fr;
|
package/src/framer/frame.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 { DataType, Series, TimeRange } from "@synnaxlabs/x";
|
|
10
|
+
import { DataType, Series, TimeRange } from "@synnaxlabs/x/telem";
|
|
11
11
|
import { describe, expect, it, test } from "vitest";
|
|
12
12
|
|
|
13
13
|
import { framer } from "@/framer";
|
package/src/framer/frame.ts
CHANGED
|
@@ -11,13 +11,13 @@ import {
|
|
|
11
11
|
Size,
|
|
12
12
|
Series,
|
|
13
13
|
TimeRange,
|
|
14
|
-
toArray,
|
|
15
14
|
DataType,
|
|
16
|
-
unique,
|
|
17
15
|
TimeStamp,
|
|
18
16
|
type TelemValue,
|
|
19
17
|
MultiSeries,
|
|
20
|
-
} from "@synnaxlabs/x";
|
|
18
|
+
} from "@synnaxlabs/x/telem";
|
|
19
|
+
import { toArray } from "@synnaxlabs/x/toArray";
|
|
20
|
+
import { unique } from "@synnaxlabs/x/unique";
|
|
21
21
|
import { z } from "zod";
|
|
22
22
|
|
|
23
23
|
import {
|
|
@@ -142,8 +142,8 @@ export class Frame {
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
throw new ValidationError(
|
|
145
|
-
`[Frame] - invalid frame construction parameters. data parameter ust be a frame
|
|
146
|
-
payload, a list of lazy arrays, a lazy array, a map, or a record keyed by channel
|
|
145
|
+
`[Frame] - invalid frame construction parameters. data parameter ust be a frame
|
|
146
|
+
payload, a list of lazy arrays, a lazy array, a map, or a record keyed by channel
|
|
147
147
|
name. keys parameter must be a set of channel keys or channel names.`,
|
|
148
148
|
);
|
|
149
149
|
}
|
|
@@ -398,7 +398,10 @@ export class Frame {
|
|
|
398
398
|
|
|
399
399
|
export const series = z.object({
|
|
400
400
|
timeRange: TimeRange.z.optional(),
|
|
401
|
-
alignment: z
|
|
401
|
+
alignment: z
|
|
402
|
+
.bigint()
|
|
403
|
+
.or(z.string().transform((s) => BigInt(s)))
|
|
404
|
+
.optional(),
|
|
402
405
|
dataType: DataType.z,
|
|
403
406
|
data: z.string().transform(
|
|
404
407
|
(s) =>
|
|
@@ -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, Rate, TimeRange, TimeSpan, TimeStamp } from "@synnaxlabs/x";
|
|
10
|
+
import { DataType, Rate, TimeRange, TimeSpan, TimeStamp } from "@synnaxlabs/x/telem";
|
|
11
11
|
import { describe, test, expect } from "vitest";
|
|
12
12
|
|
|
13
13
|
import { type channel } from "@/channel";
|
package/src/framer/iterator.ts
CHANGED
|
@@ -33,19 +33,18 @@ export class StreamProxy<RQ extends z.ZodTypeAny, RS extends z.ZodTypeAny> {
|
|
|
33
33
|
|
|
34
34
|
async closeAndAck(): Promise<void> {
|
|
35
35
|
this.stream.closeSend();
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (!(err instanceof EOF)) throw err;
|
|
36
|
+
while (true) {
|
|
37
|
+
const [res, err] = await this.stream.receive();
|
|
38
|
+
if (res != null)
|
|
39
|
+
console.warn(
|
|
40
|
+
`${this.name} received unexpected response on closure.
|
|
41
|
+
Please report this error to the Synnax team. ${JSON.stringify(res)}`,
|
|
42
|
+
);
|
|
43
|
+
if (err != null) {
|
|
44
|
+
if (err instanceof EOF) return;
|
|
45
|
+
throw err;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
49
48
|
}
|
|
50
49
|
|
|
51
50
|
closeSend(): void {
|
|
@@ -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 { DataType, Rate, TimeStamp } from "@synnaxlabs/x";
|
|
11
10
|
import { describe, test, expect, it } from "vitest";
|
|
11
|
+
import { DataType, Rate, TimeStamp } from "@synnaxlabs/x/telem";
|
|
12
12
|
|
|
13
13
|
import { type channel } from "@/channel";
|
|
14
14
|
import { newClient } from "@/setupspecs";
|
package/src/framer/streamer.ts
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
10
|
import { errorZ, type Stream, type StreamClient } from "@synnaxlabs/freighter";
|
|
11
|
-
import {
|
|
11
|
+
import { observe } from "@synnaxlabs/x";
|
|
12
|
+
import { TimeStamp, type CrudeTimeStamp } from "@synnaxlabs/x/telem";
|
|
12
13
|
import { z } from "zod";
|
|
13
14
|
|
|
14
15
|
import { type Key, type Params } from "@/channel/payload";
|
|
@@ -88,3 +89,26 @@ export class Streamer implements AsyncIterator<Frame>, AsyncIterable<Frame> {
|
|
|
88
89
|
return this;
|
|
89
90
|
}
|
|
90
91
|
}
|
|
92
|
+
|
|
93
|
+
export class ObservableStreamer<V = Frame>
|
|
94
|
+
extends observe.Observer<Frame, V>
|
|
95
|
+
implements observe.ObservableAsyncCloseable<V>
|
|
96
|
+
{
|
|
97
|
+
private readonly streamer: Streamer;
|
|
98
|
+
private readonly closePromise: Promise<void>;
|
|
99
|
+
|
|
100
|
+
constructor(streamer: Streamer, transform?: observe.Transform<Frame, V>) {
|
|
101
|
+
super(transform);
|
|
102
|
+
this.streamer = streamer;
|
|
103
|
+
this.closePromise = this.stream();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async close(): Promise<void> {
|
|
107
|
+
this.streamer.close();
|
|
108
|
+
await this.closePromise;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private async stream(): Promise<void> {
|
|
112
|
+
for await (const frame of this.streamer) this.notify(frame);
|
|
113
|
+
}
|
|
114
|
+
}
|