@synnaxlabs/client 0.49.0 → 0.49.3

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.
@@ -3,6 +3,7 @@ import { CrudeSeries, CrudeTimeRange, CrudeTimeStamp, MultiSeries } from '@synna
3
3
  import { channel } from '../channel';
4
4
  import { Frame } from './frame';
5
5
  import { Iterator, IteratorConfig } from './iterator';
6
+ import { ReadRequest } from './reader';
6
7
  import { Streamer, StreamerConfig } from './streamer';
7
8
  import { Writer, WriterConfig } from './writer';
8
9
  import { ontology } from '../ontology';
@@ -18,6 +19,7 @@ export declare class Client {
18
19
  private readonly streamClient;
19
20
  private readonly retriever;
20
21
  private readonly deleter;
22
+ private readonly reader;
21
23
  constructor(stream: WebSocketClient, unary: UnaryClient, retriever: channel.Retriever);
22
24
  /**
23
25
  * Opens a new iterator over the given channels within the provided time range.
@@ -53,6 +55,7 @@ export declare class Client {
53
55
  write(start: CrudeTimeStamp, data: Record<channel.KeyOrName, CrudeSeries>): Promise<void>;
54
56
  read(tr: CrudeTimeRange, channel: channel.KeyOrName): Promise<MultiSeries>;
55
57
  read(tr: CrudeTimeRange, channels: channel.Params): Promise<Frame>;
58
+ read(request: ReadRequest): Promise<ReadableStream<Uint8Array>>;
56
59
  private readFrame;
57
60
  readLatest(channel: channel.KeyOrName, n: number): Promise<MultiSeries>;
58
61
  readLatest(channels: channel.Params, n: number): Promise<Frame>;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/framer/client.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,WAAW,EAGjB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAa,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC7E,OAAO,EAAgB,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACrF,OAAO,EAAE,MAAM,EAAE,KAAK,YAAY,EAAc,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,eAAO,MAAM,UAAU,2BAA6C,CAAC;AACrE,eAAO,MAAM,gBAAgB;;;;;;CAAiB,CAAC;AAE/C,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkB;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;gBAGhC,MAAM,EAAE,eAAe,EACvB,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,OAAO,CAAC,SAAS;IAO9B;;;;;;;OAOG;IACG,YAAY,CAChB,EAAE,EAAE,cAAc,EAClB,QAAQ,EAAE,OAAO,CAAC,MAAM,EACxB,IAAI,CAAC,EAAE,cAAc,GACpB,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAIvD;;;;;;;;;;OAUG;IACG,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC;IAIvD,KAAK,CACT,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,OAAO,CAAC,SAAS,EAC1B,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,IAAI,CAAC;IAEV,KAAK,CACT,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,OAAO,CAAC,WAAW,EAC7B,IAAI,EAAE,WAAW,EAAE,GAClB,OAAO,CAAC,IAAI,CAAC;IAEV,KAAK,CACT,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,WAAW,CAAC,GAC3C,OAAO,CAAC,IAAI,CAAC;IAuCV,IAAI,CAAC,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IAE1E,IAAI,CAAC,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;YAY1D,SAAS;IAcjB,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAEvE,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;YAYvD,gBAAgB;IAcxB,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAajF"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/framer/client.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,WAAW,EAGjB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAa,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC7E,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAgB,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACrF,OAAO,EAAE,MAAM,EAAE,KAAK,YAAY,EAAc,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,eAAO,MAAM,UAAU,2BAA6C,CAAC;AACrE,eAAO,MAAM,gBAAgB;;;;;;CAAiB,CAAC;AAE/C,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkB;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAG9B,MAAM,EAAE,eAAe,EACvB,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,OAAO,CAAC,SAAS;IAQ9B;;;;;;;OAOG;IACG,YAAY,CAChB,EAAE,EAAE,cAAc,EAClB,QAAQ,EAAE,OAAO,CAAC,MAAM,EACxB,IAAI,CAAC,EAAE,cAAc,GACpB,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAIvD;;;;;;;;;;OAUG;IACG,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC;IAIvD,KAAK,CACT,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,OAAO,CAAC,SAAS,EAC1B,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,IAAI,CAAC;IAEV,KAAK,CACT,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,OAAO,CAAC,WAAW,EAC7B,IAAI,EAAE,WAAW,EAAE,GAClB,OAAO,CAAC,IAAI,CAAC;IAEV,KAAK,CACT,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,WAAW,CAAC,GAC3C,OAAO,CAAC,IAAI,CAAC;IAuCV,IAAI,CAAC,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IAC1E,IAAI,CAAC,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAClE,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;YAYvD,SAAS;IAcjB,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAEvE,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;YAYvD,gBAAgB;IAcxB,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAOjF"}
@@ -2,6 +2,7 @@ export * from './client';
2
2
  export * from './frame';
3
3
  export * from './iterator';
4
4
  export * from './payload';
5
+ export * from './reader';
5
6
  export * from './streamer';
6
7
  export * from './writer';
7
8
  //# sourceMappingURL=external.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"external.d.ts","sourceRoot":"","sources":["../../../src/framer/external.ts"],"names":[],"mappings":"AASA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"external.d.ts","sourceRoot":"","sources":["../../../src/framer/external.ts"],"names":[],"mappings":"AASA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC"}
@@ -8,6 +8,11 @@ export interface IteratorConfig {
8
8
  * resulting from a call to next with {@link AUTO_SPAN}.
9
9
  */
10
10
  chunkSize?: number;
11
+ /**
12
+ * downsampleFactor is the factor to downsample the data by. If downsampleFactor is
13
+ * less than or equal to 1, no downsampling will be performed.
14
+ */
15
+ downsampleFactor?: number;
11
16
  }
12
17
  /**
13
18
  * Used to iterate over a clusters telemetry in time-order. It should not be
@@ -1 +1 @@
1
- {"version":3,"file":"iterator.d.ts","sourceRoot":"","sources":["../../../src/framer/iterator.ts"],"names":[],"mappings":"AASA,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,cAAc,EAGnB,QAAQ,EAET,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,KAAK,EAAU,MAAM,gBAAgB,CAAC;AAG/C,eAAO,MAAM,SAAS,UAAmB,CAAC;AAsC1C,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwC;IAC/D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,KAAK,EAAE,KAAK,CAAC;IAEb,OAAO;IAMP;;;;;;;;;;OAUG;WACU,KAAK,CAChB,EAAE,EAAE,cAAc,EAClB,QAAQ,EAAE,OAAO,CAAC,MAAM,EACxB,SAAS,EAAE,OAAO,CAAC,SAAS,EAC5B,MAAM,EAAE,YAAY,EACpB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,QAAQ,CAAC;IAapB;;;;;;;;;;OAUG;IACG,IAAI,CAAC,IAAI,GAAE,aAAyB,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7D;;;;;;;;;;OAUG;IACG,IAAI,CAAC,IAAI,GAAE,aAAyB,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7D;;;;;;;OAOG;IACG,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAInC;;;;;;OAMG;IACG,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAIlC;;;;;;;OAOG;IACG,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IAIrD;;;;;;;OAOG;IACG,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IAIrD;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAI/B;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC;YAIhD,OAAO;CAStB"}
1
+ {"version":3,"file":"iterator.d.ts","sourceRoot":"","sources":["../../../src/framer/iterator.ts"],"names":[],"mappings":"AASA,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,cAAc,EAGnB,QAAQ,EAET,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,KAAK,EAAU,MAAM,gBAAgB,CAAC;AAG/C,eAAO,MAAM,SAAS,UAAmB,CAAC;AAuC1C,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwC;IAC/D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,KAAK,EAAE,KAAK,CAAC;IAEb,OAAO;IAMP;;;;;;;;;;OAUG;WACU,KAAK,CAChB,EAAE,EAAE,cAAc,EAClB,QAAQ,EAAE,OAAO,CAAC,MAAM,EACxB,SAAS,EAAE,OAAO,CAAC,SAAS,EAC5B,MAAM,EAAE,YAAY,EACpB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,QAAQ,CAAC;IAcpB;;;;;;;;;;OAUG;IACG,IAAI,CAAC,IAAI,GAAE,aAAyB,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7D;;;;;;;;;;OAUG;IACG,IAAI,CAAC,IAAI,GAAE,aAAyB,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7D;;;;;;;OAOG;IACG,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAInC;;;;;;OAMG;IACG,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAIlC;;;;;;;OAOG;IACG,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IAIrD;;;;;;;OAOG;IACG,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IAIrD;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAI/B;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC;YAIhD,OAAO;CAStB"}
@@ -0,0 +1,18 @@
1
+ import { WebSocketClient } from '@synnaxlabs/freighter';
2
+ import { CrudeTimeRange } from '@synnaxlabs/x';
3
+ import { channel } from '../channel';
4
+ import { IteratorConfig } from './iterator';
5
+ export interface ReadRequest {
6
+ channels: channel.Params;
7
+ timeRange: CrudeTimeRange;
8
+ channelNames?: Record<channel.KeyOrName, string>;
9
+ responseType: "csv";
10
+ iteratorConfig?: IteratorConfig;
11
+ }
12
+ export declare class Reader {
13
+ private readonly retriever;
14
+ private readonly streamClient;
15
+ constructor(retriever: channel.Retriever, streamClient: WebSocketClient);
16
+ read(request: ReadRequest): Promise<ReadableStream<Uint8Array>>;
17
+ }
18
+ //# sourceMappingURL=reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../../src/framer/reader.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,KAAK,cAAc,EAAgB,MAAM,eAAe,CAAC;AAElE,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAElE,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC;IACzB,SAAS,EAAE,cAAc,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACjD,YAAY,EAAE,KAAK,CAAC;IACpB,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkB;gBAEnC,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,YAAY,EAAE,eAAe;IAKjE,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;CAiCtE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=reader.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reader.spec.d.ts","sourceRoot":"","sources":["../../../src/framer/reader.spec.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synnaxlabs/client",
3
- "version": "0.49.0",
3
+ "version": "0.49.3",
4
4
  "description": "The Synnax Client Library",
5
5
  "keywords": [
6
6
  "synnax",
@@ -26,8 +26,8 @@
26
26
  "dependencies": {
27
27
  "async-mutex": "^0.5.0",
28
28
  "zod": "^4.1.12",
29
- "@synnaxlabs/freighter": "^0.49.0",
30
- "@synnaxlabs/x": "^0.49.0"
29
+ "@synnaxlabs/x": "^0.49.3",
30
+ "@synnaxlabs/freighter": "^0.49.0"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@vitest/coverage-v8": "^3.2.4",
@@ -38,8 +38,8 @@
38
38
  "vite": "^7.1.12",
39
39
  "vitest": "^3.2.4",
40
40
  "@synnaxlabs/tsconfig": "^0.43.0",
41
- "@synnaxlabs/vite-plugin": "^0.43.0",
42
- "eslint-config-synnaxlabs": "^0.43.0"
41
+ "eslint-config-synnaxlabs": "^0.43.0",
42
+ "@synnaxlabs/vite-plugin": "^0.43.0"
43
43
  },
44
44
  "type": "module",
45
45
  "types": "dist/src/index.d.ts",
@@ -21,6 +21,7 @@ import { channel } from "@/channel";
21
21
  import { Deleter } from "@/framer/deleter";
22
22
  import { Frame } from "@/framer/frame";
23
23
  import { AUTO_SPAN, Iterator, type IteratorConfig } from "@/framer/iterator";
24
+ import { Reader, type ReadRequest } from "@/framer/reader";
24
25
  import { openStreamer, type Streamer, type StreamerConfig } from "@/framer/streamer";
25
26
  import { Writer, type WriterConfig, WriterMode } from "@/framer/writer";
26
27
  import { ontology } from "@/ontology";
@@ -32,6 +33,7 @@ export class Client {
32
33
  private readonly streamClient: WebSocketClient;
33
34
  private readonly retriever: channel.Retriever;
34
35
  private readonly deleter: Deleter;
36
+ private readonly reader: Reader;
35
37
 
36
38
  constructor(
37
39
  stream: WebSocketClient,
@@ -41,6 +43,7 @@ export class Client {
41
43
  this.streamClient = stream;
42
44
  this.retriever = retriever;
43
45
  this.deleter = new Deleter(unary);
46
+ this.reader = new Reader(retriever, stream);
44
47
  }
45
48
 
46
49
  /**
@@ -140,15 +143,15 @@ export class Client {
140
143
  }
141
144
 
142
145
  async read(tr: CrudeTimeRange, channel: channel.KeyOrName): Promise<MultiSeries>;
143
-
144
146
  async read(tr: CrudeTimeRange, channels: channel.Params): Promise<Frame>;
145
-
147
+ async read(request: ReadRequest): Promise<ReadableStream<Uint8Array>>;
146
148
  async read(
147
- tr: CrudeTimeRange,
148
- channels: channel.Params,
149
- ): Promise<MultiSeries | Frame> {
150
- const { single } = channel.analyzeParams(channels);
151
- const fr = await this.readFrame(tr, channels);
149
+ tr: CrudeTimeRange | ReadRequest,
150
+ channels?: channel.Params,
151
+ ): Promise<MultiSeries | Frame | ReadableStream<Uint8Array>> {
152
+ if (!("start" in tr)) return this.reader.read(tr);
153
+ const { single } = channel.analyzeParams(channels!);
154
+ const fr = await this.readFrame(tr, channels!);
152
155
  if (single) return fr.get(channels as channel.KeyOrName);
153
156
  return fr;
154
157
  }
@@ -199,13 +202,7 @@ export class Client {
199
202
  const { normalized, variant } = channel.analyzeParams(channels);
200
203
  const bounds = new TimeRange(timeRange);
201
204
  if (variant === "keys")
202
- return await this.deleter.delete({
203
- keys: normalized as channel.Key[],
204
- bounds,
205
- });
206
- return await this.deleter.delete({
207
- names: normalized as string[],
208
- bounds,
209
- });
205
+ return await this.deleter.delete({ keys: normalized as channel.Key[], bounds });
206
+ return await this.deleter.delete({ names: normalized as string[], bounds });
210
207
  }
211
208
  }
@@ -11,5 +11,6 @@ export * from "@/framer/client";
11
11
  export * from "@/framer/frame";
12
12
  export * from "@/framer/iterator";
13
13
  export * from "@/framer/payload";
14
+ export * from "@/framer/reader";
14
15
  export * from "@/framer/streamer";
15
16
  export * from "@/framer/writer";
@@ -99,4 +99,71 @@ describe("Iterator", () => {
99
99
  await iter.close();
100
100
  }
101
101
  });
102
+ test("downsample factor 2", async () => {
103
+ const channels = await newIndexedPair(client);
104
+ const [idx_ch, data_ch] = channels;
105
+ const writer = await client.openWriter({ start: TimeStamp.SECOND, channels });
106
+ await writer.write({
107
+ [idx_ch.key]: secondsLinspace(1, 8),
108
+ [data_ch.key]: new Float64Array([1, 2, 3, 4, 5, 6, 7, 8]),
109
+ });
110
+ await writer.close();
111
+ const iter = await client.openIterator(TimeRange.MAX, channels, {
112
+ downsampleFactor: 2,
113
+ });
114
+
115
+ try {
116
+ expect(await iter.seekFirst()).toBe(true);
117
+ expect(await iter.next(AUTO_SPAN)).toBe(true);
118
+ // [1, 2, 3, 4, 5, 6, 7, 8] downsampled by 2 = [1, 3, 5, 7]
119
+ expect(iter.value.get(data_ch.key).data).toEqual(new Float64Array([1, 3, 5, 7]));
120
+ expect(await iter.next(AUTO_SPAN)).toBe(false);
121
+ } finally {
122
+ await iter.close();
123
+ }
124
+ });
125
+ test("downsample factor 3", async () => {
126
+ const channels = await newIndexedPair(client);
127
+ const [idx_ch, data_ch] = channels;
128
+ const writer = await client.openWriter({ start: TimeStamp.SECOND, channels });
129
+ await writer.write({
130
+ [idx_ch.key]: secondsLinspace(1, 9),
131
+ [data_ch.key]: new Float64Array([1, 2, 3, 4, 5, 6, 7, 8, 9]),
132
+ });
133
+ await writer.close();
134
+ const iter = await client.openIterator(TimeRange.MAX, channels, {
135
+ downsampleFactor: 3,
136
+ });
137
+
138
+ try {
139
+ expect(await iter.seekFirst()).toBe(true);
140
+ expect(await iter.next(AUTO_SPAN)).toBe(true);
141
+ // [1, 2, 3, 4, 5, 6, 7, 8, 9] downsampled by 3 = [1, 4, 7]
142
+ expect(iter.value.get(data_ch.key).data).toEqual(new Float64Array([1, 4, 7]));
143
+ expect(await iter.next(AUTO_SPAN)).toBe(false);
144
+ } finally {
145
+ await iter.close();
146
+ }
147
+ });
148
+ test("no downsample when factor is 1", async () => {
149
+ const channels = await newIndexedPair(client);
150
+ const [idx_ch, data_ch] = channels;
151
+ const writer = await client.openWriter({ start: TimeStamp.SECOND, channels });
152
+ await writer.write({
153
+ [idx_ch.key]: secondsLinspace(1, 4),
154
+ [data_ch.key]: new Float64Array([1, 2, 3, 4]),
155
+ });
156
+ await writer.close();
157
+ const iter = await client.openIterator(TimeRange.MAX, channels, {
158
+ downsampleFactor: 1,
159
+ });
160
+ try {
161
+ expect(await iter.seekFirst()).toBe(true);
162
+ expect(await iter.next(AUTO_SPAN)).toBe(true);
163
+ expect(iter.value.get(data_ch.key).data).toEqual(new Float64Array([1, 2, 3, 4]));
164
+ expect(await iter.next(AUTO_SPAN)).toBe(false);
165
+ } finally {
166
+ await iter.close();
167
+ }
168
+ });
102
169
  });
@@ -51,6 +51,7 @@ const reqZ = z.object({
51
51
  stamp: TimeStamp.z.optional(),
52
52
  keys: channel.keyZ.array().optional(),
53
53
  chunkSize: z.number().optional(),
54
+ downsampleFactor: z.int().optional(),
54
55
  });
55
56
  interface Request extends z.infer<typeof reqZ> {}
56
57
 
@@ -67,6 +68,11 @@ export interface IteratorConfig {
67
68
  * resulting from a call to next with {@link AUTO_SPAN}.
68
69
  */
69
70
  chunkSize?: number;
71
+ /**
72
+ * downsampleFactor is the factor to downsample the data by. If downsampleFactor is
73
+ * less than or equal to 1, no downsampling will be performed.
74
+ */
75
+ downsampleFactor?: number;
70
76
  }
71
77
 
72
78
  /**
@@ -114,6 +120,7 @@ export class Iterator {
114
120
  keys: Array.from(adapter.keys),
115
121
  bounds: new TimeRange(tr),
116
122
  chunkSize: opts.chunkSize ?? 1e5,
123
+ downsampleFactor: opts.downsampleFactor ?? 1,
117
124
  });
118
125
  return iter;
119
126
  }