@synnaxlabs/x 0.14.1 → 0.15.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@synnaxlabs/x",
3
3
  "private": false,
4
- "version": "0.14.1",
4
+ "version": "0.15.0",
5
5
  "type": "module",
6
6
  "description": "Common Utilities for Synnax Labs",
7
7
  "repository": "https://github.com/synnaxlabs/synnax/tree/main/x/go",
@@ -27,9 +27,9 @@
27
27
  "eslint": "^8.55.0",
28
28
  "vite": "^5.1.2",
29
29
  "vitest": "^1.2.2",
30
+ "@synnaxlabs/vite-plugin": "0.0.1",
30
31
  "eslint-config-synnaxlabs": "0.0.1",
31
- "@synnaxlabs/tsconfig": "0.0.2",
32
- "@synnaxlabs/vite-plugin": "0.0.1"
32
+ "@synnaxlabs/tsconfig": "0.0.2"
33
33
  },
34
34
  "main": "dist/x.cjs",
35
35
  "module": "dist/x.js",
@@ -7,9 +7,9 @@
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, DataTypeT, NativeTypedArray } from "@/telem/telem";
10
+ import { DataType, type DataTypeT, type TypedArray } from "@/telem/telem";
11
11
 
12
- export const randomSeries = (length: number, dataType: DataTypeT): NativeTypedArray => {
12
+ export const randomSeries = (length: number, dataType: DataTypeT): TypedArray => {
13
13
  // generate random bytes of the correct length
14
14
  const bytes = new Uint8Array(length * new DataType(dataType).density.valueOf());
15
15
  for (let i = 0; i < bytes.byteLength; i++) {
@@ -11,13 +11,37 @@ import { describe, expect, test, it } from "vitest";
11
11
  import { z } from "zod";
12
12
 
13
13
  import { MockGLBufferController } from "@/mock/MockGLBufferController";
14
- import { Series } from "@/telem/series";
15
- import { DataType, Rate, Size, TimeRange, TimeStamp } from "@/telem/telem";
14
+ import { Series, isCrudeSeries, MultiSeries } from "@/telem/series";
15
+ import { DataType, Rate, Size, TimeRange, TimeSpan, TimeStamp } from "@/telem/telem";
16
16
 
17
17
  describe("Series", () => {
18
18
  describe("construction", () => {
19
- test("valid from native", () => {
20
- const a = new Series({ data: new Float32Array([1, 2, 3]) });
19
+ const IS_CRUDE_SERIES_SPEC: Array<[unknown, boolean]> = [
20
+ [{}, false],
21
+ [{ constructor: {} }, false],
22
+ [1, true],
23
+ [[1, 2, 3], true],
24
+ [["a", "b", "c"], true],
25
+ [new Float32Array([12]), true],
26
+ ];
27
+ IS_CRUDE_SERIES_SPEC.forEach(([value, expected]) => {
28
+ it(`should return ${expected} for ${JSON.stringify(value)}`, () => {
29
+ expect(isCrudeSeries(value)).toEqual(expected);
30
+ });
31
+ });
32
+
33
+ test("from another series", () => {
34
+ const a = new Series({
35
+ data: new Float32Array([1, 2, 3]),
36
+ timeRange: new TimeRange(TimeStamp.seconds(5), TimeStamp.seconds(20)),
37
+ });
38
+ const b = new Series(a);
39
+ expect(b.buffer).toBe(a.buffer);
40
+ expect(b.timeRange).toBe(a.timeRange);
41
+ });
42
+
43
+ test("valid from typed array", () => {
44
+ const a = new Series(new Float32Array([1, 2, 3]));
21
45
  expect(a.dataType.toString()).toBe(DataType.FLOAT32.toString());
22
46
  expect(a.length).toEqual(3);
23
47
  expect(a.byteLength).toEqual(Size.bytes(12));
@@ -39,6 +63,74 @@ describe("Series", () => {
39
63
  }).toThrow();
40
64
  });
41
65
 
66
+ test("valid from js array", () => {
67
+ const a = new Series({ data: [1, 2, 3], dataType: DataType.FLOAT32 });
68
+ expect(a.dataType.toString()).toBe(DataType.FLOAT32.toString());
69
+ expect(a.length).toEqual(3);
70
+ expect(a.byteLength).toEqual(Size.bytes(12));
71
+ expect(a.byteCapacity).toEqual(Size.bytes(12));
72
+ expect(a.capacity).toEqual(3);
73
+ });
74
+
75
+ it("should assume float64 when JS numbers are passed as data", () => {
76
+ const s = new Series({ data: [1, 2, 3] });
77
+ expect(s.dataType.equals(DataType.FLOAT64));
78
+ });
79
+
80
+ it("should assume float64 when a single number is passed in", () => {
81
+ const s = new Series(1);
82
+ expect(s.dataType.equals(DataType.FLOAT64)).toBeTruthy();
83
+ });
84
+
85
+ it("should assume string when JS strings are passed as data", () => {
86
+ const s = new Series({ data: ["apple", "banana", "carrot"] });
87
+ expect(s.dataType.equals(DataType.STRING));
88
+ expect(s.length).toEqual(3);
89
+ });
90
+
91
+ it("should assume string when a single string is passed as data", () => {
92
+ const s = new Series("abc");
93
+ expect(s.dataType.equals(DataType.STRING)).toBeTruthy();
94
+ expect(s.length).toEqual(1);
95
+ });
96
+
97
+ it("should assume JSON when JS objects are passed as data", () => {
98
+ const s = new Series({ data: [{ a: 1, b: "apple" }] });
99
+ expect(s.dataType.equals(DataType.JSON));
100
+ expect(s.length).toEqual(1);
101
+ });
102
+
103
+ it("should correctly interpret a bigint as an int64", () => {
104
+ const s = new Series(1n);
105
+ expect(s.dataType.equals(DataType.INT64)).toBeTruthy();
106
+ expect(s.length).toEqual(1);
107
+ });
108
+
109
+ it("should correctly interpret a TimeStamp object as a data type of timestamp", () => {
110
+ const s = new Series(TimeStamp.now());
111
+ expect(s.dataType).toEqual(DataType.TIMESTAMP);
112
+ });
113
+
114
+ it("should correctly interpret an array of TimeStamps as a data type of timestamp", () => {
115
+ const s = new Series([TimeStamp.now(), TimeStamp.now().add(TimeSpan.seconds(1))]);
116
+ expect(s.dataType).toEqual(DataType.TIMESTAMP);
117
+ });
118
+
119
+ it("should correctly interpret a Date object as a data type of timestamp", () => {
120
+ const s = new Series(new Date());
121
+ expect(s.dataType).toEqual(DataType.TIMESTAMP);
122
+ });
123
+
124
+ it("should encode objects as JSON", () => {
125
+ const a = new Series({ data: [{ a: 1, b: "apple" }], dataType: DataType.JSON });
126
+ expect(a.dataType.toString()).toBe(DataType.JSON.toString());
127
+ });
128
+
129
+ it("should correctly separate strings", () => {
130
+ const a = new Series({ data: ["apple"], dataType: DataType.STRING });
131
+ expect(a.dataType.toString()).toBe(DataType.STRING.toString());
132
+ });
133
+
42
134
  test("from buffer with data type provided", () => {
43
135
  const a = new Series({ data: new ArrayBuffer(4), dataType: DataType.FLOAT32 });
44
136
  expect(a.dataType.toString()).toBe(DataType.FLOAT32.toString());
@@ -103,6 +195,48 @@ describe("Series", () => {
103
195
  series.at(3, true);
104
196
  }).toThrow();
105
197
  });
198
+ it("should return the correct value for a string series", () => {
199
+ const series = new Series({
200
+ data: ["apple", "banana", "carrot"],
201
+ dataType: DataType.STRING,
202
+ });
203
+ expect(series.at(0)).toEqual("apple");
204
+ expect(series.at(1)).toEqual("banana");
205
+ expect(series.at(2)).toEqual("carrot");
206
+ expect(series.at(-1)).toEqual("carrot");
207
+ });
208
+ it("should return the correct value for a JSON series", () => {
209
+ const series = new Series({
210
+ data: [
211
+ { a: 1, b: "apple" },
212
+ { a: 2, b: "banana" },
213
+ ],
214
+ dataType: DataType.JSON,
215
+ });
216
+ expect(series.at(0)).toEqual({ a: 1, b: "apple" });
217
+ expect(series.at(1)).toEqual({ a: 2, b: "banana" });
218
+ });
219
+ it("should throw an error if the index is out of bounds for a string series", () => {
220
+ const series = new Series({
221
+ data: ["apple", "banana", "carrot"],
222
+ dataType: DataType.STRING,
223
+ });
224
+ expect(() => {
225
+ series.at(3, true);
226
+ }).toThrow();
227
+ });
228
+ it("should throw an error if the index is out of bounds for a JSON series", () => {
229
+ const series = new Series({
230
+ data: [
231
+ { a: 1, b: "apple" },
232
+ { a: 2, b: "banana" },
233
+ ],
234
+ dataType: DataType.JSON,
235
+ });
236
+ expect(() => {
237
+ series.at(2, true);
238
+ }).toThrow();
239
+ });
106
240
  });
107
241
 
108
242
  describe("slice", () => {
@@ -135,6 +269,11 @@ describe("Series", () => {
135
269
  expect(series.max).toEqual(3);
136
270
  expect(series.min).toEqual(1);
137
271
  });
272
+ it("should throw an error if that data type is not numeric", () => {
273
+ const series = new Series({ data: ["a", "b", "c"] });
274
+ expect(() => series.max == null).toThrow();
275
+ expect(() => series.min == null).toThrow();
276
+ });
138
277
  });
139
278
 
140
279
  describe("conversion", () => {
@@ -364,4 +503,109 @@ describe("Series", () => {
364
503
  expect(series.binarySearch(6)).toEqual(5);
365
504
  });
366
505
  });
506
+
507
+ describe("array construction", () => {
508
+ it("should correctly a JS array from a series", () => {
509
+ const s = new Series([1, 2, 3]);
510
+ const arr = Array.from(s);
511
+ expect(arr).toEqual([1, 2, 3]);
512
+ });
513
+ it("should correctly construct a js array from a string series", () => {
514
+ const s = new Series(["apple", "banana", "carrot"]);
515
+ const arr = Array.from(s);
516
+ expect(arr).toEqual(["apple", "banana", "carrot"]);
517
+ });
518
+ it("should correctly construct a JS array from a JSON series", () => {
519
+ const s = new Series([
520
+ { a: 1, b: "apple" },
521
+ { a: 2, b: "banana" },
522
+ { a: 3, b: "carrot" },
523
+ ]);
524
+ const arr = Array.from(s);
525
+ expect(arr).toEqual([
526
+ { a: 1, b: "apple" },
527
+ { a: 2, b: "banana" },
528
+ { a: 3, b: "carrot" },
529
+ ]);
530
+ });
531
+ });
532
+ });
533
+
534
+ describe("MultiSeries", () => {
535
+ describe("length", () => {
536
+ it("should correctly return the length of the multi-series", () => {
537
+ const a = new Series(new Float32Array([1, 2, 3]));
538
+ const b = new Series(new Float32Array([4, 5, 6]));
539
+ const multi = new MultiSeries([a, b]);
540
+ expect(multi.length).toEqual(6);
541
+ });
542
+ });
543
+ describe("at", () => {
544
+ it("should correctly return the value at a particular index", () => {
545
+ const a = new Series(new Float32Array([1, 2, 3]));
546
+ const b = new Series(new Float32Array([4, 5, 6]));
547
+ const multi = new MultiSeries([a, b]);
548
+ expect(multi.at(0)).toEqual(1);
549
+ expect(multi.at(1)).toEqual(2);
550
+ expect(multi.at(2)).toEqual(3);
551
+ expect(multi.at(3)).toEqual(4);
552
+ expect(multi.at(4)).toEqual(5);
553
+ expect(multi.at(5)).toEqual(6);
554
+ });
555
+ it("should correctly return a value via negative indexing", () => {
556
+ const a = new Series(new Float32Array([1, 2, 3]));
557
+ const b = new Series(new Float32Array([4, 5, 6]));
558
+ const multi = new MultiSeries([a, b]);
559
+ expect(multi.at(-1)).toEqual(6);
560
+ expect(multi.at(-2)).toEqual(5);
561
+ expect(multi.at(-3)).toEqual(4);
562
+ expect(multi.at(-4)).toEqual(3);
563
+ expect(multi.at(-5)).toEqual(2);
564
+ expect(multi.at(-6)).toEqual(1);
565
+ });
566
+ });
567
+
568
+ describe("array construction", () => {
569
+ it("should correctly construct a JS array from a multi-series", () => {
570
+ const a = new Series(new Float32Array([1, 2, 3]));
571
+ const b = new Series(new Float32Array([4, 5, 6]));
572
+ const multi = new MultiSeries([a, b]);
573
+ const arr = Array.from(multi);
574
+ expect(arr).toEqual([1, 2, 3, 4, 5, 6]);
575
+ });
576
+ it("should correctly construct a JS array from a multi-series of strings", () => {
577
+ const a = new Series(["apple", "banana", "carrot"]);
578
+ const b = new Series(["dog", "elephant", "fox"]);
579
+ const multi = new MultiSeries([a, b]);
580
+ const arr = Array.from(multi);
581
+ expect(arr).toEqual(["apple", "banana", "carrot", "dog", "elephant", "fox"]);
582
+ });
583
+ it("should correctly construct a JS array from a multi-series of JSON", () => {
584
+ const a = new Series([
585
+ { a: 1, b: "apple" },
586
+ { a: 2, b: "banana" },
587
+ { a: 3, b: "carrot" },
588
+ ]);
589
+ const b = new Series([
590
+ { a: 4, b: "dog" },
591
+ { a: 5, b: "elephant" },
592
+ { a: 6, b: "fox" },
593
+ ]);
594
+ const multi = new MultiSeries([a, b]);
595
+ const arr = Array.from(multi);
596
+ expect(arr).toEqual([
597
+ { a: 1, b: "apple" },
598
+ { a: 2, b: "banana" },
599
+ { a: 3, b: "carrot" },
600
+ { a: 4, b: "dog" },
601
+ { a: 5, b: "elephant" },
602
+ { a: 6, b: "fox" },
603
+ ]);
604
+ });
605
+ it("should correctly construct a JS array from a multi-series with no series", () => {
606
+ const multi = new MultiSeries([]);
607
+ const arr = Array.from(multi);
608
+ expect(arr).toEqual([]);
609
+ });
610
+ });
367
611
  });