@synnaxlabs/x 0.54.1 → 0.55.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 (83) hide show
  1. package/.turbo/turbo-build.log +8 -8
  2. package/dist/src/binary/codec.d.ts.map +1 -1
  3. package/dist/src/color/color.d.ts +1 -1
  4. package/dist/src/color/palette.d.ts +2 -2
  5. package/dist/src/deep/atKeys.d.ts +27 -0
  6. package/dist/src/deep/atKeys.d.ts.map +1 -0
  7. package/dist/src/deep/atKeys.spec.d.ts +2 -0
  8. package/dist/src/deep/atKeys.spec.d.ts.map +1 -0
  9. package/dist/src/deep/external.d.ts +1 -0
  10. package/dist/src/deep/external.d.ts.map +1 -1
  11. package/dist/src/fmt/external.d.ts +3 -0
  12. package/dist/src/fmt/external.d.ts.map +1 -0
  13. package/dist/src/fmt/index.d.ts +2 -0
  14. package/dist/src/fmt/index.d.ts.map +1 -0
  15. package/dist/src/fmt/path.d.ts +13 -0
  16. package/dist/src/fmt/path.d.ts.map +1 -0
  17. package/dist/src/fmt/path.spec.d.ts +2 -0
  18. package/dist/src/fmt/path.spec.d.ts.map +1 -0
  19. package/dist/src/fmt/value.d.ts +23 -0
  20. package/dist/src/fmt/value.d.ts.map +1 -0
  21. package/dist/src/fmt/value.spec.d.ts +2 -0
  22. package/dist/src/fmt/value.spec.d.ts.map +1 -0
  23. package/dist/src/index.d.ts +1 -0
  24. package/dist/src/index.d.ts.map +1 -1
  25. package/dist/src/label/types.gen.d.ts +2 -2
  26. package/dist/src/narrow/narrow.d.ts +9 -0
  27. package/dist/src/narrow/narrow.d.ts.map +1 -1
  28. package/dist/src/primitive/primitive.d.ts +10 -0
  29. package/dist/src/primitive/primitive.d.ts.map +1 -1
  30. package/dist/src/status/status.d.ts +14 -2
  31. package/dist/src/status/status.d.ts.map +1 -1
  32. package/dist/src/status/types.gen.d.ts +1 -1
  33. package/dist/src/strings/strings.d.ts +9 -0
  34. package/dist/src/strings/strings.d.ts.map +1 -1
  35. package/dist/src/telem/clockSkew.d.ts +17 -0
  36. package/dist/src/telem/clockSkew.d.ts.map +1 -0
  37. package/dist/src/telem/clockSkew.spec.d.ts +2 -0
  38. package/dist/src/telem/clockSkew.spec.d.ts.map +1 -0
  39. package/dist/src/telem/external.d.ts +1 -0
  40. package/dist/src/telem/external.d.ts.map +1 -1
  41. package/dist/src/telem/series.d.ts +5 -5
  42. package/dist/src/telem/series.d.ts.map +1 -1
  43. package/dist/src/telem/telem.d.ts +16 -15
  44. package/dist/src/telem/telem.d.ts.map +1 -1
  45. package/dist/src/zod/external.d.ts +1 -0
  46. package/dist/src/zod/external.d.ts.map +1 -1
  47. package/dist/src/zod/parse.d.ts +47 -0
  48. package/dist/src/zod/parse.d.ts.map +1 -0
  49. package/dist/src/zod/parse.spec.d.ts +2 -0
  50. package/dist/src/zod/parse.spec.d.ts.map +1 -0
  51. package/dist/x.cjs +13 -7
  52. package/dist/x.js +3277 -2892
  53. package/package.json +8 -8
  54. package/src/binary/codec.ts +3 -2
  55. package/src/deep/atKeys.spec.ts +107 -0
  56. package/src/deep/atKeys.ts +49 -0
  57. package/src/deep/external.ts +1 -0
  58. package/src/fmt/external.ts +11 -0
  59. package/src/fmt/index.ts +10 -0
  60. package/src/fmt/path.spec.ts +46 -0
  61. package/src/fmt/path.ts +30 -0
  62. package/src/fmt/value.spec.ts +206 -0
  63. package/src/fmt/value.ts +83 -0
  64. package/src/index.ts +1 -0
  65. package/src/narrow/narrow.spec.ts +43 -0
  66. package/src/narrow/narrow.ts +15 -0
  67. package/src/primitive/primitive.spec.ts +51 -0
  68. package/src/primitive/primitive.ts +12 -0
  69. package/src/status/status.spec.ts +146 -0
  70. package/src/status/status.ts +65 -18
  71. package/src/strings/strings.spec.ts +19 -0
  72. package/src/strings/strings.ts +16 -0
  73. package/src/telem/clockSkew.spec.ts +58 -0
  74. package/src/telem/clockSkew.ts +46 -0
  75. package/src/telem/external.ts +1 -0
  76. package/src/telem/series.spec.ts +52 -4
  77. package/src/telem/series.ts +118 -42
  78. package/src/telem/telem.spec.ts +19 -0
  79. package/src/telem/telem.ts +10 -5
  80. package/src/zod/external.ts +1 -0
  81. package/src/zod/parse.spec.ts +702 -0
  82. package/src/zod/parse.ts +519 -0
  83. package/tsconfig.tsbuildinfo +1 -1
@@ -114,7 +114,7 @@ const nullArrayZ = z
114
114
  .union([z.null(), z.undefined()])
115
115
  .transform(() => new Uint8Array().buffer);
116
116
 
117
- const NEW_LINE = 10;
117
+ const UINT32_SIZE = 4;
118
118
 
119
119
  type JSType = "string" | "number" | "bigint";
120
120
 
@@ -358,12 +358,42 @@ export class Series<T extends TelemValue = TelemValue>
358
358
  data_ = data_.map((v) => new TimeStamp(v as CrudeTimeStamp).valueOf());
359
359
  if (this.dataType.equals(DataType.STRING)) {
360
360
  this.cachedLength = data_.length;
361
- this._data = new TextEncoder().encode(`${data_.join("\n")}\n`).buffer;
361
+ const encoded = (data_ as string[]).map((s) => new TextEncoder().encode(s));
362
+ const totalBytes = encoded.reduce(
363
+ (acc, e) => acc + UINT32_SIZE + e.byteLength,
364
+ 0,
365
+ );
366
+ const buf = new ArrayBuffer(totalBytes);
367
+ const view = new DataView(buf);
368
+ const bytes = new Uint8Array(buf);
369
+ let offset = 0;
370
+ for (const e of encoded) {
371
+ view.setUint32(offset, e.byteLength, true);
372
+ offset += UINT32_SIZE;
373
+ bytes.set(e, offset);
374
+ offset += e.byteLength;
375
+ }
376
+ this._data = buf;
362
377
  } else if (this.dataType.equals(DataType.JSON)) {
363
378
  this.cachedLength = data_.length;
364
- this._data = new TextEncoder().encode(
365
- `${data_.map((d) => binary.JSON_CODEC.encodeString(d)).join("\n")}\n`,
366
- ).buffer;
379
+ const encoded = data_.map((d) =>
380
+ new TextEncoder().encode(binary.JSON_CODEC.encodeString(d)),
381
+ );
382
+ const totalBytes = encoded.reduce(
383
+ (acc, e) => acc + UINT32_SIZE + e.byteLength,
384
+ 0,
385
+ );
386
+ const buf = new ArrayBuffer(totalBytes);
387
+ const view = new DataView(buf);
388
+ const bytes = new Uint8Array(buf);
389
+ let offset = 0;
390
+ for (const e of encoded) {
391
+ view.setUint32(offset, e.byteLength, true);
392
+ offset += UINT32_SIZE;
393
+ bytes.set(e, offset);
394
+ offset += e.byteLength;
395
+ }
396
+ this._data = buf;
367
397
  } else if (this.dataType.usesBigInt && typeof first === "number")
368
398
  this._data = new this.dataType.Array(
369
399
  data_.map((v) => BigInt(Math.round(v as number))),
@@ -456,14 +486,25 @@ export class Series<T extends TelemValue = TelemValue>
456
486
  private writeVariable(other: Series): number {
457
487
  if (this.writePos === FULL_BUFFER) return 0;
458
488
  const available = this.byteCapacity.valueOf() - this.writePos;
459
- const toWrite = other.subBytes(0, available);
460
- this.writeToUnderlyingData(toWrite);
461
- this.writePos += toWrite.byteLength.valueOf();
462
- if (this.cachedLength != null) {
463
- this.cachedLength += toWrite.length;
464
- this.calculateCachedLength();
489
+ const otherBuf = other.buffer;
490
+ const otherByteLen = other.byteLength.valueOf();
491
+ const view = new DataView(otherBuf);
492
+ let offset = 0;
493
+ let samplesWritten = 0;
494
+ while (offset + UINT32_SIZE <= otherByteLen) {
495
+ const sampleLen = view.getUint32(offset, true);
496
+ const recordSize = UINT32_SIZE + sampleLen;
497
+ if (offset + recordSize > available) break;
498
+ offset += recordSize;
499
+ samplesWritten++;
465
500
  }
466
- return toWrite.length;
501
+ if (offset === 0) return 0;
502
+ const toWrite = other.subBytes(0, offset);
503
+ this.writeToUnderlyingData(toWrite);
504
+ this.writePos += offset;
505
+ this.cachedLength = (this.cachedLength ?? 0) + samplesWritten;
506
+ this._cachedIndexes = undefined;
507
+ return samplesWritten;
467
508
  }
468
509
 
469
510
  private writeFixed(other: Series): number {
@@ -511,8 +552,21 @@ export class Series<T extends TelemValue = TelemValue>
511
552
  * @returns An array of string representations of the series values.
512
553
  */
513
554
  toStrings(): string[] {
514
- if (this.dataType.isVariable)
515
- return new TextDecoder().decode(this.underlyingData).split("\n").slice(0, -1);
555
+ if (this.dataType.isVariable) {
556
+ const result: string[] = [];
557
+ const buf = this.buffer;
558
+ const byteLen = this.byteLength.valueOf();
559
+ const view = new DataView(buf);
560
+ const decoder = new TextDecoder();
561
+ let offset = 0;
562
+ while (offset + UINT32_SIZE <= byteLen) {
563
+ const len = view.getUint32(offset, true);
564
+ offset += UINT32_SIZE;
565
+ result.push(decoder.decode(new Uint8Array(buf, offset, len)));
566
+ offset += len;
567
+ }
568
+ return result;
569
+ }
516
570
  return Array.from(this).map((d) => d.toString());
517
571
  }
518
572
 
@@ -560,7 +614,7 @@ export class Series<T extends TelemValue = TelemValue>
560
614
 
561
615
  /**
562
616
  * Returns the number of samples in this array.
563
- * For variable length data types, this is calculated by counting newlines.
617
+ * For variable length data types, this is calculated by scanning uint32 length prefixes.
564
618
  * @returns The number of samples in the series.
565
619
  */
566
620
  get length(): number {
@@ -575,12 +629,18 @@ export class Series<T extends TelemValue = TelemValue>
575
629
  if (!this.dataType.isVariable)
576
630
  throw new Error("cannot calculate length of a non-variable length data type");
577
631
  let cl = 0;
578
- const ci: number[] = [0];
579
- this.data.forEach((v, i) => {
580
- if (v !== NEW_LINE) return;
632
+ const ci: number[] = [];
633
+ const buf = this.buffer;
634
+ const byteLen = this.byteLength.valueOf();
635
+ const view = new DataView(buf);
636
+ let offset = 0;
637
+ while (offset + UINT32_SIZE <= byteLen) {
638
+ const len = view.getUint32(offset, true);
639
+ offset += UINT32_SIZE;
640
+ ci.push(offset);
641
+ offset += len;
581
642
  cl++;
582
- ci.push(i + 1);
583
- });
643
+ }
584
644
  this._cachedIndexes = ci;
585
645
  this.cachedLength = cl;
586
646
  return cl;
@@ -742,28 +802,40 @@ export class Series<T extends TelemValue = TelemValue>
742
802
 
743
803
  private atVariable(index: number, required: boolean): T | undefined {
744
804
  let start = 0;
745
- let end = 0;
805
+ let len = 0;
806
+ const buf = this.buffer;
807
+ const view = new DataView(buf);
746
808
  if (this._cachedIndexes != null) {
809
+ if (index < 0) index = this._cachedIndexes.length + index;
810
+ if (index < 0 || index >= this._cachedIndexes.length) {
811
+ if (required) throw new Error(`[series] - no value at index ${index}`);
812
+ return undefined;
813
+ }
747
814
  start = this._cachedIndexes[index];
748
- end = this._cachedIndexes[index + 1] - 1;
815
+ len = view.getUint32(start - UINT32_SIZE, true);
749
816
  } else {
750
817
  if (index < 0) index = this.length + index;
751
- for (let i = 0; i < this.data.length; i++)
752
- if (this.data[i] === NEW_LINE) {
753
- if (index === 0) {
754
- end = i;
755
- break;
756
- }
757
- start = i + 1;
758
- index--;
818
+ const byteLen = this.byteLength.valueOf();
819
+ let offset = 0;
820
+ let found = false;
821
+ while (offset + UINT32_SIZE <= byteLen) {
822
+ const sampleLen = view.getUint32(offset, true);
823
+ offset += UINT32_SIZE;
824
+ if (index === 0) {
825
+ start = offset;
826
+ len = sampleLen;
827
+ found = true;
828
+ break;
759
829
  }
760
- if (end === 0) end = this.data.length;
761
- if (start >= end || index > 0) {
830
+ offset += sampleLen;
831
+ index--;
832
+ }
833
+ if (!found) {
762
834
  if (required) throw new Error(`[series] - no value at index ${index}`);
763
835
  return undefined;
764
836
  }
765
837
  }
766
- const slice = this.data.slice(start, end);
838
+ const slice = new Uint8Array(buf, start, len);
767
839
  if (this.dataType.equals(DataType.STRING))
768
840
  return new TextDecoder().decode(slice) as T;
769
841
  return caseconv.snakeToCamel(JSON.parse(new TextDecoder().decode(slice))) as T;
@@ -1069,8 +1141,9 @@ class SubIterator<T> implements Iterator<T> {
1069
1141
 
1070
1142
  class StringSeriesIterator implements Iterator<string> {
1071
1143
  private readonly series: Series;
1072
- private index: number;
1144
+ private byteOffset: number;
1073
1145
  private readonly decoder: TextDecoder;
1146
+ private readonly view: DataView;
1074
1147
 
1075
1148
  constructor(series: Series) {
1076
1149
  if (!series.dataType.isVariable)
@@ -1078,18 +1151,21 @@ class StringSeriesIterator implements Iterator<string> {
1078
1151
  "cannot create a variable series iterator for a non-variable series",
1079
1152
  );
1080
1153
  this.series = series;
1081
- this.index = 0;
1154
+ this.byteOffset = 0;
1082
1155
  this.decoder = new TextDecoder();
1156
+ this.view = new DataView(series.buffer);
1083
1157
  }
1084
1158
 
1085
1159
  next(): IteratorResult<string> {
1086
- const start = this.index;
1087
- const data = this.series.data;
1088
- while (this.index < data.length && data[this.index] !== NEW_LINE) this.index++;
1089
- const end = this.index;
1090
- if (start === end) return { done: true, value: undefined };
1091
- this.index++;
1092
- const s = this.decoder.decode(this.series.buffer.slice(start, end));
1160
+ const byteLen = this.series.byteLength.valueOf();
1161
+ if (this.byteOffset + UINT32_SIZE > byteLen)
1162
+ return { done: true, value: undefined };
1163
+ const len = this.view.getUint32(this.byteOffset, true);
1164
+ this.byteOffset += UINT32_SIZE;
1165
+ const s = this.decoder.decode(
1166
+ new Uint8Array(this.series.buffer, this.byteOffset, len),
1167
+ );
1168
+ this.byteOffset += len;
1093
1169
  return { done: false, value: s };
1094
1170
  }
1095
1171
  }
@@ -1057,6 +1057,25 @@ describe("TimeSpan", () => {
1057
1057
  expect(result.valueOf()).toBe(700n);
1058
1058
  });
1059
1059
 
1060
+ test("abs of positive value", () => {
1061
+ const ts = new TimeSpan(1000);
1062
+ expect(ts.abs().valueOf()).toBe(1000n);
1063
+ });
1064
+
1065
+ test("abs of negative value", () => {
1066
+ const ts = new TimeSpan(-500);
1067
+ expect(ts.abs().valueOf()).toBe(500n);
1068
+ });
1069
+
1070
+ test("abs of zero", () => {
1071
+ expect(TimeSpan.ZERO.abs().valueOf()).toBe(0n);
1072
+ });
1073
+
1074
+ test("abs returns TimeSpan instance", () => {
1075
+ const ts = new TimeSpan(-1000);
1076
+ expect(ts.abs()).toBeInstanceOf(TimeSpan);
1077
+ });
1078
+
1060
1079
  test("mult", () => {
1061
1080
  const ts = new TimeSpan(1000);
1062
1081
  const result = ts.mult(2);
@@ -1190,6 +1190,11 @@ export class TimeSpan
1190
1190
  return new TimeSpan(this.valueOf() - new TimeSpan(other).valueOf());
1191
1191
  }
1192
1192
 
1193
+ abs(): TimeSpan {
1194
+ const v = this.valueOf();
1195
+ return new TimeSpan(v < 0n ? -v : v);
1196
+ }
1197
+
1193
1198
  /**
1194
1199
  * Creates a TimeSpan representing the given number of nanoseconds.
1195
1200
  *
@@ -2014,14 +2019,14 @@ export class DataType
2014
2019
  static readonly TIMESTAMP = new DataType("timestamp");
2015
2020
  /** Represents a UUID data type. */
2016
2021
  static readonly UUID = new DataType("uuid");
2017
- /** Represents a string data type. Strings have an unknown density, and are separate
2018
- * by a newline character. */
2022
+ /** Represents a string data type. Strings have an unknown density and are encoded
2023
+ * as uint32-length-prefixed samples. */
2019
2024
  static readonly STRING = new DataType("string");
2020
- /** Represents a JSON data type. JSON has an unknown density, and is separated by a
2021
- * newline character. */
2025
+ /** Represents a JSON data type. JSON has an unknown density and is encoded as
2026
+ * uint32-length-prefixed samples. */
2022
2027
  static readonly JSON = new DataType("json");
2023
2028
  /** Represents a bytes data type for arbitrary byte arrays. Bytes have an unknown
2024
- * density, and are separated by a newline character. */
2029
+ * density and are encoded as uint32-length-prefixed samples. */
2025
2030
  static readonly BYTES = new DataType("bytes");
2026
2031
 
2027
2032
  private static readonly ARRAY_CONSTRUCTORS: Map<string, TypedArrayConstructor> =
@@ -8,6 +8,7 @@
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
10
  export * from "@/zod/nullToUndefined";
11
+ export * from "@/zod/parse";
11
12
  export * from "@/zod/schemas";
12
13
  export * from "@/zod/toArray";
13
14
  export * from "@/zod/util";