@synnaxlabs/client 0.38.0 → 0.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +7 -7
- package/dist/access/payload.d.ts +6 -6
- package/dist/access/payload.d.ts.map +1 -1
- package/dist/access/policy/client.d.ts +5 -3
- package/dist/access/policy/client.d.ts.map +1 -1
- package/dist/access/policy/external.d.ts +1 -0
- package/dist/access/policy/external.d.ts.map +1 -1
- package/dist/access/policy/ontology.d.ts +5 -0
- package/dist/access/policy/ontology.d.ts.map +1 -0
- package/dist/access/policy/payload.d.ts +86 -89
- package/dist/access/policy/payload.d.ts.map +1 -1
- package/dist/access/policy/retriever.d.ts +7 -6
- package/dist/access/policy/retriever.d.ts.map +1 -1
- package/dist/access/policy/writer.d.ts +2 -2
- package/dist/access/policy/writer.d.ts.map +1 -1
- package/dist/auth/auth.d.ts +2 -1
- package/dist/auth/auth.d.ts.map +1 -1
- package/dist/channel/client.d.ts +8 -7
- package/dist/channel/client.d.ts.map +1 -1
- package/dist/channel/payload.d.ts +13 -11
- package/dist/channel/payload.d.ts.map +1 -1
- package/dist/channel/retriever.d.ts +9 -6
- package/dist/channel/retriever.d.ts.map +1 -1
- package/dist/channel/writer.d.ts +6 -4
- package/dist/channel/writer.d.ts.map +1 -1
- package/dist/client.cjs +30 -30
- package/dist/client.d.ts +4 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +3488 -3500
- package/dist/connection/checker.d.ts +5 -4
- package/dist/connection/checker.d.ts.map +1 -1
- package/dist/control/state.d.ts +10 -8
- package/dist/control/state.d.ts.map +1 -1
- package/dist/errors.d.ts +5 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/framer/adapter.d.ts +14 -15
- package/dist/framer/adapter.d.ts.map +1 -1
- package/dist/framer/client.d.ts +13 -15
- package/dist/framer/client.d.ts.map +1 -1
- package/dist/framer/deleter.d.ts +3 -2
- package/dist/framer/deleter.d.ts.map +1 -1
- package/dist/framer/frame.d.ts +31 -27
- package/dist/framer/frame.d.ts.map +1 -1
- package/dist/framer/iterator.d.ts +4 -5
- package/dist/framer/iterator.d.ts.map +1 -1
- package/dist/framer/streamer.d.ts +5 -6
- package/dist/framer/streamer.d.ts.map +1 -1
- package/dist/framer/writer.d.ts +42 -39
- package/dist/framer/writer.d.ts.map +1 -1
- package/dist/hardware/device/client.d.ts +17 -12
- package/dist/hardware/device/client.d.ts.map +1 -1
- package/dist/hardware/device/payload.d.ts +19 -16
- package/dist/hardware/device/payload.d.ts.map +1 -1
- package/dist/hardware/rack/client.d.ts +15 -15
- package/dist/hardware/rack/client.d.ts.map +1 -1
- package/dist/hardware/rack/payload.d.ts +9 -8
- package/dist/hardware/rack/payload.d.ts.map +1 -1
- package/dist/hardware/task/client.d.ts +38 -29
- package/dist/hardware/task/client.d.ts.map +1 -1
- package/dist/hardware/task/payload.d.ts +58 -53
- package/dist/hardware/task/payload.d.ts.map +1 -1
- package/dist/label/client.d.ts +4 -3
- package/dist/label/client.d.ts.map +1 -1
- package/dist/label/payload.d.ts +4 -4
- package/dist/label/payload.d.ts.map +1 -1
- package/dist/label/retriever.d.ts.map +1 -1
- package/dist/label/writer.d.ts +13 -10
- package/dist/label/writer.d.ts.map +1 -1
- package/dist/ontology/client.d.ts +12 -10
- package/dist/ontology/client.d.ts.map +1 -1
- package/dist/ontology/group/client.d.ts +5 -4
- package/dist/ontology/group/client.d.ts.map +1 -1
- package/dist/ontology/group/group.d.ts +7 -5
- package/dist/ontology/group/group.d.ts.map +1 -1
- package/dist/ontology/group/payload.d.ts +6 -5
- package/dist/ontology/group/payload.d.ts.map +1 -1
- package/dist/ontology/group/writer.d.ts +8 -8
- package/dist/ontology/group/writer.d.ts.map +1 -1
- package/dist/ontology/payload.d.ts +72 -62
- package/dist/ontology/payload.d.ts.map +1 -1
- package/dist/ontology/writer.d.ts.map +1 -1
- package/dist/ranger/alias.d.ts +9 -10
- package/dist/ranger/alias.d.ts.map +1 -1
- package/dist/ranger/client.d.ts +18 -18
- package/dist/ranger/client.d.ts.map +1 -1
- package/dist/ranger/external.d.ts +1 -1
- package/dist/ranger/external.d.ts.map +1 -1
- package/dist/ranger/kv.d.ts +18 -14
- package/dist/ranger/kv.d.ts.map +1 -1
- package/dist/ranger/payload.d.ts +13 -13
- package/dist/ranger/payload.d.ts.map +1 -1
- package/dist/ranger/writer.d.ts +14 -14
- package/dist/ranger/writer.d.ts.map +1 -1
- package/dist/setupspecs.d.ts.map +1 -1
- package/dist/signals/observable.d.ts +3 -1
- package/dist/signals/observable.d.ts.map +1 -1
- package/dist/user/client.d.ts +5 -3
- package/dist/user/client.d.ts.map +1 -1
- package/dist/user/payload.d.ts +7 -6
- package/dist/user/payload.d.ts.map +1 -1
- package/dist/user/retriever.d.ts +2 -1
- package/dist/user/retriever.d.ts.map +1 -1
- package/dist/user/writer.d.ts +2 -2
- package/dist/user/writer.d.ts.map +1 -1
- package/dist/util/decodeJSONString.d.ts +3 -0
- package/dist/util/decodeJSONString.d.ts.map +1 -0
- package/dist/util/parseWithoutKeyConversion.d.ts +3 -0
- package/dist/util/parseWithoutKeyConversion.d.ts.map +1 -0
- package/dist/util/retrieve.d.ts +1 -1
- package/dist/util/retrieve.d.ts.map +1 -1
- package/dist/util/telem.d.ts.map +1 -1
- package/dist/util/zod.d.ts.map +1 -1
- package/dist/workspace/client.d.ts +6 -60
- package/dist/workspace/client.d.ts.map +1 -1
- package/dist/workspace/external.d.ts +3 -0
- package/dist/workspace/external.d.ts.map +1 -0
- package/dist/workspace/index.d.ts +1 -1
- package/dist/workspace/index.d.ts.map +1 -1
- package/dist/workspace/lineplot/client.d.ts +5 -44
- package/dist/workspace/lineplot/client.d.ts.map +1 -1
- package/dist/workspace/lineplot/external.d.ts +3 -0
- package/dist/workspace/lineplot/external.d.ts.map +1 -0
- package/dist/workspace/lineplot/index.d.ts +1 -1
- package/dist/workspace/lineplot/index.d.ts.map +1 -1
- package/dist/workspace/lineplot/payload.d.ts +45 -0
- package/dist/workspace/lineplot/payload.d.ts.map +1 -0
- package/dist/workspace/log/client.d.ts +5 -44
- package/dist/workspace/log/client.d.ts.map +1 -1
- package/dist/workspace/log/external.d.ts +3 -0
- package/dist/workspace/log/external.d.ts.map +1 -0
- package/dist/workspace/log/index.d.ts +1 -1
- package/dist/workspace/log/index.d.ts.map +1 -1
- package/dist/workspace/log/payload.d.ts +45 -0
- package/dist/workspace/log/payload.d.ts.map +1 -0
- package/dist/workspace/payload.d.ts +60 -0
- package/dist/workspace/payload.d.ts.map +1 -0
- package/dist/workspace/schematic/client.d.ts +5 -68
- package/dist/workspace/schematic/client.d.ts.map +1 -1
- package/dist/workspace/schematic/external.d.ts +3 -0
- package/dist/workspace/schematic/external.d.ts.map +1 -0
- package/dist/workspace/schematic/index.d.ts +1 -1
- package/dist/workspace/schematic/index.d.ts.map +1 -1
- package/dist/workspace/schematic/payload.d.ts +71 -0
- package/dist/workspace/schematic/payload.d.ts.map +1 -0
- package/dist/workspace/table/client.d.ts +5 -57
- package/dist/workspace/table/client.d.ts.map +1 -1
- package/dist/workspace/table/external.d.ts +3 -0
- package/dist/workspace/table/external.d.ts.map +1 -0
- package/dist/workspace/table/index.d.ts +1 -1
- package/dist/workspace/table/index.d.ts.map +1 -1
- package/dist/workspace/table/payload.d.ts +60 -0
- package/dist/workspace/table/payload.d.ts.map +1 -0
- package/eslint.config.js +1 -1
- package/examples/node/basicReadWrite.js +27 -27
- package/examples/node/liveStream.js +16 -16
- package/examples/node/seriesAndFrames.js +39 -39
- package/examples/node/streamWrite.js +48 -46
- package/package.json +14 -12
- package/src/access/client.ts +1 -1
- package/src/access/external.ts +1 -1
- package/src/access/index.ts +1 -1
- package/src/access/payload.ts +13 -13
- package/src/access/policy/client.ts +14 -13
- package/src/access/policy/external.ts +2 -1
- package/src/access/policy/index.ts +1 -1
- package/src/access/policy/ontology.ts +17 -0
- package/src/access/policy/payload.ts +8 -20
- package/src/access/policy/policy.spec.ts +17 -17
- package/src/access/policy/retriever.ts +3 -2
- package/src/access/policy/writer.ts +5 -5
- package/src/auth/auth.spec.ts +28 -24
- package/src/auth/auth.ts +8 -12
- package/src/auth/index.ts +1 -1
- package/src/channel/batchRetriever.spec.ts +26 -23
- package/src/channel/channel.spec.ts +1 -1
- package/src/channel/client.ts +24 -24
- package/src/channel/external.ts +1 -1
- package/src/channel/index.ts +1 -1
- package/src/channel/payload.ts +17 -21
- package/src/channel/retriever.ts +21 -22
- package/src/channel/writer.ts +12 -14
- package/src/client.ts +7 -17
- package/src/connection/checker.ts +10 -12
- package/src/connection/connection.spec.ts +18 -6
- package/src/connection/index.ts +1 -1
- package/src/control/client.ts +1 -1
- package/src/control/external.ts +1 -1
- package/src/control/index.ts +1 -1
- package/src/control/state.spec.ts +1 -1
- package/src/control/state.ts +9 -10
- package/src/errors.spec.ts +2 -2
- package/src/errors.ts +9 -1
- package/src/framer/adapter.spec.ts +29 -24
- package/src/framer/adapter.ts +38 -42
- package/src/framer/client.spec.ts +6 -12
- package/src/framer/client.ts +35 -39
- package/src/framer/deleter.spec.ts +1 -1
- package/src/framer/deleter.ts +6 -7
- package/src/framer/external.ts +1 -1
- package/src/framer/frame.spec.ts +1 -1
- package/src/framer/frame.ts +63 -51
- package/src/framer/index.ts +1 -1
- package/src/framer/iterator.spec.ts +1 -1
- package/src/framer/iterator.ts +12 -17
- package/src/framer/streamProxy.ts +2 -2
- package/src/framer/streamer.spec.ts +3 -11
- package/src/framer/streamer.ts +16 -20
- package/src/framer/writer.spec.ts +49 -8
- package/src/framer/writer.ts +40 -32
- package/src/hardware/client.ts +1 -1
- package/src/hardware/device/client.ts +65 -40
- package/src/hardware/device/device.spec.ts +50 -34
- package/src/hardware/device/external.ts +1 -1
- package/src/hardware/device/index.ts +1 -1
- package/src/hardware/device/payload.ts +30 -30
- package/src/hardware/external.ts +1 -1
- package/src/hardware/index.ts +1 -1
- package/src/hardware/rack/client.ts +53 -66
- package/src/hardware/rack/external.ts +1 -1
- package/src/hardware/rack/index.ts +1 -1
- package/src/hardware/rack/payload.ts +10 -19
- package/src/hardware/rack/rack.spec.ts +13 -1
- package/src/hardware/task/client.ts +161 -132
- package/src/hardware/task/external.ts +1 -1
- package/src/hardware/task/index.ts +1 -1
- package/src/hardware/task/payload.ts +50 -69
- package/src/hardware/task/task.spec.ts +99 -82
- package/src/index.ts +1 -1
- package/src/label/client.ts +13 -16
- package/src/label/external.ts +1 -1
- package/src/label/index.ts +1 -1
- package/src/label/label.spec.ts +1 -1
- package/src/label/payload.ts +4 -10
- package/src/label/retriever.ts +4 -8
- package/src/label/writer.ts +9 -16
- package/src/ontology/client.ts +31 -29
- package/src/ontology/external.ts +1 -1
- package/src/ontology/group/client.ts +6 -6
- package/src/ontology/group/external.ts +1 -1
- package/src/ontology/group/group.spec.ts +5 -5
- package/src/ontology/group/group.ts +11 -8
- package/src/ontology/group/index.ts +1 -1
- package/src/ontology/group/payload.ts +12 -36
- package/src/ontology/group/writer.ts +23 -27
- package/src/ontology/index.ts +1 -1
- package/src/ontology/ontology.spec.ts +16 -16
- package/src/ontology/payload.ts +68 -44
- package/src/ontology/writer.ts +17 -24
- package/src/ranger/alias.ts +26 -43
- package/src/ranger/client.ts +34 -41
- package/src/ranger/external.ts +2 -2
- package/src/ranger/index.ts +1 -1
- package/src/ranger/kv.ts +10 -33
- package/src/ranger/payload.ts +15 -37
- package/src/ranger/ranger.spec.ts +2 -3
- package/src/ranger/writer.ts +9 -27
- package/src/setupspecs.ts +1 -1
- package/src/signals/external.ts +1 -1
- package/src/signals/index.ts +1 -1
- package/src/signals/observable.ts +4 -5
- package/src/transport.ts +1 -1
- package/src/user/client.ts +9 -5
- package/src/user/external.ts +1 -1
- package/src/user/index.ts +1 -1
- package/src/user/payload.ts +6 -10
- package/src/user/retriever.ts +2 -2
- package/src/user/user.spec.ts +18 -16
- package/src/user/writer.ts +4 -11
- package/src/util/decodeJSONString.ts +13 -0
- package/src/util/parseWithoutKeyConversion.ts +19 -0
- package/src/util/retrieve.spec.ts +4 -14
- package/src/util/retrieve.ts +3 -13
- package/src/util/telem.ts +2 -2
- package/src/util/zod.ts +1 -1
- package/src/vite-env.d.ts +2 -1
- package/src/workspace/client.ts +39 -57
- package/src/workspace/external.ts +11 -0
- package/src/workspace/index.ts +2 -2
- package/src/workspace/lineplot/client.ts +31 -36
- package/src/workspace/lineplot/external.ts +11 -0
- package/src/workspace/lineplot/index.ts +2 -2
- package/src/workspace/lineplot/linePlot.spec.ts +2 -3
- package/src/workspace/lineplot/payload.ts +32 -0
- package/src/workspace/log/client.ts +34 -39
- package/src/workspace/log/external.ts +11 -0
- package/src/workspace/log/index.ts +2 -2
- package/src/workspace/log/log.spec.ts +6 -19
- package/src/workspace/log/payload.ts +32 -0
- package/src/workspace/payload.ts +36 -0
- package/src/workspace/schematic/client.ts +39 -56
- package/src/workspace/schematic/external.ts +11 -0
- package/src/workspace/schematic/index.ts +2 -2
- package/src/workspace/schematic/payload.ts +37 -0
- package/src/workspace/schematic/schematic.spec.ts +16 -7
- package/src/workspace/table/client.ts +36 -50
- package/src/workspace/table/external.ts +11 -0
- package/src/workspace/table/index.ts +2 -2
- package/src/workspace/table/payload.ts +36 -0
- package/src/workspace/table/table.spec.ts +1 -1
- package/src/workspace/workspace.spec.ts +2 -3
- package/vite.config.ts +1 -1
- package/dist/channel/creator.d.ts +0 -9
- package/dist/channel/creator.d.ts.map +0 -1
- package/src/channel/creator.ts +0 -37
package/src/framer/frame.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Use of this software is governed by the Business Source License included in the file
|
|
4
4
|
// licenses/BSL.txt.
|
|
@@ -20,20 +20,17 @@ import {
|
|
|
20
20
|
} from "@synnaxlabs/x/telem";
|
|
21
21
|
import { z } from "zod";
|
|
22
22
|
|
|
23
|
-
import {
|
|
24
|
-
type Key,
|
|
25
|
-
type KeyOrName,
|
|
26
|
-
type Keys,
|
|
27
|
-
type Names,
|
|
28
|
-
type Params,
|
|
29
|
-
} from "@/channel/payload";
|
|
23
|
+
import { type channel } from "@/channel";
|
|
30
24
|
import { UnexpectedError, ValidationError } from "@/errors";
|
|
31
25
|
|
|
26
|
+
export const ONTOLOGY_TYPE = "framer";
|
|
27
|
+
export type OntologyType = typeof ONTOLOGY_TYPE;
|
|
28
|
+
|
|
32
29
|
type ColumnType = "key" | "name" | null;
|
|
33
30
|
|
|
34
|
-
export interface
|
|
31
|
+
export interface Digest extends Record<channel.KeyOrName, SeriesDigest[]> {}
|
|
35
32
|
|
|
36
|
-
const columnType = (columns: Params): ColumnType => {
|
|
33
|
+
const columnType = (columns: channel.Params): ColumnType => {
|
|
37
34
|
const arrKeys = toArray(columns);
|
|
38
35
|
if (arrKeys.length === 0) return null;
|
|
39
36
|
if (typeof arrKeys[0] === "number") return "key";
|
|
@@ -41,7 +38,10 @@ const columnType = (columns: Params): ColumnType => {
|
|
|
41
38
|
return "name";
|
|
42
39
|
};
|
|
43
40
|
|
|
44
|
-
const validateMatchedColsAndSeries = (
|
|
41
|
+
const validateMatchedColsAndSeries = (
|
|
42
|
+
columns: channel.Params,
|
|
43
|
+
series: Series[],
|
|
44
|
+
): void => {
|
|
45
45
|
const colsArr = toArray(columns);
|
|
46
46
|
if (colsArr.length === series.length) return;
|
|
47
47
|
const colType = columnType(columns);
|
|
@@ -55,11 +55,11 @@ const validateMatchedColsAndSeries = (columns: Params, series: Series[]): void =
|
|
|
55
55
|
);
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
-
export type
|
|
58
|
+
export type Crude =
|
|
59
59
|
| Frame
|
|
60
|
-
|
|
|
61
|
-
| Map<KeyOrName, Series[] | Series>
|
|
62
|
-
| Record<KeyOrName, Series[] | Series>;
|
|
60
|
+
| CrudePayload
|
|
61
|
+
| Map<channel.KeyOrName, Series[] | Series>
|
|
62
|
+
| Record<channel.KeyOrName, Series[] | Series>;
|
|
63
63
|
|
|
64
64
|
/**
|
|
65
65
|
* A frame is a collection of series mapped to a particular channel. Frames
|
|
@@ -97,10 +97,13 @@ export type CrudeFrame =
|
|
|
97
97
|
* and array can be square.
|
|
98
98
|
*/
|
|
99
99
|
export class Frame {
|
|
100
|
-
readonly columns: Keys | Names = [];
|
|
100
|
+
readonly columns: channel.Keys | channel.Names = [];
|
|
101
101
|
readonly series: Series[] = [];
|
|
102
102
|
|
|
103
|
-
constructor(
|
|
103
|
+
constructor(
|
|
104
|
+
columnsOrData: channel.Params | Crude = [],
|
|
105
|
+
series: Series | Series[] = [],
|
|
106
|
+
) {
|
|
104
107
|
if (columnsOrData instanceof Frame) {
|
|
105
108
|
this.columns = columnsOrData.columns;
|
|
106
109
|
this.series = columnsOrData.series;
|
|
@@ -118,7 +121,7 @@ export class Frame {
|
|
|
118
121
|
// Construction from a payload.
|
|
119
122
|
if (isObject) {
|
|
120
123
|
if ("keys" in columnsOrData && "series" in columnsOrData) {
|
|
121
|
-
const data_ = columnsOrData as
|
|
124
|
+
const data_ = columnsOrData as Payload;
|
|
122
125
|
data_.series ??= [];
|
|
123
126
|
data_.keys ??= [];
|
|
124
127
|
const series = data_.series.map((a) => seriesFromPayload(a));
|
|
@@ -139,7 +142,7 @@ export class Frame {
|
|
|
139
142
|
["string", "number"].includes(typeof columnsOrData)
|
|
140
143
|
) {
|
|
141
144
|
const data_ = toArray(series);
|
|
142
|
-
const cols = toArray(columnsOrData) as Keys | Names;
|
|
145
|
+
const cols = toArray(columnsOrData) as channel.Keys | channel.Names;
|
|
143
146
|
validateMatchedColsAndSeries(cols, data_);
|
|
144
147
|
data_.forEach((d, i) => this.push(cols[i], d));
|
|
145
148
|
return;
|
|
@@ -166,16 +169,16 @@ export class Frame {
|
|
|
166
169
|
* @returns the channel keys if the frame is keyed by channel key, and throws an error
|
|
167
170
|
* otherwise.
|
|
168
171
|
*/
|
|
169
|
-
get keys(): Keys {
|
|
172
|
+
get keys(): channel.Keys {
|
|
170
173
|
if (this.colType === "name") throw new UnexpectedError("colType is not key");
|
|
171
|
-
return (this.columns as Keys) ?? [];
|
|
174
|
+
return (this.columns as channel.Keys) ?? [];
|
|
172
175
|
}
|
|
173
176
|
|
|
174
177
|
/**
|
|
175
178
|
* @returns the unique channel keys if the frame is keyed by channel key, and throws an
|
|
176
179
|
* error otherwise.
|
|
177
180
|
*/
|
|
178
|
-
get uniqueKeys(): Keys {
|
|
181
|
+
get uniqueKeys(): channel.Keys {
|
|
179
182
|
return unique.unique(this.keys);
|
|
180
183
|
}
|
|
181
184
|
|
|
@@ -183,27 +186,27 @@ export class Frame {
|
|
|
183
186
|
* @returns the channel names if the frame is keyed by channel name, and throws an error
|
|
184
187
|
* otherwise.
|
|
185
188
|
*/
|
|
186
|
-
get names(): Names {
|
|
189
|
+
get names(): channel.Names {
|
|
187
190
|
if (this.colType === "key") throw new UnexpectedError("colType is not name");
|
|
188
|
-
return (this.columns as Names) ?? [];
|
|
191
|
+
return (this.columns as channel.Names) ?? [];
|
|
189
192
|
}
|
|
190
193
|
|
|
191
194
|
/**
|
|
192
195
|
* @returns the unique channel names if the frame is keyed by channel name, and throws an
|
|
193
196
|
* otherwise.
|
|
194
197
|
*/
|
|
195
|
-
get uniqueNames(): Names {
|
|
198
|
+
get uniqueNames(): channel.Names {
|
|
196
199
|
return unique.unique(this.names);
|
|
197
200
|
}
|
|
198
201
|
|
|
199
202
|
/**
|
|
200
203
|
* @returns the unique columns in the frame.
|
|
201
204
|
*/
|
|
202
|
-
get uniqueColumns(): Keys | Names {
|
|
205
|
+
get uniqueColumns(): channel.Keys | channel.Names {
|
|
203
206
|
return this.colType === "key" ? this.uniqueKeys : this.uniqueNames;
|
|
204
207
|
}
|
|
205
208
|
|
|
206
|
-
toPayload():
|
|
209
|
+
toPayload(): Payload {
|
|
207
210
|
return {
|
|
208
211
|
series: this.series.map((a) => seriesToPayload(a)),
|
|
209
212
|
keys: this.keys,
|
|
@@ -249,7 +252,7 @@ export class Frame {
|
|
|
249
252
|
return ranges.every((tr) => tr.equals(ranges[0]));
|
|
250
253
|
}
|
|
251
254
|
|
|
252
|
-
timeRange(col?: KeyOrName): TimeRange {
|
|
255
|
+
timeRange(col?: channel.KeyOrName): TimeRange {
|
|
253
256
|
if (col == null) {
|
|
254
257
|
if (this.columns.length === 0) return TimeRange.ZERO;
|
|
255
258
|
const start = TimeStamp.min(...this.series.map((a) => a.timeRange.start));
|
|
@@ -273,16 +276,17 @@ export class Frame {
|
|
|
273
276
|
* @returns lazy series matching the given channel key or name.
|
|
274
277
|
* @param key the channel key or name.
|
|
275
278
|
*/
|
|
276
|
-
get(key: KeyOrName): MultiSeries;
|
|
279
|
+
get(key: channel.KeyOrName): MultiSeries;
|
|
277
280
|
|
|
278
281
|
/**
|
|
279
282
|
* @returns a frame with the given channel keys or names.
|
|
280
283
|
* @param keys the channel keys or names.
|
|
281
284
|
*/
|
|
282
|
-
get(keys: Keys | Names): Frame;
|
|
285
|
+
get(keys: channel.Keys | channel.Names): Frame;
|
|
283
286
|
|
|
284
|
-
get(key: KeyOrName | Keys | Names): MultiSeries | Frame {
|
|
285
|
-
if (Array.isArray(key))
|
|
287
|
+
get(key: channel.KeyOrName | channel.Keys | channel.Names): MultiSeries | Frame {
|
|
288
|
+
if (Array.isArray(key))
|
|
289
|
+
return this.filter((k) => (key as channel.Keys).includes(k as channel.Key));
|
|
286
290
|
return new MultiSeries(this.series.filter((_, i) => this.columns[i] === key));
|
|
287
291
|
}
|
|
288
292
|
|
|
@@ -292,7 +296,7 @@ export class Frame {
|
|
|
292
296
|
* @param key the channel key or name;
|
|
293
297
|
* @param v the series to push.
|
|
294
298
|
*/
|
|
295
|
-
push(key: KeyOrName, ...v: Series[]): void;
|
|
299
|
+
push(key: channel.KeyOrName, ...v: Series[]): void;
|
|
296
300
|
|
|
297
301
|
/**
|
|
298
302
|
* Pushes the frame onto the current frame.
|
|
@@ -301,20 +305,20 @@ export class Frame {
|
|
|
301
305
|
*/
|
|
302
306
|
push(frame: Frame): void;
|
|
303
307
|
|
|
304
|
-
push(keyOrFrame: KeyOrName | Frame, ...v: Series[]): void {
|
|
308
|
+
push(keyOrFrame: channel.KeyOrName | Frame, ...v: Series[]): void {
|
|
305
309
|
if (keyOrFrame instanceof Frame) {
|
|
306
310
|
if (this.colType !== null && keyOrFrame.colType !== this.colType)
|
|
307
311
|
throw new ValidationError("keyVariant must match");
|
|
308
312
|
this.series.push(...keyOrFrame.series);
|
|
309
|
-
(this.columns as Keys).push(...(keyOrFrame.columns as Keys));
|
|
313
|
+
(this.columns as channel.Keys).push(...(keyOrFrame.columns as channel.Keys));
|
|
310
314
|
} else {
|
|
311
315
|
this.series.push(...v);
|
|
312
316
|
if (typeof keyOrFrame === "string" && this.colType === "key")
|
|
313
317
|
throw new ValidationError("keyVariant must match");
|
|
314
318
|
else if (typeof keyOrFrame !== "string" && this.colType === "name")
|
|
315
319
|
throw new ValidationError("keyVariant must match");
|
|
316
|
-
(this.columns as Keys).push(
|
|
317
|
-
...(Array.from({ length: v.length }, () => keyOrFrame) as Keys),
|
|
320
|
+
(this.columns as channel.Keys).push(
|
|
321
|
+
...(Array.from({ length: v.length }, () => keyOrFrame) as channel.Keys),
|
|
318
322
|
);
|
|
319
323
|
}
|
|
320
324
|
}
|
|
@@ -324,7 +328,7 @@ export class Frame {
|
|
|
324
328
|
* provided frame.
|
|
325
329
|
*/
|
|
326
330
|
concat(frame: Frame): Frame {
|
|
327
|
-
return new Frame([...this.columns, ...frame.columns] as Keys, [
|
|
331
|
+
return new Frame([...this.columns, ...frame.columns] as channel.Keys, [
|
|
328
332
|
...this.series,
|
|
329
333
|
...frame.series,
|
|
330
334
|
]);
|
|
@@ -334,10 +338,10 @@ export class Frame {
|
|
|
334
338
|
* @returns true if the frame contains the provided channel key or name.
|
|
335
339
|
* @param channel the channel key or name to check.
|
|
336
340
|
*/
|
|
337
|
-
has(channel: KeyOrName): boolean {
|
|
341
|
+
has(channel: channel.KeyOrName): boolean {
|
|
338
342
|
if (typeof channel === "string" && this.colType === "key") return false;
|
|
339
343
|
if (typeof channel === "number" && this.colType === "name") return false;
|
|
340
|
-
return (this.columns as Keys).includes(channel as Key);
|
|
344
|
+
return (this.columns as channel.Keys).includes(channel as channel.Key);
|
|
341
345
|
}
|
|
342
346
|
|
|
343
347
|
/**
|
|
@@ -345,7 +349,9 @@ export class Frame {
|
|
|
345
349
|
* @param fn a function that takes a channel key and series and returns a
|
|
346
350
|
* boolean.
|
|
347
351
|
*/
|
|
348
|
-
map(
|
|
352
|
+
map(
|
|
353
|
+
fn: (k: channel.KeyOrName, arr: Series, i: number) => [channel.KeyOrName, Series],
|
|
354
|
+
): Frame {
|
|
349
355
|
const frame = new Frame();
|
|
350
356
|
this.forEach((k, arr, i) => frame.push(...fn(k, arr, i)));
|
|
351
357
|
return frame;
|
|
@@ -356,19 +362,25 @@ export class Frame {
|
|
|
356
362
|
*
|
|
357
363
|
* @param fn a function that takes a channel key and series.
|
|
358
364
|
*/
|
|
359
|
-
forEach(fn: (k: KeyOrName, arr: Series, i: number) => void): void {
|
|
365
|
+
forEach(fn: (k: channel.KeyOrName, arr: Series, i: number) => void): void {
|
|
360
366
|
this.columns.forEach((k, i) => {
|
|
361
367
|
const a = this.series[i];
|
|
362
368
|
fn(k, a, i);
|
|
363
369
|
});
|
|
364
370
|
}
|
|
365
371
|
|
|
366
|
-
at(index: number, required: true): Record<KeyOrName, TelemValue>;
|
|
372
|
+
at(index: number, required: true): Record<channel.KeyOrName, TelemValue>;
|
|
367
373
|
|
|
368
|
-
at(
|
|
374
|
+
at(
|
|
375
|
+
index: number,
|
|
376
|
+
required?: false,
|
|
377
|
+
): Record<channel.KeyOrName, TelemValue | undefined>;
|
|
369
378
|
|
|
370
|
-
at(
|
|
371
|
-
|
|
379
|
+
at(
|
|
380
|
+
index: number,
|
|
381
|
+
required = false,
|
|
382
|
+
): Record<channel.KeyOrName, TelemValue | undefined> {
|
|
383
|
+
const res: Record<channel.KeyOrName, TelemValue> = {};
|
|
372
384
|
this.uniqueColumns.forEach((k) => {
|
|
373
385
|
res[k] = this.get(k).at(index, required as true);
|
|
374
386
|
});
|
|
@@ -380,7 +392,7 @@ export class Frame {
|
|
|
380
392
|
* the provided filter function.
|
|
381
393
|
* @param fn a function that takes a channel key and series and returns a boolean.
|
|
382
394
|
*/
|
|
383
|
-
filter(fn: (k: KeyOrName, arr: Series, i: number) => boolean): Frame {
|
|
395
|
+
filter(fn: (k: channel.KeyOrName, arr: Series, i: number) => boolean): Frame {
|
|
384
396
|
const frame = new Frame();
|
|
385
397
|
this.columns.forEach((k, i) => {
|
|
386
398
|
const a = this.series[i];
|
|
@@ -398,8 +410,8 @@ export class Frame {
|
|
|
398
410
|
* @returns a digest of information about the structure of the frame for debugging
|
|
399
411
|
* purposes.
|
|
400
412
|
*/
|
|
401
|
-
get digest():
|
|
402
|
-
const digest:
|
|
413
|
+
get digest(): Digest {
|
|
414
|
+
const digest: Digest = {};
|
|
403
415
|
this.keys.forEach((k, i) => {
|
|
404
416
|
const sd = this.series[i].digest;
|
|
405
417
|
if (k in digest) digest[k].push(sd);
|
|
@@ -425,9 +437,9 @@ export const frameZ = z.object({
|
|
|
425
437
|
]),
|
|
426
438
|
});
|
|
427
439
|
|
|
428
|
-
export
|
|
440
|
+
export interface Payload extends z.output<typeof frameZ> {}
|
|
429
441
|
|
|
430
|
-
export
|
|
442
|
+
export interface CrudePayload extends z.input<typeof frameZ> {}
|
|
431
443
|
|
|
432
444
|
export const seriesFromPayload = (series: SeriesPayload): Series => {
|
|
433
445
|
const { dataType, data, timeRange, alignment } = series;
|
package/src/framer/index.ts
CHANGED
package/src/framer/iterator.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Use of this software is governed by the Business Source License included in the file
|
|
4
4
|
// licenses/BSL.txt.
|
|
@@ -18,9 +18,8 @@ import {
|
|
|
18
18
|
} from "@synnaxlabs/x/telem";
|
|
19
19
|
import { z } from "zod";
|
|
20
20
|
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import { ReadFrameAdapter } from "@/framer/adapter";
|
|
21
|
+
import { channel } from "@/channel";
|
|
22
|
+
import { ReadAdapter } from "@/framer/adapter";
|
|
24
23
|
import { Frame, frameZ } from "@/framer/frame";
|
|
25
24
|
import { StreamProxy } from "@/framer/streamProxy";
|
|
26
25
|
|
|
@@ -49,11 +48,10 @@ const reqZ = z.object({
|
|
|
49
48
|
span: TimeSpan.z.optional(),
|
|
50
49
|
bounds: TimeRange.z.optional(),
|
|
51
50
|
stamp: TimeStamp.z.optional(),
|
|
52
|
-
keys:
|
|
51
|
+
keys: channel.keyZ.array().optional(),
|
|
53
52
|
chunkSize: z.number().optional(),
|
|
54
53
|
});
|
|
55
|
-
|
|
56
|
-
type Request = z.infer<typeof reqZ>;
|
|
54
|
+
interface Request extends z.infer<typeof reqZ> {}
|
|
57
55
|
|
|
58
56
|
const resZ = z.object({
|
|
59
57
|
variant: z.nativeEnum(ResponseVariant),
|
|
@@ -65,8 +63,8 @@ const resZ = z.object({
|
|
|
65
63
|
|
|
66
64
|
export interface IteratorConfig {
|
|
67
65
|
/** chunkSize is the maximum number of samples contained per channel in the frame
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
* resulting from a call to next with {@link AUTO_SPAN}.
|
|
67
|
+
*/
|
|
70
68
|
chunkSize?: number;
|
|
71
69
|
}
|
|
72
70
|
|
|
@@ -81,13 +79,10 @@ export interface IteratorConfig {
|
|
|
81
79
|
export class Iterator {
|
|
82
80
|
private static readonly ENDPOINT = "/frame/iterate";
|
|
83
81
|
private readonly stream: StreamProxy<typeof reqZ, typeof resZ>;
|
|
84
|
-
private readonly adapter:
|
|
82
|
+
private readonly adapter: ReadAdapter;
|
|
85
83
|
value: Frame;
|
|
86
84
|
|
|
87
|
-
private constructor(
|
|
88
|
-
stream: Stream<typeof reqZ, typeof resZ>,
|
|
89
|
-
adapter: ReadFrameAdapter,
|
|
90
|
-
) {
|
|
85
|
+
private constructor(stream: Stream<typeof reqZ, typeof resZ>, adapter: ReadAdapter) {
|
|
91
86
|
this.stream = new StreamProxy("Iterator", stream);
|
|
92
87
|
this.value = new Frame();
|
|
93
88
|
this.adapter = adapter;
|
|
@@ -106,12 +101,12 @@ export class Iterator {
|
|
|
106
101
|
*/
|
|
107
102
|
static async _open(
|
|
108
103
|
tr: CrudeTimeRange,
|
|
109
|
-
channels: Params,
|
|
110
|
-
retriever: Retriever,
|
|
104
|
+
channels: channel.Params,
|
|
105
|
+
retriever: channel.Retriever,
|
|
111
106
|
client: StreamClient,
|
|
112
107
|
opts: IteratorConfig = {},
|
|
113
108
|
): Promise<Iterator> {
|
|
114
|
-
const adapter = await
|
|
109
|
+
const adapter = await ReadAdapter.open(retriever, channels);
|
|
115
110
|
const stream = await client.stream(Iterator.ENDPOINT, reqZ, resZ);
|
|
116
111
|
const iter = new Iterator(stream, adapter);
|
|
117
112
|
await iter.execute({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Use of this software is governed by the Business Source License included in the file
|
|
4
4
|
// licenses/BSL.txt.
|
|
@@ -35,7 +35,7 @@ export class StreamProxy<RQ extends z.ZodTypeAny, RS extends z.ZodTypeAny> {
|
|
|
35
35
|
const [res, err] = await this.stream.receive();
|
|
36
36
|
if (res != null)
|
|
37
37
|
console.warn(
|
|
38
|
-
`${this.name} received unexpected response on closure.
|
|
38
|
+
`${this.name} received unexpected response on closure.
|
|
39
39
|
Please report this error to the Synnax team. ${JSON.stringify(res)}`,
|
|
40
40
|
);
|
|
41
41
|
if (err != null) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Use of this software is governed by the Business Source License included in the file
|
|
4
4
|
// licenses/BSL.txt.
|
|
@@ -239,16 +239,8 @@ describe("Streamer - Calculated Channels", () => {
|
|
|
239
239
|
|
|
240
240
|
// Create source channels
|
|
241
241
|
const [channelA, channelB] = await client.channels.create([
|
|
242
|
-
{
|
|
243
|
-
|
|
244
|
-
dataType: DataType.FLOAT64,
|
|
245
|
-
index: timeChannel.key,
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
name: "multi_test_b",
|
|
249
|
-
dataType: DataType.FLOAT64,
|
|
250
|
-
index: timeChannel.key,
|
|
251
|
-
},
|
|
242
|
+
{ name: "multi_test_a", dataType: DataType.FLOAT64, index: timeChannel.key },
|
|
243
|
+
{ name: "multi_test_b", dataType: DataType.FLOAT64, index: timeChannel.key },
|
|
252
244
|
]);
|
|
253
245
|
|
|
254
246
|
// Create calculated channel with multiple operations
|
package/src/framer/streamer.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Use of this software is governed by the Business Source License included in the file
|
|
4
4
|
// licenses/BSL.txt.
|
|
@@ -11,50 +11,43 @@ import { EOF, errorZ, type Stream, type StreamClient } from "@synnaxlabs/freight
|
|
|
11
11
|
import { observe } from "@synnaxlabs/x";
|
|
12
12
|
import { z } from "zod";
|
|
13
13
|
|
|
14
|
-
import { type
|
|
15
|
-
import {
|
|
16
|
-
import { ReadFrameAdapter } from "@/framer/adapter";
|
|
14
|
+
import { type channel } from "@/channel";
|
|
15
|
+
import { ReadAdapter } from "@/framer/adapter";
|
|
17
16
|
import { Frame, frameZ } from "@/framer/frame";
|
|
18
17
|
import { StreamProxy } from "@/framer/streamProxy";
|
|
19
18
|
|
|
20
|
-
const reqZ = z.object({ keys: z.number().array()
|
|
19
|
+
const reqZ = z.object({ keys: z.number().array(), downsampleFactor: z.number() });
|
|
21
20
|
|
|
22
|
-
const resZ = z.object({
|
|
23
|
-
frame: frameZ,
|
|
24
|
-
error: errorZ.optional().nullable(),
|
|
25
|
-
});
|
|
21
|
+
const resZ = z.object({ frame: frameZ, error: errorZ.optional().nullable() });
|
|
26
22
|
|
|
27
23
|
const ENDPOINT = "/frame/stream";
|
|
28
24
|
|
|
29
25
|
export interface StreamerConfig {
|
|
30
|
-
channels: Params;
|
|
26
|
+
channels: channel.Params;
|
|
31
27
|
downsampleFactor?: number;
|
|
32
28
|
}
|
|
33
29
|
|
|
34
30
|
export class Streamer implements AsyncIterator<Frame>, AsyncIterable<Frame> {
|
|
35
31
|
private readonly stream: StreamProxy<typeof reqZ, typeof resZ>;
|
|
36
|
-
private readonly adapter:
|
|
32
|
+
private readonly adapter: ReadAdapter;
|
|
37
33
|
private readonly downsampleFactor: number;
|
|
38
34
|
|
|
39
|
-
private constructor(
|
|
40
|
-
stream: Stream<typeof reqZ, typeof resZ>,
|
|
41
|
-
adapter: ReadFrameAdapter,
|
|
42
|
-
) {
|
|
35
|
+
private constructor(stream: Stream<typeof reqZ, typeof resZ>, adapter: ReadAdapter) {
|
|
43
36
|
this.stream = new StreamProxy("Streamer", stream);
|
|
44
37
|
this.adapter = adapter;
|
|
45
38
|
this.downsampleFactor = 1;
|
|
46
39
|
}
|
|
47
40
|
|
|
48
|
-
get keys(): Key[] {
|
|
41
|
+
get keys(): channel.Key[] {
|
|
49
42
|
return this.adapter.keys;
|
|
50
43
|
}
|
|
51
44
|
|
|
52
45
|
static async _open(
|
|
53
|
-
retriever: Retriever,
|
|
46
|
+
retriever: channel.Retriever,
|
|
54
47
|
client: StreamClient,
|
|
55
48
|
{ channels, downsampleFactor }: StreamerConfig,
|
|
56
49
|
): Promise<Streamer> {
|
|
57
|
-
const adapter = await
|
|
50
|
+
const adapter = await ReadAdapter.open(retriever, channels);
|
|
58
51
|
const stream = await client.stream(ENDPOINT, reqZ, resZ);
|
|
59
52
|
const streamer = new Streamer(stream, adapter);
|
|
60
53
|
stream.send({ keys: adapter.keys, downsampleFactor: downsampleFactor ?? 1 });
|
|
@@ -77,9 +70,12 @@ export class Streamer implements AsyncIterator<Frame>, AsyncIterable<Frame> {
|
|
|
77
70
|
return this.adapter.adapt(new Frame((await this.stream.receive()).frame));
|
|
78
71
|
}
|
|
79
72
|
|
|
80
|
-
async update(channels: Params): Promise<void> {
|
|
73
|
+
async update(channels: channel.Params): Promise<void> {
|
|
81
74
|
await this.adapter.update(channels);
|
|
82
|
-
this.stream.send({
|
|
75
|
+
this.stream.send({
|
|
76
|
+
keys: this.adapter.keys,
|
|
77
|
+
downsampleFactor: this.downsampleFactor,
|
|
78
|
+
});
|
|
83
79
|
}
|
|
84
80
|
|
|
85
81
|
close(): void {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Use of this software is governed by the Business Source License included in the file
|
|
4
4
|
// licenses/BSL.txt.
|
|
@@ -12,7 +12,7 @@ import { DataType, Rate, TimeRange, TimeSpan, TimeStamp } from "@synnaxlabs/x/te
|
|
|
12
12
|
import { describe, expect, test } from "vitest";
|
|
13
13
|
|
|
14
14
|
import { type channel } from "@/channel";
|
|
15
|
-
import { UnauthorizedError } from "@/errors";
|
|
15
|
+
import { UnauthorizedError, ValidationError } from "@/errors";
|
|
16
16
|
import { ALWAYS_INDEX_PERSIST_ON_AUTO_COMMIT, WriterMode } from "@/framer/writer";
|
|
17
17
|
import { newClient } from "@/setupspecs";
|
|
18
18
|
import { randomSeries } from "@/util/telem";
|
|
@@ -22,7 +22,7 @@ const client = newClient();
|
|
|
22
22
|
const newChannel = async (): Promise<channel.Channel> =>
|
|
23
23
|
await client.channels.create({
|
|
24
24
|
leaseholder: 1,
|
|
25
|
-
name: `test-${id.
|
|
25
|
+
name: `test-${id.create()}`,
|
|
26
26
|
rate: Rate.hz(1),
|
|
27
27
|
dataType: DataType.FLOAT64,
|
|
28
28
|
});
|
|
@@ -40,6 +40,7 @@ describe("Writer", () => {
|
|
|
40
40
|
}
|
|
41
41
|
expect(true).toBeTruthy();
|
|
42
42
|
});
|
|
43
|
+
|
|
43
44
|
test("write to unknown channel key", async () => {
|
|
44
45
|
const ch = await newChannel();
|
|
45
46
|
const writer = await client.openWriter({ start: 0, channels: ch.key });
|
|
@@ -48,6 +49,7 @@ describe("Writer", () => {
|
|
|
48
49
|
).rejects.toThrow("Channel billy bob not found");
|
|
49
50
|
await writer.close();
|
|
50
51
|
});
|
|
52
|
+
|
|
51
53
|
test("stream when mode is set ot persist only", async () => {
|
|
52
54
|
const ch = await newChannel();
|
|
53
55
|
const stream = await client.openStreamer(ch.key);
|
|
@@ -68,6 +70,7 @@ describe("Writer", () => {
|
|
|
68
70
|
]);
|
|
69
71
|
expect(v).toEqual(123);
|
|
70
72
|
});
|
|
73
|
+
|
|
71
74
|
test("write with auto commit on", async () => {
|
|
72
75
|
const ch = await newChannel();
|
|
73
76
|
const writer = await client.openWriter({
|
|
@@ -85,6 +88,7 @@ describe("Writer", () => {
|
|
|
85
88
|
const f = await client.read(new TimeRange(0, TimeStamp.seconds(10)), ch.key);
|
|
86
89
|
expect(f.length).toEqual(10);
|
|
87
90
|
});
|
|
91
|
+
|
|
88
92
|
test("write with auto commit and alwaysPersist", async () => {
|
|
89
93
|
const ch = await newChannel();
|
|
90
94
|
const writer = await client.openWriter({
|
|
@@ -100,6 +104,7 @@ describe("Writer", () => {
|
|
|
100
104
|
}
|
|
101
105
|
expect(true).toBeTruthy();
|
|
102
106
|
});
|
|
107
|
+
|
|
103
108
|
test("write with auto commit and a set interval", async () => {
|
|
104
109
|
const ch = await newChannel();
|
|
105
110
|
const writer = await client.openWriter({
|
|
@@ -115,6 +120,41 @@ describe("Writer", () => {
|
|
|
115
120
|
}
|
|
116
121
|
expect(true).toBeTruthy();
|
|
117
122
|
});
|
|
123
|
+
|
|
124
|
+
test("write with out of order timestamp", async () => {
|
|
125
|
+
const indexCh = await client.channels.create({
|
|
126
|
+
name: "idx",
|
|
127
|
+
dataType: DataType.TIMESTAMP,
|
|
128
|
+
isIndex: true,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
const dataCh = await client.channels.create({
|
|
132
|
+
name: "data",
|
|
133
|
+
dataType: DataType.FLOAT64,
|
|
134
|
+
index: indexCh.key,
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const writer = await client.openWriter({
|
|
138
|
+
start: TimeStamp.now(),
|
|
139
|
+
channels: [indexCh.key, dataCh.key],
|
|
140
|
+
enableAutoCommit: true,
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
let errAccumulated: boolean = false;
|
|
144
|
+
for (let i = 0; i < 10; i++) {
|
|
145
|
+
await new Promise((resolve) => setTimeout(resolve, 5));
|
|
146
|
+
errAccumulated = !(await writer.write({
|
|
147
|
+
[indexCh.key]: BigInt(i),
|
|
148
|
+
[dataCh.key]: i,
|
|
149
|
+
}));
|
|
150
|
+
if (errAccumulated) break;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
expect(errAccumulated).toBeTruthy();
|
|
154
|
+
|
|
155
|
+
await expect(writer.close()).rejects.toThrow(ValidationError);
|
|
156
|
+
});
|
|
157
|
+
|
|
118
158
|
test("write with errOnUnauthorized", async () => {
|
|
119
159
|
const ch = await newChannel();
|
|
120
160
|
const w1 = await client.openWriter({
|
|
@@ -123,14 +163,11 @@ describe("Writer", () => {
|
|
|
123
163
|
});
|
|
124
164
|
|
|
125
165
|
await expect(
|
|
126
|
-
client.openWriter({
|
|
127
|
-
start: 0,
|
|
128
|
-
channels: ch.key,
|
|
129
|
-
errOnUnauthorized: true,
|
|
130
|
-
}),
|
|
166
|
+
client.openWriter({ start: 0, channels: ch.key, errOnUnauthorized: true }),
|
|
131
167
|
).rejects.toThrow(UnauthorizedError);
|
|
132
168
|
await w1.close();
|
|
133
169
|
});
|
|
170
|
+
|
|
134
171
|
test("setAuthority", async () => {
|
|
135
172
|
const ch = await newChannel();
|
|
136
173
|
const w1 = await client.openWriter({
|
|
@@ -159,6 +196,7 @@ describe("Writer", () => {
|
|
|
159
196
|
await w1.close();
|
|
160
197
|
await w2.close();
|
|
161
198
|
});
|
|
199
|
+
|
|
162
200
|
test("setAuthority with name keys", async () => {
|
|
163
201
|
const ch = await newChannel();
|
|
164
202
|
const w1 = await client.openWriter({
|
|
@@ -187,6 +225,7 @@ describe("Writer", () => {
|
|
|
187
225
|
await w1.close();
|
|
188
226
|
await w2.close();
|
|
189
227
|
});
|
|
228
|
+
|
|
190
229
|
test("setAuthority with name-value pair", async () => {
|
|
191
230
|
const ch = await newChannel();
|
|
192
231
|
const w1 = await client.openWriter({
|
|
@@ -215,6 +254,7 @@ describe("Writer", () => {
|
|
|
215
254
|
await w1.close();
|
|
216
255
|
await w2.close();
|
|
217
256
|
});
|
|
257
|
+
|
|
218
258
|
test("setAuthority on all channels", async () => {
|
|
219
259
|
const ch = await newChannel();
|
|
220
260
|
const w1 = await client.openWriter({
|
|
@@ -244,6 +284,7 @@ describe("Writer", () => {
|
|
|
244
284
|
await w2.close();
|
|
245
285
|
});
|
|
246
286
|
});
|
|
287
|
+
|
|
247
288
|
describe("Client", () => {
|
|
248
289
|
test("Client - basic write", async () => {
|
|
249
290
|
const ch = await newChannel();
|