@synnaxlabs/client 0.26.7 → 0.27.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/README.md +36 -10
- package/api/client.api.md +3077 -0
- package/api-extractor.json +7 -0
- package/dist/access/client.d.ts +0 -1
- package/dist/access/payload.d.ts +0 -1
- package/dist/auth/auth.d.ts +0 -1
- package/dist/channel/client.d.ts +6 -2
- package/dist/channel/client.d.ts.map +1 -1
- package/dist/channel/creator.d.ts +0 -1
- package/dist/channel/payload.d.ts +4 -1
- package/dist/channel/payload.d.ts.map +1 -1
- package/dist/channel/retriever.d.ts +0 -1
- package/dist/channel/writer.d.ts +0 -1
- package/dist/client.cjs +17 -17
- package/dist/client.d.ts +6 -7
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +2006 -1745
- package/dist/connection/checker.d.ts +0 -1
- package/dist/control/client.d.ts +0 -1
- package/dist/control/client.d.ts.map +1 -1
- package/dist/control/state.d.ts +0 -1
- package/dist/errors.d.ts +0 -1
- package/dist/framer/adapter.d.ts +0 -1
- package/dist/framer/client.d.ts +0 -1
- package/dist/framer/deleter.d.ts +0 -1
- package/dist/framer/frame.d.ts +11 -12
- package/dist/framer/iterator.d.ts +0 -1
- package/dist/framer/streamProxy.d.ts +0 -1
- package/dist/framer/streamer.d.ts +0 -1
- package/dist/framer/writer.d.ts +0 -1
- package/dist/framer/writer.d.ts.map +1 -1
- package/dist/hardware/client.d.ts +0 -1
- package/dist/hardware/device/client.d.ts +0 -1
- package/dist/hardware/device/payload.d.ts +0 -1
- package/dist/hardware/device/payload.d.ts.map +1 -1
- package/dist/hardware/rack/client.d.ts +0 -1
- package/dist/hardware/rack/payload.d.ts +0 -1
- package/dist/hardware/rack/payload.d.ts.map +1 -1
- package/dist/hardware/task/client.d.ts +0 -1
- package/dist/hardware/task/payload.d.ts +0 -1
- package/dist/hardware/task/payload.d.ts.map +1 -1
- package/dist/label/client.d.ts +8 -6
- package/dist/label/client.d.ts.map +1 -1
- package/dist/label/payload.d.ts +0 -1
- package/dist/label/retriever.d.ts +0 -1
- package/dist/label/retriever.d.ts.map +1 -1
- package/dist/label/writer.d.ts +32 -2
- package/dist/label/writer.d.ts.map +1 -1
- package/dist/ontology/client.d.ts +124 -11
- package/dist/ontology/client.d.ts.map +1 -1
- package/dist/ontology/group/client.d.ts +0 -1
- package/dist/ontology/group/group.d.ts +0 -1
- package/dist/ontology/group/payload.d.ts +0 -1
- package/dist/ontology/group/writer.d.ts +0 -1
- package/dist/ontology/payload.d.ts +5 -1
- package/dist/ontology/payload.d.ts.map +1 -1
- package/dist/ontology/writer.d.ts +4 -5
- package/dist/ontology/writer.d.ts.map +1 -1
- package/dist/ranger/alias.d.ts +0 -1
- package/dist/ranger/client.d.ts +55 -14
- 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 +42 -5
- package/dist/ranger/kv.d.ts.map +1 -1
- package/dist/ranger/payload.d.ts +5 -2
- package/dist/ranger/payload.d.ts.map +1 -1
- package/dist/ranger/writer.d.ts +107 -2
- package/dist/ranger/writer.d.ts.map +1 -1
- package/dist/setupspecs.d.ts +0 -1
- package/dist/signals/observable.d.ts +0 -1
- package/dist/transport.d.ts +0 -1
- package/dist/user/client.d.ts +0 -1
- package/dist/user/payload.d.ts +0 -1
- package/dist/util/retrieve.d.ts +0 -1
- package/dist/util/telem.d.ts +0 -1
- package/dist/util/zod.d.ts +0 -1
- package/dist/workspace/client.d.ts +0 -1
- package/dist/workspace/lineplot/client.d.ts +0 -1
- package/dist/workspace/lineplot/payload.d.ts +0 -1
- package/dist/workspace/lineplot/retriever.d.ts +0 -1
- package/dist/workspace/lineplot/writer.d.ts +0 -1
- package/dist/workspace/payload.d.ts +0 -1
- package/dist/workspace/retriever.d.ts +0 -1
- package/dist/workspace/schematic/client.d.ts +0 -1
- package/dist/workspace/schematic/payload.d.ts +0 -1
- package/dist/workspace/schematic/retriever.d.ts +0 -1
- package/dist/workspace/schematic/writer.d.ts +0 -1
- package/dist/workspace/writer.d.ts +0 -1
- package/package.json +14 -12
- package/src/access/access.spec.ts +11 -11
- package/src/channel/batchRetriever.spec.ts +2 -0
- package/src/channel/channel.spec.ts +51 -31
- package/src/channel/client.ts +7 -0
- package/src/channel/payload.ts +1 -0
- package/src/client.ts +4 -3
- package/src/control/client.ts +9 -0
- package/src/errors.spec.ts +9 -0
- package/src/framer/frame.spec.ts +2 -2
- package/src/framer/frame.ts +22 -22
- package/src/framer/writer.ts +2 -1
- package/src/hardware/device/payload.ts +9 -0
- package/src/hardware/rack/payload.ts +9 -0
- package/src/hardware/task/payload.ts +9 -0
- package/src/label/client.ts +49 -19
- package/src/label/label.spec.ts +9 -0
- package/src/label/retriever.ts +2 -1
- package/src/label/writer.ts +11 -3
- package/src/ontology/client.ts +214 -13
- package/src/ontology/payload.ts +4 -0
- package/src/ontology/writer.ts +26 -12
- package/src/ranger/client.ts +204 -28
- package/src/ranger/external.ts +1 -1
- package/src/ranger/kv.ts +50 -11
- package/src/ranger/payload.ts +9 -5
- package/src/ranger/ranger.spec.ts +114 -49
- package/src/ranger/writer.ts +7 -2
- package/vite.config.ts +1 -1
- package/dist/ranger/active.d.ts +0 -11
- package/dist/ranger/active.d.ts.map +0 -1
- package/dist/ranger/range.d.ts +0 -32
- package/dist/ranger/range.d.ts.map +0 -1
- package/src/ranger/active.ts +0 -74
- package/src/ranger/range.ts +0 -98
|
@@ -2,7 +2,6 @@ import { UnaryClient } from '@synnaxlabs/freighter';
|
|
|
2
2
|
import { UnknownRecord } from '@synnaxlabs/x/record';
|
|
3
3
|
import { Key, Params, Schematic } from './payload';
|
|
4
4
|
import { NewSchematic } from './writer';
|
|
5
|
-
|
|
6
5
|
export declare class Client {
|
|
7
6
|
private readonly writer;
|
|
8
7
|
private readonly retriever;
|
|
@@ -2,7 +2,6 @@ import { UnaryClient } from '@synnaxlabs/freighter';
|
|
|
2
2
|
import { UnknownRecord } from '@synnaxlabs/x/record';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { Key, Params, Schematic } from './payload';
|
|
5
|
-
|
|
6
5
|
export declare const newSchematicZ: z.ZodEffects<z.ZodObject<{
|
|
7
6
|
name: z.ZodString;
|
|
8
7
|
key: z.ZodOptional<z.ZodString>;
|
|
@@ -2,7 +2,6 @@ import { UnaryClient } from '@synnaxlabs/freighter';
|
|
|
2
2
|
import { UnknownRecord } from '@synnaxlabs/x/record';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { Workspace } from './payload';
|
|
5
|
-
|
|
6
5
|
declare const newWorkspaceZ: z.ZodEffects<z.ZodObject<{
|
|
7
6
|
name: z.ZodString;
|
|
8
7
|
key: z.ZodOptional<z.ZodString>;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synnaxlabs/client",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.27.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "The Client Library for Synnax",
|
|
7
7
|
"repository": "https://github.com/synnaxlabs/synnax/tree/main/client/ts",
|
|
@@ -18,19 +18,19 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"async-mutex": "^0.5.0",
|
|
20
20
|
"zod": "3.23.8",
|
|
21
|
-
"@synnaxlabs/freighter": "0.
|
|
22
|
-
"@synnaxlabs/x": "0.
|
|
21
|
+
"@synnaxlabs/freighter": "0.27.0",
|
|
22
|
+
"@synnaxlabs/x": "0.27.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@types/node": "^
|
|
26
|
-
"@vitest/coverage-v8": "^
|
|
27
|
-
"eslint": "^9.
|
|
28
|
-
"typescript": "^5.5.
|
|
29
|
-
"vite": "5.
|
|
30
|
-
"vitest": "^
|
|
25
|
+
"@types/node": "^22.2.0",
|
|
26
|
+
"@vitest/coverage-v8": "^2.0.5",
|
|
27
|
+
"eslint": "^9.9.0",
|
|
28
|
+
"typescript": "^5.5.4",
|
|
29
|
+
"vite": "5.4.0",
|
|
30
|
+
"vitest": "^2.0.5",
|
|
31
31
|
"@synnaxlabs/tsconfig": "0.0.2",
|
|
32
|
-
"
|
|
33
|
-
"
|
|
32
|
+
"@synnaxlabs/vite-plugin": "0.0.1",
|
|
33
|
+
"eslint-config-synnaxlabs": "0.0.1"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"zod": "^3.23.8"
|
|
@@ -44,6 +44,8 @@
|
|
|
44
44
|
"test": "vitest",
|
|
45
45
|
"cov": "vitest --coverage",
|
|
46
46
|
"lint": "eslint \"src/**/*.ts*\"",
|
|
47
|
-
"fix": "eslint \"src/**/*.ts*\" --fix"
|
|
47
|
+
"fix": "eslint \"src/**/*.ts*\" --fix",
|
|
48
|
+
"genApi": "tsc --noEmit && vite build && npx api-extractor run --local",
|
|
49
|
+
"checkApi": "tsc --noEmit && vite build && npx api-extractor run"
|
|
48
50
|
}
|
|
49
51
|
}
|
|
@@ -23,7 +23,7 @@ const client = newClient();
|
|
|
23
23
|
|
|
24
24
|
describe("Policy", () => {
|
|
25
25
|
describe("create", () => {
|
|
26
|
-
test("create one", async () => {
|
|
26
|
+
test.skip("create one", async () => {
|
|
27
27
|
const policy = await client.access.create({
|
|
28
28
|
subjects: [{ type: UserOntologyType, key: "1" }],
|
|
29
29
|
objects: [
|
|
@@ -40,7 +40,7 @@ describe("Policy", () => {
|
|
|
40
40
|
]);
|
|
41
41
|
expect(policy.actions).toEqual(["update"]);
|
|
42
42
|
});
|
|
43
|
-
test("create many", async () => {
|
|
43
|
+
test.skip("create many", async () => {
|
|
44
44
|
const policies = await client.access.create([
|
|
45
45
|
{
|
|
46
46
|
subjects: [{ type: UserOntologyType, key: "10" }],
|
|
@@ -62,11 +62,11 @@ describe("Policy", () => {
|
|
|
62
62
|
actions: ["update"],
|
|
63
63
|
},
|
|
64
64
|
]);
|
|
65
|
-
expect(policies.length).toEqual(
|
|
65
|
+
expect(policies.length).toEqual(3);
|
|
66
66
|
expect(policies[0].subjects[0].key).toEqual("10");
|
|
67
67
|
expect(policies[1].subjects[1].key).toEqual("21");
|
|
68
68
|
});
|
|
69
|
-
test("create instances of policies", async () => {
|
|
69
|
+
test.skip("create instances of policies", async () => {
|
|
70
70
|
const policy = {
|
|
71
71
|
key: undefined,
|
|
72
72
|
subjects: [
|
|
@@ -85,7 +85,7 @@ describe("Policy", () => {
|
|
|
85
85
|
expect(p.key).not.toEqual(policy.key);
|
|
86
86
|
});
|
|
87
87
|
});
|
|
88
|
-
test("retrieve by subject", async () => {
|
|
88
|
+
test.skip("retrieve by subject", async () => {
|
|
89
89
|
const key1 = id.id();
|
|
90
90
|
const policies = [
|
|
91
91
|
{
|
|
@@ -120,13 +120,13 @@ describe("Policy", () => {
|
|
|
120
120
|
expect(p).toHaveLength(2);
|
|
121
121
|
expect([p[0].actions, p[1].actions].sort()).toEqual([["delete"], ["update"]]);
|
|
122
122
|
});
|
|
123
|
-
test("retrieve by subject - not found", async () => {
|
|
123
|
+
test.skip("retrieve by subject - not found", async () => {
|
|
124
124
|
const res = await client.access.retrieve({ type: UserOntologyType, key: "999" });
|
|
125
125
|
expect(res).toHaveLength(0);
|
|
126
126
|
});
|
|
127
127
|
|
|
128
128
|
describe("delete", async () => {
|
|
129
|
-
test("delete one", async () => {
|
|
129
|
+
test.skip("delete one", async () => {
|
|
130
130
|
const id1 = id.id();
|
|
131
131
|
const id2 = id.id();
|
|
132
132
|
const id3 = id.id();
|
|
@@ -163,7 +163,7 @@ describe("Policy", () => {
|
|
|
163
163
|
expect(res).toHaveLength(1);
|
|
164
164
|
expect(res[0].actions).toEqual(["delete"]);
|
|
165
165
|
});
|
|
166
|
-
test("delete many", async () => {
|
|
166
|
+
test.skip("delete many", async () => {
|
|
167
167
|
const id1 = id.id();
|
|
168
168
|
const id2 = id.id();
|
|
169
169
|
const id3 = id.id();
|
|
@@ -203,7 +203,7 @@ describe("Policy", () => {
|
|
|
203
203
|
});
|
|
204
204
|
});
|
|
205
205
|
describe("registration", async () => {
|
|
206
|
-
test("register a user", async () => {
|
|
206
|
+
test.skip("register a user", async () => {
|
|
207
207
|
const username = id.id();
|
|
208
208
|
await client.user.register(username, "pwd1");
|
|
209
209
|
new Synnax({
|
|
@@ -213,14 +213,14 @@ describe("Policy", () => {
|
|
|
213
213
|
password: "pwd1",
|
|
214
214
|
});
|
|
215
215
|
});
|
|
216
|
-
test("duplicate username", async () => {
|
|
216
|
+
test.skip("duplicate username", async () => {
|
|
217
217
|
const username = id.id();
|
|
218
218
|
await client.user.register(username, "pwd1");
|
|
219
219
|
await expect(client.user.register(username, "pwd1")).rejects.toThrow(AuthError);
|
|
220
220
|
});
|
|
221
221
|
});
|
|
222
222
|
describe("privilege", async () => {
|
|
223
|
-
test("new user", async () => {
|
|
223
|
+
test.skip("new user", async () => {
|
|
224
224
|
const username = id.id();
|
|
225
225
|
const user2 = await client.user.register(username, "pwd1");
|
|
226
226
|
expect(user2).toBeDefined();
|
|
@@ -55,6 +55,7 @@ describe("channelRetriever", () => {
|
|
|
55
55
|
rate: Rate.hz(1),
|
|
56
56
|
leaseholder: 1,
|
|
57
57
|
index: 0,
|
|
58
|
+
virtual: false,
|
|
58
59
|
}));
|
|
59
60
|
});
|
|
60
61
|
const retriever = new DebouncedBatchRetriever(base, 10);
|
|
@@ -81,6 +82,7 @@ describe("channelRetriever", () => {
|
|
|
81
82
|
rate: Rate.hz(1),
|
|
82
83
|
leaseholder: 1,
|
|
83
84
|
index: 0,
|
|
85
|
+
virtual: false,
|
|
84
86
|
}));
|
|
85
87
|
});
|
|
86
88
|
const retriever = new DebouncedBatchRetriever(base, 10);
|
|
@@ -30,6 +30,7 @@ describe("Channel", () => {
|
|
|
30
30
|
expect(channel.rate).toEqual(Rate.hz(1));
|
|
31
31
|
expect(channel.dataType).toEqual(DataType.FLOAT32);
|
|
32
32
|
});
|
|
33
|
+
|
|
33
34
|
test("create index and indexed pair", async () => {
|
|
34
35
|
const one = await client.channels.create({
|
|
35
36
|
name: "Time",
|
|
@@ -44,6 +45,7 @@ describe("Channel", () => {
|
|
|
44
45
|
});
|
|
45
46
|
expect(two.key).not.toEqual(0);
|
|
46
47
|
});
|
|
48
|
+
|
|
47
49
|
test("create many", async () => {
|
|
48
50
|
const channels = await client.channels.create([
|
|
49
51
|
{
|
|
@@ -63,6 +65,7 @@ describe("Channel", () => {
|
|
|
63
65
|
expect(channels[0].name).toEqual("test1");
|
|
64
66
|
expect(channels[1].name).toEqual("test2");
|
|
65
67
|
});
|
|
68
|
+
|
|
66
69
|
test("create instances of channels", async () => {
|
|
67
70
|
const timeIndexChannel = await client.channels.create({
|
|
68
71
|
name: "time",
|
|
@@ -89,6 +92,20 @@ describe("Channel", () => {
|
|
|
89
92
|
});
|
|
90
93
|
await client.channels.create([sensorOne, sensorTwo, sensorThree]);
|
|
91
94
|
});
|
|
95
|
+
|
|
96
|
+
describe("virtual", () => {
|
|
97
|
+
it("should create a virtual channel", async () => {
|
|
98
|
+
const channel = await client.channels.create({
|
|
99
|
+
name: "test",
|
|
100
|
+
dataType: DataType.JSON,
|
|
101
|
+
virtual: true,
|
|
102
|
+
});
|
|
103
|
+
expect(channel.virtual).toEqual(true);
|
|
104
|
+
const retrieved = await client.channels.retrieve(channel.key);
|
|
105
|
+
expect(retrieved.virtual).toBeTruthy();
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
92
109
|
describe("retrieveIfNameExists", () => {
|
|
93
110
|
it("should retrieve the existing channel when it exists", async () => {
|
|
94
111
|
const name = `test-${Math.random()}-${TimeStamp.now().valueOf()}`;
|
|
@@ -159,38 +176,41 @@ describe("Channel", () => {
|
|
|
159
176
|
});
|
|
160
177
|
});
|
|
161
178
|
});
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
179
|
+
|
|
180
|
+
describe("retrieve", () => {
|
|
181
|
+
test("retrieve by key", async () => {
|
|
182
|
+
const channel = await client.channels.create({
|
|
183
|
+
name: "test",
|
|
184
|
+
leaseholder: 1,
|
|
185
|
+
rate: Rate.hz(1),
|
|
186
|
+
dataType: DataType.FLOAT32,
|
|
187
|
+
});
|
|
188
|
+
const retrieved = await client.channels.retrieve(channel.key);
|
|
189
|
+
expect(retrieved.name).toEqual("test");
|
|
190
|
+
expect(retrieved.leaseholder).toEqual(1);
|
|
191
|
+
expect(retrieved.rate).toEqual(Rate.hz(1));
|
|
192
|
+
expect(retrieved.dataType).toEqual(DataType.FLOAT32);
|
|
193
|
+
});
|
|
194
|
+
test("retrieve by key - not found", async () => {
|
|
195
|
+
await expect(
|
|
196
|
+
async () => await client.channels.retrieve("1-1000"),
|
|
197
|
+
).rejects.toThrow(QueryError);
|
|
198
|
+
});
|
|
199
|
+
test("retrieve by name", async () => {
|
|
200
|
+
const retrieved = await client.channels.retrieve(["test"]);
|
|
201
|
+
expect(retrieved.length).toBeGreaterThan(0);
|
|
202
|
+
retrieved.forEach((ch) => expect(ch.name).toEqual("test"));
|
|
203
|
+
});
|
|
204
|
+
test("retrieve by key - not found", async () => {
|
|
205
|
+
await expect(
|
|
206
|
+
async () => await client.channels.retrieve("1-1000"),
|
|
207
|
+
).rejects.toThrow(NotFoundError);
|
|
208
|
+
});
|
|
209
|
+
test("retrieve by name", async () => {
|
|
210
|
+
const retrieved = await client.channels.retrieve(["test"]);
|
|
211
|
+
expect(retrieved.length).toBeGreaterThan(0);
|
|
212
|
+
retrieved.forEach((ch) => expect(ch.name).toEqual("test"));
|
|
168
213
|
});
|
|
169
|
-
const retrieved = await client.channels.retrieve(channel.key);
|
|
170
|
-
expect(retrieved.name).toEqual("test");
|
|
171
|
-
expect(retrieved.leaseholder).toEqual(1);
|
|
172
|
-
expect(retrieved.rate).toEqual(Rate.hz(1));
|
|
173
|
-
expect(retrieved.dataType).toEqual(DataType.FLOAT32);
|
|
174
|
-
});
|
|
175
|
-
test("retrieve by key - not found", async () => {
|
|
176
|
-
await expect(async () => await client.channels.retrieve("1-1000")).rejects.toThrow(
|
|
177
|
-
QueryError,
|
|
178
|
-
);
|
|
179
|
-
});
|
|
180
|
-
test("retrieve by name", async () => {
|
|
181
|
-
const retrieved = await client.channels.retrieve(["test"]);
|
|
182
|
-
expect(retrieved.length).toBeGreaterThan(0);
|
|
183
|
-
retrieved.forEach((ch) => expect(ch.name).toEqual("test"));
|
|
184
|
-
});
|
|
185
|
-
test("retrieve by key - not found", async () => {
|
|
186
|
-
await expect(async () => await client.channels.retrieve("1-1000")).rejects.toThrow(
|
|
187
|
-
NotFoundError,
|
|
188
|
-
);
|
|
189
|
-
});
|
|
190
|
-
test("retrieve by name", async () => {
|
|
191
|
-
const retrieved = await client.channels.retrieve(["test"]);
|
|
192
|
-
expect(retrieved.length).toBeGreaterThan(0);
|
|
193
|
-
retrieved.forEach((ch) => expect(ch.name).toEqual("test"));
|
|
194
214
|
});
|
|
195
215
|
|
|
196
216
|
describe("delete", async () => {
|
package/src/channel/client.ts
CHANGED
|
@@ -101,6 +101,11 @@ export class Channel {
|
|
|
101
101
|
* should not be relied upon in the current version of Synnax.
|
|
102
102
|
*/
|
|
103
103
|
readonly alias: string | undefined;
|
|
104
|
+
/**
|
|
105
|
+
* Whether the channel is virtual. Virtual channels do not store any data in the
|
|
106
|
+
* database, but can still be used for streaming purposes.
|
|
107
|
+
*/
|
|
108
|
+
readonly virtual: boolean;
|
|
104
109
|
|
|
105
110
|
constructor({
|
|
106
111
|
dataType,
|
|
@@ -111,6 +116,7 @@ export class Channel {
|
|
|
111
116
|
isIndex = false,
|
|
112
117
|
index = 0,
|
|
113
118
|
internal = false,
|
|
119
|
+
virtual = false,
|
|
114
120
|
frameClient,
|
|
115
121
|
alias,
|
|
116
122
|
}: NewPayload & {
|
|
@@ -126,6 +132,7 @@ export class Channel {
|
|
|
126
132
|
this.isIndex = isIndex;
|
|
127
133
|
this.internal = internal;
|
|
128
134
|
this.alias = alias;
|
|
135
|
+
this.virtual = virtual;
|
|
129
136
|
this._frameClient = frameClient ?? null;
|
|
130
137
|
}
|
|
131
138
|
|
package/src/channel/payload.ts
CHANGED
package/src/client.ts
CHANGED
|
@@ -44,8 +44,8 @@ export const synnaxPropsZ = z.object({
|
|
|
44
44
|
required_error: "Port is required",
|
|
45
45
|
}),
|
|
46
46
|
),
|
|
47
|
-
username: z.string().
|
|
48
|
-
password: z.string().
|
|
47
|
+
username: z.string().min(1, "Username is required"),
|
|
48
|
+
password: z.string().min(1, "Password is required"),
|
|
49
49
|
connectivityPollFrequency: TimeSpan.z.default(TimeSpan.seconds(30)),
|
|
50
50
|
secure: z.boolean().optional().default(false),
|
|
51
51
|
name: z.string().optional(),
|
|
@@ -125,13 +125,14 @@ export default class Synnax extends framer.Client {
|
|
|
125
125
|
this.control = new control.Client(this);
|
|
126
126
|
this.ontology = new ontology.Client(transport.unary, this);
|
|
127
127
|
const rangeWriter = new ranger.Writer(this.transport.unary);
|
|
128
|
-
this.labels = new label.Client(this.transport.unary, this);
|
|
128
|
+
this.labels = new label.Client(this.transport.unary, this, this.ontology);
|
|
129
129
|
this.ranges = new ranger.Client(
|
|
130
130
|
this,
|
|
131
131
|
rangeWriter,
|
|
132
132
|
this.transport.unary,
|
|
133
133
|
chRetriever,
|
|
134
134
|
this.labels,
|
|
135
|
+
this.ontology,
|
|
135
136
|
);
|
|
136
137
|
this.access = new access.Client(this.transport.unary);
|
|
137
138
|
this.user = new user.Client(this.transport.unary);
|
package/src/control/client.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
// Copyright 2024 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
|
+
|
|
1
10
|
import { StateTracker } from "@/control/state";
|
|
2
11
|
import { framer } from "@/framer";
|
|
3
12
|
|
package/src/errors.spec.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
// Copyright 2024 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
|
+
|
|
1
10
|
import { MatchableErrorType } from "@synnaxlabs/freighter/src/errors";
|
|
2
11
|
import { describe, expect, test } from "vitest";
|
|
3
12
|
|
package/src/framer/frame.spec.ts
CHANGED
|
@@ -156,7 +156,7 @@ describe("framer.Frame", () => {
|
|
|
156
156
|
});
|
|
157
157
|
|
|
158
158
|
describe("weaklyAligned", () => {
|
|
159
|
-
it("should return true if all keys have the same
|
|
159
|
+
it("should return true if all keys have the same time range", () => {
|
|
160
160
|
const f = new framer.Frame(
|
|
161
161
|
new Map([
|
|
162
162
|
[
|
|
@@ -182,7 +182,7 @@ describe("framer.Frame", () => {
|
|
|
182
182
|
expect(f.isWeaklyAligned).toEqual(true);
|
|
183
183
|
});
|
|
184
184
|
|
|
185
|
-
it("should return false if any key has a different
|
|
185
|
+
it("should return false if any key has a different time range", () => {
|
|
186
186
|
const f = new framer.Frame(
|
|
187
187
|
new Map([
|
|
188
188
|
[
|
package/src/framer/frame.ts
CHANGED
|
@@ -39,17 +39,17 @@ const columnType = (columns: Params): ColumnType => {
|
|
|
39
39
|
return "name";
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
const
|
|
42
|
+
const validateMatchedColsAndSeries = (columns: Params, series: Series[]): void => {
|
|
43
43
|
const colsArr = toArray(columns);
|
|
44
|
-
if (colsArr.length ===
|
|
44
|
+
if (colsArr.length === series.length) return;
|
|
45
45
|
const colType = columnType(columns);
|
|
46
46
|
if (columnType === null)
|
|
47
47
|
throw new ValidationError(
|
|
48
48
|
"[Frame] - channel keys or names must be provided when constructing a frame.",
|
|
49
49
|
);
|
|
50
50
|
throw new ValidationError(
|
|
51
|
-
`[Frame] - ${colType as string}s and
|
|
52
|
-
Got ${colsArr.length} ${colType as string}s and ${
|
|
51
|
+
`[Frame] - ${colType as string}s and series must be the same length.
|
|
52
|
+
Got ${colsArr.length} ${colType as string}s and ${series.length} series.`,
|
|
53
53
|
);
|
|
54
54
|
};
|
|
55
55
|
|
|
@@ -65,15 +65,15 @@ export type CrudeFrame =
|
|
|
65
65
|
*
|
|
66
66
|
* Frames have two important characteristics: alignment and orientation.
|
|
67
67
|
*
|
|
68
|
-
* A frame's alignment defines how correlated the
|
|
68
|
+
* A frame's alignment defines how correlated the series for different channels in the
|
|
69
69
|
* frame are:
|
|
70
70
|
*
|
|
71
|
-
* - A frame is weakly aligned if
|
|
71
|
+
* - A frame is weakly aligned if the time range occupied by all series of a
|
|
72
72
|
* particular channel is the same for all channels in the frame. This means that the
|
|
73
|
-
*
|
|
73
|
+
* series for a particular channel can have gaps between them.
|
|
74
74
|
*
|
|
75
75
|
* - A strongly aligned frame means that all channels share the same rate/index and
|
|
76
|
-
* there are no gaps in time between
|
|
76
|
+
* there are no gaps in time between series. Strongly aligned frames are natural
|
|
77
77
|
* to interpret, as the values in a particular 'row' of the frame share the same
|
|
78
78
|
* timestamp. All frames written to Synnax must be strongly aligned.
|
|
79
79
|
*
|
|
@@ -85,7 +85,7 @@ export type CrudeFrame =
|
|
|
85
85
|
*
|
|
86
86
|
* - Horizontal frames have a single channel, and are strongly aligned by default.
|
|
87
87
|
* A horizontal frame typically has a single array (in which case, it's also 'square'),
|
|
88
|
-
* although it can have multiple
|
|
88
|
+
* although it can have multiple series if all the series are continuous in time.
|
|
89
89
|
*
|
|
90
90
|
* - Vertical frames are strongly aligned and have on or more channels, but ONLY a single
|
|
91
91
|
* array per channel. Synnax requires that all frames written to the database are
|
|
@@ -98,7 +98,7 @@ export class Frame {
|
|
|
98
98
|
readonly columns: Keys | Names = [];
|
|
99
99
|
readonly series: Series[] = [];
|
|
100
100
|
|
|
101
|
-
constructor(columnsOrData: Params | CrudeFrame = [],
|
|
101
|
+
constructor(columnsOrData: Params | CrudeFrame = [], series: Series | Series[] = []) {
|
|
102
102
|
if (columnsOrData instanceof Frame) {
|
|
103
103
|
this.columns = columnsOrData.columns;
|
|
104
104
|
this.series = columnsOrData.series;
|
|
@@ -117,9 +117,9 @@ export class Frame {
|
|
|
117
117
|
if (isObject) {
|
|
118
118
|
if ("keys" in columnsOrData && "series" in columnsOrData) {
|
|
119
119
|
const data_ = columnsOrData as FramePayload;
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
data_.keys.forEach((key, i) => this.push(key,
|
|
120
|
+
const series = data_.series.map((a) => seriesFromPayload(a));
|
|
121
|
+
validateMatchedColsAndSeries(data_.keys, series);
|
|
122
|
+
data_.keys.forEach((key, i) => this.push(key, series[i]));
|
|
123
123
|
} else
|
|
124
124
|
Object.entries(columnsOrData).forEach(([k, v]) => {
|
|
125
125
|
const key = parseInt(k);
|
|
@@ -129,21 +129,21 @@ export class Frame {
|
|
|
129
129
|
return;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
// Construction from a set of
|
|
132
|
+
// Construction from a set of series and columns.
|
|
133
133
|
if (
|
|
134
134
|
Array.isArray(columnsOrData) ||
|
|
135
135
|
["string", "number"].includes(typeof columnsOrData)
|
|
136
136
|
) {
|
|
137
|
-
const data_ = toArray(
|
|
137
|
+
const data_ = toArray(series);
|
|
138
138
|
const cols = toArray(columnsOrData) as Keys | Names;
|
|
139
|
-
|
|
139
|
+
validateMatchedColsAndSeries(cols, data_);
|
|
140
140
|
data_.forEach((d, i) => this.push(cols[i], d));
|
|
141
141
|
return;
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
throw new ValidationError(
|
|
145
145
|
`[Frame] - invalid frame construction parameters. data parameter ust be a frame
|
|
146
|
-
payload, a list of lazy
|
|
146
|
+
payload, a list of lazy series, a lazy array, a map, or a record keyed by channel
|
|
147
147
|
name. keys parameter must be a set of channel keys or channel names.`,
|
|
148
148
|
);
|
|
149
149
|
}
|
|
@@ -218,8 +218,8 @@ export class Frame {
|
|
|
218
218
|
/**
|
|
219
219
|
* @returns true if the frame is horizontal. Horizontal frames have a single channel,
|
|
220
220
|
* and are strongly aligned by default.A horizontal frame typically has a single array
|
|
221
|
-
* (in which case, it's also 'square'), although it can have multiple
|
|
222
|
-
* the
|
|
221
|
+
* (in which case, it's also 'square'), although it can have multiple series if all
|
|
222
|
+
* the series are continuous in time.
|
|
223
223
|
*/
|
|
224
224
|
get isHorizontal(): boolean {
|
|
225
225
|
return this.uniqueColumns.length === 1;
|
|
@@ -235,8 +235,8 @@ export class Frame {
|
|
|
235
235
|
|
|
236
236
|
/**
|
|
237
237
|
* @returns true if the frame is weakly aligned. A frame is weakly aligned if it meets
|
|
238
|
-
* the time range occupied by all
|
|
239
|
-
* channels in the frame. This means that the
|
|
238
|
+
* the time range occupied by all series of a particular channel is the same for all
|
|
239
|
+
* channels in the frame. This means that the series for a particular channel can have
|
|
240
240
|
* gaps between them.
|
|
241
241
|
*/
|
|
242
242
|
get isWeaklyAligned(): boolean {
|
|
@@ -266,7 +266,7 @@ export class Frame {
|
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
/**
|
|
269
|
-
* @returns lazy
|
|
269
|
+
* @returns lazy series matching the given channel key or name.
|
|
270
270
|
* @param key the channel key or name.
|
|
271
271
|
*/
|
|
272
272
|
get(key: KeyOrName): MultiSeries;
|
package/src/framer/writer.ts
CHANGED
|
@@ -54,7 +54,8 @@ const constructWriterMode = (mode: CrudeWriterMode): WriterMode => {
|
|
|
54
54
|
case "persistStream":
|
|
55
55
|
return WriterMode.PersistStream;
|
|
56
56
|
default:
|
|
57
|
-
return mode;
|
|
57
|
+
if (typeof mode === "number" && mode in WriterMode) return mode;
|
|
58
|
+
throw new Error(`invalid writer mode: ${mode}`);
|
|
58
59
|
}
|
|
59
60
|
};
|
|
60
61
|
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
// Copyright 2024 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
|
+
|
|
1
10
|
import { binary, UnknownRecord } from "@synnaxlabs/x";
|
|
2
11
|
import { z } from "zod";
|
|
3
12
|
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
// Copyright 2024 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
|
+
|
|
1
10
|
import { z } from "zod";
|
|
2
11
|
|
|
3
12
|
import { ontology } from "@/ontology";
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
// Copyright 2024 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
|
+
|
|
1
10
|
import { binary, observe, UnknownRecord } from "@synnaxlabs/x";
|
|
2
11
|
import { z } from "zod";
|
|
3
12
|
|