@synnaxlabs/client 0.38.0 → 0.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +7 -7
- package/dist/access/payload.d.ts +6 -6
- package/dist/access/payload.d.ts.map +1 -1
- package/dist/access/policy/client.d.ts +5 -3
- package/dist/access/policy/client.d.ts.map +1 -1
- package/dist/access/policy/external.d.ts +1 -0
- package/dist/access/policy/external.d.ts.map +1 -1
- package/dist/access/policy/ontology.d.ts +5 -0
- package/dist/access/policy/ontology.d.ts.map +1 -0
- package/dist/access/policy/payload.d.ts +86 -89
- package/dist/access/policy/payload.d.ts.map +1 -1
- package/dist/access/policy/retriever.d.ts +7 -6
- package/dist/access/policy/retriever.d.ts.map +1 -1
- package/dist/access/policy/writer.d.ts +2 -2
- package/dist/access/policy/writer.d.ts.map +1 -1
- package/dist/auth/auth.d.ts +2 -1
- package/dist/auth/auth.d.ts.map +1 -1
- package/dist/channel/client.d.ts +8 -7
- package/dist/channel/client.d.ts.map +1 -1
- package/dist/channel/payload.d.ts +13 -11
- package/dist/channel/payload.d.ts.map +1 -1
- package/dist/channel/retriever.d.ts +9 -6
- package/dist/channel/retriever.d.ts.map +1 -1
- package/dist/channel/writer.d.ts +6 -4
- package/dist/channel/writer.d.ts.map +1 -1
- package/dist/client.cjs +30 -30
- package/dist/client.d.ts +4 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +3488 -3500
- package/dist/connection/checker.d.ts +5 -4
- package/dist/connection/checker.d.ts.map +1 -1
- package/dist/control/state.d.ts +10 -8
- package/dist/control/state.d.ts.map +1 -1
- package/dist/errors.d.ts +5 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/framer/adapter.d.ts +14 -15
- package/dist/framer/adapter.d.ts.map +1 -1
- package/dist/framer/client.d.ts +13 -15
- package/dist/framer/client.d.ts.map +1 -1
- package/dist/framer/deleter.d.ts +3 -2
- package/dist/framer/deleter.d.ts.map +1 -1
- package/dist/framer/frame.d.ts +31 -27
- package/dist/framer/frame.d.ts.map +1 -1
- package/dist/framer/iterator.d.ts +4 -5
- package/dist/framer/iterator.d.ts.map +1 -1
- package/dist/framer/streamer.d.ts +5 -6
- package/dist/framer/streamer.d.ts.map +1 -1
- package/dist/framer/writer.d.ts +42 -39
- package/dist/framer/writer.d.ts.map +1 -1
- package/dist/hardware/device/client.d.ts +17 -12
- package/dist/hardware/device/client.d.ts.map +1 -1
- package/dist/hardware/device/payload.d.ts +19 -16
- package/dist/hardware/device/payload.d.ts.map +1 -1
- package/dist/hardware/rack/client.d.ts +15 -15
- package/dist/hardware/rack/client.d.ts.map +1 -1
- package/dist/hardware/rack/payload.d.ts +9 -8
- package/dist/hardware/rack/payload.d.ts.map +1 -1
- package/dist/hardware/task/client.d.ts +38 -29
- package/dist/hardware/task/client.d.ts.map +1 -1
- package/dist/hardware/task/payload.d.ts +58 -53
- package/dist/hardware/task/payload.d.ts.map +1 -1
- package/dist/label/client.d.ts +4 -3
- package/dist/label/client.d.ts.map +1 -1
- package/dist/label/payload.d.ts +4 -4
- package/dist/label/payload.d.ts.map +1 -1
- package/dist/label/retriever.d.ts.map +1 -1
- package/dist/label/writer.d.ts +13 -10
- package/dist/label/writer.d.ts.map +1 -1
- package/dist/ontology/client.d.ts +12 -10
- package/dist/ontology/client.d.ts.map +1 -1
- package/dist/ontology/group/client.d.ts +5 -4
- package/dist/ontology/group/client.d.ts.map +1 -1
- package/dist/ontology/group/group.d.ts +7 -5
- package/dist/ontology/group/group.d.ts.map +1 -1
- package/dist/ontology/group/payload.d.ts +6 -5
- package/dist/ontology/group/payload.d.ts.map +1 -1
- package/dist/ontology/group/writer.d.ts +8 -8
- package/dist/ontology/group/writer.d.ts.map +1 -1
- package/dist/ontology/payload.d.ts +72 -62
- package/dist/ontology/payload.d.ts.map +1 -1
- package/dist/ontology/writer.d.ts.map +1 -1
- package/dist/ranger/alias.d.ts +9 -10
- package/dist/ranger/alias.d.ts.map +1 -1
- package/dist/ranger/client.d.ts +18 -18
- package/dist/ranger/client.d.ts.map +1 -1
- package/dist/ranger/external.d.ts +1 -1
- package/dist/ranger/external.d.ts.map +1 -1
- package/dist/ranger/kv.d.ts +18 -14
- package/dist/ranger/kv.d.ts.map +1 -1
- package/dist/ranger/payload.d.ts +13 -13
- package/dist/ranger/payload.d.ts.map +1 -1
- package/dist/ranger/writer.d.ts +14 -14
- package/dist/ranger/writer.d.ts.map +1 -1
- package/dist/setupspecs.d.ts.map +1 -1
- package/dist/signals/observable.d.ts +3 -1
- package/dist/signals/observable.d.ts.map +1 -1
- package/dist/user/client.d.ts +5 -3
- package/dist/user/client.d.ts.map +1 -1
- package/dist/user/payload.d.ts +7 -6
- package/dist/user/payload.d.ts.map +1 -1
- package/dist/user/retriever.d.ts +2 -1
- package/dist/user/retriever.d.ts.map +1 -1
- package/dist/user/writer.d.ts +2 -2
- package/dist/user/writer.d.ts.map +1 -1
- package/dist/util/decodeJSONString.d.ts +3 -0
- package/dist/util/decodeJSONString.d.ts.map +1 -0
- package/dist/util/parseWithoutKeyConversion.d.ts +3 -0
- package/dist/util/parseWithoutKeyConversion.d.ts.map +1 -0
- package/dist/util/retrieve.d.ts +1 -1
- package/dist/util/retrieve.d.ts.map +1 -1
- package/dist/util/telem.d.ts.map +1 -1
- package/dist/util/zod.d.ts.map +1 -1
- package/dist/workspace/client.d.ts +6 -60
- package/dist/workspace/client.d.ts.map +1 -1
- package/dist/workspace/external.d.ts +3 -0
- package/dist/workspace/external.d.ts.map +1 -0
- package/dist/workspace/index.d.ts +1 -1
- package/dist/workspace/index.d.ts.map +1 -1
- package/dist/workspace/lineplot/client.d.ts +5 -44
- package/dist/workspace/lineplot/client.d.ts.map +1 -1
- package/dist/workspace/lineplot/external.d.ts +3 -0
- package/dist/workspace/lineplot/external.d.ts.map +1 -0
- package/dist/workspace/lineplot/index.d.ts +1 -1
- package/dist/workspace/lineplot/index.d.ts.map +1 -1
- package/dist/workspace/lineplot/payload.d.ts +45 -0
- package/dist/workspace/lineplot/payload.d.ts.map +1 -0
- package/dist/workspace/log/client.d.ts +5 -44
- package/dist/workspace/log/client.d.ts.map +1 -1
- package/dist/workspace/log/external.d.ts +3 -0
- package/dist/workspace/log/external.d.ts.map +1 -0
- package/dist/workspace/log/index.d.ts +1 -1
- package/dist/workspace/log/index.d.ts.map +1 -1
- package/dist/workspace/log/payload.d.ts +45 -0
- package/dist/workspace/log/payload.d.ts.map +1 -0
- package/dist/workspace/payload.d.ts +60 -0
- package/dist/workspace/payload.d.ts.map +1 -0
- package/dist/workspace/schematic/client.d.ts +5 -68
- package/dist/workspace/schematic/client.d.ts.map +1 -1
- package/dist/workspace/schematic/external.d.ts +3 -0
- package/dist/workspace/schematic/external.d.ts.map +1 -0
- package/dist/workspace/schematic/index.d.ts +1 -1
- package/dist/workspace/schematic/index.d.ts.map +1 -1
- package/dist/workspace/schematic/payload.d.ts +71 -0
- package/dist/workspace/schematic/payload.d.ts.map +1 -0
- package/dist/workspace/table/client.d.ts +5 -57
- package/dist/workspace/table/client.d.ts.map +1 -1
- package/dist/workspace/table/external.d.ts +3 -0
- package/dist/workspace/table/external.d.ts.map +1 -0
- package/dist/workspace/table/index.d.ts +1 -1
- package/dist/workspace/table/index.d.ts.map +1 -1
- package/dist/workspace/table/payload.d.ts +60 -0
- package/dist/workspace/table/payload.d.ts.map +1 -0
- package/eslint.config.js +1 -1
- package/examples/node/basicReadWrite.js +27 -27
- package/examples/node/liveStream.js +16 -16
- package/examples/node/seriesAndFrames.js +39 -39
- package/examples/node/streamWrite.js +48 -46
- package/package.json +14 -12
- package/src/access/client.ts +1 -1
- package/src/access/external.ts +1 -1
- package/src/access/index.ts +1 -1
- package/src/access/payload.ts +13 -13
- package/src/access/policy/client.ts +14 -13
- package/src/access/policy/external.ts +2 -1
- package/src/access/policy/index.ts +1 -1
- package/src/access/policy/ontology.ts +17 -0
- package/src/access/policy/payload.ts +8 -20
- package/src/access/policy/policy.spec.ts +17 -17
- package/src/access/policy/retriever.ts +3 -2
- package/src/access/policy/writer.ts +5 -5
- package/src/auth/auth.spec.ts +28 -24
- package/src/auth/auth.ts +8 -12
- package/src/auth/index.ts +1 -1
- package/src/channel/batchRetriever.spec.ts +26 -23
- package/src/channel/channel.spec.ts +1 -1
- package/src/channel/client.ts +24 -24
- package/src/channel/external.ts +1 -1
- package/src/channel/index.ts +1 -1
- package/src/channel/payload.ts +17 -21
- package/src/channel/retriever.ts +21 -22
- package/src/channel/writer.ts +12 -14
- package/src/client.ts +7 -17
- package/src/connection/checker.ts +10 -12
- package/src/connection/connection.spec.ts +18 -6
- package/src/connection/index.ts +1 -1
- package/src/control/client.ts +1 -1
- package/src/control/external.ts +1 -1
- package/src/control/index.ts +1 -1
- package/src/control/state.spec.ts +1 -1
- package/src/control/state.ts +9 -10
- package/src/errors.spec.ts +2 -2
- package/src/errors.ts +9 -1
- package/src/framer/adapter.spec.ts +29 -24
- package/src/framer/adapter.ts +38 -42
- package/src/framer/client.spec.ts +6 -12
- package/src/framer/client.ts +35 -39
- package/src/framer/deleter.spec.ts +1 -1
- package/src/framer/deleter.ts +6 -7
- package/src/framer/external.ts +1 -1
- package/src/framer/frame.spec.ts +1 -1
- package/src/framer/frame.ts +63 -51
- package/src/framer/index.ts +1 -1
- package/src/framer/iterator.spec.ts +1 -1
- package/src/framer/iterator.ts +12 -17
- package/src/framer/streamProxy.ts +2 -2
- package/src/framer/streamer.spec.ts +3 -11
- package/src/framer/streamer.ts +16 -20
- package/src/framer/writer.spec.ts +49 -8
- package/src/framer/writer.ts +40 -32
- package/src/hardware/client.ts +1 -1
- package/src/hardware/device/client.ts +65 -40
- package/src/hardware/device/device.spec.ts +50 -34
- package/src/hardware/device/external.ts +1 -1
- package/src/hardware/device/index.ts +1 -1
- package/src/hardware/device/payload.ts +30 -30
- package/src/hardware/external.ts +1 -1
- package/src/hardware/index.ts +1 -1
- package/src/hardware/rack/client.ts +53 -66
- package/src/hardware/rack/external.ts +1 -1
- package/src/hardware/rack/index.ts +1 -1
- package/src/hardware/rack/payload.ts +10 -19
- package/src/hardware/rack/rack.spec.ts +13 -1
- package/src/hardware/task/client.ts +161 -132
- package/src/hardware/task/external.ts +1 -1
- package/src/hardware/task/index.ts +1 -1
- package/src/hardware/task/payload.ts +50 -69
- package/src/hardware/task/task.spec.ts +99 -82
- package/src/index.ts +1 -1
- package/src/label/client.ts +13 -16
- package/src/label/external.ts +1 -1
- package/src/label/index.ts +1 -1
- package/src/label/label.spec.ts +1 -1
- package/src/label/payload.ts +4 -10
- package/src/label/retriever.ts +4 -8
- package/src/label/writer.ts +9 -16
- package/src/ontology/client.ts +31 -29
- package/src/ontology/external.ts +1 -1
- package/src/ontology/group/client.ts +6 -6
- package/src/ontology/group/external.ts +1 -1
- package/src/ontology/group/group.spec.ts +5 -5
- package/src/ontology/group/group.ts +11 -8
- package/src/ontology/group/index.ts +1 -1
- package/src/ontology/group/payload.ts +12 -36
- package/src/ontology/group/writer.ts +23 -27
- package/src/ontology/index.ts +1 -1
- package/src/ontology/ontology.spec.ts +16 -16
- package/src/ontology/payload.ts +68 -44
- package/src/ontology/writer.ts +17 -24
- package/src/ranger/alias.ts +26 -43
- package/src/ranger/client.ts +34 -41
- package/src/ranger/external.ts +2 -2
- package/src/ranger/index.ts +1 -1
- package/src/ranger/kv.ts +10 -33
- package/src/ranger/payload.ts +15 -37
- package/src/ranger/ranger.spec.ts +2 -3
- package/src/ranger/writer.ts +9 -27
- package/src/setupspecs.ts +1 -1
- package/src/signals/external.ts +1 -1
- package/src/signals/index.ts +1 -1
- package/src/signals/observable.ts +4 -5
- package/src/transport.ts +1 -1
- package/src/user/client.ts +9 -5
- package/src/user/external.ts +1 -1
- package/src/user/index.ts +1 -1
- package/src/user/payload.ts +6 -10
- package/src/user/retriever.ts +2 -2
- package/src/user/user.spec.ts +18 -16
- package/src/user/writer.ts +4 -11
- package/src/util/decodeJSONString.ts +13 -0
- package/src/util/parseWithoutKeyConversion.ts +19 -0
- package/src/util/retrieve.spec.ts +4 -14
- package/src/util/retrieve.ts +3 -13
- package/src/util/telem.ts +2 -2
- package/src/util/zod.ts +1 -1
- package/src/vite-env.d.ts +2 -1
- package/src/workspace/client.ts +39 -57
- package/src/workspace/external.ts +11 -0
- package/src/workspace/index.ts +2 -2
- package/src/workspace/lineplot/client.ts +31 -36
- package/src/workspace/lineplot/external.ts +11 -0
- package/src/workspace/lineplot/index.ts +2 -2
- package/src/workspace/lineplot/linePlot.spec.ts +2 -3
- package/src/workspace/lineplot/payload.ts +32 -0
- package/src/workspace/log/client.ts +34 -39
- package/src/workspace/log/external.ts +11 -0
- package/src/workspace/log/index.ts +2 -2
- package/src/workspace/log/log.spec.ts +6 -19
- package/src/workspace/log/payload.ts +32 -0
- package/src/workspace/payload.ts +36 -0
- package/src/workspace/schematic/client.ts +39 -56
- package/src/workspace/schematic/external.ts +11 -0
- package/src/workspace/schematic/index.ts +2 -2
- package/src/workspace/schematic/payload.ts +37 -0
- package/src/workspace/schematic/schematic.spec.ts +16 -7
- package/src/workspace/table/client.ts +36 -50
- package/src/workspace/table/external.ts +11 -0
- package/src/workspace/table/index.ts +2 -2
- package/src/workspace/table/payload.ts +36 -0
- package/src/workspace/table/table.spec.ts +1 -1
- package/src/workspace/workspace.spec.ts +2 -3
- package/vite.config.ts +1 -1
- package/dist/channel/creator.d.ts +0 -9
- package/dist/channel/creator.d.ts.map +0 -1
- package/src/channel/creator.ts +0 -37
|
@@ -0,0 +1,17 @@
|
|
|
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
|
+
// This needs to be a separate file because these types are imported by the ontology
|
|
11
|
+
// module, but the policy module need to import the ID schema from the ontology module.
|
|
12
|
+
|
|
13
|
+
export const ONTOLOGY_TYPE = "policy";
|
|
14
|
+
export type OntologyType = typeof ONTOLOGY_TYPE;
|
|
15
|
+
|
|
16
|
+
export const ALLOW_ALL_ONTOLOGY_TYPE = "allow_all";
|
|
17
|
+
export type AllowAllOntologyType = typeof ALLOW_ALL_ONTOLOGY_TYPE;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Use of this software is governed by the Business Source License included in the file
|
|
4
4
|
// licenses/BSL.txt.
|
|
@@ -16,30 +16,18 @@ import { nullableArrayZ } from "@/util/zod";
|
|
|
16
16
|
export const keyZ = z.string().uuid();
|
|
17
17
|
export type Key = z.infer<typeof keyZ>;
|
|
18
18
|
|
|
19
|
-
export const newPolicyZ = z.object({
|
|
20
|
-
key: keyZ.optional(),
|
|
21
|
-
subjects: ontology.crudeIDZ.array().or(ontology.crudeIDZ),
|
|
22
|
-
objects: ontology.crudeIDZ.array().or(ontology.crudeIDZ),
|
|
23
|
-
actions: actionZ.array().or(actionZ),
|
|
24
|
-
});
|
|
25
|
-
export type NewPolicy = z.input<typeof newPolicyZ>;
|
|
26
|
-
|
|
27
19
|
export const policyZ = z.object({
|
|
28
20
|
key: keyZ,
|
|
29
21
|
subjects: nullableArrayZ(ontology.idZ),
|
|
30
22
|
objects: nullableArrayZ(ontology.idZ),
|
|
31
23
|
actions: nullableArrayZ(actionZ),
|
|
32
24
|
});
|
|
33
|
-
export
|
|
34
|
-
|
|
35
|
-
export const ONTOLOGY_TYPE: ontology.ResourceType = "policy";
|
|
25
|
+
export interface Policy extends z.infer<typeof policyZ> {}
|
|
36
26
|
|
|
37
|
-
export const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
export const ALLOW_ALL_ONTOLOGY_ID = new ontology.ID({
|
|
43
|
-
type: ALLOW_ALL_ONTOLOGY_TYPE,
|
|
44
|
-
key: "",
|
|
27
|
+
export const newZ = z.object({
|
|
28
|
+
key: keyZ.optional(),
|
|
29
|
+
subjects: ontology.crudeIDZ.array().or(ontology.crudeIDZ),
|
|
30
|
+
objects: ontology.crudeIDZ.array().or(ontology.crudeIDZ),
|
|
31
|
+
actions: actionZ.array().or(actionZ),
|
|
45
32
|
});
|
|
33
|
+
export interface New extends z.input<typeof newZ> {}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Use of this software is governed by the Business Source License included in the file
|
|
4
4
|
// licenses/BSL.txt.
|
|
@@ -94,7 +94,7 @@ describe("Policy", () => {
|
|
|
94
94
|
});
|
|
95
95
|
describe("many", () => {
|
|
96
96
|
test("with keys", async () => {
|
|
97
|
-
const policiesToCreate: policy.
|
|
97
|
+
const policiesToCreate: policy.New[] = [
|
|
98
98
|
{
|
|
99
99
|
subjects: [{ type: user.ONTOLOGY_TYPE, key: "10" }],
|
|
100
100
|
objects: [
|
|
@@ -185,8 +185,8 @@ describe("Policy", () => {
|
|
|
185
185
|
await client.access.policy.delete([policies[0].key, policies[1].key]);
|
|
186
186
|
});
|
|
187
187
|
test("by subject", async () => {
|
|
188
|
-
const key1 = id.
|
|
189
|
-
const key2 = id.
|
|
188
|
+
const key1 = id.create();
|
|
189
|
+
const key2 = id.create();
|
|
190
190
|
const created = await client.access.policy.create([
|
|
191
191
|
{
|
|
192
192
|
subjects: [
|
|
@@ -216,10 +216,10 @@ describe("Policy", () => {
|
|
|
216
216
|
});
|
|
217
217
|
describe("delete", async () => {
|
|
218
218
|
test("one", async () => {
|
|
219
|
-
const id1 = id.
|
|
220
|
-
const id2 = id.
|
|
221
|
-
const id3 = id.
|
|
222
|
-
const policies: policy.
|
|
219
|
+
const id1 = id.create();
|
|
220
|
+
const id2 = id.create();
|
|
221
|
+
const id3 = id.create();
|
|
222
|
+
const policies: policy.New[] = [
|
|
223
223
|
{
|
|
224
224
|
subjects: [
|
|
225
225
|
{ type: user.ONTOLOGY_TYPE, key: id1 },
|
|
@@ -250,10 +250,10 @@ describe("Policy", () => {
|
|
|
250
250
|
await client.access.policy.delete(created[1].key);
|
|
251
251
|
});
|
|
252
252
|
test("many", async () => {
|
|
253
|
-
const id1 = id.
|
|
254
|
-
const id2 = id.
|
|
255
|
-
const id3 = id.
|
|
256
|
-
const policies: policy.
|
|
253
|
+
const id1 = id.create();
|
|
254
|
+
const id2 = id.create();
|
|
255
|
+
const id3 = id.create();
|
|
256
|
+
const policies: policy.New[] = [
|
|
257
257
|
{
|
|
258
258
|
subjects: [
|
|
259
259
|
{ type: user.ONTOLOGY_TYPE, key: id1 },
|
|
@@ -288,7 +288,7 @@ describe("Policy", () => {
|
|
|
288
288
|
|
|
289
289
|
describe("privilege", async () => {
|
|
290
290
|
test("new user", async () => {
|
|
291
|
-
const username = id.
|
|
291
|
+
const username = id.create();
|
|
292
292
|
const user2 = await client.user.create({ username, password: "pwd1" });
|
|
293
293
|
expect(user2).toBeDefined();
|
|
294
294
|
const client2 = new Synnax({
|
|
@@ -298,7 +298,7 @@ describe("privilege", async () => {
|
|
|
298
298
|
password: "pwd1",
|
|
299
299
|
});
|
|
300
300
|
await expect(
|
|
301
|
-
client2.user.create({ username: id.
|
|
301
|
+
client2.user.create({ username: id.create(), password: id.create() }),
|
|
302
302
|
).rejects.toThrow(AuthError);
|
|
303
303
|
|
|
304
304
|
const policy = await client.access.policy.create({
|
|
@@ -307,11 +307,11 @@ describe("privilege", async () => {
|
|
|
307
307
|
actions: ["create"],
|
|
308
308
|
});
|
|
309
309
|
|
|
310
|
-
const newUsername = id.
|
|
310
|
+
const newUsername = id.create();
|
|
311
311
|
|
|
312
312
|
const newUser = await client2.user.create({
|
|
313
313
|
username: newUsername,
|
|
314
|
-
password: id.
|
|
314
|
+
password: id.create(),
|
|
315
315
|
});
|
|
316
316
|
|
|
317
317
|
expect(newUser.username).toEqual(newUsername);
|
|
@@ -320,7 +320,7 @@ describe("privilege", async () => {
|
|
|
320
320
|
await client.access.policy.delete(policy.key);
|
|
321
321
|
|
|
322
322
|
await expect(
|
|
323
|
-
client2.user.create({ username: id.
|
|
323
|
+
client2.user.create({ username: id.create(), password: id.create() }),
|
|
324
324
|
).rejects.toThrow(AuthError);
|
|
325
325
|
});
|
|
326
326
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Use of this software is governed by the Business Source License included in the file
|
|
4
4
|
// licenses/BSL.txt.
|
|
@@ -18,7 +18,8 @@ const reqZ = z.object({
|
|
|
18
18
|
keys: keyZ.array().optional(),
|
|
19
19
|
subjects: ontology.idZ.array().optional(),
|
|
20
20
|
});
|
|
21
|
-
|
|
21
|
+
interface Request extends z.infer<typeof reqZ> {}
|
|
22
|
+
|
|
22
23
|
const resZ = z.object({ policies: nullableArrayZ(policyZ) });
|
|
23
24
|
|
|
24
25
|
const ENDPOINT = "/access/policy/retrieve";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Use of this software is governed by the Business Source License included in the file
|
|
4
4
|
// licenses/BSL.txt.
|
|
@@ -14,8 +14,8 @@ import { z } from "zod";
|
|
|
14
14
|
import {
|
|
15
15
|
type Key,
|
|
16
16
|
keyZ,
|
|
17
|
-
type
|
|
18
|
-
|
|
17
|
+
type New,
|
|
18
|
+
newZ,
|
|
19
19
|
type Policy,
|
|
20
20
|
policyZ,
|
|
21
21
|
} from "@/access/policy/payload";
|
|
@@ -36,8 +36,8 @@ export class Writer {
|
|
|
36
36
|
this.client = client;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
async create(policies:
|
|
40
|
-
const parsedPolicies =
|
|
39
|
+
async create(policies: New | New[]): Promise<Policy[]> {
|
|
40
|
+
const parsedPolicies = newZ.array().parse(toArray(policies));
|
|
41
41
|
const req = parsedPolicies.map((policy) => ({
|
|
42
42
|
objects: toArray(policy.objects),
|
|
43
43
|
actions: toArray(policy.actions),
|
package/src/auth/auth.spec.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Use of this software is governed by the Business Source License included in the file
|
|
4
4
|
// licenses/BSL.txt.
|
|
@@ -12,7 +12,7 @@ import { URL } from "@synnaxlabs/x/url";
|
|
|
12
12
|
import { describe, expect, it, test } from "vitest";
|
|
13
13
|
|
|
14
14
|
import { auth } from "@/auth";
|
|
15
|
-
import { AuthError, InvalidTokenError } from "@/errors";
|
|
15
|
+
import { AuthError, ExpiredTokenError, InvalidTokenError } from "@/errors";
|
|
16
16
|
import { HOST, PORT } from "@/setupspecs";
|
|
17
17
|
import { Transport } from "@/transport";
|
|
18
18
|
|
|
@@ -46,30 +46,34 @@ describe("auth", () => {
|
|
|
46
46
|
expect(err).toBeInstanceOf(AuthError);
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
-
describe("
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
describe("token retry", () => {
|
|
50
|
+
const ERROR_TYPES = [InvalidTokenError, ExpiredTokenError];
|
|
51
|
+
ERROR_TYPES.forEach((ErrorType) => {
|
|
52
|
+
it(`should re-authenticate and retry the request for ${ErrorType.name}`, async () => {
|
|
53
|
+
const transport = new Transport(new URL({ host: HOST, port: PORT }));
|
|
54
|
+
const client = new auth.Client(transport.unary, {
|
|
55
|
+
username: "synnax",
|
|
56
|
+
password: "seldon",
|
|
57
|
+
});
|
|
58
|
+
const mw = client.middleware();
|
|
59
|
+
let isFirst = true;
|
|
60
|
+
let tkOne: string | undefined;
|
|
61
|
+
let tkTwo: string | undefined;
|
|
62
|
+
const [, err] = await mw(DUMMY_CTX, async () => {
|
|
63
|
+
if (isFirst) {
|
|
64
|
+
isFirst = false;
|
|
65
|
+
tkOne = client.token;
|
|
66
|
+
return [DUMMY_CTX, new ErrorType()];
|
|
67
|
+
}
|
|
68
|
+
tkTwo = client.token;
|
|
69
|
+
return [DUMMY_CTX, null];
|
|
70
|
+
});
|
|
71
|
+
expect(err).toBeNull();
|
|
72
|
+
expect(tkOne).toBeDefined();
|
|
73
|
+
expect(tkTwo).toBeDefined();
|
|
55
74
|
});
|
|
56
|
-
const mw = client.middleware();
|
|
57
|
-
let isFirst = true;
|
|
58
|
-
let tkOne: string | undefined;
|
|
59
|
-
let tkTwo: string | undefined;
|
|
60
|
-
const [, err] = await mw(DUMMY_CTX, async () => {
|
|
61
|
-
if (isFirst) {
|
|
62
|
-
isFirst = false;
|
|
63
|
-
tkOne = client.token;
|
|
64
|
-
return [DUMMY_CTX, new InvalidTokenError()];
|
|
65
|
-
}
|
|
66
|
-
tkTwo = client.token;
|
|
67
|
-
return [DUMMY_CTX, null];
|
|
68
|
-
});
|
|
69
|
-
expect(err).toBeNull();
|
|
70
|
-
expect(tkOne).toBeDefined();
|
|
71
|
-
expect(tkTwo).toBeDefined();
|
|
72
75
|
});
|
|
76
|
+
|
|
73
77
|
it("should fail after MAX_RETRIES", async () => {
|
|
74
78
|
const transport = new Transport(new URL({ host: HOST, port: PORT }));
|
|
75
79
|
const client = new auth.Client(transport.unary, {
|
package/src/auth/auth.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Use of this software is governed by the Business Source License included in the file
|
|
4
4
|
// licenses/BSL.txt.
|
|
@@ -10,19 +10,13 @@
|
|
|
10
10
|
import { type Middleware, sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
|
|
11
11
|
import { z } from "zod";
|
|
12
12
|
|
|
13
|
-
import { InvalidTokenError } from "@/errors";
|
|
13
|
+
import { ExpiredTokenError, InvalidTokenError } from "@/errors";
|
|
14
14
|
import { user } from "@/user";
|
|
15
15
|
|
|
16
|
-
const insecureCredentialsZ = z.object({
|
|
17
|
-
|
|
18
|
-
password: z.string(),
|
|
19
|
-
});
|
|
20
|
-
type InsecureCredentials = z.infer<typeof insecureCredentialsZ>;
|
|
16
|
+
const insecureCredentialsZ = z.object({ username: z.string(), password: z.string() });
|
|
17
|
+
interface InsecureCredentials extends z.infer<typeof insecureCredentialsZ> {}
|
|
21
18
|
|
|
22
|
-
const tokenResponseZ = z.object({
|
|
23
|
-
token: z.string(),
|
|
24
|
-
user: user.userZ,
|
|
25
|
-
});
|
|
19
|
+
const tokenResponseZ = z.object({ token: z.string(), user: user.userZ });
|
|
26
20
|
|
|
27
21
|
const LOGIN_ENDPOINT = "/auth/login";
|
|
28
22
|
|
|
@@ -37,6 +31,8 @@ const changePasswordReqZ = z.object({
|
|
|
37
31
|
});
|
|
38
32
|
const changePasswordResZ = z.object({});
|
|
39
33
|
|
|
34
|
+
const RETRY_ON = [InvalidTokenError, ExpiredTokenError] as const;
|
|
35
|
+
|
|
40
36
|
export class Client {
|
|
41
37
|
token: string | undefined;
|
|
42
38
|
private readonly client: UnaryClient;
|
|
@@ -94,7 +90,7 @@ export class Client {
|
|
|
94
90
|
}
|
|
95
91
|
reqCtx.params.Authorization = `Bearer ${this.token}`;
|
|
96
92
|
const [resCtx, err] = await next(reqCtx);
|
|
97
|
-
if (
|
|
93
|
+
if (RETRY_ON.some((e) => e.matches(err)) && this.retryCount < MAX_RETRIES) {
|
|
98
94
|
this.authenticated = false;
|
|
99
95
|
this.authenticating = undefined;
|
|
100
96
|
this.retryCount += 1;
|
package/src/auth/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Use of this software is governed by the Business Source License included in the file
|
|
4
4
|
// licenses/BSL.txt.
|
|
@@ -10,42 +10,45 @@
|
|
|
10
10
|
import { DataType, Rate } from "@synnaxlabs/x/telem";
|
|
11
11
|
import { describe, expect, it, vi } from "vitest";
|
|
12
12
|
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
analyzeChannelParams,
|
|
16
|
-
DebouncedBatchRetriever,
|
|
17
|
-
type RetrieveOptions,
|
|
18
|
-
type Retriever,
|
|
19
|
-
} from "@/channel/retriever";
|
|
13
|
+
import { channel } from "@/channel";
|
|
20
14
|
|
|
21
|
-
class MockRetriever implements Retriever {
|
|
22
|
-
func: (
|
|
15
|
+
class MockRetriever implements channel.Retriever {
|
|
16
|
+
func: (
|
|
17
|
+
channels: channel.Params,
|
|
18
|
+
options?: channel.RetrieveOptions,
|
|
19
|
+
) => Promise<channel.Payload[]>;
|
|
23
20
|
|
|
24
21
|
constructor(
|
|
25
|
-
func: (
|
|
22
|
+
func: (
|
|
23
|
+
channels: channel.Params,
|
|
24
|
+
options?: channel.RetrieveOptions,
|
|
25
|
+
) => Promise<channel.Payload[]>,
|
|
26
26
|
) {
|
|
27
27
|
this.func = func;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
async search(): Promise<Payload[]> {
|
|
30
|
+
async search(): Promise<channel.Payload[]> {
|
|
31
31
|
throw new Error("Method not implemented.");
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
async page(): Promise<Payload[]> {
|
|
34
|
+
async page(): Promise<channel.Payload[]> {
|
|
35
35
|
throw new Error("Method not implemented.");
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
async retrieve(
|
|
38
|
+
async retrieve(
|
|
39
|
+
channels: channel.Params,
|
|
40
|
+
options?: channel.RetrieveOptions,
|
|
41
|
+
): Promise<channel.Payload[]> {
|
|
39
42
|
return await this.func(channels, options);
|
|
40
43
|
}
|
|
41
44
|
}
|
|
42
45
|
|
|
43
|
-
describe("
|
|
46
|
+
describe("channelchannel.Retriever", () => {
|
|
44
47
|
it("should batch multiple retrieve requests", async () => {
|
|
45
48
|
const called = vi.fn();
|
|
46
|
-
const base = new MockRetriever(async (batch): Promise<Payload[]> => {
|
|
49
|
+
const base = new MockRetriever(async (batch): Promise<channel.Payload[]> => {
|
|
47
50
|
called(batch);
|
|
48
|
-
const { normalized } =
|
|
51
|
+
const { normalized } = channel.analyzeParams(batch);
|
|
49
52
|
return normalized.map((key) => ({
|
|
50
53
|
key: key as number,
|
|
51
54
|
name: `channel-${key}`,
|
|
@@ -60,7 +63,7 @@ describe("channelRetriever", () => {
|
|
|
60
63
|
requires: [],
|
|
61
64
|
}));
|
|
62
65
|
});
|
|
63
|
-
const retriever = new DebouncedBatchRetriever(base, 10);
|
|
66
|
+
const retriever = new channel.DebouncedBatchRetriever(base, 10);
|
|
64
67
|
const res = await Promise.all([
|
|
65
68
|
retriever.retrieve([1]),
|
|
66
69
|
retriever.retrieve([2]),
|
|
@@ -72,9 +75,9 @@ describe("channelRetriever", () => {
|
|
|
72
75
|
});
|
|
73
76
|
it("should only fetch duplicate keys once", async () => {
|
|
74
77
|
const called = vi.fn();
|
|
75
|
-
const base = new MockRetriever(async (batch): Promise<Payload[]> => {
|
|
78
|
+
const base = new MockRetriever(async (batch): Promise<channel.Payload[]> => {
|
|
76
79
|
called(batch);
|
|
77
|
-
const { normalized } =
|
|
80
|
+
const { normalized } = channel.analyzeParams(batch);
|
|
78
81
|
return normalized.map((key) => ({
|
|
79
82
|
key: key as number,
|
|
80
83
|
name: `channel-${key}`,
|
|
@@ -89,7 +92,7 @@ describe("channelRetriever", () => {
|
|
|
89
92
|
requires: [],
|
|
90
93
|
}));
|
|
91
94
|
});
|
|
92
|
-
const retriever = new DebouncedBatchRetriever(base, 10);
|
|
95
|
+
const retriever = new channel.DebouncedBatchRetriever(base, 10);
|
|
93
96
|
const res = await Promise.all([
|
|
94
97
|
retriever.retrieve([1]),
|
|
95
98
|
retriever.retrieve([2]),
|
|
@@ -100,10 +103,10 @@ describe("channelRetriever", () => {
|
|
|
100
103
|
expect(res.map((r) => r.map((c) => c.key))).toEqual([[1], [2], [1, 2]]);
|
|
101
104
|
});
|
|
102
105
|
it("should throw an error if the fetch fails", async () => {
|
|
103
|
-
const base = new MockRetriever(async (): Promise<Payload[]> => {
|
|
106
|
+
const base = new MockRetriever(async (): Promise<channel.Payload[]> => {
|
|
104
107
|
throw new Error("failed to fetch");
|
|
105
108
|
});
|
|
106
|
-
const retriever = new DebouncedBatchRetriever(base, 10);
|
|
109
|
+
const retriever = new channel.DebouncedBatchRetriever(base, 10);
|
|
107
110
|
await expect(retriever.retrieve([1])).rejects.toThrow("failed to fetch");
|
|
108
111
|
});
|
|
109
112
|
});
|
package/src/channel/client.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Use of this software is governed by the Business Source License included in the file
|
|
4
4
|
// licenses/BSL.txt.
|
|
@@ -22,16 +22,17 @@ import { toArray } from "@synnaxlabs/x/toArray";
|
|
|
22
22
|
import { z } from "zod";
|
|
23
23
|
|
|
24
24
|
import {
|
|
25
|
+
channelZ,
|
|
25
26
|
type Key,
|
|
26
27
|
type KeyOrName,
|
|
27
|
-
type
|
|
28
|
-
|
|
28
|
+
type Name,
|
|
29
|
+
type New,
|
|
30
|
+
ONTOLOGY_TYPE,
|
|
29
31
|
type Params,
|
|
30
32
|
type Payload,
|
|
31
|
-
payload,
|
|
32
33
|
} from "@/channel/payload";
|
|
33
34
|
import {
|
|
34
|
-
|
|
35
|
+
analyzeParams,
|
|
35
36
|
CacheRetriever,
|
|
36
37
|
ClusterRetriever,
|
|
37
38
|
DebouncedBatchRetriever,
|
|
@@ -41,7 +42,7 @@ import {
|
|
|
41
42
|
import { type Writer } from "@/channel/writer";
|
|
42
43
|
import { ValidationError } from "@/errors";
|
|
43
44
|
import { type framer } from "@/framer";
|
|
44
|
-
import {
|
|
45
|
+
import { ontology } from "@/ontology";
|
|
45
46
|
import { group } from "@/ontology/group";
|
|
46
47
|
import { checkForMultipleOrNoResults } from "@/util/retrieve";
|
|
47
48
|
|
|
@@ -69,7 +70,7 @@ export class Channel {
|
|
|
69
70
|
* A human-readable name for the channel. This name is not guaranteed to be
|
|
70
71
|
* unique.
|
|
71
72
|
*/
|
|
72
|
-
readonly name:
|
|
73
|
+
readonly name: Name;
|
|
73
74
|
/**
|
|
74
75
|
* The rate at which the channel samples telemetry. This only applies to fixed rate
|
|
75
76
|
* channels, and will be 0 if the channel is indexed.
|
|
@@ -109,7 +110,7 @@ export class Channel {
|
|
|
109
110
|
*/
|
|
110
111
|
readonly virtual: boolean;
|
|
111
112
|
/**
|
|
112
|
-
* Only used for calculated channels. Specifies the
|
|
113
|
+
* Only used for calculated channels. Specifies the Lua expression used to evaluate
|
|
113
114
|
* the calculated value
|
|
114
115
|
*/
|
|
115
116
|
readonly expression: string;
|
|
@@ -132,10 +133,7 @@ export class Channel {
|
|
|
132
133
|
alias,
|
|
133
134
|
expression = "",
|
|
134
135
|
requires = [],
|
|
135
|
-
}:
|
|
136
|
-
frameClient?: framer.Client;
|
|
137
|
-
density?: CrudeDensity;
|
|
138
|
-
}) {
|
|
136
|
+
}: New & { frameClient?: framer.Client; density?: CrudeDensity }) {
|
|
139
137
|
this.key = key;
|
|
140
138
|
this.name = name;
|
|
141
139
|
this.rate = new Rate(rate ?? 0);
|
|
@@ -163,7 +161,7 @@ export class Channel {
|
|
|
163
161
|
* network transportation, but also provided to you as a convenience.
|
|
164
162
|
*/
|
|
165
163
|
get payload(): Payload {
|
|
166
|
-
return
|
|
164
|
+
return channelZ.parse({
|
|
167
165
|
key: this.key,
|
|
168
166
|
name: this.name,
|
|
169
167
|
rate: this.rate.valueOf(),
|
|
@@ -186,7 +184,7 @@ export class Channel {
|
|
|
186
184
|
* @returns the ontology ID of the channel
|
|
187
185
|
*/
|
|
188
186
|
get ontologyID(): ontology.ID {
|
|
189
|
-
return
|
|
187
|
+
return ontologyID(this.key);
|
|
190
188
|
}
|
|
191
189
|
|
|
192
190
|
/**
|
|
@@ -215,9 +213,7 @@ const RETRIEVE_GROUP_ENDPOINT = "/channel/retrieve-group";
|
|
|
215
213
|
|
|
216
214
|
const retrieveGroupReqZ = z.object({});
|
|
217
215
|
|
|
218
|
-
const retrieveGroupResZ = z.object({
|
|
219
|
-
group: group.groupZ,
|
|
220
|
-
});
|
|
216
|
+
const retrieveGroupResZ = z.object({ group: group.groupZ });
|
|
221
217
|
|
|
222
218
|
/**
|
|
223
219
|
* The core client class for executing channel operations against a Synnax
|
|
@@ -225,7 +221,7 @@ const retrieveGroupResZ = z.object({
|
|
|
225
221
|
* through the `channels` property of an {@link Synnax} client.
|
|
226
222
|
*/
|
|
227
223
|
export class Client implements AsyncTermSearcher<string, Key, Channel> {
|
|
228
|
-
readonly type =
|
|
224
|
+
readonly type = ONTOLOGY_TYPE;
|
|
229
225
|
private readonly frameClient: framer.Client;
|
|
230
226
|
private readonly client: UnaryClient;
|
|
231
227
|
readonly retriever: Retriever;
|
|
@@ -278,7 +274,7 @@ export class Client implements AsyncTermSearcher<string, Key, Channel> {
|
|
|
278
274
|
* });
|
|
279
275
|
* ```
|
|
280
276
|
*/
|
|
281
|
-
async create(channel:
|
|
277
|
+
async create(channel: New, options?: CreateOptions): Promise<Channel>;
|
|
282
278
|
|
|
283
279
|
/**
|
|
284
280
|
* Creates multiple channels with the given properties. The order of the channels
|
|
@@ -303,10 +299,10 @@ export class Client implements AsyncTermSearcher<string, Key, Channel> {
|
|
|
303
299
|
*
|
|
304
300
|
* @param channels
|
|
305
301
|
*/
|
|
306
|
-
async create(channels:
|
|
302
|
+
async create(channels: New[], options?: CreateOptions): Promise<Channel[]>;
|
|
307
303
|
|
|
308
304
|
async create(
|
|
309
|
-
channels:
|
|
305
|
+
channels: New | New[],
|
|
310
306
|
options: CreateOptions = {},
|
|
311
307
|
): Promise<Channel | Channel[]> {
|
|
312
308
|
const { retrieveIfNameExists = false } = options;
|
|
@@ -387,7 +383,7 @@ export class Client implements AsyncTermSearcher<string, Key, Channel> {
|
|
|
387
383
|
* @param channels - The keys or names of the channels to delete.
|
|
388
384
|
*/
|
|
389
385
|
async delete(channels: Params): Promise<void> {
|
|
390
|
-
const { normalized, variant } =
|
|
386
|
+
const { normalized, variant } = analyzeParams(channels);
|
|
391
387
|
if (variant === "keys")
|
|
392
388
|
return await this.writer.delete({ keys: normalized as Key[] });
|
|
393
389
|
return await this.writer.delete({ names: normalized as string[] });
|
|
@@ -395,7 +391,6 @@ export class Client implements AsyncTermSearcher<string, Key, Channel> {
|
|
|
395
391
|
|
|
396
392
|
async rename(key: Key, name: string): Promise<void>;
|
|
397
393
|
async rename(keys: Key[], names: string[]): Promise<void>;
|
|
398
|
-
|
|
399
394
|
async rename(keys: Key | Key[], names: string | string[]): Promise<void> {
|
|
400
395
|
return await this.writer.rename(toArray(keys), toArray(names));
|
|
401
396
|
}
|
|
@@ -447,16 +442,18 @@ export const isCalculated = ({ virtual, expression }: Payload): boolean =>
|
|
|
447
442
|
virtual && expression !== "";
|
|
448
443
|
|
|
449
444
|
export const resolveCalculatedIndex = async (
|
|
450
|
-
retrieve: (key: Key) => Promise<Payload>,
|
|
445
|
+
retrieve: (key: Key) => Promise<Payload | null>,
|
|
451
446
|
channel: Payload,
|
|
452
447
|
): Promise<Key | null> => {
|
|
453
448
|
if (!isCalculated(channel)) return channel.index;
|
|
454
449
|
for (const required of channel.requires) {
|
|
455
450
|
const requiredChannel = await retrieve(required);
|
|
451
|
+
if (requiredChannel == null) return null;
|
|
456
452
|
if (!requiredChannel.virtual) return requiredChannel.index;
|
|
457
453
|
}
|
|
458
454
|
for (const required of channel.requires) {
|
|
459
455
|
const requiredChannel = await retrieve(required);
|
|
456
|
+
if (requiredChannel == null) return null;
|
|
460
457
|
if (isCalculated(requiredChannel)) {
|
|
461
458
|
const index = await resolveCalculatedIndex(retrieve, requiredChannel);
|
|
462
459
|
if (index != null) return index;
|
|
@@ -464,3 +461,6 @@ export const resolveCalculatedIndex = async (
|
|
|
464
461
|
}
|
|
465
462
|
return null;
|
|
466
463
|
};
|
|
464
|
+
|
|
465
|
+
export const ontologyID = (key: Key): ontology.ID =>
|
|
466
|
+
new ontology.ID({ type: ONTOLOGY_TYPE, key: key.toString() });
|
package/src/channel/external.ts
CHANGED
package/src/channel/index.ts
CHANGED