@synnaxlabs/client 0.47.0 → 0.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +7 -7
- package/dist/client.cjs +35 -35
- package/dist/client.js +6264 -5984
- package/dist/eslint.config.d.ts +3 -2
- package/dist/eslint.config.d.ts.map +1 -1
- package/dist/src/access/client.d.ts +3 -1
- package/dist/src/access/client.d.ts.map +1 -1
- package/dist/src/access/enforce.d.ts +35 -0
- package/dist/src/access/enforce.d.ts.map +1 -0
- package/dist/src/access/enforce.spec.d.ts +2 -0
- package/dist/src/access/enforce.spec.d.ts.map +1 -0
- package/dist/src/access/external.d.ts +3 -0
- package/dist/src/access/external.d.ts.map +1 -1
- package/dist/src/access/payload.d.ts +0 -6
- package/dist/src/access/payload.d.ts.map +1 -1
- package/dist/src/access/policy/access.spec.d.ts +2 -0
- package/dist/src/access/policy/access.spec.d.ts.map +1 -0
- package/dist/src/access/policy/client.d.ts +485 -31
- package/dist/src/access/policy/client.d.ts.map +1 -1
- package/dist/src/access/policy/payload.d.ts +36 -113
- package/dist/src/access/policy/payload.d.ts.map +1 -1
- package/dist/src/access/role/client.d.ts +135 -0
- package/dist/src/access/role/client.d.ts.map +1 -0
- package/dist/src/access/role/external.d.ts.map +1 -0
- package/dist/src/access/role/index.d.ts +2 -0
- package/dist/src/access/role/index.d.ts.map +1 -0
- package/dist/src/access/role/payload.d.ts +27 -0
- package/dist/src/access/role/payload.d.ts.map +1 -0
- package/dist/src/access/role/role.spec.d.ts +2 -0
- package/dist/src/access/role/role.spec.d.ts.map +1 -0
- package/dist/src/arc/access.spec.d.ts +2 -0
- package/dist/src/arc/access.spec.d.ts.map +1 -0
- package/dist/src/arc/client.d.ts +5 -14
- package/dist/src/arc/client.d.ts.map +1 -1
- package/dist/src/arc/payload.d.ts +11 -2
- package/dist/src/arc/payload.d.ts.map +1 -1
- package/dist/src/auth/auth.d.ts +5 -3
- package/dist/src/auth/auth.d.ts.map +1 -1
- package/dist/src/channel/access.spec.d.ts +2 -0
- package/dist/src/channel/access.spec.d.ts.map +1 -0
- package/dist/src/channel/client.d.ts +0 -1
- package/dist/src/channel/client.d.ts.map +1 -1
- package/dist/src/channel/payload.d.ts +19 -8
- package/dist/src/channel/payload.d.ts.map +1 -1
- package/dist/src/channel/payload.spec.d.ts +2 -0
- package/dist/src/channel/payload.spec.d.ts.map +1 -0
- package/dist/src/channel/retriever.d.ts +4 -6
- package/dist/src/channel/retriever.d.ts.map +1 -1
- package/dist/src/channel/writer.d.ts.map +1 -1
- package/dist/src/client.d.ts +18 -10
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/connection/checker.d.ts +2 -3
- package/dist/src/connection/checker.d.ts.map +1 -1
- package/dist/src/connection.spec.d.ts +2 -0
- package/dist/src/connection.spec.d.ts.map +1 -0
- package/dist/src/device/access.spec.d.ts +2 -0
- package/dist/src/device/access.spec.d.ts.map +1 -0
- package/dist/src/{hardware/device → device}/client.d.ts +14 -7
- package/dist/src/device/client.d.ts.map +1 -0
- package/dist/src/device/device.spec.d.ts.map +1 -0
- package/dist/src/device/external.d.ts.map +1 -0
- package/dist/src/device/index.d.ts.map +1 -0
- package/dist/src/{hardware/device → device}/payload.d.ts +1 -1
- package/dist/src/device/payload.d.ts.map +1 -0
- package/dist/src/errors.d.ts +3 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/framer/adapter.d.ts +2 -2
- package/dist/src/framer/adapter.d.ts.map +1 -1
- package/dist/src/framer/client.d.ts +8 -1
- package/dist/src/framer/client.d.ts.map +1 -1
- package/dist/src/framer/frame.d.ts +11 -5
- package/dist/src/framer/frame.d.ts.map +1 -1
- package/dist/src/framer/iterator.d.ts +3 -3
- package/dist/src/framer/streamer.d.ts +24 -21
- package/dist/src/framer/streamer.d.ts.map +1 -1
- package/dist/src/framer/writer.d.ts +13 -13
- package/dist/src/index.d.ts +6 -7
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/label/access.spec.d.ts +2 -0
- package/dist/src/label/access.spec.d.ts.map +1 -0
- package/dist/src/label/client.d.ts +20 -11
- package/dist/src/label/client.d.ts.map +1 -1
- package/dist/src/ontology/client.d.ts +6 -6
- package/dist/src/ontology/client.d.ts.map +1 -1
- package/dist/src/ontology/group/access.spec.d.ts +2 -0
- package/dist/src/ontology/group/access.spec.d.ts.map +1 -0
- package/dist/src/ontology/group/client.d.ts +2 -2
- package/dist/src/ontology/group/client.d.ts.map +1 -1
- package/dist/src/ontology/group/payload.d.ts +1 -2
- package/dist/src/ontology/group/payload.d.ts.map +1 -1
- package/dist/src/ontology/payload.d.ts +23 -17
- package/dist/src/ontology/payload.d.ts.map +1 -1
- package/dist/src/ontology/writer.d.ts +10 -10
- package/dist/src/ontology/writer.d.ts.map +1 -1
- package/dist/src/rack/access.spec.d.ts +2 -0
- package/dist/src/rack/access.spec.d.ts.map +1 -0
- package/dist/src/{hardware/rack → rack}/client.d.ts +15 -8
- package/dist/src/rack/client.d.ts.map +1 -0
- package/dist/src/rack/external.d.ts.map +1 -0
- package/dist/src/rack/index.d.ts.map +1 -0
- package/dist/src/{hardware/rack → rack}/payload.d.ts +1 -1
- package/dist/src/rack/payload.d.ts.map +1 -0
- package/dist/src/rack/rack.spec.d.ts.map +1 -0
- package/dist/src/ranger/access.spec.d.ts +2 -0
- package/dist/src/ranger/access.spec.d.ts.map +1 -0
- package/dist/src/ranger/alias.d.ts +1 -8
- package/dist/src/ranger/alias.d.ts.map +1 -1
- package/dist/src/ranger/client.d.ts +12 -5
- package/dist/src/ranger/client.d.ts.map +1 -1
- package/dist/src/ranger/kv.d.ts +0 -3
- package/dist/src/ranger/kv.d.ts.map +1 -1
- package/dist/src/ranger/writer.d.ts +2 -2
- package/dist/src/ranger/writer.d.ts.map +1 -1
- package/dist/src/status/access.spec.d.ts +2 -0
- package/dist/src/status/access.spec.d.ts.map +1 -0
- package/dist/src/status/client.d.ts +4 -4
- package/dist/src/status/client.d.ts.map +1 -1
- package/dist/src/status/payload.d.ts +9 -2
- package/dist/src/status/payload.d.ts.map +1 -1
- package/dist/src/task/access.spec.d.ts +2 -0
- package/dist/src/task/access.spec.d.ts.map +1 -0
- package/dist/src/{hardware/task → task}/client.d.ts +26 -15
- package/dist/src/task/client.d.ts.map +1 -0
- package/dist/src/task/external.d.ts +3 -0
- package/dist/src/task/external.d.ts.map +1 -0
- package/dist/src/task/index.d.ts.map +1 -0
- package/dist/src/{hardware/task → task}/payload.d.ts +45 -6
- package/dist/src/task/payload.d.ts.map +1 -0
- package/dist/src/task/task.spec.d.ts.map +1 -0
- package/dist/src/testutil/access.d.ts +4 -0
- package/dist/src/testutil/access.d.ts.map +1 -0
- package/dist/src/testutil/client.d.ts +3 -3
- package/dist/src/testutil/client.d.ts.map +1 -1
- package/dist/src/transport.d.ts.map +1 -1
- package/dist/src/user/access.spec.d.ts +2 -0
- package/dist/src/user/access.spec.d.ts.map +1 -0
- package/dist/src/user/client.d.ts +10 -1
- package/dist/src/user/client.d.ts.map +1 -1
- package/dist/src/user/external.d.ts +1 -1
- package/dist/src/user/external.d.ts.map +1 -1
- package/dist/src/user/payload.d.ts.map +1 -1
- package/dist/src/workspace/access.spec.d.ts +2 -0
- package/dist/src/workspace/access.spec.d.ts.map +1 -0
- package/dist/src/workspace/client.d.ts +10 -5
- package/dist/src/workspace/client.d.ts.map +1 -1
- package/dist/src/workspace/lineplot/access.spec.d.ts +2 -0
- package/dist/src/workspace/lineplot/access.spec.d.ts.map +1 -0
- package/dist/src/workspace/lineplot/client.d.ts +8 -1
- package/dist/src/workspace/lineplot/client.d.ts.map +1 -1
- package/dist/src/workspace/log/access.spec.d.ts +2 -0
- package/dist/src/workspace/log/access.spec.d.ts.map +1 -0
- package/dist/src/workspace/log/client.d.ts +8 -1
- package/dist/src/workspace/log/client.d.ts.map +1 -1
- package/dist/src/workspace/schematic/access.spec.d.ts +2 -0
- package/dist/src/workspace/schematic/access.spec.d.ts.map +1 -0
- package/dist/src/workspace/schematic/client.d.ts +8 -1
- package/dist/src/workspace/schematic/client.d.ts.map +1 -1
- package/dist/src/workspace/schematic/symbol/access.spec.d.ts +2 -0
- package/dist/src/workspace/schematic/symbol/access.spec.d.ts.map +1 -0
- package/dist/src/workspace/schematic/symbol/client.d.ts +1 -5
- package/dist/src/workspace/schematic/symbol/client.d.ts.map +1 -1
- package/dist/src/workspace/schematic/symbol/payload.d.ts +2 -2
- package/dist/src/workspace/table/access.spec.d.ts +2 -0
- package/dist/src/workspace/table/access.spec.d.ts.map +1 -0
- package/dist/src/workspace/table/client.d.ts +8 -1
- package/dist/src/workspace/table/client.d.ts.map +1 -1
- package/eslint.config.ts +3 -1
- package/package.json +8 -8
- package/src/access/client.ts +5 -2
- package/src/access/enforce.spec.ts +189 -0
- package/src/access/enforce.ts +84 -0
- package/src/access/external.ts +3 -0
- package/src/access/payload.ts +1 -13
- package/src/access/policy/access.spec.ts +147 -0
- package/src/access/policy/client.ts +21 -25
- package/src/access/policy/payload.ts +9 -5
- package/src/access/role/client.ts +135 -0
- package/src/access/role/external.ts +11 -0
- package/src/{hardware → access/role}/index.ts +1 -1
- package/src/access/role/payload.ts +32 -0
- package/src/access/role/role.spec.ts +95 -0
- package/src/arc/access.spec.ts +143 -0
- package/src/arc/client.ts +7 -31
- package/src/arc/payload.ts +4 -0
- package/src/auth/auth.spec.ts +13 -13
- package/src/auth/auth.ts +33 -11
- package/src/channel/access.spec.ts +116 -0
- package/src/channel/channel.spec.ts +63 -73
- package/src/channel/client.ts +2 -8
- package/src/channel/payload.spec.ts +171 -0
- package/src/channel/payload.ts +37 -8
- package/src/channel/retriever.ts +10 -11
- package/src/channel/writer.ts +3 -7
- package/src/client.ts +38 -28
- package/src/connection/checker.ts +10 -10
- package/src/connection/connection.spec.ts +13 -13
- package/src/connection.spec.ts +145 -0
- package/src/device/access.spec.ts +159 -0
- package/src/{hardware/device → device}/client.ts +12 -21
- package/src/{hardware/device → device}/device.spec.ts +70 -34
- package/src/device/external.ts +11 -0
- package/src/{hardware/rack → device}/index.ts +1 -1
- package/src/{hardware/device → device}/payload.ts +3 -3
- package/src/errors.ts +2 -0
- package/src/framer/adapter.spec.ts +351 -13
- package/src/framer/adapter.ts +23 -13
- package/src/framer/client.spec.ts +14 -20
- package/src/framer/client.ts +3 -5
- package/src/framer/deleter.spec.ts +1 -1
- package/src/framer/frame.spec.ts +427 -0
- package/src/framer/frame.ts +30 -3
- package/src/framer/iterator.ts +4 -4
- package/src/framer/streamer.spec.ts +155 -10
- package/src/framer/streamer.ts +35 -12
- package/src/framer/writer.spec.ts +5 -5
- package/src/index.ts +13 -7
- package/src/label/access.spec.ts +109 -0
- package/src/label/client.ts +10 -14
- package/src/ontology/client.ts +4 -6
- package/src/ontology/group/access.spec.ts +77 -0
- package/src/ontology/group/client.ts +3 -7
- package/src/ontology/group/group.spec.ts +18 -0
- package/src/ontology/group/payload.ts +2 -2
- package/src/ontology/ontology.spec.ts +2 -0
- package/src/ontology/payload.ts +18 -2
- package/src/ontology/writer.ts +3 -7
- package/src/rack/access.spec.ts +102 -0
- package/src/{hardware/rack → rack}/client.ts +14 -19
- package/src/{hardware/device/index.ts → rack/external.ts} +2 -1
- package/src/{hardware/external.ts → rack/index.ts} +1 -1
- package/src/{hardware/rack → rack}/payload.ts +2 -2
- package/src/{hardware/rack → rack}/rack.spec.ts +43 -17
- package/src/ranger/access.spec.ts +115 -0
- package/src/ranger/alias.ts +6 -14
- package/src/ranger/client.ts +13 -14
- package/src/ranger/kv.ts +7 -9
- package/src/ranger/ranger.spec.ts +4 -4
- package/src/ranger/writer.ts +3 -7
- package/src/status/access.spec.ts +129 -0
- package/src/status/client.ts +5 -9
- package/src/status/payload.ts +3 -2
- package/src/task/access.spec.ts +131 -0
- package/src/{hardware/task → task}/client.ts +50 -25
- package/src/task/external.ts +11 -0
- package/src/{hardware/task → task}/index.ts +1 -1
- package/src/{hardware/task → task}/payload.ts +22 -3
- package/src/{hardware/task → task}/task.spec.ts +197 -34
- package/src/testutil/access.ts +34 -0
- package/src/testutil/channels.ts +3 -3
- package/src/testutil/client.ts +4 -4
- package/src/transport.ts +1 -3
- package/src/user/access.spec.ts +107 -0
- package/src/user/client.ts +10 -12
- package/src/user/external.ts +12 -1
- package/src/user/payload.ts +3 -5
- package/src/workspace/access.spec.ts +108 -0
- package/src/workspace/client.ts +11 -27
- package/src/workspace/lineplot/access.spec.ts +134 -0
- package/src/workspace/lineplot/client.ts +8 -13
- package/src/workspace/log/access.spec.ts +134 -0
- package/src/workspace/log/client.ts +8 -13
- package/src/workspace/schematic/access.spec.ts +134 -0
- package/src/workspace/schematic/client.ts +9 -18
- package/src/workspace/schematic/symbol/access.spec.ts +172 -0
- package/src/workspace/schematic/symbol/client.ts +6 -17
- package/src/workspace/schematic/symbol/payload.ts +1 -1
- package/src/workspace/table/access.spec.ts +134 -0
- package/src/workspace/table/client.ts +8 -13
- package/dist/src/access/policy/policy.spec.d.ts +0 -2
- package/dist/src/access/policy/policy.spec.d.ts.map +0 -1
- package/dist/src/hardware/client.d.ts +0 -10
- package/dist/src/hardware/client.d.ts.map +0 -1
- package/dist/src/hardware/device/client.d.ts.map +0 -1
- package/dist/src/hardware/device/device.spec.d.ts.map +0 -1
- package/dist/src/hardware/device/external.d.ts.map +0 -1
- package/dist/src/hardware/device/index.d.ts.map +0 -1
- package/dist/src/hardware/device/payload.d.ts.map +0 -1
- package/dist/src/hardware/external.d.ts +0 -2
- package/dist/src/hardware/external.d.ts.map +0 -1
- package/dist/src/hardware/index.d.ts +0 -2
- package/dist/src/hardware/index.d.ts.map +0 -1
- package/dist/src/hardware/rack/client.d.ts.map +0 -1
- package/dist/src/hardware/rack/external.d.ts.map +0 -1
- package/dist/src/hardware/rack/index.d.ts.map +0 -1
- package/dist/src/hardware/rack/payload.d.ts.map +0 -1
- package/dist/src/hardware/rack/rack.spec.d.ts.map +0 -1
- package/dist/src/hardware/task/client.d.ts.map +0 -1
- package/dist/src/hardware/task/external.d.ts.map +0 -1
- package/dist/src/hardware/task/index.d.ts.map +0 -1
- package/dist/src/hardware/task/payload.d.ts.map +0 -1
- package/dist/src/hardware/task/task.spec.d.ts.map +0 -1
- package/dist/src/user/retriever.d.ts +0 -16
- package/dist/src/user/retriever.d.ts.map +0 -1
- package/dist/src/user/writer.d.ts +0 -11
- package/dist/src/user/writer.d.ts.map +0 -1
- package/src/access/policy/policy.spec.ts +0 -329
- package/src/hardware/client.ts +0 -24
- package/src/hardware/device/external.ts +0 -11
- package/src/hardware/rack/external.ts +0 -11
- package/src/hardware/task/external.ts +0 -11
- package/src/user/retriever.ts +0 -41
- package/src/user/writer.ts +0 -84
- /package/dist/src/{hardware/device → access/role}/external.d.ts +0 -0
- /package/dist/src/{hardware/device → device}/device.spec.d.ts +0 -0
- /package/dist/src/{hardware/rack → device}/external.d.ts +0 -0
- /package/dist/src/{hardware/device → device}/index.d.ts +0 -0
- /package/dist/src/{hardware/task → rack}/external.d.ts +0 -0
- /package/dist/src/{hardware/rack → rack}/index.d.ts +0 -0
- /package/dist/src/{hardware/rack → rack}/rack.spec.d.ts +0 -0
- /package/dist/src/{hardware/task → task}/index.d.ts +0 -0
- /package/dist/src/{hardware/task → task}/task.spec.d.ts +0 -0
|
@@ -0,0 +1,171 @@
|
|
|
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 } from "@synnaxlabs/x";
|
|
11
|
+
import { describe, expect, it } from "vitest";
|
|
12
|
+
|
|
13
|
+
import { escapeInvalidName, nameZ, newZ } from "@/channel/payload";
|
|
14
|
+
|
|
15
|
+
describe("nameZ", () => {
|
|
16
|
+
describe("valid names", () => {
|
|
17
|
+
const validNames = [
|
|
18
|
+
["temperature", "lowercase letters"],
|
|
19
|
+
["Pressure", "capitalized word"],
|
|
20
|
+
["sensor1", "letters followed by digit"],
|
|
21
|
+
["sensor_temp", "letters with underscore"],
|
|
22
|
+
["temp123", "letters followed by digits"],
|
|
23
|
+
["Sensor_temp", "capitalized with underscore"],
|
|
24
|
+
["temp123_sensor_temp", "complex valid name"],
|
|
25
|
+
["_private", "underscore prefix"],
|
|
26
|
+
["__double", "double underscore prefix"],
|
|
27
|
+
["a", "single letter"],
|
|
28
|
+
["A", "single capital letter"],
|
|
29
|
+
["_", "single underscore"],
|
|
30
|
+
["_1", "underscore followed by digit"],
|
|
31
|
+
];
|
|
32
|
+
validNames.forEach(([name, description]) => {
|
|
33
|
+
it(`should accept ${name} (${description})`, () => {
|
|
34
|
+
const result = nameZ.safeParse(name);
|
|
35
|
+
expect(result.success).toBe(true);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe("invalid names", () => {
|
|
41
|
+
it("should reject empty string", () => {
|
|
42
|
+
const result = nameZ.safeParse("");
|
|
43
|
+
expect(result.success).toBe(false);
|
|
44
|
+
expect(result.error?.issues[0].message).toContain("Name must not be empty");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("should reject name starting with digit", () => {
|
|
48
|
+
const result = nameZ.safeParse("1sensor");
|
|
49
|
+
expect(result.success).toBe(false);
|
|
50
|
+
// Regex validation covers both "cannot start with digit" and "invalid characters"
|
|
51
|
+
expect(result.error?.issues[0].message).toContain(
|
|
52
|
+
"can only contain letters, digits, and underscores",
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("should reject name with spaces", () => {
|
|
57
|
+
const result = nameZ.safeParse("my channel");
|
|
58
|
+
expect(result.success).toBe(false);
|
|
59
|
+
expect(result.error?.issues[0].message).toContain(
|
|
60
|
+
"can only contain letters, digits, and underscores",
|
|
61
|
+
);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("should reject name with special characters", () => {
|
|
65
|
+
const result = nameZ.safeParse("sensor!");
|
|
66
|
+
expect(result.success).toBe(false);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("should reject name with hyphens", () => {
|
|
70
|
+
const result = nameZ.safeParse("sensor-temp");
|
|
71
|
+
expect(result.success).toBe(false);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("should reject name with dots", () => {
|
|
75
|
+
const result = nameZ.safeParse("sensor.temp");
|
|
76
|
+
expect(result.success).toBe(false);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("should reject name with parentheses", () => {
|
|
80
|
+
const result = nameZ.safeParse("sensor(1)");
|
|
81
|
+
expect(result.success).toBe(false);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("should reject name with brackets", () => {
|
|
85
|
+
const result = nameZ.safeParse("sensor[0]");
|
|
86
|
+
expect(result.success).toBe(false);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe("newZ", () => {
|
|
92
|
+
const validNewChannel = {
|
|
93
|
+
name: "temperature_sensor",
|
|
94
|
+
dataType: DataType.FLOAT32,
|
|
95
|
+
virtual: true,
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
describe("name validation", () => {
|
|
99
|
+
it("should accept valid channel names", () => {
|
|
100
|
+
const result = newZ.safeParse(validNewChannel);
|
|
101
|
+
expect(result.success).toBe(true);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("should reject empty name", () => {
|
|
105
|
+
const result = newZ.safeParse({ ...validNewChannel, name: "" });
|
|
106
|
+
expect(result.success).toBe(false);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("should reject name starting with digit", () => {
|
|
110
|
+
const result = newZ.safeParse({ ...validNewChannel, name: "1sensor" });
|
|
111
|
+
expect(result.success).toBe(false);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("should reject name with spaces", () => {
|
|
115
|
+
const result = newZ.safeParse({ ...validNewChannel, name: "my channel" });
|
|
116
|
+
expect(result.success).toBe(false);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("should reject name with special characters", () => {
|
|
120
|
+
const result = newZ.safeParse({ ...validNewChannel, name: "sensor-temp" });
|
|
121
|
+
expect(result.success).toBe(false);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("should accept name with underscores", () => {
|
|
125
|
+
const result = newZ.safeParse({
|
|
126
|
+
...validNewChannel,
|
|
127
|
+
name: "sensor_temp_123",
|
|
128
|
+
});
|
|
129
|
+
expect(result.success).toBe(true);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("should accept name starting with underscore", () => {
|
|
133
|
+
const result = newZ.safeParse({ ...validNewChannel, name: "_private_sensor" });
|
|
134
|
+
expect(result.success).toBe(true);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
describe("escapeInvalidName", () => {
|
|
139
|
+
it("should escape invalid name", () => {
|
|
140
|
+
const result = escapeInvalidName("sensor-temp");
|
|
141
|
+
expect(result).toBe("sensor_temp");
|
|
142
|
+
});
|
|
143
|
+
it("should escape name starting with digit", () => {
|
|
144
|
+
const result = escapeInvalidName("1sensor");
|
|
145
|
+
expect(result).toBe("_1sensor");
|
|
146
|
+
});
|
|
147
|
+
it("should escape name with spaces", () => {
|
|
148
|
+
const result = escapeInvalidName("my channel");
|
|
149
|
+
expect(result).toBe("my_channel");
|
|
150
|
+
});
|
|
151
|
+
it("should escape name with special characters", () => {
|
|
152
|
+
const result = escapeInvalidName("sensor!");
|
|
153
|
+
expect(result).toBe("sensor_");
|
|
154
|
+
});
|
|
155
|
+
it("should escape name with hyphens", () => {
|
|
156
|
+
const result = escapeInvalidName("sensor-temp");
|
|
157
|
+
expect(result).toBe("sensor_temp");
|
|
158
|
+
});
|
|
159
|
+
it("should escape name with dots", () => {
|
|
160
|
+
const result = escapeInvalidName("sensor.temp");
|
|
161
|
+
expect(result).toBe("sensor_temp");
|
|
162
|
+
});
|
|
163
|
+
it("should allow an empty string by default", () => {
|
|
164
|
+
const result = escapeInvalidName("");
|
|
165
|
+
expect(result).toBe("");
|
|
166
|
+
});
|
|
167
|
+
it("should change empty string to underscore when changeEmptyToUnderscore is true", () => {
|
|
168
|
+
const result = escapeInvalidName("", true);
|
|
169
|
+
expect(result).toBe("_");
|
|
170
|
+
});
|
|
171
|
+
});
|
package/src/channel/payload.ts
CHANGED
|
@@ -18,6 +18,8 @@ import {
|
|
|
18
18
|
} from "@synnaxlabs/x";
|
|
19
19
|
import { z } from "zod";
|
|
20
20
|
|
|
21
|
+
import { ontology } from "@/ontology";
|
|
22
|
+
|
|
21
23
|
const errorMessage = "Channel key must be a valid uint32.";
|
|
22
24
|
export const keyZ = z.uint32().or(
|
|
23
25
|
z
|
|
@@ -28,7 +30,14 @@ export const keyZ = z.uint32().or(
|
|
|
28
30
|
);
|
|
29
31
|
export type Key = z.infer<typeof keyZ>;
|
|
30
32
|
export type Keys = Key[];
|
|
31
|
-
|
|
33
|
+
const VALID_NAME_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
34
|
+
export const nameZ = z
|
|
35
|
+
.string()
|
|
36
|
+
.min(1, "Name must not be empty")
|
|
37
|
+
.regex(
|
|
38
|
+
VALID_NAME_PATTERN,
|
|
39
|
+
"Name can only contain letters, digits, and underscores, and cannot start with a digit",
|
|
40
|
+
);
|
|
32
41
|
export type Name = z.infer<typeof nameZ>;
|
|
33
42
|
export type Names = Name[];
|
|
34
43
|
export type KeyOrName = Key | Name;
|
|
@@ -50,10 +59,10 @@ export type Operation = z.infer<typeof operationZ>;
|
|
|
50
59
|
export const statusZ = status.statusZ();
|
|
51
60
|
export type Status = z.infer<typeof statusZ>;
|
|
52
61
|
export const payloadZ = z.object({
|
|
53
|
-
name:
|
|
62
|
+
name: z.string(),
|
|
54
63
|
key: keyZ,
|
|
55
64
|
dataType: DataType.z,
|
|
56
|
-
leaseholder:
|
|
65
|
+
leaseholder: zod.uint12,
|
|
57
66
|
index: keyZ,
|
|
58
67
|
isIndex: z.boolean(),
|
|
59
68
|
internal: z.boolean(),
|
|
@@ -66,15 +75,17 @@ export const payloadZ = z.object({
|
|
|
66
75
|
});
|
|
67
76
|
export interface Payload extends z.infer<typeof payloadZ> {}
|
|
68
77
|
|
|
69
|
-
export const newZ = payloadZ.
|
|
78
|
+
export const newZ = payloadZ.extend({
|
|
70
79
|
key: keyZ.optional(),
|
|
71
|
-
|
|
80
|
+
name: nameZ,
|
|
81
|
+
leaseholder: zod.uint12.optional(),
|
|
72
82
|
index: keyZ.optional(),
|
|
73
83
|
isIndex: z.boolean().optional(),
|
|
74
|
-
internal: z.boolean().
|
|
75
|
-
virtual: z.boolean().
|
|
76
|
-
expression: z.string().
|
|
84
|
+
internal: z.boolean().default(false),
|
|
85
|
+
virtual: z.boolean().default(false),
|
|
86
|
+
expression: z.string().default(""),
|
|
77
87
|
operations: array.nullableZ(operationZ).optional(),
|
|
88
|
+
requires: array.nullableZ(keyZ).optional(),
|
|
78
89
|
});
|
|
79
90
|
|
|
80
91
|
export interface New
|
|
@@ -88,3 +99,21 @@ export const paramsZ = z.union([
|
|
|
88
99
|
zod.toArray(payloadZ).transform((p) => p.map((c) => c.key)),
|
|
89
100
|
]);
|
|
90
101
|
export type Params = Key | Name | Keys | Names | Payload | Payload[];
|
|
102
|
+
|
|
103
|
+
export const ontologyID = ontology.createIDFactory<Key>("channel");
|
|
104
|
+
export const TYPE_ONTOLOGY_ID = ontologyID(0);
|
|
105
|
+
|
|
106
|
+
const CHAR_REGEX = /[a-zA-Z0-9_]/;
|
|
107
|
+
|
|
108
|
+
export const escapeInvalidName = (name: string, changeEmptyToUnderscore = false) => {
|
|
109
|
+
if (name === "") return changeEmptyToUnderscore ? "_" : "";
|
|
110
|
+
if (name.match(VALID_NAME_PATTERN)) return name;
|
|
111
|
+
// if it doesn't match, convert non-alphanumeric characters to underscores and prepend
|
|
112
|
+
// an underscore if the first character is a digit
|
|
113
|
+
let result = "";
|
|
114
|
+
for (const char of name)
|
|
115
|
+
if (char.match(CHAR_REGEX)) result += char;
|
|
116
|
+
else result += "_";
|
|
117
|
+
if (result[0].match(/^\d/)) result = `_${result}`;
|
|
118
|
+
return result;
|
|
119
|
+
};
|
package/src/channel/retriever.ts
CHANGED
|
@@ -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 UnaryClient } from "@synnaxlabs/freighter";
|
|
11
|
-
import { array, DataType, debounce } from "@synnaxlabs/x";
|
|
10
|
+
import { sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
|
|
11
|
+
import { array, DataType, debounce, zod } from "@synnaxlabs/x";
|
|
12
12
|
import { Mutex } from "async-mutex";
|
|
13
13
|
import { z } from "zod";
|
|
14
14
|
|
|
@@ -25,25 +25,25 @@ import {
|
|
|
25
25
|
payloadZ,
|
|
26
26
|
} from "@/channel/payload";
|
|
27
27
|
import { QueryError } from "@/errors";
|
|
28
|
+
import { keyZ as rangeKeyZ } from "@/ranger/payload";
|
|
28
29
|
import {
|
|
29
30
|
analyzeParams as analyzeParameters,
|
|
30
31
|
type ParamAnalysisResult,
|
|
31
32
|
} from "@/util/retrieve";
|
|
32
33
|
|
|
33
34
|
const reqZ = z.object({
|
|
34
|
-
|
|
35
|
+
nodeKey: zod.uint12.optional(),
|
|
35
36
|
keys: keyZ.array().optional(),
|
|
36
37
|
names: z.string().array().optional(),
|
|
37
38
|
searchTerm: z.string().optional(),
|
|
38
|
-
rangeKey:
|
|
39
|
-
limit: z.
|
|
40
|
-
offset: z.
|
|
39
|
+
rangeKey: rangeKeyZ.optional(),
|
|
40
|
+
limit: z.int().optional(),
|
|
41
|
+
offset: z.int().optional(),
|
|
41
42
|
dataTypes: DataType.z.array().optional(),
|
|
42
43
|
notDataTypes: DataType.z.array().optional(),
|
|
43
44
|
virtual: z.boolean().optional(),
|
|
44
45
|
isIndex: z.boolean().optional(),
|
|
45
46
|
internal: z.boolean().optional(),
|
|
46
|
-
calculated: z.boolean().optional(),
|
|
47
47
|
legacyCalculated: z.boolean().optional(),
|
|
48
48
|
});
|
|
49
49
|
export interface RetrieveRequest extends z.input<typeof reqZ> {}
|
|
@@ -72,7 +72,6 @@ export interface Retriever {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
export class ClusterRetriever implements Retriever {
|
|
75
|
-
private static readonly ENDPOINT = "/channel/retrieve";
|
|
76
75
|
private readonly client: UnaryClient;
|
|
77
76
|
|
|
78
77
|
constructor(client: UnaryClient) {
|
|
@@ -95,13 +94,13 @@ export class ClusterRetriever implements Retriever {
|
|
|
95
94
|
}
|
|
96
95
|
|
|
97
96
|
private async execute(request: RetrieveRequest): Promise<Payload[]> {
|
|
98
|
-
const
|
|
99
|
-
|
|
97
|
+
const res = await sendRequired(
|
|
98
|
+
this.client,
|
|
99
|
+
"/channel/retrieve",
|
|
100
100
|
request,
|
|
101
101
|
reqZ,
|
|
102
102
|
resZ,
|
|
103
103
|
);
|
|
104
|
-
if (err != null) throw err;
|
|
105
104
|
return res.channels;
|
|
106
105
|
}
|
|
107
106
|
}
|
package/src/channel/writer.ts
CHANGED
|
@@ -34,10 +34,6 @@ const deleteResZ = z.object({});
|
|
|
34
34
|
const renameReqZ = z.object({ keys: keyZ.array(), names: nameZ.array() });
|
|
35
35
|
const renameResZ = z.object({});
|
|
36
36
|
|
|
37
|
-
const CREATE_ENDPOINT = "/channel/create";
|
|
38
|
-
const DELETE_ENDPOINT = "/channel/delete";
|
|
39
|
-
const RENAME_ENDPOINT = "/channel/rename";
|
|
40
|
-
|
|
41
37
|
export interface DeleteProps extends z.input<typeof deleteReqZ> {}
|
|
42
38
|
export interface RenameProps extends z.input<typeof renameReqZ> {}
|
|
43
39
|
|
|
@@ -56,7 +52,7 @@ export class Writer {
|
|
|
56
52
|
typeof createResZ
|
|
57
53
|
>(
|
|
58
54
|
this.client,
|
|
59
|
-
|
|
55
|
+
"/channel/create",
|
|
60
56
|
{
|
|
61
57
|
channels: channels.map((c) => ({
|
|
62
58
|
...c,
|
|
@@ -74,7 +70,7 @@ export class Writer {
|
|
|
74
70
|
const keys = keyZ.array().parse(props.keys ?? []);
|
|
75
71
|
await sendRequired<typeof deleteReqZ, typeof deleteResZ>(
|
|
76
72
|
this.client,
|
|
77
|
-
|
|
73
|
+
"/channel/delete",
|
|
78
74
|
props,
|
|
79
75
|
deleteReqZ,
|
|
80
76
|
deleteResZ,
|
|
@@ -86,7 +82,7 @@ export class Writer {
|
|
|
86
82
|
async rename(keys: Key[], names: string[]): Promise<void> {
|
|
87
83
|
await sendRequired<typeof renameReqZ, typeof renameResZ>(
|
|
88
84
|
this.client,
|
|
89
|
-
|
|
85
|
+
"/channel/rename",
|
|
90
86
|
{ keys, names },
|
|
91
87
|
renameReqZ,
|
|
92
88
|
renameResZ,
|
package/src/client.ts
CHANGED
|
@@ -16,21 +16,20 @@ import { auth } from "@/auth";
|
|
|
16
16
|
import { channel } from "@/channel";
|
|
17
17
|
import { connection } from "@/connection";
|
|
18
18
|
import { control } from "@/control";
|
|
19
|
+
import { device } from "@/device";
|
|
19
20
|
import { errorsMiddleware } from "@/errors";
|
|
20
21
|
import { framer } from "@/framer";
|
|
21
|
-
import { hardware } from "@/hardware";
|
|
22
|
-
import { device } from "@/hardware/device";
|
|
23
|
-
import { rack } from "@/hardware/rack";
|
|
24
|
-
import { task } from "@/hardware/task";
|
|
25
22
|
import { label } from "@/label";
|
|
26
23
|
import { ontology } from "@/ontology";
|
|
24
|
+
import { rack } from "@/rack";
|
|
27
25
|
import { ranger } from "@/ranger";
|
|
28
26
|
import { status } from "@/status";
|
|
27
|
+
import { task } from "@/task";
|
|
29
28
|
import { Transport } from "@/transport";
|
|
30
29
|
import { user } from "@/user";
|
|
31
30
|
import { workspace } from "@/workspace";
|
|
32
31
|
|
|
33
|
-
export const
|
|
32
|
+
export const synnaxParamsZ = z.object({
|
|
34
33
|
host: z.string({ error: "Host is required" }).min(1, "Host is required"),
|
|
35
34
|
port: z
|
|
36
35
|
.number({ error: "Port is required" })
|
|
@@ -38,13 +37,13 @@ export const synnaxPropsZ = z.object({
|
|
|
38
37
|
username: z.string().min(1, "Username is required"),
|
|
39
38
|
password: z.string().min(1, "Password is required"),
|
|
40
39
|
connectivityPollFrequency: TimeSpan.z.default(TimeSpan.seconds(30)),
|
|
41
|
-
secure: z.boolean().
|
|
40
|
+
secure: z.boolean().default(false),
|
|
42
41
|
name: z.string().optional(),
|
|
43
42
|
retry: breaker.breakerConfigZ.optional(),
|
|
44
43
|
});
|
|
45
44
|
|
|
46
|
-
export interface
|
|
47
|
-
export interface
|
|
45
|
+
export interface SynnaxParams extends z.input<typeof synnaxParamsZ> {}
|
|
46
|
+
export interface ParsedSynnaxParams extends z.infer<typeof synnaxParamsZ> {}
|
|
48
47
|
|
|
49
48
|
/**
|
|
50
49
|
* Client to perform operations against a Synnax cluster.
|
|
@@ -56,10 +55,10 @@ export interface ParsedSynnaxProps extends z.infer<typeof synnaxPropsZ> {}
|
|
|
56
55
|
*/
|
|
57
56
|
export default class Synnax extends framer.Client {
|
|
58
57
|
readonly createdAt: TimeStamp;
|
|
59
|
-
readonly
|
|
58
|
+
readonly params: ParsedSynnaxParams;
|
|
60
59
|
readonly ranges: ranger.Client;
|
|
61
60
|
readonly channels: channel.Client;
|
|
62
|
-
readonly auth: auth.Client
|
|
61
|
+
readonly auth: auth.Client;
|
|
63
62
|
readonly users: user.Client;
|
|
64
63
|
readonly access: access.Client;
|
|
65
64
|
readonly connectivity: connection.Checker;
|
|
@@ -67,7 +66,9 @@ export default class Synnax extends framer.Client {
|
|
|
67
66
|
readonly workspaces: workspace.Client;
|
|
68
67
|
readonly labels: label.Client;
|
|
69
68
|
readonly statuses: status.Client;
|
|
70
|
-
readonly
|
|
69
|
+
readonly tasks: task.Client;
|
|
70
|
+
readonly racks: rack.Client;
|
|
71
|
+
readonly devices: device.Client;
|
|
71
72
|
readonly control: control.Client;
|
|
72
73
|
readonly arcs: arc.Client;
|
|
73
74
|
static readonly connectivity = connection.Checker;
|
|
@@ -93,8 +94,8 @@ export default class Synnax extends framer.Client {
|
|
|
93
94
|
* A Synnax client must be closed when it is no longer needed. This will stop
|
|
94
95
|
* the client from polling the cluster for connectivity information.
|
|
95
96
|
*/
|
|
96
|
-
constructor(
|
|
97
|
-
const
|
|
97
|
+
constructor(params: SynnaxParams) {
|
|
98
|
+
const parsedParams = synnaxParamsZ.parse(params);
|
|
98
99
|
const {
|
|
99
100
|
host,
|
|
100
101
|
port,
|
|
@@ -103,33 +104,29 @@ export default class Synnax extends framer.Client {
|
|
|
103
104
|
connectivityPollFrequency,
|
|
104
105
|
secure,
|
|
105
106
|
retry: breaker,
|
|
106
|
-
} =
|
|
107
|
+
} = parsedParams;
|
|
107
108
|
const transport = new Transport(
|
|
108
109
|
new URL({ host, port: Number(port) }),
|
|
109
110
|
breaker,
|
|
110
111
|
secure,
|
|
111
112
|
);
|
|
112
113
|
transport.use(errorsMiddleware);
|
|
113
|
-
let auth_: auth.Client | undefined;
|
|
114
|
-
if (username != null && password != null) {
|
|
115
|
-
auth_ = new auth.Client(transport.unary, { username, password });
|
|
116
|
-
transport.use(auth_.middleware());
|
|
117
|
-
}
|
|
118
114
|
const chRetriever = new channel.CacheRetriever(
|
|
119
115
|
new channel.ClusterRetriever(transport.unary),
|
|
120
116
|
);
|
|
121
|
-
const chCreator = new channel.Writer(transport.unary, chRetriever);
|
|
122
117
|
super(transport.stream, transport.unary, chRetriever);
|
|
118
|
+
this.auth = new auth.Client(transport.unary, { username, password });
|
|
119
|
+
transport.use(this.auth.middleware());
|
|
120
|
+
const chCreator = new channel.Writer(transport.unary, chRetriever);
|
|
123
121
|
this.createdAt = TimeStamp.now();
|
|
124
|
-
this.
|
|
125
|
-
this.auth = auth_;
|
|
122
|
+
this.params = parsedParams;
|
|
126
123
|
this.transport = transport;
|
|
127
124
|
this.channels = new channel.Client(this, chRetriever, transport.unary, chCreator);
|
|
128
125
|
this.connectivity = new connection.Checker(
|
|
129
126
|
transport.unary,
|
|
130
127
|
connectivityPollFrequency,
|
|
131
128
|
this.clientVersion,
|
|
132
|
-
|
|
129
|
+
parsedParams.name,
|
|
133
130
|
);
|
|
134
131
|
this.control = new control.Client(this);
|
|
135
132
|
this.ontology = new ontology.Client(transport.unary, this);
|
|
@@ -147,15 +144,14 @@ export default class Synnax extends framer.Client {
|
|
|
147
144
|
this.access = new access.Client(this.transport.unary);
|
|
148
145
|
this.users = new user.Client(this.transport.unary);
|
|
149
146
|
this.workspaces = new workspace.Client(this.transport.unary);
|
|
150
|
-
|
|
151
|
-
const tasks = new task.Client(
|
|
147
|
+
this.tasks = new task.Client(
|
|
152
148
|
this.transport.unary,
|
|
153
149
|
this,
|
|
154
150
|
this.ontology,
|
|
155
151
|
this.ranges,
|
|
156
152
|
);
|
|
157
|
-
|
|
158
|
-
this.
|
|
153
|
+
this.racks = new rack.Client(this.transport.unary, this.tasks);
|
|
154
|
+
this.devices = new device.Client(this.transport.unary);
|
|
159
155
|
this.arcs = new arc.Client(this.transport.unary, this.transport.stream);
|
|
160
156
|
}
|
|
161
157
|
|
|
@@ -164,6 +160,20 @@ export default class Synnax extends framer.Client {
|
|
|
164
160
|
}
|
|
165
161
|
|
|
166
162
|
close(): void {
|
|
167
|
-
this.connectivity.
|
|
163
|
+
this.connectivity.stop();
|
|
168
164
|
}
|
|
169
165
|
}
|
|
166
|
+
|
|
167
|
+
export interface CheckConnectionParams
|
|
168
|
+
extends Pick<SynnaxParams, "host" | "port" | "secure" | "retry" | "name"> {}
|
|
169
|
+
|
|
170
|
+
export const checkConnection = async (params: CheckConnectionParams) =>
|
|
171
|
+
await newConnectionChecker(params).check();
|
|
172
|
+
|
|
173
|
+
export const newConnectionChecker = (params: CheckConnectionParams) => {
|
|
174
|
+
const { host, port, secure, name, retry } = params;
|
|
175
|
+
const retryConfig = breaker.breakerConfigZ.optional().parse(retry);
|
|
176
|
+
const url = new URL({ host, port: Number(port) });
|
|
177
|
+
const transport = new Transport(url, retryConfig, secure);
|
|
178
|
+
return new connection.Checker(transport.unary, undefined, __VERSION__, name);
|
|
179
|
+
};
|
|
@@ -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
|
|
10
|
+
import { sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
|
|
11
11
|
import { migrate, TimeSpan } from "@synnaxlabs/x";
|
|
12
12
|
import { z } from "zod";
|
|
13
13
|
|
|
@@ -29,6 +29,7 @@ const responseZ = z.object({
|
|
|
29
29
|
clusterKey: z.string(),
|
|
30
30
|
nodeVersion: z.string().optional(),
|
|
31
31
|
});
|
|
32
|
+
const requestZ = z.void();
|
|
32
33
|
|
|
33
34
|
const DEFAULT: State = {
|
|
34
35
|
clusterKey: "",
|
|
@@ -52,7 +53,6 @@ const createWarning = (
|
|
|
52
53
|
|
|
53
54
|
/** Polls a synnax cluster for connectivity information. */
|
|
54
55
|
export class Checker {
|
|
55
|
-
private static readonly ENDPOINT = "/connectivity/check";
|
|
56
56
|
static readonly DEFAULT: State = DEFAULT;
|
|
57
57
|
private readonly _state: State;
|
|
58
58
|
private readonly pollFrequency = TimeSpan.seconds(30);
|
|
@@ -81,11 +81,11 @@ export class Checker {
|
|
|
81
81
|
this.clientVersion = clientVersion;
|
|
82
82
|
this.name = name;
|
|
83
83
|
void this.check();
|
|
84
|
-
this.
|
|
84
|
+
this.start();
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
/** Stops the connectivity client from polling the cluster for connectivity */
|
|
88
|
-
|
|
88
|
+
stop(): void {
|
|
89
89
|
if (this.interval != null) clearInterval(this.interval);
|
|
90
90
|
}
|
|
91
91
|
|
|
@@ -96,13 +96,13 @@ export class Checker {
|
|
|
96
96
|
async check(): Promise<State> {
|
|
97
97
|
const prevStatus = this._state.status;
|
|
98
98
|
try {
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
99
|
+
const res = await sendRequired(
|
|
100
|
+
this.client,
|
|
101
|
+
"/connectivity/check",
|
|
102
|
+
undefined,
|
|
103
|
+
requestZ,
|
|
103
104
|
responseZ,
|
|
104
105
|
);
|
|
105
|
-
if (err != null) throw err;
|
|
106
106
|
const nodeVersion = res.nodeVersion;
|
|
107
107
|
const clientVersion = this.clientVersion;
|
|
108
108
|
const warned = this.versionWarned;
|
|
@@ -156,7 +156,7 @@ export class Checker {
|
|
|
156
156
|
this.onChangeHandlers.push(callback);
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
private
|
|
159
|
+
private start(): void {
|
|
160
160
|
this.interval = setInterval(() => {
|
|
161
161
|
void this.check();
|
|
162
162
|
}, this.pollFrequency.milliseconds);
|
|
@@ -13,18 +13,18 @@ import { z } from "zod";
|
|
|
13
13
|
|
|
14
14
|
import { auth } from "@/auth";
|
|
15
15
|
import { connection } from "@/connection";
|
|
16
|
-
import {
|
|
16
|
+
import { TEST_CLIENT_PARAMS } from "@/testutil/client";
|
|
17
17
|
import { Transport } from "@/transport";
|
|
18
18
|
|
|
19
19
|
describe("connectivity", () => {
|
|
20
20
|
it("should connect to the server", async () => {
|
|
21
21
|
const transport = new Transport(
|
|
22
22
|
new URL({
|
|
23
|
-
host:
|
|
24
|
-
port: Number(
|
|
23
|
+
host: TEST_CLIENT_PARAMS.host,
|
|
24
|
+
port: Number(TEST_CLIENT_PARAMS.port),
|
|
25
25
|
}),
|
|
26
26
|
);
|
|
27
|
-
const client = new auth.Client(transport.unary,
|
|
27
|
+
const client = new auth.Client(transport.unary, TEST_CLIENT_PARAMS);
|
|
28
28
|
transport.use(client.middleware());
|
|
29
29
|
const connectivity = new connection.Checker(
|
|
30
30
|
transport.unary,
|
|
@@ -39,11 +39,11 @@ describe("connectivity", () => {
|
|
|
39
39
|
it("should pull the server and client versions", async () => {
|
|
40
40
|
const transport = new Transport(
|
|
41
41
|
new URL({
|
|
42
|
-
host:
|
|
43
|
-
port: Number(
|
|
42
|
+
host: TEST_CLIENT_PARAMS.host,
|
|
43
|
+
port: Number(TEST_CLIENT_PARAMS.port),
|
|
44
44
|
}),
|
|
45
45
|
);
|
|
46
|
-
const client = new auth.Client(transport.unary,
|
|
46
|
+
const client = new auth.Client(transport.unary, TEST_CLIENT_PARAMS);
|
|
47
47
|
transport.use(client.middleware());
|
|
48
48
|
const connectivity = new connection.Checker(
|
|
49
49
|
transport.unary,
|
|
@@ -57,11 +57,11 @@ describe("connectivity", () => {
|
|
|
57
57
|
it("should adjust state if the server is too old", async () => {
|
|
58
58
|
const transport = new Transport(
|
|
59
59
|
new URL({
|
|
60
|
-
host:
|
|
61
|
-
port: Number(
|
|
60
|
+
host: TEST_CLIENT_PARAMS.host,
|
|
61
|
+
port: Number(TEST_CLIENT_PARAMS.port),
|
|
62
62
|
}),
|
|
63
63
|
);
|
|
64
|
-
const client = new auth.Client(transport.unary,
|
|
64
|
+
const client = new auth.Client(transport.unary, TEST_CLIENT_PARAMS);
|
|
65
65
|
transport.use(client.middleware());
|
|
66
66
|
const connectivity = new connection.Checker(
|
|
67
67
|
transport.unary,
|
|
@@ -75,11 +75,11 @@ describe("connectivity", () => {
|
|
|
75
75
|
it("should adjust state if the server is too new", async () => {
|
|
76
76
|
const transport = new Transport(
|
|
77
77
|
new URL({
|
|
78
|
-
host:
|
|
79
|
-
port: Number(
|
|
78
|
+
host: TEST_CLIENT_PARAMS.host,
|
|
79
|
+
port: Number(TEST_CLIENT_PARAMS.port),
|
|
80
80
|
}),
|
|
81
81
|
);
|
|
82
|
-
const client = new auth.Client(transport.unary,
|
|
82
|
+
const client = new auth.Client(transport.unary, TEST_CLIENT_PARAMS);
|
|
83
83
|
transport.use(client.middleware());
|
|
84
84
|
const connectivity = new connection.Checker(transport.unary, undefined, "0.0.0");
|
|
85
85
|
const state = await connectivity.check();
|