@synnaxlabs/x 0.8.0 → 0.10.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.
Files changed (61) hide show
  1. package/.turbo/turbo-build.log +11 -10
  2. package/dist/binary/index.d.ts +1 -1
  3. package/dist/change/change.d.ts +4 -2
  4. package/dist/change/index.d.ts +1 -1
  5. package/dist/compare/index.d.ts +1 -1
  6. package/dist/deep/delete.d.ts +1 -1
  7. package/dist/deep/external.d.ts +7 -7
  8. package/dist/deep/index.d.ts +1 -1
  9. package/dist/deep/merge.d.ts +1 -1
  10. package/dist/deep/path.d.ts +37 -0
  11. package/dist/deep/path.spec.d.ts +1 -0
  12. package/dist/destructor.d.ts +1 -0
  13. package/dist/index.d.ts +1 -0
  14. package/dist/kv/index.d.ts +1 -1
  15. package/dist/mock/index.d.ts +1 -1
  16. package/dist/observe/index.d.ts +1 -1
  17. package/dist/observe/observe.d.ts +1 -1
  18. package/dist/runtime/external.d.ts +2 -2
  19. package/dist/runtime/index.d.ts +1 -1
  20. package/dist/shallowCopy.d.ts +1 -0
  21. package/dist/spatial/bounds.d.ts +48 -9
  22. package/dist/spatial/box.d.ts +9 -35
  23. package/dist/spatial/dimensions.d.ts +1 -1
  24. package/dist/spatial/direction.d.ts +1 -1
  25. package/dist/spatial/external.d.ts +8 -8
  26. package/dist/spatial/index.d.ts +1 -1
  27. package/dist/spatial/location.d.ts +1 -1
  28. package/dist/spatial/position.d.ts +1 -1
  29. package/dist/spatial/scale.d.ts +5 -5
  30. package/dist/spatial/spatial.d.ts +1 -1
  31. package/dist/spatial/xy.d.ts +5 -2
  32. package/dist/telem/generate.d.ts +1 -1
  33. package/dist/telem/index.d.ts +3 -3
  34. package/dist/telem/series.d.ts +31 -5
  35. package/dist/telem/telem.d.ts +3 -0
  36. package/dist/toArray.d.ts +1 -0
  37. package/dist/x.cjs.js +289 -60
  38. package/dist/x.cjs.js.map +1 -1
  39. package/dist/x.es.js +289 -60
  40. package/dist/x.es.js.map +1 -1
  41. package/package.json +6 -6
  42. package/src/change/change.ts +13 -11
  43. package/src/deep/delete.ts +1 -1
  44. package/src/deep/external.ts +1 -1
  45. package/src/deep/path.spec.ts +82 -0
  46. package/src/deep/path.ts +95 -0
  47. package/src/destructor.ts +2 -0
  48. package/src/index.ts +1 -0
  49. package/src/observe/observe.ts +2 -2
  50. package/src/shallowCopy.ts +6 -0
  51. package/src/spatial/bounds.spec.ts +218 -0
  52. package/src/spatial/bounds.ts +155 -19
  53. package/src/spatial/box.ts +5 -0
  54. package/src/spatial/xy.ts +10 -2
  55. package/src/telem/series.spec.ts +54 -46
  56. package/src/telem/series.ts +93 -56
  57. package/src/telem/telem.spec.ts +17 -1
  58. package/src/telem/telem.ts +28 -0
  59. package/src/toArray.ts +3 -0
  60. package/dist/deep/key.d.ts +0 -30
  61. package/src/deep/key.ts +0 -46
@@ -7,7 +7,8 @@
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 { date, type z } from "zod";
10
+ import { nanoid } from "nanoid/non-secure";
11
+ import { type z } from "zod";
11
12
 
12
13
  import { compare } from "@/compare";
13
14
  import { bounds } from "@/spatial";
@@ -39,20 +40,47 @@ interface GL {
39
40
  }
40
41
 
41
42
  export interface SeriesDigest {
43
+ key: string;
42
44
  dataType: string;
43
45
  sampleOffset: SampleValue;
44
- alignment: number;
46
+ alignment: bounds.Bounds;
45
47
  timeRange?: string;
46
48
  length: number;
47
49
  }
48
50
 
51
+ interface BaseSeriesProps {
52
+ dataType?: CrudeDataType;
53
+ timeRange?: TimeRange;
54
+ sampleOffset?: SampleValue;
55
+ glBufferUsage?: GLBufferUsage;
56
+ alignment?: number;
57
+ key?: string;
58
+ }
59
+
60
+ export interface SeriesProps extends BaseSeriesProps {
61
+ data: ArrayBuffer | NativeTypedArray;
62
+ }
63
+
64
+ export interface SeriesAllocProps extends BaseSeriesProps {
65
+ length: number;
66
+ dataType: CrudeDataType;
67
+ }
68
+
49
69
  const FULL_BUFFER = -1;
50
70
 
71
+ export interface SeriesMemInfo {
72
+ key: string;
73
+ length: number;
74
+ byteLength: Size;
75
+ glBuffer: boolean;
76
+ }
77
+
51
78
  /**
52
79
  * Series is a strongly typed array of telemetry samples backed by an underlying binary
53
80
  * buffer.
54
81
  */
55
82
  export class Series {
83
+ key: string = "";
56
84
  /** The data type of the array */
57
85
  readonly dataType: DataType;
58
86
  /**
@@ -78,36 +106,26 @@ export class Series {
78
106
  /** Tracks the number of entities currently using this array. */
79
107
  private _refCount: number = 0;
80
108
 
81
- static alloc(
82
- length: number,
83
- dataType: CrudeDataType,
84
- timeRange?: TimeRange,
85
- sampleOffset?: SampleValue,
86
- glBufferUsage: GLBufferUsage = "static",
87
- alignment: number = 0,
88
- ): Series {
109
+ static alloc({ length, dataType, ...props }: SeriesAllocProps): Series {
89
110
  if (length === 0)
90
111
  throw new Error("[Series] - cannot allocate an array of length 0");
91
112
  const data = new new DataType(dataType).Array(length);
92
- const arr = new Series(
93
- data.buffer,
113
+ const arr = new Series({
114
+ data: data.buffer,
94
115
  dataType,
95
- timeRange,
96
- sampleOffset,
97
- glBufferUsage,
98
- alignment,
99
- );
116
+ ...props,
117
+ });
100
118
  arr.writePos = 0;
101
119
  return arr;
102
120
  }
103
121
 
104
122
  static generateTimestamps(length: number, rate: Rate, start: TimeStamp): Series {
105
- const tr = start.spanRange(rate.span(length));
123
+ const timeRange = start.spanRange(rate.span(length));
106
124
  const data = new BigInt64Array(length);
107
125
  for (let i = 0; i < length; i++) {
108
126
  data[i] = BigInt(start.add(rate.span(i)).valueOf());
109
127
  }
110
- return new Series(data, DataType.TIMESTAMP, tr);
128
+ return new Series({ data, dataType: DataType.TIMESTAMP, timeRange });
111
129
  }
112
130
 
113
131
  get refCount(): number {
@@ -116,24 +134,25 @@ export class Series {
116
134
 
117
135
  static fromStrings(data: string[], timeRange?: TimeRange): Series {
118
136
  const buffer = new TextEncoder().encode(data.join("\n") + "\n");
119
- return new Series(buffer, DataType.STRING, timeRange);
137
+ return new Series({ data: buffer, dataType: DataType.STRING, timeRange });
120
138
  }
121
139
 
122
140
  static fromJSON<T>(data: T[], timeRange?: TimeRange): Series {
123
141
  const buffer = new TextEncoder().encode(
124
142
  data.map((d) => JSON.stringify(d)).join("\n") + "\n",
125
143
  );
126
- return new Series(buffer, DataType.JSON, timeRange);
127
- }
128
-
129
- constructor(
130
- data: ArrayBuffer | NativeTypedArray,
131
- dataType?: CrudeDataType,
132
- timeRange?: TimeRange,
133
- sampleOffset?: SampleValue,
134
- glBufferUsage: GLBufferUsage = "static",
135
- alignment: number = 0,
136
- ) {
144
+ return new Series({ data: buffer, dataType: DataType.JSON, timeRange });
145
+ }
146
+
147
+ constructor({
148
+ data,
149
+ dataType,
150
+ timeRange,
151
+ sampleOffset = 0,
152
+ glBufferUsage = "static",
153
+ alignment = 0,
154
+ key = nanoid(),
155
+ }: SeriesProps) {
137
156
  if (dataType == null && !(data instanceof ArrayBuffer)) {
138
157
  this.dataType = new DataType(data);
139
158
  } else if (dataType != null) {
@@ -143,6 +162,7 @@ export class Series {
143
162
  "must provide a data type when constructing a Series from a buffer",
144
163
  );
145
164
  }
165
+ this.key = key;
146
166
  this.alignment = alignment;
147
167
  this.sampleOffset = sampleOffset ?? 0;
148
168
  this._data = data;
@@ -273,14 +293,14 @@ export class Series {
273
293
  for (let i = 0; i < this.length; i++) {
274
294
  data[i] = convertDataType(this.dataType, target, this.data[i], sampleOffset);
275
295
  }
276
- return new Series(
277
- data.buffer,
278
- target,
279
- this._timeRange,
296
+ return new Series({
297
+ data: data.buffer,
298
+ dataType: target,
299
+ timeRange: this._timeRange,
280
300
  sampleOffset,
281
- this.gl.bufferUsage,
282
- this.alignment,
283
- );
301
+ glBufferUsage: this.gl.bufferUsage,
302
+ alignment: this.alignment,
303
+ });
284
304
  }
285
305
 
286
306
  private calcRawMax(): SampleValue {
@@ -383,7 +403,9 @@ export class Series {
383
403
  const { buffer, bufferUsage, prevBuffer } = this.gl;
384
404
 
385
405
  // If no buffer has been created yet, create one.
386
- if (buffer == null) this.gl.buffer = gl.createBuffer();
406
+ if (buffer == null) {
407
+ this.gl.buffer = gl.createBuffer();
408
+ }
387
409
  // If the current write position is the same as the previous buffer, we're already
388
410
  // up date.
389
411
  if (this.writePos === prevBuffer) return;
@@ -413,14 +435,28 @@ export class Series {
413
435
 
414
436
  get digest(): SeriesDigest {
415
437
  return {
438
+ key: this.key,
416
439
  dataType: this.dataType.toString(),
417
440
  sampleOffset: this.sampleOffset,
418
- alignment: this.alignment,
441
+ alignment: this.alignmentBounds,
419
442
  timeRange: this._timeRange?.toString(),
420
443
  length: this.length,
421
444
  };
422
445
  }
423
446
 
447
+ get memInfo(): SeriesMemInfo {
448
+ return {
449
+ key: this.key,
450
+ length: this.length,
451
+ byteLength: this.byteLength,
452
+ glBuffer: this.gl.buffer != null,
453
+ };
454
+ }
455
+
456
+ get alignmentBounds(): bounds.Bounds {
457
+ return bounds.construct(this.alignment, this.alignment + this.length);
458
+ }
459
+
424
460
  private maybeGarbageCollectGLBuffer(gl: GLBufferController): void {
425
461
  if (this.gl.buffer == null) return;
426
462
  gl.deleteBuffer(this.gl.buffer);
@@ -435,26 +471,27 @@ export class Series {
435
471
  }
436
472
 
437
473
  slice(start: number, end?: number): Series {
438
- const d = this.data.slice(start, end);
439
- return new Series(
440
- d,
441
- this.dataType,
442
- TimeRange.ZERO,
443
- this.sampleOffset,
444
- this.gl.bufferUsage,
445
- this.alignment + start,
446
- );
474
+ if (start <= 0 && (end == null || end >= this.length)) return this;
475
+ const data = this.data.slice(start, end);
476
+ return new Series({
477
+ data,
478
+ dataType: this.dataType,
479
+ timeRange: this._timeRange,
480
+ sampleOffset: this.sampleOffset,
481
+ glBufferUsage: this.gl.bufferUsage,
482
+ alignment: this.alignment + start,
483
+ });
447
484
  }
448
485
 
449
486
  reAlign(alignment: number): Series {
450
- return new Series(
451
- this.buffer,
452
- this.dataType,
453
- TimeRange.ZERO,
454
- this.sampleOffset,
455
- "static",
487
+ return new Series({
488
+ data: this.buffer,
489
+ dataType: this.dataType,
490
+ timeRange: TimeRange.ZERO,
491
+ sampleOffset: this.sampleOffset,
492
+ glBufferUsage: "static",
456
493
  alignment,
457
- );
494
+ });
458
495
  }
459
496
  }
460
497
 
@@ -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 { describe, expect, test } from "vitest";
10
+ import { describe, expect, it, test } from "vitest";
11
11
 
12
12
  import { DataType, Density, Rate, Size, TimeRange, TimeSpan, TimeStamp } from "@/telem";
13
13
 
@@ -291,6 +291,22 @@ describe("TimeRange", () => {
291
291
  expect(tr.overlapsWith(two)).toBeFalsy();
292
292
  expect(two.overlapsWith(tr)).toBeFalsy();
293
293
  });
294
+ describe("boundBy", () => {
295
+ it("should bound the time range to the provided constraints", () => {
296
+ const tr = new TimeRange(TimeSpan.seconds(1), TimeSpan.seconds(4));
297
+ const bound = new TimeRange(TimeSpan.seconds(2), TimeSpan.seconds(3));
298
+ const bounded = tr.boundBy(bound);
299
+ const expected = new TimeRange(TimeSpan.seconds(2), TimeSpan.seconds(3));
300
+ expect(bounded.equals(expected)).toBeTruthy();
301
+ })
302
+ it("should bound the time range even if the start is after the end", () => {
303
+ const tr = new TimeRange(TimeSpan.seconds(4), TimeSpan.seconds(1));
304
+ const bound = new TimeRange(TimeSpan.seconds(2), TimeSpan.seconds(3));
305
+ const bounded = tr.boundBy(bound);
306
+ const expected = new TimeRange(TimeSpan.seconds(3), TimeSpan.seconds(2));
307
+ expect(bounded.equals(expected)).toBeTruthy();
308
+ })
309
+ });
294
310
  });
295
311
 
296
312
  describe("DataType", () => {
@@ -898,6 +898,15 @@ export class TimeRange implements Stringer {
898
898
  return this.start.beforeEq(other) && this.end.after(other);
899
899
  }
900
900
 
901
+ boundBy(other: TimeRange): TimeRange {
902
+ const next = new TimeRange(this.start, this.end);
903
+ if (other.start.after(this.start)) next.start = other.start;
904
+ if (other.start.after(this.end)) next.end = other.start;
905
+ if (other.end.before(this.end)) next.end = other.end;
906
+ if (other.end.before(this.start)) next.start = other.end;
907
+ return next;
908
+ }
909
+
901
910
  /** The maximum possible time range. */
902
911
  static readonly MAX = new TimeRange(TimeStamp.MIN, TimeStamp.MAX);
903
912
 
@@ -1064,6 +1073,25 @@ export class DataType extends String implements Stringer {
1064
1073
  [DataType.UUID.toString(), Density.BIT128],
1065
1074
  ]);
1066
1075
 
1076
+ /** All the data types. */
1077
+ static readonly ALL = [
1078
+ DataType.UNKNOWN,
1079
+ DataType.FLOAT64,
1080
+ DataType.FLOAT32,
1081
+ DataType.INT64,
1082
+ DataType.INT32,
1083
+ DataType.INT16,
1084
+ DataType.INT8,
1085
+ DataType.UINT64,
1086
+ DataType.UINT32,
1087
+ DataType.UINT16,
1088
+ DataType.UINT8,
1089
+ DataType.TIMESTAMP,
1090
+ DataType.UUID,
1091
+ DataType.STRING,
1092
+ DataType.JSON,
1093
+ ];
1094
+
1067
1095
  static readonly BIG_INT_TYPES = [DataType.INT64, DataType.UINT64, DataType.TIMESTAMP];
1068
1096
 
1069
1097
  /** A zod schema for a DataType. */
package/src/toArray.ts CHANGED
@@ -9,3 +9,6 @@
9
9
 
10
10
  export const toArray = <T>(value: T | T[]): T[] =>
11
11
  Array.isArray(value) ? value : [value];
12
+
13
+ export const nullToArr = <T>(value: T | T[] | null): T[] =>
14
+ Array.isArray(value) ? value : value === null ? [] : [value];
@@ -1,30 +0,0 @@
1
- import { type Join } from '../join';
2
- type Prev = [
3
- never,
4
- 0,
5
- 1,
6
- 2,
7
- 3,
8
- 4,
9
- 5,
10
- 6,
11
- 7,
12
- 8,
13
- 9,
14
- 10,
15
- 11,
16
- 12,
17
- 13,
18
- 14,
19
- 15,
20
- 16,
21
- 17,
22
- 18,
23
- 19,
24
- 20,
25
- ...Array<0>
26
- ];
27
- export type Key<T, D extends number = 5> = [D] extends [never] ? never : T extends object ? {
28
- [K in keyof T]-?: K extends string | number ? `${K}` | Join<K, Key<T[K], Prev[D]>> : never;
29
- }[keyof T] : "";
30
- export {};
package/src/deep/key.ts DELETED
@@ -1,46 +0,0 @@
1
- // Copyright 2023 Synnax Labs, Inc.
2
- //
3
- // Use of this software is governed by the Business Source License included in the file
4
- // licenses/BSL.txt.
5
- //
6
- // As of the Change Date specified in that file, in accordance with the Business Source
7
- // License, use of this software will be governed by the Apache License, Version 2.0,
8
- // included in the file licenses/APL.txt.
9
-
10
- import { type Join } from "@/join";
11
-
12
- type Prev = [
13
- never,
14
- 0,
15
- 1,
16
- 2,
17
- 3,
18
- 4,
19
- 5,
20
- 6,
21
- 7,
22
- 8,
23
- 9,
24
- 10,
25
- 11,
26
- 12,
27
- 13,
28
- 14,
29
- 15,
30
- 16,
31
- 17,
32
- 18,
33
- 19,
34
- 20,
35
- ...Array<0>,
36
- ];
37
-
38
- export type Key<T, D extends number = 5> = [D] extends [never]
39
- ? never
40
- : T extends object
41
- ? {
42
- [K in keyof T]-?: K extends string | number
43
- ? `${K}` | Join<K, Key<T[K], Prev[D]>>
44
- : never;
45
- }[keyof T]
46
- : "";