@synnaxlabs/client 0.48.0 → 0.49.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +6 -6
- package/dist/client.cjs +33 -31
- package/dist/client.js +6522 -6167
- 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 +18 -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 +9 -5
- package/dist/src/client.d.ts.map +1 -1
- 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/client.d.ts +11 -1
- package/dist/src/framer/client.d.ts.map +1 -1
- package/dist/src/framer/frame.d.ts +10 -5
- package/dist/src/framer/frame.d.ts.map +1 -1
- package/dist/src/framer/iterator.d.ts +3 -3
- package/dist/src/framer/reader.d.ts +16 -0
- package/dist/src/framer/reader.d.ts.map +1 -0
- package/dist/src/framer/reader.spec.d.ts +2 -0
- package/dist/src/framer/reader.spec.d.ts.map +1 -0
- 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 +4 -5
- 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/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/package.json +3 -3
- 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.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 +35 -7
- package/src/channel/retriever.ts +10 -11
- package/src/channel/writer.ts +3 -7
- package/src/client.ts +14 -18
- 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 +14 -14
- package/src/framer/client.spec.ts +14 -20
- package/src/framer/client.ts +15 -20
- package/src/framer/deleter.spec.ts +1 -1
- package/src/framer/frame.spec.ts +131 -0
- package/src/framer/frame.ts +10 -2
- package/src/framer/iterator.ts +3 -3
- package/src/framer/reader.spec.ts +736 -0
- package/src/framer/reader.ts +265 -0
- package/src/framer/streamer.spec.ts +100 -12
- package/src/framer/streamer.ts +29 -9
- package/src/framer/writer.spec.ts +5 -5
- package/src/index.ts +4 -5
- 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/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
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(),
|
|
@@ -68,12 +77,13 @@ export interface Payload extends z.infer<typeof payloadZ> {}
|
|
|
68
77
|
|
|
69
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(),
|
|
78
88
|
requires: array.nullableZ(keyZ).optional(),
|
|
79
89
|
});
|
|
@@ -89,3 +99,21 @@ export const paramsZ = z.union([
|
|
|
89
99
|
zod.toArray(payloadZ).transform((p) => p.map((c) => c.key)),
|
|
90
100
|
]);
|
|
91
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,16 +16,15 @@ 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";
|
|
@@ -38,7 +37,7 @@ export const synnaxParamsZ = 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
|
});
|
|
@@ -59,7 +58,7 @@ export default class Synnax extends framer.Client {
|
|
|
59
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;
|
|
@@ -110,19 +111,15 @@ export default class Synnax extends framer.Client {
|
|
|
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
122
|
this.params = parsedParams;
|
|
125
|
-
this.auth = auth_;
|
|
126
123
|
this.transport = transport;
|
|
127
124
|
this.channels = new channel.Client(this, chRetriever, transport.unary, chCreator);
|
|
128
125
|
this.connectivity = new connection.Checker(
|
|
@@ -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
|
|
|
@@ -0,0 +1,159 @@
|
|
|
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 { id } from "@synnaxlabs/x";
|
|
11
|
+
import { describe, expect, it } from "vitest";
|
|
12
|
+
|
|
13
|
+
import { device } from "@/device";
|
|
14
|
+
import { AuthError, NotFoundError } from "@/errors";
|
|
15
|
+
import { createTestClientWithPolicy } from "@/testutil/access";
|
|
16
|
+
import { createTestClient } from "@/testutil/client";
|
|
17
|
+
|
|
18
|
+
const client = createTestClient();
|
|
19
|
+
|
|
20
|
+
describe("device", () => {
|
|
21
|
+
describe("access control", () => {
|
|
22
|
+
it("should deny access when no retrieve policy exists", async () => {
|
|
23
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
24
|
+
name: "test",
|
|
25
|
+
objects: [],
|
|
26
|
+
actions: [],
|
|
27
|
+
});
|
|
28
|
+
const rack = await client.racks.create({
|
|
29
|
+
name: "test",
|
|
30
|
+
});
|
|
31
|
+
const randomDevice = await client.devices.create({
|
|
32
|
+
key: id.create(),
|
|
33
|
+
rack: rack.key,
|
|
34
|
+
location: "Dev1",
|
|
35
|
+
name: "test",
|
|
36
|
+
make: "ni",
|
|
37
|
+
model: "test",
|
|
38
|
+
properties: {},
|
|
39
|
+
});
|
|
40
|
+
await expect(
|
|
41
|
+
userClient.devices.retrieve({ key: randomDevice.key }),
|
|
42
|
+
).rejects.toThrow(AuthError);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("should allow the caller to retrieve devices with the correct policy", async () => {
|
|
46
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
47
|
+
name: "test",
|
|
48
|
+
objects: [device.ontologyID("")],
|
|
49
|
+
actions: ["retrieve"],
|
|
50
|
+
});
|
|
51
|
+
const rack = await client.racks.create({
|
|
52
|
+
name: "test",
|
|
53
|
+
});
|
|
54
|
+
const randomDevice = await client.devices.create({
|
|
55
|
+
key: id.create(),
|
|
56
|
+
rack: rack.key,
|
|
57
|
+
location: "Dev1",
|
|
58
|
+
name: "test",
|
|
59
|
+
make: "ni",
|
|
60
|
+
model: "test",
|
|
61
|
+
properties: {},
|
|
62
|
+
});
|
|
63
|
+
const retrieved = await userClient.devices.retrieve({
|
|
64
|
+
key: randomDevice.key,
|
|
65
|
+
});
|
|
66
|
+
expect(retrieved.key).toBe(randomDevice.key);
|
|
67
|
+
expect(retrieved.name).toBe(randomDevice.name);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("should allow the caller to create devices with the correct policy", async () => {
|
|
71
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
72
|
+
name: "test",
|
|
73
|
+
objects: [device.ontologyID("")],
|
|
74
|
+
actions: ["create"],
|
|
75
|
+
});
|
|
76
|
+
const rack = await client.racks.create({
|
|
77
|
+
name: "test",
|
|
78
|
+
});
|
|
79
|
+
await userClient.devices.create({
|
|
80
|
+
key: id.create(),
|
|
81
|
+
rack: rack.key,
|
|
82
|
+
location: "Dev1",
|
|
83
|
+
name: "test",
|
|
84
|
+
make: "ni",
|
|
85
|
+
model: "test",
|
|
86
|
+
properties: {},
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("should deny access when no create policy exists", async () => {
|
|
91
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
92
|
+
name: "test",
|
|
93
|
+
objects: [device.ontologyID("")],
|
|
94
|
+
actions: [],
|
|
95
|
+
});
|
|
96
|
+
const rack = await client.racks.create({
|
|
97
|
+
name: "test",
|
|
98
|
+
});
|
|
99
|
+
await expect(
|
|
100
|
+
userClient.devices.create({
|
|
101
|
+
key: id.create(),
|
|
102
|
+
rack: rack.key,
|
|
103
|
+
location: "Dev1",
|
|
104
|
+
name: "test",
|
|
105
|
+
make: "ni",
|
|
106
|
+
model: "test",
|
|
107
|
+
properties: {},
|
|
108
|
+
}),
|
|
109
|
+
).rejects.toThrow(AuthError);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("should allow the caller to delete devices with the correct policy", async () => {
|
|
113
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
114
|
+
name: "test",
|
|
115
|
+
objects: [device.ontologyID("")],
|
|
116
|
+
actions: ["delete", "retrieve"],
|
|
117
|
+
});
|
|
118
|
+
const rack = await client.racks.create({
|
|
119
|
+
name: "test",
|
|
120
|
+
});
|
|
121
|
+
const randomDevice = await client.devices.create({
|
|
122
|
+
key: id.create(),
|
|
123
|
+
rack: rack.key,
|
|
124
|
+
location: "Dev1",
|
|
125
|
+
name: "test",
|
|
126
|
+
make: "ni",
|
|
127
|
+
model: "test",
|
|
128
|
+
properties: {},
|
|
129
|
+
});
|
|
130
|
+
await userClient.devices.delete(randomDevice.key);
|
|
131
|
+
await expect(
|
|
132
|
+
userClient.devices.retrieve({ key: randomDevice.key }),
|
|
133
|
+
).rejects.toThrow(NotFoundError);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it("should deny access when no delete policy exists", async () => {
|
|
137
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
138
|
+
name: "test",
|
|
139
|
+
objects: [device.ontologyID("")],
|
|
140
|
+
actions: [],
|
|
141
|
+
});
|
|
142
|
+
const rack = await client.racks.create({
|
|
143
|
+
name: "test",
|
|
144
|
+
});
|
|
145
|
+
const randomDevice = await client.devices.create({
|
|
146
|
+
key: id.create(),
|
|
147
|
+
rack: rack.key,
|
|
148
|
+
location: "Dev1",
|
|
149
|
+
name: "test",
|
|
150
|
+
make: "ni",
|
|
151
|
+
model: "test",
|
|
152
|
+
properties: {},
|
|
153
|
+
});
|
|
154
|
+
await expect(userClient.devices.delete(randomDevice.key)).rejects.toThrow(
|
|
155
|
+
AuthError,
|
|
156
|
+
);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
});
|
|
@@ -11,25 +11,13 @@ import { sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
|
|
|
11
11
|
import { array, type record } from "@synnaxlabs/x";
|
|
12
12
|
import { z } from "zod";
|
|
13
13
|
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
type Key,
|
|
18
|
-
keyZ,
|
|
19
|
-
type New,
|
|
20
|
-
newZ,
|
|
21
|
-
} from "@/hardware/device/payload";
|
|
22
|
-
import { keyZ as rackKeyZ } from "@/hardware/rack/payload";
|
|
23
|
-
import { type ontology } from "@/ontology";
|
|
14
|
+
import { type Device, deviceZ, type Key, keyZ, type New, newZ } from "@/device/payload";
|
|
15
|
+
import { ontology } from "@/ontology";
|
|
16
|
+
import { keyZ as rackKeyZ } from "@/rack/payload";
|
|
24
17
|
import { checkForMultipleOrNoResults } from "@/util/retrieve";
|
|
25
18
|
|
|
26
19
|
export const SET_CHANNEL_NAME = "sy_device_set";
|
|
27
20
|
export const DELETE_CHANNEL_NAME = "sy_device_delete";
|
|
28
|
-
export const STATUS_CHANNEL_NAME = "sy_device_status";
|
|
29
|
-
|
|
30
|
-
const RETRIEVE_ENDPOINT = "/hardware/device/retrieve";
|
|
31
|
-
const CREATE_ENDPOINT = "/hardware/device/create";
|
|
32
|
-
const DELETE_ENDPOINT = "/hardware/device/delete";
|
|
33
21
|
|
|
34
22
|
const createReqZ = z.object({ devices: newZ.array() });
|
|
35
23
|
const createResZ = z.object({ devices: deviceZ.array() });
|
|
@@ -45,8 +33,8 @@ const retrieveRequestZ = z.object({
|
|
|
45
33
|
locations: z.string().array().optional(),
|
|
46
34
|
racks: rackKeyZ.array().optional(),
|
|
47
35
|
searchTerm: z.string().optional(),
|
|
48
|
-
limit: z.
|
|
49
|
-
offset: z.
|
|
36
|
+
limit: z.int().optional(),
|
|
37
|
+
offset: z.int().optional(),
|
|
50
38
|
includeStatus: z.boolean().optional(),
|
|
51
39
|
});
|
|
52
40
|
const retrieveResZ = z.object({ devices: array.nullableZ(deviceZ) });
|
|
@@ -97,7 +85,7 @@ export class Client {
|
|
|
97
85
|
const isSingle = typeof args === "object" && "key" in args;
|
|
98
86
|
const res = await sendRequired(
|
|
99
87
|
this.client,
|
|
100
|
-
|
|
88
|
+
"/device/retrieve",
|
|
101
89
|
args,
|
|
102
90
|
retrieveArgsZ,
|
|
103
91
|
retrieveResZ,
|
|
@@ -127,7 +115,7 @@ export class Client {
|
|
|
127
115
|
const isSingle = !Array.isArray(devices);
|
|
128
116
|
const res = await sendRequired(
|
|
129
117
|
this.client,
|
|
130
|
-
|
|
118
|
+
"/device/create",
|
|
131
119
|
{ devices: array.toArray(devices) },
|
|
132
120
|
createReqZ,
|
|
133
121
|
createResZ,
|
|
@@ -139,7 +127,7 @@ export class Client {
|
|
|
139
127
|
async delete(keys: Key | Key[]): Promise<void> {
|
|
140
128
|
await sendRequired(
|
|
141
129
|
this.client,
|
|
142
|
-
|
|
130
|
+
"/device/delete",
|
|
143
131
|
{ keys: array.toArray(keys) },
|
|
144
132
|
deleteReqZ,
|
|
145
133
|
deleteResZ,
|
|
@@ -147,4 +135,7 @@ export class Client {
|
|
|
147
135
|
}
|
|
148
136
|
}
|
|
149
137
|
|
|
150
|
-
export const ontologyID =
|
|
138
|
+
export const ontologyID = ontology.createIDFactory<Key>("device");
|
|
139
|
+
export const TYPE_ONTOLOGY_ID = ontologyID("");
|
|
140
|
+
|
|
141
|
+
export const statusKey = (key: Key): string => ontology.idToString(ontologyID(key));
|