@synnaxlabs/client 0.47.0 → 0.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +7 -7
- package/dist/client.cjs +35 -35
- package/dist/client.js +6264 -5984
- package/dist/eslint.config.d.ts +3 -2
- package/dist/eslint.config.d.ts.map +1 -1
- package/dist/src/access/client.d.ts +3 -1
- package/dist/src/access/client.d.ts.map +1 -1
- package/dist/src/access/enforce.d.ts +35 -0
- package/dist/src/access/enforce.d.ts.map +1 -0
- package/dist/src/access/enforce.spec.d.ts +2 -0
- package/dist/src/access/enforce.spec.d.ts.map +1 -0
- package/dist/src/access/external.d.ts +3 -0
- package/dist/src/access/external.d.ts.map +1 -1
- package/dist/src/access/payload.d.ts +0 -6
- package/dist/src/access/payload.d.ts.map +1 -1
- package/dist/src/access/policy/access.spec.d.ts +2 -0
- package/dist/src/access/policy/access.spec.d.ts.map +1 -0
- package/dist/src/access/policy/client.d.ts +485 -31
- package/dist/src/access/policy/client.d.ts.map +1 -1
- package/dist/src/access/policy/payload.d.ts +36 -113
- package/dist/src/access/policy/payload.d.ts.map +1 -1
- package/dist/src/access/role/client.d.ts +135 -0
- package/dist/src/access/role/client.d.ts.map +1 -0
- package/dist/src/access/role/external.d.ts.map +1 -0
- package/dist/src/access/role/index.d.ts +2 -0
- package/dist/src/access/role/index.d.ts.map +1 -0
- package/dist/src/access/role/payload.d.ts +27 -0
- package/dist/src/access/role/payload.d.ts.map +1 -0
- package/dist/src/access/role/role.spec.d.ts +2 -0
- package/dist/src/access/role/role.spec.d.ts.map +1 -0
- package/dist/src/arc/access.spec.d.ts +2 -0
- package/dist/src/arc/access.spec.d.ts.map +1 -0
- package/dist/src/arc/client.d.ts +5 -14
- package/dist/src/arc/client.d.ts.map +1 -1
- package/dist/src/arc/payload.d.ts +11 -2
- package/dist/src/arc/payload.d.ts.map +1 -1
- package/dist/src/auth/auth.d.ts +5 -3
- package/dist/src/auth/auth.d.ts.map +1 -1
- package/dist/src/channel/access.spec.d.ts +2 -0
- package/dist/src/channel/access.spec.d.ts.map +1 -0
- package/dist/src/channel/client.d.ts +0 -1
- package/dist/src/channel/client.d.ts.map +1 -1
- package/dist/src/channel/payload.d.ts +19 -8
- package/dist/src/channel/payload.d.ts.map +1 -1
- package/dist/src/channel/payload.spec.d.ts +2 -0
- package/dist/src/channel/payload.spec.d.ts.map +1 -0
- package/dist/src/channel/retriever.d.ts +4 -6
- package/dist/src/channel/retriever.d.ts.map +1 -1
- package/dist/src/channel/writer.d.ts.map +1 -1
- package/dist/src/client.d.ts +18 -10
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/connection/checker.d.ts +2 -3
- package/dist/src/connection/checker.d.ts.map +1 -1
- package/dist/src/connection.spec.d.ts +2 -0
- package/dist/src/connection.spec.d.ts.map +1 -0
- package/dist/src/device/access.spec.d.ts +2 -0
- package/dist/src/device/access.spec.d.ts.map +1 -0
- package/dist/src/{hardware/device → device}/client.d.ts +14 -7
- package/dist/src/device/client.d.ts.map +1 -0
- package/dist/src/device/device.spec.d.ts.map +1 -0
- package/dist/src/device/external.d.ts.map +1 -0
- package/dist/src/device/index.d.ts.map +1 -0
- package/dist/src/{hardware/device → device}/payload.d.ts +1 -1
- package/dist/src/device/payload.d.ts.map +1 -0
- package/dist/src/errors.d.ts +3 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/framer/adapter.d.ts +2 -2
- package/dist/src/framer/adapter.d.ts.map +1 -1
- package/dist/src/framer/client.d.ts +8 -1
- package/dist/src/framer/client.d.ts.map +1 -1
- package/dist/src/framer/frame.d.ts +11 -5
- package/dist/src/framer/frame.d.ts.map +1 -1
- package/dist/src/framer/iterator.d.ts +3 -3
- package/dist/src/framer/streamer.d.ts +24 -21
- package/dist/src/framer/streamer.d.ts.map +1 -1
- package/dist/src/framer/writer.d.ts +13 -13
- package/dist/src/index.d.ts +6 -7
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/label/access.spec.d.ts +2 -0
- package/dist/src/label/access.spec.d.ts.map +1 -0
- package/dist/src/label/client.d.ts +20 -11
- package/dist/src/label/client.d.ts.map +1 -1
- package/dist/src/ontology/client.d.ts +6 -6
- package/dist/src/ontology/client.d.ts.map +1 -1
- package/dist/src/ontology/group/access.spec.d.ts +2 -0
- package/dist/src/ontology/group/access.spec.d.ts.map +1 -0
- package/dist/src/ontology/group/client.d.ts +2 -2
- package/dist/src/ontology/group/client.d.ts.map +1 -1
- package/dist/src/ontology/group/payload.d.ts +1 -2
- package/dist/src/ontology/group/payload.d.ts.map +1 -1
- package/dist/src/ontology/payload.d.ts +23 -17
- package/dist/src/ontology/payload.d.ts.map +1 -1
- package/dist/src/ontology/writer.d.ts +10 -10
- package/dist/src/ontology/writer.d.ts.map +1 -1
- package/dist/src/rack/access.spec.d.ts +2 -0
- package/dist/src/rack/access.spec.d.ts.map +1 -0
- package/dist/src/{hardware/rack → rack}/client.d.ts +15 -8
- package/dist/src/rack/client.d.ts.map +1 -0
- package/dist/src/rack/external.d.ts.map +1 -0
- package/dist/src/rack/index.d.ts.map +1 -0
- package/dist/src/{hardware/rack → rack}/payload.d.ts +1 -1
- package/dist/src/rack/payload.d.ts.map +1 -0
- package/dist/src/rack/rack.spec.d.ts.map +1 -0
- package/dist/src/ranger/access.spec.d.ts +2 -0
- package/dist/src/ranger/access.spec.d.ts.map +1 -0
- package/dist/src/ranger/alias.d.ts +1 -8
- package/dist/src/ranger/alias.d.ts.map +1 -1
- package/dist/src/ranger/client.d.ts +12 -5
- package/dist/src/ranger/client.d.ts.map +1 -1
- package/dist/src/ranger/kv.d.ts +0 -3
- package/dist/src/ranger/kv.d.ts.map +1 -1
- package/dist/src/ranger/writer.d.ts +2 -2
- package/dist/src/ranger/writer.d.ts.map +1 -1
- package/dist/src/status/access.spec.d.ts +2 -0
- package/dist/src/status/access.spec.d.ts.map +1 -0
- package/dist/src/status/client.d.ts +4 -4
- package/dist/src/status/client.d.ts.map +1 -1
- package/dist/src/status/payload.d.ts +9 -2
- package/dist/src/status/payload.d.ts.map +1 -1
- package/dist/src/task/access.spec.d.ts +2 -0
- package/dist/src/task/access.spec.d.ts.map +1 -0
- package/dist/src/{hardware/task → task}/client.d.ts +26 -15
- package/dist/src/task/client.d.ts.map +1 -0
- package/dist/src/task/external.d.ts +3 -0
- package/dist/src/task/external.d.ts.map +1 -0
- package/dist/src/task/index.d.ts.map +1 -0
- package/dist/src/{hardware/task → task}/payload.d.ts +45 -6
- package/dist/src/task/payload.d.ts.map +1 -0
- package/dist/src/task/task.spec.d.ts.map +1 -0
- package/dist/src/testutil/access.d.ts +4 -0
- package/dist/src/testutil/access.d.ts.map +1 -0
- package/dist/src/testutil/client.d.ts +3 -3
- package/dist/src/testutil/client.d.ts.map +1 -1
- package/dist/src/transport.d.ts.map +1 -1
- package/dist/src/user/access.spec.d.ts +2 -0
- package/dist/src/user/access.spec.d.ts.map +1 -0
- package/dist/src/user/client.d.ts +10 -1
- package/dist/src/user/client.d.ts.map +1 -1
- package/dist/src/user/external.d.ts +1 -1
- package/dist/src/user/external.d.ts.map +1 -1
- package/dist/src/user/payload.d.ts.map +1 -1
- package/dist/src/workspace/access.spec.d.ts +2 -0
- package/dist/src/workspace/access.spec.d.ts.map +1 -0
- package/dist/src/workspace/client.d.ts +10 -5
- package/dist/src/workspace/client.d.ts.map +1 -1
- package/dist/src/workspace/lineplot/access.spec.d.ts +2 -0
- package/dist/src/workspace/lineplot/access.spec.d.ts.map +1 -0
- package/dist/src/workspace/lineplot/client.d.ts +8 -1
- package/dist/src/workspace/lineplot/client.d.ts.map +1 -1
- package/dist/src/workspace/log/access.spec.d.ts +2 -0
- package/dist/src/workspace/log/access.spec.d.ts.map +1 -0
- package/dist/src/workspace/log/client.d.ts +8 -1
- package/dist/src/workspace/log/client.d.ts.map +1 -1
- package/dist/src/workspace/schematic/access.spec.d.ts +2 -0
- package/dist/src/workspace/schematic/access.spec.d.ts.map +1 -0
- package/dist/src/workspace/schematic/client.d.ts +8 -1
- package/dist/src/workspace/schematic/client.d.ts.map +1 -1
- package/dist/src/workspace/schematic/symbol/access.spec.d.ts +2 -0
- package/dist/src/workspace/schematic/symbol/access.spec.d.ts.map +1 -0
- package/dist/src/workspace/schematic/symbol/client.d.ts +1 -5
- package/dist/src/workspace/schematic/symbol/client.d.ts.map +1 -1
- package/dist/src/workspace/schematic/symbol/payload.d.ts +2 -2
- package/dist/src/workspace/table/access.spec.d.ts +2 -0
- package/dist/src/workspace/table/access.spec.d.ts.map +1 -0
- package/dist/src/workspace/table/client.d.ts +8 -1
- package/dist/src/workspace/table/client.d.ts.map +1 -1
- package/eslint.config.ts +3 -1
- package/package.json +8 -8
- package/src/access/client.ts +5 -2
- package/src/access/enforce.spec.ts +189 -0
- package/src/access/enforce.ts +84 -0
- package/src/access/external.ts +3 -0
- package/src/access/payload.ts +1 -13
- package/src/access/policy/access.spec.ts +147 -0
- package/src/access/policy/client.ts +21 -25
- package/src/access/policy/payload.ts +9 -5
- package/src/access/role/client.ts +135 -0
- package/src/access/role/external.ts +11 -0
- package/src/{hardware → access/role}/index.ts +1 -1
- package/src/access/role/payload.ts +32 -0
- package/src/access/role/role.spec.ts +95 -0
- package/src/arc/access.spec.ts +143 -0
- package/src/arc/client.ts +7 -31
- package/src/arc/payload.ts +4 -0
- package/src/auth/auth.spec.ts +13 -13
- package/src/auth/auth.ts +33 -11
- package/src/channel/access.spec.ts +116 -0
- package/src/channel/channel.spec.ts +63 -73
- package/src/channel/client.ts +2 -8
- package/src/channel/payload.spec.ts +171 -0
- package/src/channel/payload.ts +37 -8
- package/src/channel/retriever.ts +10 -11
- package/src/channel/writer.ts +3 -7
- package/src/client.ts +38 -28
- package/src/connection/checker.ts +10 -10
- package/src/connection/connection.spec.ts +13 -13
- package/src/connection.spec.ts +145 -0
- package/src/device/access.spec.ts +159 -0
- package/src/{hardware/device → device}/client.ts +12 -21
- package/src/{hardware/device → device}/device.spec.ts +70 -34
- package/src/device/external.ts +11 -0
- package/src/{hardware/rack → device}/index.ts +1 -1
- package/src/{hardware/device → device}/payload.ts +3 -3
- package/src/errors.ts +2 -0
- package/src/framer/adapter.spec.ts +351 -13
- package/src/framer/adapter.ts +23 -13
- package/src/framer/client.spec.ts +14 -20
- package/src/framer/client.ts +3 -5
- package/src/framer/deleter.spec.ts +1 -1
- package/src/framer/frame.spec.ts +427 -0
- package/src/framer/frame.ts +30 -3
- package/src/framer/iterator.ts +4 -4
- package/src/framer/streamer.spec.ts +155 -10
- package/src/framer/streamer.ts +35 -12
- package/src/framer/writer.spec.ts +5 -5
- package/src/index.ts +13 -7
- package/src/label/access.spec.ts +109 -0
- package/src/label/client.ts +10 -14
- package/src/ontology/client.ts +4 -6
- package/src/ontology/group/access.spec.ts +77 -0
- package/src/ontology/group/client.ts +3 -7
- package/src/ontology/group/group.spec.ts +18 -0
- package/src/ontology/group/payload.ts +2 -2
- package/src/ontology/ontology.spec.ts +2 -0
- package/src/ontology/payload.ts +18 -2
- package/src/ontology/writer.ts +3 -7
- package/src/rack/access.spec.ts +102 -0
- package/src/{hardware/rack → rack}/client.ts +14 -19
- package/src/{hardware/device/index.ts → rack/external.ts} +2 -1
- package/src/{hardware/external.ts → rack/index.ts} +1 -1
- package/src/{hardware/rack → rack}/payload.ts +2 -2
- package/src/{hardware/rack → rack}/rack.spec.ts +43 -17
- package/src/ranger/access.spec.ts +115 -0
- package/src/ranger/alias.ts +6 -14
- package/src/ranger/client.ts +13 -14
- package/src/ranger/kv.ts +7 -9
- package/src/ranger/ranger.spec.ts +4 -4
- package/src/ranger/writer.ts +3 -7
- package/src/status/access.spec.ts +129 -0
- package/src/status/client.ts +5 -9
- package/src/status/payload.ts +3 -2
- package/src/task/access.spec.ts +131 -0
- package/src/{hardware/task → task}/client.ts +50 -25
- package/src/task/external.ts +11 -0
- package/src/{hardware/task → task}/index.ts +1 -1
- package/src/{hardware/task → task}/payload.ts +22 -3
- package/src/{hardware/task → task}/task.spec.ts +197 -34
- package/src/testutil/access.ts +34 -0
- package/src/testutil/channels.ts +3 -3
- package/src/testutil/client.ts +4 -4
- package/src/transport.ts +1 -3
- package/src/user/access.spec.ts +107 -0
- package/src/user/client.ts +10 -12
- package/src/user/external.ts +12 -1
- package/src/user/payload.ts +3 -5
- package/src/workspace/access.spec.ts +108 -0
- package/src/workspace/client.ts +11 -27
- package/src/workspace/lineplot/access.spec.ts +134 -0
- package/src/workspace/lineplot/client.ts +8 -13
- package/src/workspace/log/access.spec.ts +134 -0
- package/src/workspace/log/client.ts +8 -13
- package/src/workspace/schematic/access.spec.ts +134 -0
- package/src/workspace/schematic/client.ts +9 -18
- package/src/workspace/schematic/symbol/access.spec.ts +172 -0
- package/src/workspace/schematic/symbol/client.ts +6 -17
- package/src/workspace/schematic/symbol/payload.ts +1 -1
- package/src/workspace/table/access.spec.ts +134 -0
- package/src/workspace/table/client.ts +8 -13
- package/dist/src/access/policy/policy.spec.d.ts +0 -2
- package/dist/src/access/policy/policy.spec.d.ts.map +0 -1
- package/dist/src/hardware/client.d.ts +0 -10
- package/dist/src/hardware/client.d.ts.map +0 -1
- package/dist/src/hardware/device/client.d.ts.map +0 -1
- package/dist/src/hardware/device/device.spec.d.ts.map +0 -1
- package/dist/src/hardware/device/external.d.ts.map +0 -1
- package/dist/src/hardware/device/index.d.ts.map +0 -1
- package/dist/src/hardware/device/payload.d.ts.map +0 -1
- package/dist/src/hardware/external.d.ts +0 -2
- package/dist/src/hardware/external.d.ts.map +0 -1
- package/dist/src/hardware/index.d.ts +0 -2
- package/dist/src/hardware/index.d.ts.map +0 -1
- package/dist/src/hardware/rack/client.d.ts.map +0 -1
- package/dist/src/hardware/rack/external.d.ts.map +0 -1
- package/dist/src/hardware/rack/index.d.ts.map +0 -1
- package/dist/src/hardware/rack/payload.d.ts.map +0 -1
- package/dist/src/hardware/rack/rack.spec.d.ts.map +0 -1
- package/dist/src/hardware/task/client.d.ts.map +0 -1
- package/dist/src/hardware/task/external.d.ts.map +0 -1
- package/dist/src/hardware/task/index.d.ts.map +0 -1
- package/dist/src/hardware/task/payload.d.ts.map +0 -1
- package/dist/src/hardware/task/task.spec.d.ts.map +0 -1
- package/dist/src/user/retriever.d.ts +0 -16
- package/dist/src/user/retriever.d.ts.map +0 -1
- package/dist/src/user/writer.d.ts +0 -11
- package/dist/src/user/writer.d.ts.map +0 -1
- package/src/access/policy/policy.spec.ts +0 -329
- package/src/hardware/client.ts +0 -24
- package/src/hardware/device/external.ts +0 -11
- package/src/hardware/rack/external.ts +0 -11
- package/src/hardware/task/external.ts +0 -11
- package/src/user/retriever.ts +0 -41
- package/src/user/writer.ts +0 -84
- /package/dist/src/{hardware/device → access/role}/external.d.ts +0 -0
- /package/dist/src/{hardware/device → device}/device.spec.d.ts +0 -0
- /package/dist/src/{hardware/rack → device}/external.d.ts +0 -0
- /package/dist/src/{hardware/device → device}/index.d.ts +0 -0
- /package/dist/src/{hardware/task → rack}/external.d.ts +0 -0
- /package/dist/src/{hardware/rack → rack}/index.d.ts +0 -0
- /package/dist/src/{hardware/rack → rack}/rack.spec.d.ts +0 -0
- /package/dist/src/{hardware/task → task}/index.d.ts +0 -0
- /package/dist/src/{hardware/task → task}/task.spec.d.ts +0 -0
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
import { binary, record, status, zod } from "@synnaxlabs/x";
|
|
11
11
|
import { z } from "zod";
|
|
12
12
|
|
|
13
|
-
import { keyZ as rackKeyZ } from "@/
|
|
13
|
+
import { keyZ as rackKeyZ } from "@/rack/payload";
|
|
14
14
|
import { decodeJSONString } from "@/util/decodeJSONString";
|
|
15
15
|
|
|
16
16
|
export const keyZ = z.string();
|
|
17
17
|
export type Key = z.infer<typeof keyZ>;
|
|
18
18
|
|
|
19
|
-
export const
|
|
20
|
-
export const statusZ = status.statusZ(
|
|
19
|
+
export const statusDetailsZ = z.object({ rack: rackKeyZ, device: keyZ });
|
|
20
|
+
export const statusZ = status.statusZ(statusDetailsZ);
|
|
21
21
|
|
|
22
22
|
export interface Status extends z.infer<typeof statusZ> {}
|
|
23
23
|
|
package/src/errors.ts
CHANGED
|
@@ -51,6 +51,8 @@ export class InvalidTokenError extends AuthError.sub("invalid_token") {}
|
|
|
51
51
|
|
|
52
52
|
export class ExpiredTokenError extends AuthError.sub("expired_token") {}
|
|
53
53
|
|
|
54
|
+
export class AccessDeniedError extends AuthError.sub("access_denied") {}
|
|
55
|
+
|
|
54
56
|
/**
|
|
55
57
|
* UnexpectedError is raised when an unexpected error occurs.
|
|
56
58
|
*/
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
|
-
import { DataType, Series, TimeStamp } from "@synnaxlabs/x";
|
|
10
|
+
import { DataType, id, Series, TimeStamp } from "@synnaxlabs/x";
|
|
11
11
|
import { beforeAll, describe, expect, it } from "vitest";
|
|
12
12
|
|
|
13
13
|
import { type channel } from "@/channel";
|
|
@@ -24,12 +24,12 @@ describe("WriteFrameAdapter", () => {
|
|
|
24
24
|
|
|
25
25
|
beforeAll(async () => {
|
|
26
26
|
timeCh = await client.channels.create({
|
|
27
|
-
name:
|
|
27
|
+
name: id.create(),
|
|
28
28
|
dataType: DataType.TIMESTAMP,
|
|
29
29
|
isIndex: true,
|
|
30
30
|
});
|
|
31
31
|
dataCh = await client.channels.create({
|
|
32
|
-
name:
|
|
32
|
+
name: id.create(),
|
|
33
33
|
dataType: DataType.FLOAT32,
|
|
34
34
|
index: timeCh.key,
|
|
35
35
|
});
|
|
@@ -118,7 +118,7 @@ describe("WriteFrameAdapter", () => {
|
|
|
118
118
|
|
|
119
119
|
it("should correctly adapt a name and JSON value", async () => {
|
|
120
120
|
const jsonChannel = await client.channels.create({
|
|
121
|
-
name:
|
|
121
|
+
name: id.create(),
|
|
122
122
|
dataType: DataType.JSON,
|
|
123
123
|
virtual: true,
|
|
124
124
|
});
|
|
@@ -134,7 +134,7 @@ describe("WriteFrameAdapter", () => {
|
|
|
134
134
|
|
|
135
135
|
it("should correctly adapt a name and a json typed series", async () => {
|
|
136
136
|
const jsonChannel = await client.channels.create({
|
|
137
|
-
name:
|
|
137
|
+
name: id.create(),
|
|
138
138
|
dataType: DataType.JSON,
|
|
139
139
|
virtual: true,
|
|
140
140
|
});
|
|
@@ -150,7 +150,7 @@ describe("WriteFrameAdapter", () => {
|
|
|
150
150
|
|
|
151
151
|
it("should correctly adapt a numeric value to a BigInt keyed by key", async () => {
|
|
152
152
|
const bigIntCh = await client.channels.create({
|
|
153
|
-
name:
|
|
153
|
+
name: id.create(),
|
|
154
154
|
dataType: DataType.INT64,
|
|
155
155
|
virtual: true,
|
|
156
156
|
});
|
|
@@ -176,7 +176,7 @@ describe("WriteFrameAdapter", () => {
|
|
|
176
176
|
|
|
177
177
|
it("should return true when adding a new channel", async () => {
|
|
178
178
|
const newCh = await client.channels.create({
|
|
179
|
-
name:
|
|
179
|
+
name: id.create(),
|
|
180
180
|
dataType: DataType.FLOAT32,
|
|
181
181
|
index: timeCh.key,
|
|
182
182
|
});
|
|
@@ -191,7 +191,7 @@ describe("WriteFrameAdapter", () => {
|
|
|
191
191
|
|
|
192
192
|
it("should return true when replacing channels", async () => {
|
|
193
193
|
const newCh = await client.channels.create({
|
|
194
|
-
name:
|
|
194
|
+
name: id.create(),
|
|
195
195
|
dataType: DataType.FLOAT32,
|
|
196
196
|
index: timeCh.key,
|
|
197
197
|
});
|
|
@@ -213,22 +213,28 @@ describe("WriteFrameAdapter", () => {
|
|
|
213
213
|
});
|
|
214
214
|
});
|
|
215
215
|
|
|
216
|
-
describe("
|
|
216
|
+
describe("ReadFrameAdapter", () => {
|
|
217
217
|
let timeCh: channel.Channel;
|
|
218
218
|
let dataCh: channel.Channel;
|
|
219
|
+
let extraCh: channel.Channel;
|
|
219
220
|
let adapter: ReadAdapter;
|
|
220
221
|
|
|
221
222
|
beforeAll(async () => {
|
|
222
223
|
timeCh = await client.channels.create({
|
|
223
|
-
name:
|
|
224
|
+
name: id.create(),
|
|
224
225
|
dataType: DataType.TIMESTAMP,
|
|
225
226
|
isIndex: true,
|
|
226
227
|
});
|
|
227
228
|
dataCh = await client.channels.create({
|
|
228
|
-
name:
|
|
229
|
+
name: id.create(),
|
|
229
230
|
dataType: DataType.FLOAT32,
|
|
230
231
|
index: timeCh.key,
|
|
231
232
|
});
|
|
233
|
+
extraCh = await client.channels.create({
|
|
234
|
+
name: id.create(),
|
|
235
|
+
dataType: DataType.FLOAT64,
|
|
236
|
+
index: timeCh.key,
|
|
237
|
+
});
|
|
232
238
|
|
|
233
239
|
adapter = await ReadAdapter.open(client.channels.retriever, [
|
|
234
240
|
timeCh.key,
|
|
@@ -236,6 +242,338 @@ describe("ReadAdapter", () => {
|
|
|
236
242
|
]);
|
|
237
243
|
});
|
|
238
244
|
|
|
245
|
+
describe("adapt", () => {
|
|
246
|
+
describe("with keys (no conversion)", () => {
|
|
247
|
+
describe("hot path - exact channel match", () => {
|
|
248
|
+
it("should return frame unchanged when all channels match", () => {
|
|
249
|
+
// HOT PATH: Frame has exactly the channels registered with adapter
|
|
250
|
+
const ts = TimeStamp.now().valueOf();
|
|
251
|
+
const inputFrame = new Frame({
|
|
252
|
+
[timeCh.key]: new Series([ts]),
|
|
253
|
+
[dataCh.key]: new Series([1.5]),
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
const result = adapter.adapt(inputFrame);
|
|
257
|
+
|
|
258
|
+
// Frame should be returned unchanged (zero allocations)
|
|
259
|
+
expect(result).toBe(inputFrame); // Same object reference
|
|
260
|
+
expect(result.columns).toHaveLength(2);
|
|
261
|
+
expect(result.has(timeCh.key)).toBe(true);
|
|
262
|
+
expect(result.has(dataCh.key)).toBe(true);
|
|
263
|
+
expect(result.get(timeCh.key).at(0)).toEqual(ts);
|
|
264
|
+
expect(result.get(dataCh.key).at(0)).toEqual(1.5);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it("should preserve series data types in hot path", () => {
|
|
268
|
+
const ts = TimeStamp.now().valueOf();
|
|
269
|
+
const inputFrame = new Frame({
|
|
270
|
+
[timeCh.key]: new Series({ data: [ts], dataType: DataType.TIMESTAMP }),
|
|
271
|
+
[dataCh.key]: new Series({ data: [1.5], dataType: DataType.FLOAT32 }),
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const result = adapter.adapt(inputFrame);
|
|
275
|
+
|
|
276
|
+
// Data types should be preserved
|
|
277
|
+
expect(result.get(timeCh.key).dataType).toEqual(DataType.TIMESTAMP);
|
|
278
|
+
expect(result.get(dataCh.key).dataType).toEqual(DataType.FLOAT32);
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
describe("cold path - filtering needed", () => {
|
|
283
|
+
it("should filter out extra channels in key mode", () => {
|
|
284
|
+
// COLD PATH: Frame has extra channels not in adapter
|
|
285
|
+
const ts = TimeStamp.now().valueOf();
|
|
286
|
+
const inputFrame = new Frame({
|
|
287
|
+
[timeCh.key]: new Series([ts]),
|
|
288
|
+
[dataCh.key]: new Series([1.5]),
|
|
289
|
+
[extraCh.key]: new Series([999.0]), // Extra channel
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
const result = adapter.adapt(inputFrame);
|
|
293
|
+
|
|
294
|
+
// Should filter out extraCh
|
|
295
|
+
expect(result).not.toBe(inputFrame); // Different object (filtered)
|
|
296
|
+
expect(result.columns).toHaveLength(2);
|
|
297
|
+
expect(result.has(timeCh.key)).toBe(true);
|
|
298
|
+
expect(result.has(dataCh.key)).toBe(true);
|
|
299
|
+
expect(result.has(extraCh.key)).toBe(false);
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
it("should handle partial matches in key mode", () => {
|
|
303
|
+
// Frame has some matching and some extra channels
|
|
304
|
+
const ts = TimeStamp.now().valueOf();
|
|
305
|
+
const inputFrame = new Frame({
|
|
306
|
+
[timeCh.key]: new Series([ts]),
|
|
307
|
+
[extraCh.key]: new Series([999.0]),
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
const result = adapter.adapt(inputFrame);
|
|
311
|
+
|
|
312
|
+
expect(result.columns).toHaveLength(1);
|
|
313
|
+
expect(result.has(timeCh.key)).toBe(true);
|
|
314
|
+
expect(result.has(extraCh.key)).toBe(false);
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it("should return empty frame when no channels match in key mode", () => {
|
|
318
|
+
const inputFrame = new Frame({
|
|
319
|
+
[extraCh.key]: new Series([999.0]),
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
const result = adapter.adapt(inputFrame);
|
|
323
|
+
|
|
324
|
+
expect(result.columns).toHaveLength(0);
|
|
325
|
+
expect(result.series).toHaveLength(0);
|
|
326
|
+
});
|
|
327
|
+
});
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
describe("with names (conversion)", () => {
|
|
331
|
+
let nameAdapter: ReadAdapter;
|
|
332
|
+
|
|
333
|
+
beforeAll(async () => {
|
|
334
|
+
// Create adapter with channel names (triggers key-to-name mapping)
|
|
335
|
+
nameAdapter = await ReadAdapter.open(client.channels.retriever, [
|
|
336
|
+
timeCh.name,
|
|
337
|
+
dataCh.name,
|
|
338
|
+
]);
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
describe("hot path - exact match, only convert", () => {
|
|
342
|
+
it("should convert channel keys to names when all channels match", () => {
|
|
343
|
+
// HOT PATH: Frame has exactly the channels in adapter
|
|
344
|
+
const ts = TimeStamp.now().valueOf();
|
|
345
|
+
const inputFrame = new Frame({
|
|
346
|
+
[timeCh.key]: new Series([ts]),
|
|
347
|
+
[dataCh.key]: new Series([2.5]),
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
const result = nameAdapter.adapt(inputFrame);
|
|
351
|
+
|
|
352
|
+
// Output should have names instead of keys (one allocation for conversion)
|
|
353
|
+
expect(result.columns).toHaveLength(2);
|
|
354
|
+
expect(result.has(timeCh.name)).toBe(true);
|
|
355
|
+
expect(result.has(dataCh.name)).toBe(true);
|
|
356
|
+
expect(result.get(timeCh.name).at(0)).toEqual(ts);
|
|
357
|
+
expect(result.get(dataCh.name).at(0)).toEqual(2.5);
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
it("should handle multiple values in hot path", () => {
|
|
361
|
+
const ts = TimeStamp.now().valueOf();
|
|
362
|
+
const inputFrame = new Frame({
|
|
363
|
+
[timeCh.key]: new Series([ts, ts + 1000n]),
|
|
364
|
+
[dataCh.key]: new Series([1.0, 2.0]),
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
const result = nameAdapter.adapt(inputFrame);
|
|
368
|
+
|
|
369
|
+
expect(result.columns).toHaveLength(2);
|
|
370
|
+
expect(result.get(timeCh.name)).toHaveLength(2);
|
|
371
|
+
expect(result.get(dataCh.name)).toHaveLength(2);
|
|
372
|
+
expect(result.get(timeCh.name).at(0)).toEqual(ts);
|
|
373
|
+
expect(result.get(timeCh.name).at(1)).toEqual(ts + 1000n);
|
|
374
|
+
expect(result.get(dataCh.name).at(0)).toEqual(1.0);
|
|
375
|
+
expect(result.get(dataCh.name).at(1)).toEqual(2.0);
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
it("should preserve data types during name conversion", () => {
|
|
379
|
+
const ts = TimeStamp.now().valueOf();
|
|
380
|
+
const inputFrame = new Frame({
|
|
381
|
+
[timeCh.key]: new Series({ data: [ts], dataType: DataType.TIMESTAMP }),
|
|
382
|
+
[dataCh.key]: new Series({ data: [3.5], dataType: DataType.FLOAT32 }),
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
const result = nameAdapter.adapt(inputFrame);
|
|
386
|
+
|
|
387
|
+
expect(result.get(timeCh.name).dataType).toEqual(DataType.TIMESTAMP);
|
|
388
|
+
expect(result.get(dataCh.name).dataType).toEqual(DataType.FLOAT32);
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
describe("cold path - filter and convert", () => {
|
|
393
|
+
it("should filter out extra channels while converting", async () => {
|
|
394
|
+
// COLD PATH: Frame has extra channels that need filtering
|
|
395
|
+
const ts = TimeStamp.now().valueOf();
|
|
396
|
+
const inputFrame = new Frame({
|
|
397
|
+
[timeCh.key]: new Series([ts]),
|
|
398
|
+
[dataCh.key]: new Series([1.5]),
|
|
399
|
+
[extraCh.key]: new Series([999.0]), // Extra channel
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
const result = nameAdapter.adapt(inputFrame);
|
|
403
|
+
|
|
404
|
+
// Should filter extraCh and convert remaining keys to names
|
|
405
|
+
expect(result.columns).toHaveLength(2);
|
|
406
|
+
expect(result.has(timeCh.name)).toBe(true);
|
|
407
|
+
expect(result.has(dataCh.name)).toBe(true);
|
|
408
|
+
expect(result.has(extraCh.key)).toBe(false);
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
it("should handle partial matches while converting", async () => {
|
|
412
|
+
const filterAdapter = await ReadAdapter.open(client.channels.retriever, [
|
|
413
|
+
timeCh.name,
|
|
414
|
+
]);
|
|
415
|
+
|
|
416
|
+
const ts = TimeStamp.now().valueOf();
|
|
417
|
+
const inputFrame = new Frame({
|
|
418
|
+
[timeCh.key]: new Series([ts]),
|
|
419
|
+
[extraCh.key]: new Series([999.0]),
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
const result = filterAdapter.adapt(inputFrame);
|
|
423
|
+
|
|
424
|
+
expect(result.columns).toHaveLength(1);
|
|
425
|
+
expect(result.has(timeCh.name)).toBe(true);
|
|
426
|
+
expect(result.has(extraCh.key)).toBe(false);
|
|
427
|
+
expect(result.get(timeCh.name).at(0)).toEqual(ts);
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
it("should return empty frame when no channels match", async () => {
|
|
431
|
+
const filterAdapter = await ReadAdapter.open(client.channels.retriever, [
|
|
432
|
+
timeCh.name,
|
|
433
|
+
]);
|
|
434
|
+
|
|
435
|
+
const inputFrame = new Frame({
|
|
436
|
+
[extraCh.key]: new Series([999.0]),
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
const result = filterAdapter.adapt(inputFrame);
|
|
440
|
+
|
|
441
|
+
expect(result.columns).toHaveLength(0);
|
|
442
|
+
expect(result.series).toHaveLength(0);
|
|
443
|
+
});
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
describe("edge cases", () => {
|
|
448
|
+
it("should handle empty frames", () => {
|
|
449
|
+
const inputFrame = new Frame({});
|
|
450
|
+
|
|
451
|
+
const result = adapter.adapt(inputFrame);
|
|
452
|
+
|
|
453
|
+
expect(result.columns).toHaveLength(0);
|
|
454
|
+
expect(result.series).toHaveLength(0);
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
it("should handle frames with empty series", () => {
|
|
458
|
+
const inputFrame = new Frame({
|
|
459
|
+
[timeCh.key]: new Series({ data: [], dataType: DataType.TIMESTAMP }),
|
|
460
|
+
[dataCh.key]: new Series({ data: [], dataType: DataType.FLOAT32 }),
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
const result = adapter.adapt(inputFrame);
|
|
464
|
+
|
|
465
|
+
expect(result.columns).toHaveLength(2);
|
|
466
|
+
expect(result.get(timeCh.key)).toHaveLength(0);
|
|
467
|
+
expect(result.get(dataCh.key)).toHaveLength(0);
|
|
468
|
+
});
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
describe("data integrity", () => {
|
|
472
|
+
it("should preserve series values across multiple data types", async () => {
|
|
473
|
+
const int64Ch = await client.channels.create({
|
|
474
|
+
name: id.create(),
|
|
475
|
+
dataType: DataType.INT64,
|
|
476
|
+
index: timeCh.key,
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
const testAdapter = await ReadAdapter.open(client.channels.retriever, [
|
|
480
|
+
timeCh.key,
|
|
481
|
+
dataCh.key,
|
|
482
|
+
int64Ch.key,
|
|
483
|
+
]);
|
|
484
|
+
|
|
485
|
+
const ts = TimeStamp.now().valueOf();
|
|
486
|
+
const inputFrame = new Frame({
|
|
487
|
+
[timeCh.key]: new Series([ts, ts + 1000n]),
|
|
488
|
+
[dataCh.key]: new Series([1.5, 2.5]),
|
|
489
|
+
[int64Ch.key]: new Series([100n, 200n]),
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
const result = testAdapter.adapt(inputFrame);
|
|
493
|
+
|
|
494
|
+
// Verify all values preserved
|
|
495
|
+
expect(result.get(timeCh.key).at(0)).toEqual(ts);
|
|
496
|
+
expect(result.get(timeCh.key).at(1)).toEqual(ts + 1000n);
|
|
497
|
+
expect(result.get(dataCh.key).at(0)).toEqual(1.5);
|
|
498
|
+
expect(result.get(dataCh.key).at(1)).toEqual(2.5);
|
|
499
|
+
expect(result.get(int64Ch.key).at(0)).toEqual(100n);
|
|
500
|
+
expect(result.get(int64Ch.key).at(1)).toEqual(200n);
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
it("should preserve series lengths after filtering", () => {
|
|
504
|
+
const ts = TimeStamp.now().valueOf();
|
|
505
|
+
const inputFrame = new Frame({
|
|
506
|
+
[timeCh.key]: new Series([ts, ts + 1000n, ts + 2000n]),
|
|
507
|
+
[dataCh.key]: new Series([1.0, 2.0, 3.0]),
|
|
508
|
+
[extraCh.key]: new Series([999.0, 888.0, 777.0]),
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
const result = adapter.adapt(inputFrame);
|
|
512
|
+
|
|
513
|
+
// Lengths should be preserved for included channels
|
|
514
|
+
expect(result.get(timeCh.key)).toHaveLength(3);
|
|
515
|
+
expect(result.get(dataCh.key)).toHaveLength(3);
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
it("should preserve series order", () => {
|
|
519
|
+
const ts = TimeStamp.now().valueOf();
|
|
520
|
+
// Create frame with explicit column order
|
|
521
|
+
const inputFrame = new Frame(
|
|
522
|
+
[dataCh.key, timeCh.key],
|
|
523
|
+
[new Series([1.0, 2.0, 3.0]), new Series([ts, ts + 1000n, ts + 2000n])],
|
|
524
|
+
);
|
|
525
|
+
|
|
526
|
+
const result = adapter.adapt(inputFrame);
|
|
527
|
+
|
|
528
|
+
// Order should be preserved (dataCh first, then timeCh)
|
|
529
|
+
expect(result.columns[0]).toEqual(dataCh.key);
|
|
530
|
+
expect(result.columns[1]).toEqual(timeCh.key);
|
|
531
|
+
});
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
describe("state management", () => {
|
|
535
|
+
it("should handle multiple sequential updates correctly", async () => {
|
|
536
|
+
// Start with NAME mode to enable filtering
|
|
537
|
+
const newAdapter = await ReadAdapter.open(client.channels.retriever, [
|
|
538
|
+
timeCh.name,
|
|
539
|
+
]);
|
|
540
|
+
|
|
541
|
+
// Initial state: only timeCh registered
|
|
542
|
+
const ts = TimeStamp.now().valueOf();
|
|
543
|
+
const inputFrame = new Frame({
|
|
544
|
+
[timeCh.key]: new Series([ts]),
|
|
545
|
+
[dataCh.key]: new Series([1.5]),
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
// Should filter out dataCh and convert timeCh key to name
|
|
549
|
+
let result = newAdapter.adapt(inputFrame);
|
|
550
|
+
expect(result.columns).toHaveLength(1);
|
|
551
|
+
expect(result.has(timeCh.name)).toBe(true);
|
|
552
|
+
expect(result.has(dataCh.name)).toBe(false);
|
|
553
|
+
|
|
554
|
+
// Update to include dataCh
|
|
555
|
+
await newAdapter.update([timeCh.name, dataCh.name]);
|
|
556
|
+
|
|
557
|
+
// Should now include both channels (converted to names)
|
|
558
|
+
result = newAdapter.adapt(inputFrame);
|
|
559
|
+
expect(result.columns).toHaveLength(2);
|
|
560
|
+
expect(result.has(timeCh.name)).toBe(true);
|
|
561
|
+
expect(result.has(dataCh.name)).toBe(true);
|
|
562
|
+
});
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
describe("codec integration", () => {
|
|
566
|
+
it("should update codec when channels change", async () => {
|
|
567
|
+
const codecAdapter = await ReadAdapter.open(client.channels.retriever, [
|
|
568
|
+
timeCh.key,
|
|
569
|
+
]);
|
|
570
|
+
expect(codecAdapter.keys).toHaveLength(1);
|
|
571
|
+
await codecAdapter.update([timeCh.key, dataCh.key]);
|
|
572
|
+
expect(codecAdapter.keys).toHaveLength(2);
|
|
573
|
+
});
|
|
574
|
+
});
|
|
575
|
+
});
|
|
576
|
+
|
|
239
577
|
describe("update", () => {
|
|
240
578
|
it("should return false when updating with the same channels", async () => {
|
|
241
579
|
const hasChanged = await adapter.update([timeCh.key, dataCh.key]);
|
|
@@ -244,7 +582,7 @@ describe("ReadAdapter", () => {
|
|
|
244
582
|
|
|
245
583
|
it("should return true when adding a new channel", async () => {
|
|
246
584
|
const newCh = await client.channels.create({
|
|
247
|
-
name:
|
|
585
|
+
name: id.create(),
|
|
248
586
|
dataType: DataType.FLOAT32,
|
|
249
587
|
index: timeCh.key,
|
|
250
588
|
});
|
|
@@ -259,7 +597,7 @@ describe("ReadAdapter", () => {
|
|
|
259
597
|
|
|
260
598
|
it("should return true when replacing channels", async () => {
|
|
261
599
|
const newCh = await client.channels.create({
|
|
262
|
-
name:
|
|
600
|
+
name: id.create(),
|
|
263
601
|
dataType: DataType.FLOAT32,
|
|
264
602
|
index: timeCh.key,
|
|
265
603
|
});
|
package/src/framer/adapter.ts
CHANGED
|
@@ -17,13 +17,13 @@ import { type CrudeFrame, Frame } from "@/framer/frame";
|
|
|
17
17
|
export class ReadAdapter {
|
|
18
18
|
private adapter: Map<channel.Key, channel.Name> | null;
|
|
19
19
|
retriever: channel.Retriever;
|
|
20
|
-
keys: channel.Key
|
|
20
|
+
keys: Set<channel.Key>;
|
|
21
21
|
codec: Codec;
|
|
22
22
|
|
|
23
23
|
private constructor(retriever: channel.Retriever) {
|
|
24
24
|
this.retriever = retriever;
|
|
25
25
|
this.adapter = null;
|
|
26
|
-
this.keys =
|
|
26
|
+
this.keys = new Set();
|
|
27
27
|
this.codec = new Codec();
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -40,7 +40,10 @@ export class ReadAdapter {
|
|
|
40
40
|
const { variant, normalized } = channel.analyzeParams(channels);
|
|
41
41
|
const fetched = await this.retriever.retrieve(normalized);
|
|
42
42
|
const newKeys = fetched.map((c) => c.key);
|
|
43
|
-
if (
|
|
43
|
+
if (
|
|
44
|
+
compare.uniqueUnorderedPrimitiveArrays(Array.from(this.keys), newKeys) ===
|
|
45
|
+
compare.EQUAL
|
|
46
|
+
)
|
|
44
47
|
return false;
|
|
45
48
|
this.codec.update(
|
|
46
49
|
newKeys,
|
|
@@ -48,7 +51,7 @@ export class ReadAdapter {
|
|
|
48
51
|
);
|
|
49
52
|
if (variant === "keys") {
|
|
50
53
|
this.adapter = null;
|
|
51
|
-
this.keys = normalized as channel.Key[];
|
|
54
|
+
this.keys = new Set(normalized as channel.Key[]);
|
|
52
55
|
return true;
|
|
53
56
|
}
|
|
54
57
|
const a = new Map<channel.Key, channel.Name>();
|
|
@@ -58,20 +61,27 @@ export class ReadAdapter {
|
|
|
58
61
|
if (channel == null) throw new Error(`Channel ${name} not found`);
|
|
59
62
|
a.set(channel.key, channel.name);
|
|
60
63
|
});
|
|
61
|
-
this.keys =
|
|
64
|
+
this.keys = new Set(this.adapter.keys());
|
|
62
65
|
return true;
|
|
63
66
|
}
|
|
64
67
|
|
|
65
|
-
adapt(
|
|
66
|
-
if (this.adapter == null)
|
|
68
|
+
adapt(frm: Frame): Frame {
|
|
69
|
+
if (this.adapter == null) {
|
|
70
|
+
let shouldFilter = false;
|
|
71
|
+
frm.forEach((k) => {
|
|
72
|
+
if (!this.keys.has(k as channel.Key)) shouldFilter = true;
|
|
73
|
+
});
|
|
74
|
+
if (shouldFilter) return frm.filter((k) => this.keys.has(k as channel.Key));
|
|
75
|
+
return frm;
|
|
76
|
+
}
|
|
67
77
|
const a = this.adapter;
|
|
68
|
-
return
|
|
69
|
-
if (typeof
|
|
70
|
-
const name = a.get(
|
|
71
|
-
if (name == null)
|
|
72
|
-
return [name, arr];
|
|
78
|
+
return frm.mapFilter((col, arr) => {
|
|
79
|
+
if (typeof col === "number") {
|
|
80
|
+
const name = a.get(col);
|
|
81
|
+
if (name == null) return [col, arr, false];
|
|
82
|
+
return [name, arr, true];
|
|
73
83
|
}
|
|
74
|
-
return [
|
|
84
|
+
return [col, arr, true];
|
|
75
85
|
});
|
|
76
86
|
}
|
|
77
87
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
|
-
import { TimeSpan, TimeStamp } from "@synnaxlabs/x";
|
|
10
|
+
import { id, TimeSpan, TimeStamp } from "@synnaxlabs/x";
|
|
11
11
|
import { describe, expect, it } from "vitest";
|
|
12
12
|
|
|
13
13
|
import { createTestClient } from "@/testutil/client";
|
|
@@ -17,14 +17,13 @@ const client = createTestClient();
|
|
|
17
17
|
describe("Client", () => {
|
|
18
18
|
describe("read + write", () => {
|
|
19
19
|
it("should correctly write and read a frame of data", async () => {
|
|
20
|
-
const rand = `${TimeStamp.now().toString()}${Math.random()}`;
|
|
21
20
|
const time = await client.channels.create({
|
|
22
|
-
name:
|
|
21
|
+
name: id.create(),
|
|
23
22
|
dataType: "timestamp",
|
|
24
23
|
isIndex: true,
|
|
25
24
|
});
|
|
26
25
|
const data = await client.channels.create({
|
|
27
|
-
name:
|
|
26
|
+
name: id.create(),
|
|
28
27
|
dataType: "float32",
|
|
29
28
|
index: time.key,
|
|
30
29
|
});
|
|
@@ -38,14 +37,13 @@ describe("Client", () => {
|
|
|
38
37
|
expect(Array.from(frame.get(data.key))).toEqual([1]);
|
|
39
38
|
});
|
|
40
39
|
it("should correctly write a single series of data", async () => {
|
|
41
|
-
const rand = `${TimeStamp.now().toString()}${Math.random()}`;
|
|
42
40
|
const time = await client.channels.create({
|
|
43
|
-
name:
|
|
41
|
+
name: id.create(),
|
|
44
42
|
dataType: "timestamp",
|
|
45
43
|
isIndex: true,
|
|
46
44
|
});
|
|
47
45
|
const data = await client.channels.create({
|
|
48
|
-
name:
|
|
46
|
+
name: id.create(),
|
|
49
47
|
dataType: "float32",
|
|
50
48
|
index: time.key,
|
|
51
49
|
});
|
|
@@ -62,14 +60,13 @@ describe("Client", () => {
|
|
|
62
60
|
});
|
|
63
61
|
describe("readLatestN", () => {
|
|
64
62
|
it("should correctly read the latest N samples from a single channel", async () => {
|
|
65
|
-
const rand = `${TimeStamp.now().toString()}${Math.random()}`;
|
|
66
63
|
const time = await client.channels.create({
|
|
67
|
-
name:
|
|
64
|
+
name: id.create(),
|
|
68
65
|
dataType: "timestamp",
|
|
69
66
|
isIndex: true,
|
|
70
67
|
});
|
|
71
68
|
const data = await client.channels.create({
|
|
72
|
-
name:
|
|
69
|
+
name: id.create(),
|
|
73
70
|
dataType: "float32",
|
|
74
71
|
index: time.key,
|
|
75
72
|
});
|
|
@@ -94,19 +91,18 @@ describe("Client", () => {
|
|
|
94
91
|
});
|
|
95
92
|
|
|
96
93
|
it("should correctly read the latest N samples from multiple channels", async () => {
|
|
97
|
-
const rand = `${TimeStamp.now().toString()}${Math.random()}`;
|
|
98
94
|
const time = await client.channels.create({
|
|
99
|
-
name:
|
|
95
|
+
name: id.create(),
|
|
100
96
|
dataType: "timestamp",
|
|
101
97
|
isIndex: true,
|
|
102
98
|
});
|
|
103
99
|
const data1 = await client.channels.create({
|
|
104
|
-
name:
|
|
100
|
+
name: id.create(),
|
|
105
101
|
dataType: "float32",
|
|
106
102
|
index: time.key,
|
|
107
103
|
});
|
|
108
104
|
const data2 = await client.channels.create({
|
|
109
|
-
name:
|
|
105
|
+
name: id.create(),
|
|
110
106
|
dataType: "float32",
|
|
111
107
|
index: time.key,
|
|
112
108
|
});
|
|
@@ -142,14 +138,13 @@ describe("Client", () => {
|
|
|
142
138
|
});
|
|
143
139
|
|
|
144
140
|
it("should return empty series when no data exists", async () => {
|
|
145
|
-
const rand = `${TimeStamp.now().toString()}${Math.random()}`;
|
|
146
141
|
const time = await client.channels.create({
|
|
147
|
-
name:
|
|
142
|
+
name: id.create(),
|
|
148
143
|
dataType: "timestamp",
|
|
149
144
|
isIndex: true,
|
|
150
145
|
});
|
|
151
146
|
const data = await client.channels.create({
|
|
152
|
-
name:
|
|
147
|
+
name: id.create(),
|
|
153
148
|
dataType: "float32",
|
|
154
149
|
index: time.key,
|
|
155
150
|
});
|
|
@@ -159,14 +154,13 @@ describe("Client", () => {
|
|
|
159
154
|
});
|
|
160
155
|
|
|
161
156
|
it("should correctly handle N larger than available data", async () => {
|
|
162
|
-
const rand = `${TimeStamp.now().toString()}${Math.random()}`;
|
|
163
157
|
const time = await client.channels.create({
|
|
164
|
-
name:
|
|
158
|
+
name: id.create(),
|
|
165
159
|
dataType: "timestamp",
|
|
166
160
|
isIndex: true,
|
|
167
161
|
});
|
|
168
162
|
const data = await client.channels.create({
|
|
169
|
-
name:
|
|
163
|
+
name: id.create(),
|
|
170
164
|
dataType: "float32",
|
|
171
165
|
index: time.key,
|
|
172
166
|
});
|