@synnaxlabs/x 0.45.1 → 0.46.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 (116) hide show
  1. package/.turbo/turbo-build.log +33 -31
  2. package/dist/array.cjs +1 -1
  3. package/dist/array.js +2 -5
  4. package/dist/binary.cjs +1 -1
  5. package/dist/binary.js +1 -1
  6. package/dist/box-BXWXSkKu.js +203 -0
  7. package/dist/box-rH3ggwXk.cjs +1 -0
  8. package/dist/box.cjs +1 -1
  9. package/dist/box.js +1 -1
  10. package/dist/caseconv.cjs +1 -1
  11. package/dist/caseconv.js +1 -1
  12. package/dist/deep.cjs +1 -1
  13. package/dist/deep.js +1 -1
  14. package/dist/{external-tyaEMW4S.js → external-2YWy569j.js} +3 -3
  15. package/dist/{external-uXk0Avrg.cjs → external-B6edOwoQ.cjs} +1 -1
  16. package/dist/{external-BPgtxa8d.js → external-B80i4ymZ.js} +2 -2
  17. package/dist/external-BxmTQZ6m.cjs +1 -0
  18. package/dist/external-DLiGrXn7.cjs +1 -0
  19. package/dist/external-Du5qzfYv.js +35 -0
  20. package/dist/get-CtJEJIC_.js +82 -0
  21. package/dist/get-D2VRwUw4.cjs +1 -0
  22. package/dist/{index-CwGPVvbl.cjs → index-Bfvg0v-N.cjs} +1 -1
  23. package/dist/{index-uDxeM-cl.cjs → index-CyNZHQFw.cjs} +1 -1
  24. package/dist/{index-Bxlv0uf_.js → index-qmkoZBNO.js} +1 -1
  25. package/dist/{index-BHXRDFYj.js → index-yz34Wc2p.js} +1 -1
  26. package/dist/index.cjs +3 -3
  27. package/dist/index.js +411 -378
  28. package/dist/{location-BPoXwOni.cjs → location-0qDBiCqP.cjs} +1 -1
  29. package/dist/{location-CVxysrHI.js → location-BIzpxczO.js} +1 -1
  30. package/dist/location.cjs +1 -1
  31. package/dist/location.js +1 -1
  32. package/dist/runtime.cjs +1 -1
  33. package/dist/runtime.js +1 -1
  34. package/dist/{scale-DjxC6ep2.js → scale-BBWhTUqJ.js} +3 -3
  35. package/dist/{scale-BHs716im.cjs → scale-BXy1w8R_.cjs} +1 -1
  36. package/dist/scale.cjs +1 -1
  37. package/dist/scale.js +1 -1
  38. package/dist/series-B2zqvP8A.cjs +6 -0
  39. package/dist/{series-W5Aafjeu.js → series-Clbw-fZI.js} +543 -451
  40. package/dist/spatial.cjs +1 -1
  41. package/dist/spatial.js +4 -4
  42. package/dist/src/array/external.d.ts +4 -0
  43. package/dist/src/array/external.d.ts.map +1 -0
  44. package/dist/src/array/index.d.ts +1 -1
  45. package/dist/src/array/index.d.ts.map +1 -1
  46. package/dist/src/array/nullable.d.ts +3 -0
  47. package/dist/src/array/nullable.d.ts.map +1 -0
  48. package/dist/src/array/update.d.ts +14 -0
  49. package/dist/src/array/update.d.ts.map +1 -0
  50. package/dist/src/array/update.spec.d.ts +2 -0
  51. package/dist/src/array/update.spec.d.ts.map +1 -0
  52. package/dist/src/index.d.ts +1 -0
  53. package/dist/src/index.d.ts.map +1 -1
  54. package/dist/src/label/index.d.ts +2 -0
  55. package/dist/src/label/index.d.ts.map +1 -0
  56. package/dist/src/label/label.d.ts +11 -0
  57. package/dist/src/label/label.d.ts.map +1 -0
  58. package/dist/src/math/constants.d.ts +16 -0
  59. package/dist/src/math/constants.d.ts.map +1 -0
  60. package/dist/src/math/external.d.ts +1 -0
  61. package/dist/src/math/external.d.ts.map +1 -1
  62. package/dist/src/migrate/migrate.d.ts +1 -1
  63. package/dist/src/spatial/box/box.d.ts.map +1 -1
  64. package/dist/src/spatial/xy/xy.d.ts +10 -0
  65. package/dist/src/spatial/xy/xy.d.ts.map +1 -1
  66. package/dist/src/status/status.d.ts +25 -15
  67. package/dist/src/status/status.d.ts.map +1 -1
  68. package/dist/src/strings/strings.d.ts +1 -0
  69. package/dist/src/strings/strings.d.ts.map +1 -1
  70. package/dist/src/telem/series.d.ts +4 -4
  71. package/dist/src/telem/series.d.ts.map +1 -1
  72. package/dist/src/telem/telem.d.ts +35 -29
  73. package/dist/src/telem/telem.d.ts.map +1 -1
  74. package/dist/telem.cjs +1 -1
  75. package/dist/telem.js +14 -13
  76. package/dist/{xy-DWwtHmgn.cjs → xy-C-MUIjVs.cjs} +1 -1
  77. package/dist/{xy-DYPw8-8C.js → xy-DnrCAZaw.js} +16 -9
  78. package/dist/xy.cjs +1 -1
  79. package/dist/xy.js +1 -1
  80. package/dist/zod.cjs +1 -1
  81. package/dist/zod.js +1 -1
  82. package/package.json +8 -8
  83. package/src/array/external.ts +12 -0
  84. package/src/array/index.ts +1 -1
  85. package/src/array/nullable.ts +7 -0
  86. package/src/array/update.spec.ts +133 -0
  87. package/src/array/update.ts +66 -0
  88. package/src/caseconv/caseconv.spec.ts +2 -0
  89. package/src/caseconv/caseconv.ts +9 -9
  90. package/src/deep/partial.spec.ts +9 -9
  91. package/src/deep/path.spec.ts +5 -2
  92. package/src/index.ts +1 -0
  93. package/src/label/index.ts +10 -0
  94. package/src/label/label.ts +20 -0
  95. package/src/math/constants.ts +29 -0
  96. package/src/math/external.ts +1 -0
  97. package/src/spatial/box/box.ts +1 -2
  98. package/src/spatial/xy/xy.ts +18 -1
  99. package/src/status/status.ts +47 -27
  100. package/src/strings/strings.spec.ts +42 -0
  101. package/src/strings/strings.ts +14 -0
  102. package/src/telem/series.ts +2 -3
  103. package/src/telem/telem.spec.ts +155 -18
  104. package/src/telem/telem.ts +185 -56
  105. package/src/testutil/testutil.spec.ts +1 -1
  106. package/src/zod/nullToUndefined.spec.ts +2 -2
  107. package/src/zod/toArray.spec.ts +9 -3
  108. package/tsconfig.tsbuildinfo +1 -1
  109. package/.vscode/settings.json +0 -5
  110. package/README.md +0 -38
  111. package/dist/box-BYuq-Gjx.js +0 -203
  112. package/dist/box-Blu-4d1n.cjs +0 -1
  113. package/dist/external-CtHGFcox.cjs +0 -1
  114. package/dist/get-CXkBfLu1.js +0 -82
  115. package/dist/get-OP63N4c3.cjs +0 -1
  116. package/dist/series-C6ZwNf8i.cjs +0 -6
@@ -16,6 +16,9 @@ import { type bounds } from "@/spatial";
16
16
  /** Time zone specification when working with time stamps. */
17
17
  export type TZInfo = "UTC" | "local";
18
18
 
19
+ const SIMPLE_DAYS_IN_YEAR = 365;
20
+ const SIMPLE_DAYS_IN_MONTH = 30;
21
+
19
22
  /** Different string formats for time stamps. */
20
23
  export type TimeStampStringFormat =
21
24
  | "ISO"
@@ -28,6 +31,9 @@ export type TimeStampStringFormat =
28
31
  | "shortDate"
29
32
  | "dateTime";
30
33
 
34
+ /** Different string formats for time spans. */
35
+ export type TimeSpanStringFormat = "full" | "semantic";
36
+
31
37
  const dateComponentsZ = z.union([
32
38
  z.tuple([z.int()]),
33
39
  z.tuple([z.int(), z.int().min(1).max(12)]),
@@ -103,7 +109,9 @@ export class TimeStamp
103
109
  if (value instanceof Number) value = value.valueOf();
104
110
  if (tzInfo === "local") offset = TimeStamp.utcOffset.valueOf();
105
111
  if (typeof value === "number")
106
- if (isFinite(value)) value = Math.trunc(value);
112
+ if (isFinite(value))
113
+ if (value === math.MAX_INT64_NUMBER) value = math.MAX_INT64;
114
+ else value = Math.trunc(value);
107
115
  else {
108
116
  if (isNaN(value)) value = 0;
109
117
  if (value === Infinity) value = TimeStamp.MAX;
@@ -156,34 +164,6 @@ export class TimeStamp
156
164
  ).valueOf();
157
165
  }
158
166
 
159
- /**
160
- * Formats the TimeStamp as a string in the specified format.
161
- *
162
- * @param format - The format to use for the string representation.
163
- * @param tzInfo - The timezone to use when creating the string representation.
164
- * @returns A string representation of the TimeStamp in the specified format.
165
- */
166
- fString(format: TimeStampStringFormat = "ISO", tzInfo: TZInfo = "UTC"): string {
167
- switch (format) {
168
- case "ISODate":
169
- return this.toISOString(tzInfo).slice(0, 10);
170
- case "ISOTime":
171
- return this.toISOString(tzInfo).slice(11, 23);
172
- case "time":
173
- return this.timeString(false, tzInfo);
174
- case "preciseTime":
175
- return this.timeString(true, tzInfo);
176
- case "date":
177
- return this.dateString();
178
- case "preciseDate":
179
- return `${this.dateString()} ${this.timeString(true, tzInfo)}`;
180
- case "dateTime":
181
- return `${this.dateString()} ${this.timeString(false, tzInfo)}`;
182
- default:
183
- return this.toISOString(tzInfo);
184
- }
185
- }
186
-
187
167
  private toISOString(tzInfo: TZInfo = "UTC"): string {
188
168
  if (tzInfo === "UTC") return this.date().toISOString();
189
169
  return this.sub(TimeStamp.utcOffset).date().toISOString();
@@ -213,7 +193,7 @@ export class TimeStamp
213
193
  * the other timestamp.
214
194
  * @param other - The other timestamp.
215
195
  */
216
- static since(other: TimeStamp): TimeSpan {
196
+ static since(other: CrudeTimeStamp): TimeSpan {
217
197
  return new TimeStamp().span(other);
218
198
  }
219
199
 
@@ -505,8 +485,8 @@ export class TimeStamp
505
485
  }
506
486
 
507
487
  /**
508
- * @reutrns the integer millisecond that the timestamp corresponds to within
509
- * its second.
488
+ * @returns the integer millisecond that the timestamp corresponds to within its
489
+ * second.
510
490
  */
511
491
  get millisecond(): number {
512
492
  return this.date().getUTCMilliseconds();
@@ -522,9 +502,32 @@ export class TimeStamp
522
502
  return new TimeStamp(d);
523
503
  }
524
504
 
525
- /** @returns the time stamp formatted as an ISO string. */
526
- toString(): string {
527
- return this.date().toISOString();
505
+ /**
506
+ * Returns a string representation of the TimeStamp.
507
+ *
508
+ * @param format - Optional format for the string representation. Defaults to "ISO".
509
+ * @param tzInfo - Optional timezone info. Defaults to "UTC".
510
+ * @returns A string representation of the TimeStamp.
511
+ */
512
+ toString(format: TimeStampStringFormat = "ISO", tzInfo: TZInfo = "UTC"): string {
513
+ switch (format) {
514
+ case "ISODate":
515
+ return this.toISOString(tzInfo).slice(0, 10);
516
+ case "ISOTime":
517
+ return this.toISOString(tzInfo).slice(11, 23);
518
+ case "time":
519
+ return this.timeString(false, tzInfo);
520
+ case "preciseTime":
521
+ return this.timeString(true, tzInfo);
522
+ case "date":
523
+ return this.dateString();
524
+ case "preciseDate":
525
+ return `${this.dateString()} ${this.timeString(true, tzInfo)}`;
526
+ case "dateTime":
527
+ return `${this.dateString()} ${this.timeString(false, tzInfo)}`;
528
+ default:
529
+ return this.toISOString(tzInfo);
530
+ }
528
531
  }
529
532
 
530
533
  /**
@@ -658,7 +661,7 @@ export class TimeStamp
658
661
  static readonly DAY = TimeStamp.days(1);
659
662
 
660
663
  /** The maximum possible value for a timestamp */
661
- static readonly MAX = new TimeStamp((1n << 63n) - 1n);
664
+ static readonly MAX = new TimeStamp(math.MAX_INT64);
662
665
 
663
666
  /** The minimum possible value for a timestamp */
664
667
  static readonly MIN = new TimeStamp(0);
@@ -805,9 +808,15 @@ export class TimeSpan
805
808
  /**
806
809
  * Returns a string representation of the TimeSpan.
807
810
  *
811
+ * @param format - Optional format for the string representation. Defaults to "full".
812
+ * - "full": Shows all non-zero units with full precision (e.g., "2d 3h 45m 12s 500ms")
813
+ * - "semantic": Shows 1-2 most significant units (e.g., "2d 3h")
808
814
  * @returns A string representation of the TimeSpan.
809
815
  */
810
- toString(): string {
816
+ toString(format: TimeSpanStringFormat = "full"): string {
817
+ if (format === "semantic") return this.toSemanticString();
818
+
819
+ // Default "full" format
811
820
  const totalDays = this.truncate(TimeSpan.DAY);
812
821
  const totalHours = this.truncate(TimeSpan.HOUR);
813
822
  const totalMinutes = this.truncate(TimeSpan.MINUTE);
@@ -834,6 +843,107 @@ export class TimeSpan
834
843
  return str.trim();
835
844
  }
836
845
 
846
+ private toSemanticString(): string {
847
+ const absValue = this.valueOf() < 0n ? -this.valueOf() : this.valueOf();
848
+ const span = new TimeSpan(absValue);
849
+ const isNegative = this.valueOf() < 0n;
850
+
851
+ if (span.valueOf() === 0n) return "0s";
852
+
853
+ if (span.lessThan(TimeSpan.SECOND)) return "< 1s";
854
+
855
+ const totalDays = span.days;
856
+ const totalHours = span.hours;
857
+ const totalMinutes = span.minutes;
858
+ const totalSeconds = span.seconds;
859
+
860
+ const years = Math.floor(totalDays / SIMPLE_DAYS_IN_YEAR);
861
+ const months = Math.floor(totalDays / SIMPLE_DAYS_IN_MONTH);
862
+ const weeks = Math.floor(totalDays / 7);
863
+ const days = Math.floor(totalDays);
864
+ const hours = Math.floor(totalHours);
865
+ const minutes = Math.floor(totalMinutes);
866
+ const seconds = Math.floor(totalSeconds);
867
+
868
+ const prefix = isNegative ? "-" : "";
869
+
870
+ if (years >= 1) {
871
+ let result = `${years}y`;
872
+ if (years < 2) {
873
+ const remainingMonths = Math.floor(
874
+ (totalDays % SIMPLE_DAYS_IN_YEAR) / SIMPLE_DAYS_IN_MONTH,
875
+ );
876
+ if (remainingMonths > 0) result += ` ${remainingMonths}mo`;
877
+ }
878
+ return prefix + result;
879
+ }
880
+
881
+ // For durations less than 1 month (30 days), prefer weeks if it's exactly divisible
882
+ if (weeks >= 1 && totalDays < SIMPLE_DAYS_IN_MONTH && totalDays % 7 === 0) {
883
+ let result = `${weeks}w`;
884
+ const remainingDays = Math.floor(totalDays % 7);
885
+ const remainingHoursAfterWeeks = Math.floor(totalHours - weeks * 7 * 24);
886
+
887
+ if (weeks < 2)
888
+ if (remainingDays > 0) result += ` ${remainingDays}d`;
889
+ else if (remainingHoursAfterWeeks > 0 && remainingHoursAfterWeeks < 24)
890
+ // Only hours remaining after full weeks (e.g., "1w 1h")
891
+ result += ` ${remainingHoursAfterWeeks}h`;
892
+
893
+ return prefix + result;
894
+ }
895
+
896
+ if (months >= 1) {
897
+ let result = `${months}mo`;
898
+ if (months < 3) {
899
+ const remainingDays = Math.floor(totalDays % SIMPLE_DAYS_IN_MONTH);
900
+ if (remainingDays > 0) result += ` ${remainingDays}d`;
901
+ }
902
+ return prefix + result;
903
+ }
904
+
905
+ if (weeks >= 1) {
906
+ let result = `${weeks}w`;
907
+ const remainingDays = Math.floor(totalDays % 7);
908
+ const remainingHoursAfterWeeks = Math.floor(totalHours - weeks * 7 * 24);
909
+
910
+ if (weeks < 2)
911
+ if (remainingDays > 0) result += ` ${remainingDays}d`;
912
+ else if (remainingHoursAfterWeeks > 0 && remainingHoursAfterWeeks < 24)
913
+ // Only hours remaining after full weeks (e.g., "1w 1h")
914
+ result += ` ${remainingHoursAfterWeeks}h`;
915
+
916
+ return prefix + result;
917
+ }
918
+
919
+ if (days >= 1) {
920
+ let result = `${days}d`;
921
+ const remainingHours = Math.floor(totalHours - days * 24);
922
+ if (days < 2 && remainingHours > 0) result += ` ${remainingHours}h`;
923
+ return prefix + result;
924
+ }
925
+
926
+ if (hours >= 1) {
927
+ let result = `${hours}h`;
928
+ if (hours < 3) {
929
+ const remainingMinutes = Math.floor(totalMinutes - hours * 60);
930
+ if (remainingMinutes > 0) result += ` ${remainingMinutes}m`;
931
+ }
932
+ return prefix + result;
933
+ }
934
+
935
+ if (minutes >= 1) {
936
+ let result = `${minutes}m`;
937
+ if (minutes < 5) {
938
+ const remainingSeconds = Math.floor(totalSeconds - minutes * 60);
939
+ if (remainingSeconds > 0) result += ` ${remainingSeconds}s`;
940
+ }
941
+ return prefix + result;
942
+ }
943
+
944
+ return `${prefix}${seconds}s`;
945
+ }
946
+
837
947
  /**
838
948
  * Multiplies the TimeSpan by a scalar value.
839
949
  *
@@ -1017,7 +1127,7 @@ export class TimeSpan
1017
1127
  static readonly DAY = TimeSpan.days(1);
1018
1128
 
1019
1129
  /** The maximum possible value for a TimeSpan. */
1020
- static readonly MAX = new TimeSpan((1n << 63n) - 1n);
1130
+ static readonly MAX = new TimeSpan(math.MAX_INT64);
1021
1131
 
1022
1132
  /** The minimum possible value for a TimeSpan. */
1023
1133
  static readonly MIN = new TimeSpan(0);
@@ -1025,7 +1135,7 @@ export class TimeSpan
1025
1135
  /** The zero value for a TimeSpan. */
1026
1136
  static readonly ZERO = new TimeSpan(0);
1027
1137
 
1028
- /** A zod schema for validating and transforming timespans */
1138
+ /** A zod schema for validating and transforming time spans */
1029
1139
  static readonly z = z.union([
1030
1140
  z.object({ value: z.bigint() }).transform((v) => new TimeSpan(v.value)),
1031
1141
  z.string().transform((n) => new TimeSpan(BigInt(n))),
@@ -1344,12 +1454,12 @@ export class TimeRange implements primitive.Stringer {
1344
1454
  }
1345
1455
 
1346
1456
  /**
1347
- * Checks if the TimeRange has a zero span.
1457
+ * Checks if the TimeRange is zero (both start and end are TimeStamp.ZERO).
1348
1458
  *
1349
- * @returns True if the TimeRange has a zero span.
1459
+ * @returns True if both start and end are TimeStamp.ZERO, false otherwise.
1350
1460
  */
1351
1461
  get isZero(): boolean {
1352
- return this.span.isZero;
1462
+ return this.start.isZero && this.end.isZero;
1353
1463
  }
1354
1464
 
1355
1465
  /**
@@ -1406,7 +1516,7 @@ export class TimeRange implements primitive.Stringer {
1406
1516
  * @returns A pretty string representation of the TimeRange.
1407
1517
  */
1408
1518
  toPrettyString(): string {
1409
- return `${this.start.fString("preciseDate")} - ${this.span.toString()}`;
1519
+ return `${this.start.toString("preciseDate")} - ${this.span.toString()}`;
1410
1520
  }
1411
1521
 
1412
1522
  /**
@@ -1495,9 +1605,6 @@ export class TimeRange implements primitive.Stringer {
1495
1605
  /** The maximum possible time range. */
1496
1606
  static readonly MAX = new TimeRange(TimeStamp.MIN, TimeStamp.MAX);
1497
1607
 
1498
- /** The minimum possible time range. */
1499
- static readonly MIN = new TimeRange(TimeStamp.MAX, TimeStamp.MIN);
1500
-
1501
1608
  /** A time range whose start and end are both zero. */
1502
1609
  static readonly ZERO = new TimeRange(TimeStamp.ZERO, TimeStamp.ZERO);
1503
1610
 
@@ -1536,7 +1643,7 @@ export class TimeRange implements primitive.Stringer {
1536
1643
  .map((r) => r.makeValid())
1537
1644
  .sort((a, b) => TimeRange.sort(a, b))
1538
1645
  .reduce<TimeRange[]>((simplified, range) => {
1539
- if (range.isZero) return simplified;
1646
+ if (range.span.isZero) return simplified;
1540
1647
  if (simplified.length === 0) {
1541
1648
  simplified.push(range);
1542
1649
  return simplified;
@@ -1595,8 +1702,10 @@ export class DataType
1595
1702
  return others.some((o) => this.equals(o));
1596
1703
  }
1597
1704
 
1598
- /** @returns a string representation of the DataType. */
1599
- toString(): string {
1705
+ /** @returns a string representation of the DataType. If short is true, a 1-4
1706
+ * character representation (i64, str, etc.) is returned instead. */
1707
+ toString(short: boolean = false): string {
1708
+ if (short) return DataType.SHORT_STRINGS.get(this.valueOf()) ?? this.valueOf();
1600
1709
  return this.valueOf();
1601
1710
  }
1602
1711
 
@@ -1739,11 +1848,11 @@ export class DataType
1739
1848
  static readonly UINT16 = new DataType("uint16");
1740
1849
  /** Represents a 8-bit unsigned integer value. */
1741
1850
  static readonly UINT8 = new DataType("uint8");
1742
- /** Represents a boolean value. Alias for UINT8. */
1743
- static readonly BOOLEAN = this.UINT8;
1851
+ /** Represents a boolean value. Stored as a 8-bit unsigned integer. */
1852
+ static readonly BOOLEAN = new DataType("boolean");
1744
1853
  /** Represents a 64-bit unix epoch. */
1745
1854
  static readonly TIMESTAMP = new DataType("timestamp");
1746
- /** Represents a UUID data type */
1855
+ /** Represents a UUID data type. */
1747
1856
  static readonly UUID = new DataType("uuid");
1748
1857
  /** Represents a string data type. Strings have an unknown density, and are separate
1749
1858
  * by a newline character. */
@@ -1822,6 +1931,24 @@ export class DataType
1822
1931
  DataType.JSON,
1823
1932
  ];
1824
1933
 
1934
+ private static readonly SHORT_STRINGS = new Map<string, string>([
1935
+ [DataType.UINT8.toString(), "u8"],
1936
+ [DataType.UINT16.toString(), "u16"],
1937
+ [DataType.UINT32.toString(), "u32"],
1938
+ [DataType.UINT64.toString(), "u64"],
1939
+ [DataType.INT8.toString(), "i8"],
1940
+ [DataType.INT16.toString(), "i16"],
1941
+ [DataType.INT32.toString(), "i32"],
1942
+ [DataType.INT64.toString(), "i64"],
1943
+ [DataType.FLOAT32.toString(), "f32"],
1944
+ [DataType.FLOAT64.toString(), "f64"],
1945
+ [DataType.BOOLEAN.toString(), "bool"],
1946
+ [DataType.TIMESTAMP.toString(), "ts"],
1947
+ [DataType.UUID.toString(), "uuid"],
1948
+ [DataType.STRING.toString(), "str"],
1949
+ [DataType.JSON.toString(), "json"],
1950
+ ]);
1951
+
1825
1952
  static readonly BIG_INT_TYPES = [DataType.INT64, DataType.UINT64, DataType.TIMESTAMP];
1826
1953
 
1827
1954
  /** A zod schema for a DataType. */
@@ -2055,14 +2182,16 @@ export interface CrudeTimeRange {
2055
2182
  end: CrudeTimeStamp;
2056
2183
  }
2057
2184
 
2185
+ export const numericTimeRangeZ = z.object({
2186
+ start: z.number(),
2187
+ end: z.number(),
2188
+ });
2189
+
2058
2190
  /**
2059
2191
  * A time range backed by numbers instead of TimeStamps/BigInts.
2060
2192
  * Involves a loss of precision, but can be useful for serialization.
2061
2193
  */
2062
- export interface NumericTimeRange {
2063
- start: number;
2064
- end: number;
2065
- }
2194
+ export interface NumericTimeRange extends z.infer<typeof numericTimeRangeZ> {}
2066
2195
 
2067
2196
  export const typedArrayZ = z.union([
2068
2197
  z.instanceof(Uint8Array),
@@ -18,7 +18,7 @@ describe("testutil", () => {
18
18
  expect(testutil.toString(123)).toBe("123");
19
19
  expect(testutil.toString(true)).toBe("true");
20
20
  expect(testutil.toString(null)).toBe("null");
21
- expect(testutil.toString(undefined)).toBe(undefined);
21
+ expect(testutil.toString(undefined)).toBeUndefined();
22
22
  });
23
23
 
24
24
  it("should handle arrays", () => {
@@ -19,10 +19,10 @@ describe("zod", () => {
19
19
  expect(schema.parse("string")).toBe("string");
20
20
  });
21
21
  it("should parse null as undefined", () => {
22
- expect(schema.parse(null)).toBe(undefined);
22
+ expect(schema.parse(null)).toBeUndefined();
23
23
  });
24
24
  it("should parse undefined as undefined", () => {
25
- expect(schema.parse(undefined)).toBe(undefined);
25
+ expect(schema.parse(undefined)).toBeUndefined();
26
26
  });
27
27
  it("should throw for other values", () => {
28
28
  expect(() => schema.parse(1)).toThrow(z.ZodError);
@@ -162,8 +162,14 @@ describe("toArray", () => {
162
162
  describe("edge cases", () => {
163
163
  it("should handle deeply nested arrays", () => {
164
164
  const schema = toArray(toArray(z.number()));
165
- const result = schema.parse([[1, 2], [3, 4]]);
166
- expect(result).toEqual([[1, 2], [3, 4]]);
165
+ const result = schema.parse([
166
+ [1, 2],
167
+ [3, 4],
168
+ ]);
169
+ expect(result).toEqual([
170
+ [1, 2],
171
+ [3, 4],
172
+ ]);
167
173
  });
168
174
 
169
175
  it("should convert single value to nested array", () => {
@@ -179,4 +185,4 @@ describe("toArray", () => {
179
185
  expect(result).toEqual(input);
180
186
  });
181
187
  });
182
- });
188
+ });