@synnaxlabs/client 0.17.4 → 0.17.5
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 +5 -5
- package/dist/client.cjs +1 -1
- package/dist/client.cjs.map +1 -1
- package/dist/client.js +5 -0
- package/dist/client.js.map +1 -1
- package/dist/framer/frame.d.ts +2 -1
- package/examples/node/liveStream.js +7 -2
- package/examples/node/package-lock.json +51 -38
- package/examples/node/package.json +1 -1
- package/examples/node/streamWrite.js +15 -8
- package/package.json +1 -1
- package/src/framer/frame.spec.ts +102 -31
- package/src/framer/frame.ts +9 -0
package/dist/framer/frame.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Size, Series, TimeRange, DataType, TimeStamp } from "@synnaxlabs/x";
|
|
1
|
+
import { Size, Series, TimeRange, DataType, TimeStamp, type TelemValue } from "@synnaxlabs/x";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { type KeyOrName, type Keys, type Names, type Params } from '../channel/payload';
|
|
4
4
|
type ColumnType = "key" | "name" | null;
|
|
@@ -98,6 +98,7 @@ export declare class Frame {
|
|
|
98
98
|
*/
|
|
99
99
|
get isWeaklyAligned(): boolean;
|
|
100
100
|
timeRange(col?: KeyOrName): TimeRange;
|
|
101
|
+
latest(): Record<string, TelemValue>;
|
|
101
102
|
get timeRanges(): TimeRange[];
|
|
102
103
|
/**
|
|
103
104
|
* @returns lazy arrays matching the given channel key or name.
|
|
@@ -18,7 +18,11 @@ const client = new Synnax({
|
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
// We can just specify the names of the channels we'd like to stream from.
|
|
21
|
-
const read_from = [
|
|
21
|
+
const read_from = [
|
|
22
|
+
"stream_write_example_time",
|
|
23
|
+
"stream_write_example_data_1",
|
|
24
|
+
"stream_write_example_data_2"
|
|
25
|
+
]
|
|
22
26
|
|
|
23
27
|
const streamer = await client.telem.newStreamer(read_from);
|
|
24
28
|
|
|
@@ -31,7 +35,8 @@ try {
|
|
|
31
35
|
for await (const frame of streamer)
|
|
32
36
|
console.log({
|
|
33
37
|
time: new TimeStamp(frame.get("stream_write_example_time")[0].at(0)).toString(),
|
|
34
|
-
|
|
38
|
+
data1: frame.get("stream_write_example_data_1")[0].at(0),
|
|
39
|
+
data2: frame.get("stream_write_example_data_2")[0].at(0)
|
|
35
40
|
})
|
|
36
41
|
} finally {
|
|
37
42
|
streamer.close();
|
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
"version": "1.0.0",
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@synnaxlabs/client": "^0.17.
|
|
12
|
+
"@synnaxlabs/client": "^0.17.4"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"node_modules/@grpc/grpc-js": {
|
|
16
|
-
"version": "1.10.
|
|
17
|
-
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.
|
|
18
|
-
"integrity": "sha512-
|
|
16
|
+
"version": "1.10.6",
|
|
17
|
+
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.6.tgz",
|
|
18
|
+
"integrity": "sha512-xP58G7wDQ4TCmN/cMUHh00DS7SRDv/+lC+xFLrTkMIN8h55X5NhZMLYbvy7dSELP15qlI6hPhNCRWVMtZMwqLA==",
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@grpc/proto-loader": "^0.7.10",
|
|
21
21
|
"@js-sdsl/ordered-map": "^4.4.2"
|
|
@@ -3017,9 +3017,9 @@
|
|
|
3017
3017
|
}
|
|
3018
3018
|
},
|
|
3019
3019
|
"node_modules/@opentelemetry/propagation-utils": {
|
|
3020
|
-
"version": "0.30.
|
|
3021
|
-
"resolved": "https://registry.npmjs.org/@opentelemetry/propagation-utils/-/propagation-utils-0.30.
|
|
3022
|
-
"integrity": "sha512-
|
|
3020
|
+
"version": "0.30.8",
|
|
3021
|
+
"resolved": "https://registry.npmjs.org/@opentelemetry/propagation-utils/-/propagation-utils-0.30.8.tgz",
|
|
3022
|
+
"integrity": "sha512-ZKjsUm//SvL8I9JS+bJpAXGpe0Fb+sO+AiWS0fb7EKKLEm3GoNAO7CDMs8GMZBZ91ElR3tBjdUKf/9MzUdYHBA==",
|
|
3023
3023
|
"engines": {
|
|
3024
3024
|
"node": ">=14"
|
|
3025
3025
|
},
|
|
@@ -3122,12 +3122,12 @@
|
|
|
3122
3122
|
}
|
|
3123
3123
|
},
|
|
3124
3124
|
"node_modules/@opentelemetry/resource-detector-alibaba-cloud": {
|
|
3125
|
-
"version": "0.28.
|
|
3126
|
-
"resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-alibaba-cloud/-/resource-detector-alibaba-cloud-0.28.
|
|
3127
|
-
"integrity": "sha512-
|
|
3125
|
+
"version": "0.28.8",
|
|
3126
|
+
"resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-alibaba-cloud/-/resource-detector-alibaba-cloud-0.28.8.tgz",
|
|
3127
|
+
"integrity": "sha512-njdK7S90OX99H0nlDh45vmGU3Bn46JSNjciU18NefyU6R3Dq5ZUU13DWxSlrCBWAiH/+SFJyHQMFsXRnTOFp6w==",
|
|
3128
3128
|
"dependencies": {
|
|
3129
3129
|
"@opentelemetry/resources": "^1.0.0",
|
|
3130
|
-
"@opentelemetry/semantic-conventions": "^1.
|
|
3130
|
+
"@opentelemetry/semantic-conventions": "^1.22.0"
|
|
3131
3131
|
},
|
|
3132
3132
|
"engines": {
|
|
3133
3133
|
"node": ">=14"
|
|
@@ -3137,13 +3137,13 @@
|
|
|
3137
3137
|
}
|
|
3138
3138
|
},
|
|
3139
3139
|
"node_modules/@opentelemetry/resource-detector-aws": {
|
|
3140
|
-
"version": "1.4.
|
|
3141
|
-
"resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-aws/-/resource-detector-aws-1.4.
|
|
3142
|
-
"integrity": "sha512-
|
|
3140
|
+
"version": "1.4.1",
|
|
3141
|
+
"resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-aws/-/resource-detector-aws-1.4.1.tgz",
|
|
3142
|
+
"integrity": "sha512-QsPJwXDxlt+IWQazST7renk9KDOAK3hsywb0Mw6gEwgEoe12EvdVcT+mCknTc+hu5WzxiTmFMtnn1TWab7To1g==",
|
|
3143
3143
|
"dependencies": {
|
|
3144
3144
|
"@opentelemetry/core": "^1.0.0",
|
|
3145
3145
|
"@opentelemetry/resources": "^1.0.0",
|
|
3146
|
-
"@opentelemetry/semantic-conventions": "^1.
|
|
3146
|
+
"@opentelemetry/semantic-conventions": "^1.22.0"
|
|
3147
3147
|
},
|
|
3148
3148
|
"engines": {
|
|
3149
3149
|
"node": ">=14"
|
|
@@ -3153,12 +3153,12 @@
|
|
|
3153
3153
|
}
|
|
3154
3154
|
},
|
|
3155
3155
|
"node_modules/@opentelemetry/resource-detector-container": {
|
|
3156
|
-
"version": "0.3.
|
|
3157
|
-
"resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-container/-/resource-detector-container-0.3.
|
|
3158
|
-
"integrity": "sha512-
|
|
3156
|
+
"version": "0.3.8",
|
|
3157
|
+
"resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-container/-/resource-detector-container-0.3.8.tgz",
|
|
3158
|
+
"integrity": "sha512-YusLYSo8Rr1yKEhakaJ2XgbfbLses5t8YsSRHhO0b6SLliZOFq9ymxoWgtuwyabNCqMMJJYuvrE3Nq0AL6sbcQ==",
|
|
3159
3159
|
"dependencies": {
|
|
3160
3160
|
"@opentelemetry/resources": "^1.0.0",
|
|
3161
|
-
"@opentelemetry/semantic-conventions": "^1.
|
|
3161
|
+
"@opentelemetry/semantic-conventions": "^1.22.0"
|
|
3162
3162
|
},
|
|
3163
3163
|
"engines": {
|
|
3164
3164
|
"node": ">=14"
|
|
@@ -3168,9 +3168,9 @@
|
|
|
3168
3168
|
}
|
|
3169
3169
|
},
|
|
3170
3170
|
"node_modules/@opentelemetry/resource-detector-gcp": {
|
|
3171
|
-
"version": "0.29.
|
|
3172
|
-
"resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.29.
|
|
3173
|
-
"integrity": "sha512-
|
|
3171
|
+
"version": "0.29.8",
|
|
3172
|
+
"resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.29.8.tgz",
|
|
3173
|
+
"integrity": "sha512-jvFtsnrQI7CLDxehp6BxtudbZ3a0HZ+Dj/vFy251280efc15gQdlvFUqXbKBw6ODt/3o38ilw8e0qePJbm2eAg==",
|
|
3174
3174
|
"dependencies": {
|
|
3175
3175
|
"@opentelemetry/core": "^1.0.0",
|
|
3176
3176
|
"@opentelemetry/resources": "^1.0.0",
|
|
@@ -3653,23 +3653,23 @@
|
|
|
3653
3653
|
}
|
|
3654
3654
|
},
|
|
3655
3655
|
"node_modules/@synnaxlabs/client": {
|
|
3656
|
-
"version": "0.17.
|
|
3657
|
-
"resolved": "https://registry.npmjs.org/@synnaxlabs/client/-/client-0.17.
|
|
3658
|
-
"integrity": "sha512-
|
|
3656
|
+
"version": "0.17.4",
|
|
3657
|
+
"resolved": "https://registry.npmjs.org/@synnaxlabs/client/-/client-0.17.4.tgz",
|
|
3658
|
+
"integrity": "sha512-fQ2VvuHMI43BO3x2E7Nl51ZhBOyMbSWeGrid/+TkGNVYyyhVh8oDQE0O5n5mRr6h+kLeKwAv3fH84zDQXTow6w==",
|
|
3659
3659
|
"dependencies": {
|
|
3660
|
-
"@synnaxlabs/freighter": "0.9.
|
|
3661
|
-
"@synnaxlabs/x": "0.14.
|
|
3660
|
+
"@synnaxlabs/freighter": "0.9.2",
|
|
3661
|
+
"@synnaxlabs/x": "0.14.2",
|
|
3662
3662
|
"async-mutex": "^0.4.0",
|
|
3663
3663
|
"zod": "3.22.4"
|
|
3664
3664
|
}
|
|
3665
3665
|
},
|
|
3666
3666
|
"node_modules/@synnaxlabs/freighter": {
|
|
3667
|
-
"version": "0.9.
|
|
3668
|
-
"resolved": "https://registry.npmjs.org/@synnaxlabs/freighter/-/freighter-0.9.
|
|
3669
|
-
"integrity": "sha512-
|
|
3667
|
+
"version": "0.9.2",
|
|
3668
|
+
"resolved": "https://registry.npmjs.org/@synnaxlabs/freighter/-/freighter-0.9.2.tgz",
|
|
3669
|
+
"integrity": "sha512-GJ63tGtSKlqiDLI+82keEIKwKmCsMI7y5ibI1DGKS/cXgeYJFUmG4BjJFM4HfVQxt56o94UP+qP4acZcLDZwGg==",
|
|
3670
3670
|
"dependencies": {
|
|
3671
3671
|
"@synnaxlabs/alamos": "0.3.0",
|
|
3672
|
-
"@synnaxlabs/x": "0.14.
|
|
3672
|
+
"@synnaxlabs/x": "0.14.2",
|
|
3673
3673
|
"js-convert-case": "^4.2.0",
|
|
3674
3674
|
"node-fetch": "2.6.11",
|
|
3675
3675
|
"ws": "^8.15.1",
|
|
@@ -3680,9 +3680,9 @@
|
|
|
3680
3680
|
}
|
|
3681
3681
|
},
|
|
3682
3682
|
"node_modules/@synnaxlabs/x": {
|
|
3683
|
-
"version": "0.14.
|
|
3684
|
-
"resolved": "https://registry.npmjs.org/@synnaxlabs/x/-/x-0.14.
|
|
3685
|
-
"integrity": "sha512
|
|
3683
|
+
"version": "0.14.2",
|
|
3684
|
+
"resolved": "https://registry.npmjs.org/@synnaxlabs/x/-/x-0.14.2.tgz",
|
|
3685
|
+
"integrity": "sha512-Js5czEi7oMhaQkDe3xGuGLbho7xBMoNIWJmrXI20lu+VbB/FyO1wVtfcdIIIZOLc3tUAdNw9ceuZXMOieRoH1g==",
|
|
3686
3686
|
"dependencies": {
|
|
3687
3687
|
"async-mutex": "^0.4.0",
|
|
3688
3688
|
"js-convert-case": "^4.2.0",
|
|
@@ -4414,14 +4414,15 @@
|
|
|
4414
4414
|
}
|
|
4415
4415
|
},
|
|
4416
4416
|
"node_modules/gaxios": {
|
|
4417
|
-
"version": "6.
|
|
4418
|
-
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.
|
|
4419
|
-
"integrity": "sha512-
|
|
4417
|
+
"version": "6.4.0",
|
|
4418
|
+
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.4.0.tgz",
|
|
4419
|
+
"integrity": "sha512-apAloYrY4dlBGlhauDAYSZveafb5U6+L9titing1wox6BvWM0TSXBp603zTrLpyLMGkrcFgohnUN150dFN/zOA==",
|
|
4420
4420
|
"dependencies": {
|
|
4421
4421
|
"extend": "^3.0.2",
|
|
4422
4422
|
"https-proxy-agent": "^7.0.1",
|
|
4423
4423
|
"is-stream": "^2.0.0",
|
|
4424
|
-
"node-fetch": "^2.6.9"
|
|
4424
|
+
"node-fetch": "^2.6.9",
|
|
4425
|
+
"uuid": "^9.0.1"
|
|
4425
4426
|
},
|
|
4426
4427
|
"engines": {
|
|
4427
4428
|
"node": ">=14"
|
|
@@ -4857,6 +4858,18 @@
|
|
|
4857
4858
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
|
4858
4859
|
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
|
|
4859
4860
|
},
|
|
4861
|
+
"node_modules/uuid": {
|
|
4862
|
+
"version": "9.0.1",
|
|
4863
|
+
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
|
4864
|
+
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
|
|
4865
|
+
"funding": [
|
|
4866
|
+
"https://github.com/sponsors/broofa",
|
|
4867
|
+
"https://github.com/sponsors/ctavan"
|
|
4868
|
+
],
|
|
4869
|
+
"bin": {
|
|
4870
|
+
"uuid": "dist/bin/uuid"
|
|
4871
|
+
}
|
|
4872
|
+
},
|
|
4860
4873
|
"node_modules/webidl-conversions": {
|
|
4861
4874
|
"version": "3.0.1",
|
|
4862
4875
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
|
@@ -23,12 +23,18 @@ const timeChannel = await client.channels.create({
|
|
|
23
23
|
}, { retrieveIfNameExists: true });
|
|
24
24
|
|
|
25
25
|
// Create a data channel that will be used to store our fake sensor data.
|
|
26
|
-
const
|
|
27
|
-
name: "
|
|
26
|
+
const dataChannel1 = await client.channels.create({
|
|
27
|
+
name: "stream_write_example_data_1",
|
|
28
28
|
dataType: "float32",
|
|
29
29
|
index: timeChannel.key,
|
|
30
30
|
}, { retrieveIfNameExists: true });
|
|
31
31
|
|
|
32
|
+
const dataChannel2 = await client.channels.create({
|
|
33
|
+
name: "stream_write_example_data_2",
|
|
34
|
+
dataType: "int32",
|
|
35
|
+
index: timeChannel.key,
|
|
36
|
+
}, { retrieveIfNameExists: true });
|
|
37
|
+
|
|
32
38
|
|
|
33
39
|
// We'll start our write at the current time. This timestamps should be the same as or
|
|
34
40
|
// just before the first timestamp we write.
|
|
@@ -44,7 +50,7 @@ const commitInterval = 500;
|
|
|
44
50
|
|
|
45
51
|
const writer = await client.telem.newWriter({
|
|
46
52
|
start,
|
|
47
|
-
channels: [timeChannel.key,
|
|
53
|
+
channels: [timeChannel.key, dataChannel1.key, dataChannel2.key]
|
|
48
54
|
});
|
|
49
55
|
|
|
50
56
|
try {
|
|
@@ -53,12 +59,13 @@ try {
|
|
|
53
59
|
await new Promise(resolve => setTimeout(resolve, roughRate.period.milliseconds));
|
|
54
60
|
i++;
|
|
55
61
|
const timestamp = TimeStamp.now();
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
[
|
|
62
|
+
const data2= i % 2;
|
|
63
|
+
const data1 = Math.sin(i / 10);
|
|
64
|
+
await writer.write({
|
|
65
|
+
[timeChannel.key]: timestamp,
|
|
66
|
+
[dataChannel1.key]: data1,
|
|
67
|
+
[dataChannel2.key]: data2,
|
|
60
68
|
});
|
|
61
|
-
await writer.write(fr);
|
|
62
69
|
|
|
63
70
|
if (i % 60 == 0)
|
|
64
71
|
console.log(`Writing sample ${i} at ${timestamp.toISOString()}`)
|
package/package.json
CHANGED
package/src/framer/frame.spec.ts
CHANGED
|
@@ -19,9 +19,9 @@ describe("framer.Frame", () => {
|
|
|
19
19
|
const f = new framer.Frame(
|
|
20
20
|
["a", "b", "c"],
|
|
21
21
|
[
|
|
22
|
-
new Series({data: new Float32Array([1, 2, 3])}),
|
|
23
|
-
new Series({data: new Float32Array([1, 2, 3])}),
|
|
24
|
-
new Series({data: new Float32Array([1, 2, 3])}),
|
|
22
|
+
new Series({ data: new Float32Array([1, 2, 3]) }),
|
|
23
|
+
new Series({ data: new Float32Array([1, 2, 3]) }),
|
|
24
|
+
new Series({ data: new Float32Array([1, 2, 3]) }),
|
|
25
25
|
],
|
|
26
26
|
);
|
|
27
27
|
expect(f.length).toEqual(9);
|
|
@@ -32,9 +32,9 @@ describe("framer.Frame", () => {
|
|
|
32
32
|
const f = new framer.Frame(
|
|
33
33
|
[12, 13, 14],
|
|
34
34
|
[
|
|
35
|
-
new Series({data: new Float32Array([1, 2, 3])}),
|
|
36
|
-
new Series({data: new Float32Array([1, 2, 3])}),
|
|
37
|
-
new Series({data: new Float32Array([1, 2, 3])}),
|
|
35
|
+
new Series({ data: new Float32Array([1, 2, 3]) }),
|
|
36
|
+
new Series({ data: new Float32Array([1, 2, 3]) }),
|
|
37
|
+
new Series({ data: new Float32Array([1, 2, 3]) }),
|
|
38
38
|
],
|
|
39
39
|
);
|
|
40
40
|
expect(f.length).toEqual(9);
|
|
@@ -42,25 +42,35 @@ describe("framer.Frame", () => {
|
|
|
42
42
|
});
|
|
43
43
|
|
|
44
44
|
test("from a single name and an array of arrays", () => {
|
|
45
|
-
const f = new framer.Frame("a", [
|
|
45
|
+
const f = new framer.Frame("a", [
|
|
46
|
+
new Series({ data: new Float32Array([1, 2, 3]) }),
|
|
47
|
+
]);
|
|
46
48
|
expect(f.length).toEqual(3);
|
|
47
49
|
expect(f.colType).toEqual("name");
|
|
48
50
|
});
|
|
49
51
|
|
|
50
52
|
test("from a single key and an array of arrays", () => {
|
|
51
|
-
const f = new framer.Frame(12, [
|
|
53
|
+
const f = new framer.Frame(12, [
|
|
54
|
+
new Series({ data: new Float32Array([1, 2, 3]) }),
|
|
55
|
+
]);
|
|
52
56
|
expect(f.length).toEqual(3);
|
|
53
57
|
expect(f.colType).toEqual("key");
|
|
54
58
|
});
|
|
55
59
|
|
|
56
60
|
test("from a single key and a single array", () => {
|
|
57
|
-
const f = new framer.Frame(
|
|
61
|
+
const f = new framer.Frame(
|
|
62
|
+
12,
|
|
63
|
+
new Series({ data: new Float32Array([1, 2, 3]) }),
|
|
64
|
+
);
|
|
58
65
|
expect(f.length).toEqual(3);
|
|
59
66
|
expect(f.colType).toEqual("key");
|
|
60
67
|
});
|
|
61
68
|
|
|
62
69
|
test("from a single name and a single array", () => {
|
|
63
|
-
const f = new framer.Frame(
|
|
70
|
+
const f = new framer.Frame(
|
|
71
|
+
"a",
|
|
72
|
+
new Series({ data: new Float32Array([1, 2, 3]) }),
|
|
73
|
+
);
|
|
64
74
|
expect(f.length).toEqual(3);
|
|
65
75
|
expect(f.colType).toEqual("name");
|
|
66
76
|
});
|
|
@@ -82,7 +92,7 @@ describe("framer.Frame", () => {
|
|
|
82
92
|
|
|
83
93
|
test("from record", () => {
|
|
84
94
|
const f = new framer.Frame({
|
|
85
|
-
a: new Series({data: new Float32Array([1, 2, 3])}),
|
|
95
|
+
a: new Series({ data: new Float32Array([1, 2, 3]) }),
|
|
86
96
|
});
|
|
87
97
|
expect(f.length.valueOf()).toEqual(3);
|
|
88
98
|
expect(f.columns.length).toEqual(1);
|
|
@@ -91,7 +101,7 @@ describe("framer.Frame", () => {
|
|
|
91
101
|
|
|
92
102
|
test("from map", () => {
|
|
93
103
|
const f = new framer.Frame(
|
|
94
|
-
new Map([[12, new Series({data: new Float32Array([1, 2, 3])})]]),
|
|
104
|
+
new Map([[12, new Series({ data: new Float32Array([1, 2, 3]) })]]),
|
|
95
105
|
);
|
|
96
106
|
expect(f.length).toEqual(3);
|
|
97
107
|
expect(f.columns.length).toEqual(1);
|
|
@@ -106,8 +116,8 @@ describe("framer.Frame", () => {
|
|
|
106
116
|
new framer.Frame(
|
|
107
117
|
["a", "b", "c"],
|
|
108
118
|
[
|
|
109
|
-
new Series({data: new Float32Array([1, 2, 3])}),
|
|
110
|
-
new Series({data: new Float32Array([1, 2, 3])}),
|
|
119
|
+
new Series({ data: new Float32Array([1, 2, 3]) }),
|
|
120
|
+
new Series({ data: new Float32Array([1, 2, 3]) }),
|
|
111
121
|
],
|
|
112
122
|
),
|
|
113
123
|
).toThrow();
|
|
@@ -119,12 +129,12 @@ describe("framer.Frame", () => {
|
|
|
119
129
|
it("should return false if a key has more than one array", () => {
|
|
120
130
|
const f = new framer.Frame(
|
|
121
131
|
new Map([
|
|
122
|
-
[12, [new Series({data: new Float32Array([1, 2, 3])})]],
|
|
132
|
+
[12, [new Series({ data: new Float32Array([1, 2, 3]) })]],
|
|
123
133
|
[
|
|
124
134
|
13,
|
|
125
135
|
[
|
|
126
|
-
new Series({data: new Float32Array([1, 2, 3])}),
|
|
127
|
-
new Series({data: new Float32Array([1, 2, 3])}),
|
|
136
|
+
new Series({ data: new Float32Array([1, 2, 3]) }),
|
|
137
|
+
new Series({ data: new Float32Array([1, 2, 3]) }),
|
|
128
138
|
],
|
|
129
139
|
],
|
|
130
140
|
]),
|
|
@@ -137,8 +147,8 @@ describe("framer.Frame", () => {
|
|
|
137
147
|
it("should return false if there is more than one key", () => {
|
|
138
148
|
const f = new framer.Frame(
|
|
139
149
|
new Map([
|
|
140
|
-
[12, [new Series({data: new Float32Array([1, 2, 3])})]],
|
|
141
|
-
[13, [new Series({data: new Float32Array([1, 2, 3])})]],
|
|
150
|
+
[12, [new Series({ data: new Float32Array([1, 2, 3]) })]],
|
|
151
|
+
[13, [new Series({ data: new Float32Array([1, 2, 3]) })]],
|
|
142
152
|
]),
|
|
143
153
|
);
|
|
144
154
|
expect(f.isHorizontal).toEqual(false);
|
|
@@ -164,7 +174,7 @@ describe("framer.Frame", () => {
|
|
|
164
174
|
new Series({
|
|
165
175
|
data: new Float32Array([1, 2, 3]),
|
|
166
176
|
timeRange: new TimeRange(500, 50000),
|
|
167
|
-
|
|
177
|
+
}),
|
|
168
178
|
],
|
|
169
179
|
],
|
|
170
180
|
]),
|
|
@@ -181,7 +191,7 @@ describe("framer.Frame", () => {
|
|
|
181
191
|
new Series({
|
|
182
192
|
data: new Float32Array([1, 2, 3]),
|
|
183
193
|
timeRange: new TimeRange(500, 50000),
|
|
184
|
-
|
|
194
|
+
}),
|
|
185
195
|
],
|
|
186
196
|
],
|
|
187
197
|
[
|
|
@@ -190,7 +200,7 @@ describe("framer.Frame", () => {
|
|
|
190
200
|
new Series({
|
|
191
201
|
data: new Float32Array([1, 2, 3]),
|
|
192
202
|
timeRange: new TimeRange(500, 50001),
|
|
193
|
-
|
|
203
|
+
}),
|
|
194
204
|
],
|
|
195
205
|
],
|
|
196
206
|
]),
|
|
@@ -201,7 +211,7 @@ describe("framer.Frame", () => {
|
|
|
201
211
|
|
|
202
212
|
describe("timeRange", () => {
|
|
203
213
|
describe("no key provided", () => {
|
|
204
|
-
it("should return the
|
|
214
|
+
it("should return the maximum time range of the frame", () => {
|
|
205
215
|
const f = new framer.Frame(
|
|
206
216
|
new Map([
|
|
207
217
|
[
|
|
@@ -210,7 +220,7 @@ describe("framer.Frame", () => {
|
|
|
210
220
|
new Series({
|
|
211
221
|
data: new Float32Array([1, 2, 3]),
|
|
212
222
|
timeRange: new TimeRange(40, 50000),
|
|
213
|
-
|
|
223
|
+
}),
|
|
214
224
|
],
|
|
215
225
|
],
|
|
216
226
|
[
|
|
@@ -219,7 +229,7 @@ describe("framer.Frame", () => {
|
|
|
219
229
|
new Series({
|
|
220
230
|
data: new Float32Array([1, 2, 3]),
|
|
221
231
|
timeRange: new TimeRange(500, 50001),
|
|
222
|
-
|
|
232
|
+
}),
|
|
223
233
|
],
|
|
224
234
|
],
|
|
225
235
|
]),
|
|
@@ -234,11 +244,11 @@ describe("framer.Frame", () => {
|
|
|
234
244
|
a: new Series({
|
|
235
245
|
data: new Float32Array([1, 2, 3]),
|
|
236
246
|
timeRange: new TimeRange(40, 50000),
|
|
237
|
-
|
|
247
|
+
}),
|
|
238
248
|
b: new Series({
|
|
239
249
|
data: new Float32Array([1, 2, 3]),
|
|
240
250
|
timeRange: new TimeRange(500, 50001),
|
|
241
|
-
|
|
251
|
+
}),
|
|
242
252
|
});
|
|
243
253
|
expect(f.timeRange("a")).toEqual(new TimeRange(40, 50000));
|
|
244
254
|
});
|
|
@@ -254,7 +264,7 @@ describe("framer.Frame", () => {
|
|
|
254
264
|
new Series({
|
|
255
265
|
data: new Float32Array([1, 2, 3]),
|
|
256
266
|
timeRange: new TimeRange(40, 50000),
|
|
257
|
-
|
|
267
|
+
}),
|
|
258
268
|
],
|
|
259
269
|
],
|
|
260
270
|
[
|
|
@@ -263,7 +273,7 @@ describe("framer.Frame", () => {
|
|
|
263
273
|
new Series({
|
|
264
274
|
data: new Float32Array([1, 2, 3]),
|
|
265
275
|
timeRange: new TimeRange(500, 50001),
|
|
266
|
-
|
|
276
|
+
}),
|
|
267
277
|
],
|
|
268
278
|
],
|
|
269
279
|
]),
|
|
@@ -283,7 +293,7 @@ describe("framer.Frame", () => {
|
|
|
283
293
|
new Series({
|
|
284
294
|
data: new Float32Array([1, 2, 3]),
|
|
285
295
|
timeRange: new TimeRange(40, 50000),
|
|
286
|
-
|
|
296
|
+
}),
|
|
287
297
|
],
|
|
288
298
|
],
|
|
289
299
|
[
|
|
@@ -292,7 +302,7 @@ describe("framer.Frame", () => {
|
|
|
292
302
|
new Series({
|
|
293
303
|
data: new Float32Array([1, 2, 3]),
|
|
294
304
|
timeRange: new TimeRange(500, 50001),
|
|
295
|
-
|
|
305
|
+
}),
|
|
296
306
|
],
|
|
297
307
|
],
|
|
298
308
|
]),
|
|
@@ -302,4 +312,65 @@ describe("framer.Frame", () => {
|
|
|
302
312
|
expect(pld.series?.[0].data.byteLength).toEqual(12);
|
|
303
313
|
});
|
|
304
314
|
});
|
|
315
|
+
|
|
316
|
+
describe("latest", () => {
|
|
317
|
+
it("should return the latest sample from each column in the frame", () => {
|
|
318
|
+
const f = new framer.Frame(
|
|
319
|
+
new Map([
|
|
320
|
+
[
|
|
321
|
+
12,
|
|
322
|
+
[
|
|
323
|
+
new Series({
|
|
324
|
+
data: new Float32Array([1, 2, 3]),
|
|
325
|
+
timeRange: new TimeRange(40, 50000),
|
|
326
|
+
}),
|
|
327
|
+
],
|
|
328
|
+
],
|
|
329
|
+
[
|
|
330
|
+
13,
|
|
331
|
+
[
|
|
332
|
+
new Series({
|
|
333
|
+
data: new Float32Array([1, 2, 3]),
|
|
334
|
+
timeRange: new TimeRange(500, 50001),
|
|
335
|
+
}),
|
|
336
|
+
],
|
|
337
|
+
],
|
|
338
|
+
]),
|
|
339
|
+
);
|
|
340
|
+
expect(f.latest()).toEqual({ 12: 3, 13: 3 });
|
|
341
|
+
});
|
|
342
|
+
it("should return the latest sample for each col in the frame - even with multiple series per col", () => {
|
|
343
|
+
const f = new framer.Frame(
|
|
344
|
+
new Map([
|
|
345
|
+
[
|
|
346
|
+
12,
|
|
347
|
+
[
|
|
348
|
+
new Series({
|
|
349
|
+
data: new Float32Array([1, 2, 3]),
|
|
350
|
+
timeRange: new TimeRange(40, 50000),
|
|
351
|
+
}),
|
|
352
|
+
new Series({
|
|
353
|
+
data: new Float32Array([4, 5, 6]),
|
|
354
|
+
timeRange: new TimeRange(40, 50000),
|
|
355
|
+
}),
|
|
356
|
+
],
|
|
357
|
+
],
|
|
358
|
+
[
|
|
359
|
+
13,
|
|
360
|
+
[
|
|
361
|
+
new Series({
|
|
362
|
+
data: new Float32Array([1, 2, 3]),
|
|
363
|
+
timeRange: new TimeRange(500, 50001),
|
|
364
|
+
}),
|
|
365
|
+
new Series({
|
|
366
|
+
data: new Float32Array([4, 5, 7]),
|
|
367
|
+
timeRange: new TimeRange(500, 50001),
|
|
368
|
+
}),
|
|
369
|
+
],
|
|
370
|
+
],
|
|
371
|
+
]),
|
|
372
|
+
);
|
|
373
|
+
expect(f.latest()).toEqual({ 12: 6, 13: 7 });
|
|
374
|
+
});
|
|
375
|
+
});
|
|
305
376
|
});
|
package/src/framer/frame.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
DataType,
|
|
16
16
|
unique,
|
|
17
17
|
TimeStamp,
|
|
18
|
+
type TelemValue,
|
|
18
19
|
} from "@synnaxlabs/x";
|
|
19
20
|
import { z } from "zod";
|
|
20
21
|
|
|
@@ -257,6 +258,14 @@ export class Frame {
|
|
|
257
258
|
);
|
|
258
259
|
}
|
|
259
260
|
|
|
261
|
+
latest(): Record<string, TelemValue> {
|
|
262
|
+
return Object.fromEntries(
|
|
263
|
+
this.columns
|
|
264
|
+
.map((c, i) => [c, this.series[i].at(-1)])
|
|
265
|
+
.filter(([_, v]) => v != null),
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
260
269
|
get timeRanges(): TimeRange[] {
|
|
261
270
|
return this.uniqueColumns.map((col) => this.timeRange(col));
|
|
262
271
|
}
|