@synnaxlabs/x 0.42.1 → 0.43.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 (296) hide show
  1. package/.turbo/turbo-build.log +93 -105
  2. package/.vscode/settings.json +4 -6
  3. package/README.md +1 -7
  4. package/dist/array.cjs +1 -0
  5. package/dist/array.js +7 -0
  6. package/dist/base-B5lQIJKc.js +38 -0
  7. package/dist/base-CTq-lhpU.cjs +1 -0
  8. package/dist/binary.cjs +1 -1
  9. package/dist/binary.js +1 -1
  10. package/dist/bounds.cjs +1 -1
  11. package/dist/bounds.js +2 -2
  12. package/dist/box.cjs +1 -1
  13. package/dist/box.js +1 -1
  14. package/dist/caseconv.cjs +1 -1
  15. package/dist/caseconv.js +2 -2
  16. package/dist/change.cjs +1 -1
  17. package/dist/change.js +10 -2
  18. package/dist/compare.cjs +1 -1
  19. package/dist/compare.js +1 -1
  20. package/dist/deep.cjs +1 -1
  21. package/dist/deep.js +92 -79
  22. package/dist/dimensions.cjs +1 -1
  23. package/dist/dimensions.js +41 -2
  24. package/dist/direction.cjs +1 -1
  25. package/dist/direction.js +1 -1
  26. package/dist/index-4GlOgZuh.js +99 -0
  27. package/dist/{direction-C-b6XTeU.cjs → index-B58dnYRu.cjs} +1 -1
  28. package/dist/index-BMGaoK93.cjs +1 -0
  29. package/dist/index-BTet04Hd.cjs +6 -0
  30. package/dist/{scale-DfJe9755.js → index-BUa-NXAX.js} +46 -46
  31. package/dist/{xy-D_LqxaGt.js → index-C-qYOegc.js} +62 -62
  32. package/dist/index-C07SBJhr.js +128 -0
  33. package/dist/{bounds-Bn5_l4Z3.js → index-C9EdKeu1.js} +77 -76
  34. package/dist/index-CM8ZDZ6s.cjs +1 -0
  35. package/dist/index-CV2JaHfw.cjs +1 -0
  36. package/dist/index-CeBvOwG8.cjs +3 -0
  37. package/dist/index-ClrGyGDp.js +205 -0
  38. package/dist/index-CqQXXeCI.cjs +1 -0
  39. package/dist/{location-C3aeu046.js → index-D6V-8SKw.js} +26 -26
  40. package/dist/index-DBGAIs_7.js +2492 -0
  41. package/dist/index-DEdq2tza.cjs +1 -0
  42. package/dist/index-DKMnHBGR.cjs +1 -0
  43. package/dist/index-Dql5FMcH.js +47 -0
  44. package/dist/{direction-BL0PhD1k.js → index-DxU1zwsd.js} +1 -1
  45. package/dist/index-WwMnwoLy.cjs +1 -0
  46. package/dist/index.cjs +5 -3
  47. package/dist/index.js +5372 -649
  48. package/dist/kv.cjs +1 -1
  49. package/dist/kv.js +45 -2
  50. package/dist/location.cjs +1 -1
  51. package/dist/location.js +1 -1
  52. package/dist/position.cjs +1 -1
  53. package/dist/position.js +83 -2
  54. package/dist/record.cjs +1 -1
  55. package/dist/record.js +8 -10
  56. package/dist/runtime.cjs +1 -1
  57. package/dist/runtime.js +27 -2
  58. package/dist/scale.cjs +1 -1
  59. package/dist/scale.js +1 -1
  60. package/dist/schemas-55Usj0Fg.js +3998 -0
  61. package/dist/schemas-DbXuI2Qr.cjs +27 -0
  62. package/dist/spatial.cjs +1 -1
  63. package/dist/spatial.js +25 -18
  64. package/dist/src/array/index.d.ts +2 -0
  65. package/dist/src/array/index.d.ts.map +1 -0
  66. package/dist/src/array/toArray.d.ts +19 -0
  67. package/dist/src/array/toArray.d.ts.map +1 -0
  68. package/dist/src/array/toArray.spec.d.ts +2 -0
  69. package/dist/src/array/toArray.spec.d.ts.map +1 -0
  70. package/dist/src/binary/codec.d.ts +8 -16
  71. package/dist/src/binary/codec.d.ts.map +1 -1
  72. package/dist/src/breaker/breaker.d.ts +6 -6
  73. package/dist/src/breaker/breaker.d.ts.map +1 -1
  74. package/dist/src/caseconv/caseconv.d.ts +1 -1
  75. package/dist/src/caseconv/caseconv.d.ts.map +1 -1
  76. package/dist/src/change/change.d.ts +3 -3
  77. package/dist/src/change/change.d.ts.map +1 -1
  78. package/dist/src/color/color.d.ts +63 -28
  79. package/dist/src/color/color.d.ts.map +1 -1
  80. package/dist/src/color/external.d.ts +0 -1
  81. package/dist/src/color/external.d.ts.map +1 -1
  82. package/dist/src/color/gradient.d.ts +9 -5
  83. package/dist/src/color/gradient.d.ts.map +1 -1
  84. package/dist/src/color/palette.d.ts +14 -6
  85. package/dist/src/color/palette.d.ts.map +1 -1
  86. package/dist/src/compare/compare.d.ts +4 -4
  87. package/dist/src/compare/compare.d.ts.map +1 -1
  88. package/dist/src/control/control.d.ts +32 -32
  89. package/dist/src/control/control.d.ts.map +1 -1
  90. package/dist/src/debounce/debounce.d.ts +1 -1
  91. package/dist/src/debounce/debounce.d.ts.map +1 -1
  92. package/dist/src/deep/delete.d.ts +1 -1
  93. package/dist/src/deep/delete.d.ts.map +1 -1
  94. package/dist/src/deep/difference.d.ts.map +1 -1
  95. package/dist/src/deep/equal.d.ts +4 -4
  96. package/dist/src/deep/equal.d.ts.map +1 -1
  97. package/dist/src/deep/merge.d.ts +1 -1
  98. package/dist/src/deep/merge.d.ts.map +1 -1
  99. package/dist/src/errors/errors.d.ts +62 -36
  100. package/dist/src/errors/errors.d.ts.map +1 -1
  101. package/dist/src/index.d.ts +4 -1
  102. package/dist/src/index.d.ts.map +1 -1
  103. package/dist/src/instance/index.d.ts +2 -0
  104. package/dist/src/instance/index.d.ts.map +1 -0
  105. package/dist/src/instance/matcher.d.ts +79 -0
  106. package/dist/src/instance/matcher.d.ts.map +1 -0
  107. package/dist/src/instance/matcher.spec.d.ts +2 -0
  108. package/dist/src/instance/matcher.spec.d.ts.map +1 -0
  109. package/dist/src/jsonrpc/jsonrpc.d.ts +40 -9
  110. package/dist/src/jsonrpc/jsonrpc.d.ts.map +1 -1
  111. package/dist/src/kv/types.d.ts +2 -2
  112. package/dist/src/kv/types.d.ts.map +1 -1
  113. package/dist/src/migrate/migrate.d.ts +5 -5
  114. package/dist/src/migrate/migrate.d.ts.map +1 -1
  115. package/dist/src/notation/notation.d.ts +1 -1
  116. package/dist/src/notation/notation.d.ts.map +1 -1
  117. package/dist/src/primitive/index.d.ts +2 -0
  118. package/dist/src/primitive/index.d.ts.map +1 -0
  119. package/dist/src/primitive/primitive.d.ts +39 -0
  120. package/dist/src/primitive/primitive.d.ts.map +1 -0
  121. package/dist/src/primitive/primitive.spec.d.ts +2 -0
  122. package/dist/src/primitive/primitive.spec.d.ts.map +1 -0
  123. package/dist/src/record.d.ts +2 -2
  124. package/dist/src/record.d.ts.map +1 -1
  125. package/dist/src/renderable.d.ts +1 -1
  126. package/dist/src/renderable.d.ts.map +1 -1
  127. package/dist/src/replace.d.ts.map +1 -1
  128. package/dist/src/runtime/detect.d.ts.map +1 -1
  129. package/dist/src/runtime/os.d.ts +1 -1
  130. package/dist/src/runtime/os.d.ts.map +1 -1
  131. package/dist/src/spatial/base.d.ts +10 -10
  132. package/dist/src/spatial/base.d.ts.map +1 -1
  133. package/dist/src/spatial/bounds/bounds.d.ts +82 -16
  134. package/dist/src/spatial/bounds/bounds.d.ts.map +1 -1
  135. package/dist/src/spatial/box/box.d.ts +7 -7
  136. package/dist/src/spatial/box/box.d.ts.map +1 -1
  137. package/dist/src/spatial/dimensions/dimensions.d.ts +5 -5
  138. package/dist/src/spatial/dimensions/dimensions.d.ts.map +1 -1
  139. package/dist/src/spatial/direction/direction.d.ts +1 -1
  140. package/dist/src/spatial/location/location.d.ts +4 -4
  141. package/dist/src/spatial/location/location.d.ts.map +1 -1
  142. package/dist/src/spatial/scale/scale.d.ts +11 -11
  143. package/dist/src/spatial/scale/scale.d.ts.map +1 -1
  144. package/dist/src/spatial/xy/xy.d.ts +5 -5
  145. package/dist/src/spatial/xy/xy.d.ts.map +1 -1
  146. package/dist/src/status/index.d.ts +2 -0
  147. package/dist/src/status/index.d.ts.map +1 -0
  148. package/dist/src/status/types.d.ts +11 -0
  149. package/dist/src/status/types.d.ts.map +1 -0
  150. package/dist/src/sync/index.d.ts.map +1 -1
  151. package/dist/src/sync/mutex.d.ts +0 -1
  152. package/dist/src/sync/mutex.d.ts.map +1 -1
  153. package/dist/src/telem/gl.d.ts +1 -1
  154. package/dist/src/telem/gl.d.ts.map +1 -1
  155. package/dist/src/telem/series.d.ts +468 -62
  156. package/dist/src/telem/series.d.ts.map +1 -1
  157. package/dist/src/telem/telem.d.ts +243 -53
  158. package/dist/src/telem/telem.d.ts.map +1 -1
  159. package/dist/src/uuid/index.d.ts +2 -0
  160. package/dist/src/uuid/index.d.ts.map +1 -0
  161. package/dist/src/uuid/uuid.d.ts +35 -0
  162. package/dist/src/uuid/uuid.d.ts.map +1 -0
  163. package/dist/src/uuid/uuid.spec.d.ts +2 -0
  164. package/dist/src/uuid/uuid.spec.d.ts.map +1 -0
  165. package/dist/src/zod/external.d.ts +1 -1
  166. package/dist/src/zod/external.d.ts.map +1 -1
  167. package/dist/src/zod/nullToUndefined.d.ts +3 -0
  168. package/dist/src/zod/nullToUndefined.d.ts.map +1 -0
  169. package/dist/src/zod/nullToUndefined.spec.d.ts +2 -0
  170. package/dist/src/zod/nullToUndefined.spec.d.ts.map +1 -0
  171. package/dist/src/zod/util.d.ts +2 -2
  172. package/dist/src/zod/util.d.ts.map +1 -1
  173. package/dist/telem.cjs +1 -1
  174. package/dist/telem.js +1 -1
  175. package/dist/xy.cjs +1 -1
  176. package/dist/xy.js +1 -1
  177. package/dist/zod.cjs +1 -1
  178. package/dist/zod.js +19 -2
  179. package/eslint.config.js +1 -1
  180. package/package.json +16 -14
  181. package/src/{toArray.ts → array/index.ts} +1 -5
  182. package/src/array/toArray.spec.ts +56 -0
  183. package/src/array/toArray.ts +28 -0
  184. package/src/binary/codec.spec.ts +201 -278
  185. package/src/binary/codec.ts +20 -76
  186. package/src/breaker/breaker.ts +3 -3
  187. package/src/caseconv/caseconv.ts +6 -4
  188. package/src/change/change.ts +2 -2
  189. package/src/color/color.spec.ts +121 -2
  190. package/src/color/color.ts +90 -54
  191. package/src/color/external.ts +0 -1
  192. package/src/color/gradient.ts +20 -28
  193. package/src/color/palette.ts +1 -1
  194. package/src/compare/compare.ts +5 -5
  195. package/src/control/control.ts +22 -19
  196. package/src/debounce/debounce.ts +1 -1
  197. package/src/deep/delete.ts +5 -4
  198. package/src/deep/difference.ts +6 -2
  199. package/src/deep/equal.spec.ts +1 -1
  200. package/src/deep/equal.ts +5 -5
  201. package/src/deep/merge.spec.ts +13 -1
  202. package/src/deep/merge.ts +16 -7
  203. package/src/deep/path.ts +1 -1
  204. package/src/errors/errors.ts +65 -44
  205. package/src/index.ts +4 -1
  206. package/src/instance/index.ts +10 -0
  207. package/src/instance/matcher.spec.ts +78 -0
  208. package/src/instance/matcher.ts +98 -0
  209. package/src/jsonrpc/jsonrpc.spec.ts +2 -1
  210. package/src/jsonrpc/jsonrpc.ts +36 -7
  211. package/src/kv/types.ts +1 -1
  212. package/src/migrate/migrate.spec.ts +1 -1
  213. package/src/migrate/migrate.ts +7 -7
  214. package/src/notation/notation.ts +1 -1
  215. package/src/primitive/index.ts +10 -0
  216. package/src/primitive/primitive.spec.ts +126 -0
  217. package/src/primitive/primitive.ts +82 -0
  218. package/src/record.ts +3 -5
  219. package/src/renderable.ts +1 -1
  220. package/src/replace.ts +9 -0
  221. package/src/runtime/detect.ts +0 -2
  222. package/src/runtime/os.ts +1 -1
  223. package/src/spatial/base.ts +1 -1
  224. package/src/spatial/bounds/bounds.spec.ts +20 -0
  225. package/src/spatial/bounds/bounds.ts +101 -18
  226. package/src/spatial/box/box.ts +1 -1
  227. package/src/spatial/dimensions/dimensions.ts +3 -3
  228. package/src/spatial/location/location.ts +1 -1
  229. package/src/spatial/scale/scale.ts +1 -1
  230. package/src/spatial/xy/xy.ts +1 -1
  231. package/src/status/index.ts +10 -0
  232. package/src/status/types.ts +22 -0
  233. package/src/sync/index.ts +9 -0
  234. package/src/sync/mutex.ts +9 -4
  235. package/src/telem/gl.ts +1 -1
  236. package/src/telem/series.spec.ts +735 -68
  237. package/src/telem/series.ts +536 -195
  238. package/src/telem/telem.spec.ts +60 -7
  239. package/src/telem/telem.ts +287 -95
  240. package/src/uuid/index.ts +10 -0
  241. package/src/uuid/uuid.spec.ts +82 -0
  242. package/src/uuid/uuid.ts +48 -0
  243. package/src/zod/external.ts +1 -1
  244. package/src/zod/nullToUndefined.spec.ts +31 -0
  245. package/src/zod/nullToUndefined.ts +23 -0
  246. package/src/zod/util.spec.ts +1 -1
  247. package/src/zod/util.ts +6 -6
  248. package/tsconfig.json +1 -1
  249. package/tsconfig.tsbuildinfo +1 -1
  250. package/vite.config.ts +1 -1
  251. package/dist/base-BAM2mqCy.cjs +0 -1
  252. package/dist/base-DFq0vvGn.js +0 -38
  253. package/dist/bounds-BQo7rvs9.cjs +0 -1
  254. package/dist/box-0YrQibkB.cjs +0 -1
  255. package/dist/box-Cc8IzcNo.js +0 -205
  256. package/dist/change-C-YELKx6.cjs +0 -1
  257. package/dist/change-DLl6DccR.js +0 -12
  258. package/dist/dimensions-CRgergMS.js +0 -43
  259. package/dist/dimensions-D2QGoNXO.cjs +0 -1
  260. package/dist/external-BPgtxa8d.js +0 -29
  261. package/dist/external-C-dNgNQw.cjs +0 -1
  262. package/dist/external-C8TFju8Q.js +0 -29
  263. package/dist/external-DWQITF5_.cjs +0 -1
  264. package/dist/external-DqPrWKvU.js +0 -47
  265. package/dist/external-uXk0Avrg.cjs +0 -1
  266. package/dist/index-BywOGO8U.js +0 -1074
  267. package/dist/index-CYYjI7Uf.cjs +0 -1
  268. package/dist/index-C_6NXBlg.cjs +0 -3
  269. package/dist/index-Dd8DLyMx.cjs +0 -1
  270. package/dist/index-DizUWH6z.js +0 -47
  271. package/dist/index-QGplUHuy.js +0 -98
  272. package/dist/location-BGl5Ddds.cjs +0 -1
  273. package/dist/position-Cai5-wi1.cjs +0 -1
  274. package/dist/position-DIglP1l2.js +0 -85
  275. package/dist/scale-BtZINJ-A.cjs +0 -1
  276. package/dist/series-B9JERcqi.js +0 -1977
  277. package/dist/series-DqJ6f97G.cjs +0 -11
  278. package/dist/spatial-BSWPzMkK.js +0 -11
  279. package/dist/spatial-DGpZ2sO3.cjs +0 -1
  280. package/dist/src/color/transformColorsToHex.d.ts +0 -6
  281. package/dist/src/color/transformColorsToHex.d.ts.map +0 -1
  282. package/dist/src/primitive.d.ts +0 -9
  283. package/dist/src/primitive.d.ts.map +0 -1
  284. package/dist/src/toArray.d.ts +0 -3
  285. package/dist/src/toArray.d.ts.map +0 -1
  286. package/dist/src/zod/integer.d.ts +0 -10
  287. package/dist/src/zod/integer.d.ts.map +0 -1
  288. package/dist/src/zod/integer.spec.d.ts +0 -2
  289. package/dist/src/zod/integer.spec.d.ts.map +0 -1
  290. package/dist/toArray.cjs +0 -1
  291. package/dist/toArray.js +0 -5
  292. package/dist/xy-B7065J2S.cjs +0 -1
  293. package/src/color/transformColorsToHex.ts +0 -30
  294. package/src/primitive.ts +0 -46
  295. package/src/zod/integer.spec.ts +0 -148
  296. package/src/zod/integer.ts +0 -38
@@ -0,0 +1,78 @@
1
+ // Copyright 2025 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 { describe, expect, it } from "vitest";
11
+
12
+ import { createMatcher, type Discriminated } from "./matcher";
13
+
14
+ describe("createMatcher", () => {
15
+ class TestClass implements Discriminated {
16
+ discriminator = "test";
17
+ constructor(public value: string) {}
18
+ }
19
+
20
+ const isTestClass = createMatcher("test", TestClass);
21
+
22
+ it("should return true for instances of the class", () => {
23
+ const instance = new TestClass("value");
24
+ expect(isTestClass(instance)).toBe(true);
25
+ });
26
+
27
+ it("should return true for objects with matching discriminator", () => {
28
+ const obj = { discriminator: "test", value: "value" };
29
+ expect(isTestClass(obj)).toBe(true);
30
+ });
31
+
32
+ it("should return false for null", () => {
33
+ expect(isTestClass(null)).toBe(false);
34
+ });
35
+
36
+ it("should return false for undefined", () => {
37
+ expect(isTestClass(undefined)).toBe(false);
38
+ });
39
+
40
+ it("should return false for non-objects", () => {
41
+ expect(isTestClass("string")).toBe(false);
42
+ expect(isTestClass(123)).toBe(false);
43
+ expect(isTestClass(true)).toBe(false);
44
+ });
45
+
46
+ it("should return false for objects with different discriminator", () => {
47
+ const obj = { discriminator: "other", value: "value" };
48
+ expect(isTestClass(obj)).toBe(false);
49
+ });
50
+
51
+ it("should return false for objects without discriminator", () => {
52
+ const obj = { value: "value" };
53
+ expect(isTestClass(obj)).toBe(false);
54
+ });
55
+
56
+ it("should work with multiple class instances", () => {
57
+ class ClassA implements Discriminated {
58
+ discriminator = "a";
59
+ constructor(public value: string) {}
60
+ }
61
+
62
+ class ClassB implements Discriminated {
63
+ discriminator = "b";
64
+ constructor(public value: string) {}
65
+ }
66
+
67
+ const isClassA = createMatcher("a", ClassA);
68
+ const isClassB = createMatcher("b", ClassB);
69
+
70
+ const instanceA = new ClassA("value");
71
+ const instanceB = new ClassB("value");
72
+
73
+ expect(isClassA(instanceA)).toBe(true);
74
+ expect(isClassA(instanceB)).toBe(false);
75
+ expect(isClassB(instanceA)).toBe(false);
76
+ expect(isClassB(instanceB)).toBe(true);
77
+ });
78
+ });
@@ -0,0 +1,98 @@
1
+ // Copyright 2025 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
+ /**
11
+ * Interface for objects that can be discriminated by a string identifier.
12
+ * Classes or objects implementing this interface must have a discriminator property
13
+ * that uniquely identifies their type.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * class User implements Discriminated {
18
+ * discriminator = "user";
19
+ * constructor(public name: string) {}
20
+ * }
21
+ * ```
22
+ */
23
+ export interface Discriminated {
24
+ discriminator: string;
25
+ }
26
+
27
+ /**
28
+ * Creates a type guard function that checks if a value is an instance of a class
29
+ * using a discriminator property. It is up to the caller to ensure that the
30
+ * discriminator property is unique, consistent across all instances of the class,
31
+ * and will not appear in objects that are not instances of the class.
32
+ *
33
+ * This is particularly useful when working with instances of classes that have
34
+ * been duplicated or mangled by a bundler.
35
+ *
36
+ * @typeParam T - The type that extends Discriminated
37
+ * @param discriminator - The string value to match against the object's discriminator property
38
+ * @param cls - The class constructor to check for instanceof
39
+ * @returns A type guard function that returns true if the value matches either condition
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * class User implements Discriminated {
44
+ * discriminator = "user";
45
+ * constructor(public name: string) {}
46
+ * }
47
+ *
48
+ * const isUser = createMatcher("user", User);
49
+ *
50
+ * // Works with class instances
51
+ * const user = new User("John");
52
+ * if (isUser(user)) {
53
+ * console.log(user.name); // TypeScript knows user is a User
54
+ * }
55
+ *
56
+ * // Works with plain objects
57
+ * const obj = { discriminator: "user", name: "John" };
58
+ * if (isUser(obj)) {
59
+ * console.log(obj.name); // TypeScript knows obj is a User
60
+ * }
61
+ * ```
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * // Working with multiple types
66
+ * class Admin implements Discriminated {
67
+ * discriminator = "admin";
68
+ * constructor(public name: string, public role: string) {}
69
+ * }
70
+ *
71
+ * class Guest implements Discriminated {
72
+ * discriminator = "guest";
73
+ * constructor(public name: string) {}
74
+ * }
75
+ *
76
+ * const isAdmin = createMatcher("admin", Admin);
77
+ * const isGuest = createMatcher("guest", Guest);
78
+ *
79
+ * function handleUser(user: unknown) {
80
+ * if (isAdmin(user)) {
81
+ * console.log(user.role); // TypeScript knows user is an Admin
82
+ * } else if (isGuest(user)) {
83
+ * console.log(user.name); // TypeScript knows user is a Guest
84
+ * }
85
+ * }
86
+ * ```
87
+ */
88
+ export const createMatcher =
89
+ <T extends Discriminated>(
90
+ discriminator: string,
91
+ cls: new (...args: any[]) => T,
92
+ ): ((value: unknown) => value is T) =>
93
+ (value: unknown): value is T =>
94
+ value instanceof cls ||
95
+ (typeof value === "object" &&
96
+ value !== null &&
97
+ "discriminator" in value &&
98
+ value.discriminator === discriminator);
@@ -109,8 +109,9 @@ describe("JSON-RPC", () => {
109
109
  });
110
110
  describe("encodeMessage", () => {
111
111
  it("should encode a message", () => {
112
- const message = {
112
+ const message: jsonRPC.Request = {
113
113
  jsonrpc: "2.0",
114
+ id: 1,
114
115
  method: "$/status/show",
115
116
  };
116
117
  const messageStr = JSON.stringify(message);
@@ -7,18 +7,47 @@
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 z from "zod";
10
+ import z from "zod/v4";
11
11
 
12
12
  import { binary } from "@/binary";
13
13
 
14
- const messageZ = z.object({
15
- jsonrpc: z.string(),
16
- id: z.number().optional(),
17
- method: z.string().optional(),
18
- params: z.unknown().optional(),
19
- result: z.unknown().optional(),
14
+ export const requestZ = z.object({
15
+ jsonrpc: z.literal("2.0"),
16
+ method: z.string(),
17
+ // params should be z.union([z.record(z.string(), z.json()),
18
+ // z.array(z.json())]).optional() but the VSCode JSON RPC implementation uses a looser
19
+ // definition of params then in the JSON-RPC spec.
20
+ params: z.any().optional(),
21
+ id: z.union([z.string(), z.number(), z.null()]).optional(),
20
22
  });
21
23
 
24
+ export type Request = z.infer<typeof requestZ>;
25
+
26
+ const baseResponseZ = z.object({
27
+ jsonrpc: z.literal("2.0"),
28
+ id: z.union([z.string(), z.number(), z.null()]),
29
+ });
30
+
31
+ const successResponseZ = baseResponseZ.extend({
32
+ result: z.json(),
33
+ });
34
+
35
+ const errorResponseZ = baseResponseZ.extend({
36
+ error: z.object({
37
+ code: z.number().int(),
38
+ // This should be z.string(), but the VSCode JSON RPC implementation uses a looser
39
+ // definition of error than the JSON-RPC spec.
40
+ message: z.string().optional(),
41
+ data: z.json().optional(),
42
+ }),
43
+ });
44
+
45
+ export const responseZ = z.union([successResponseZ, errorResponseZ]);
46
+
47
+ export type Response = z.infer<typeof responseZ>;
48
+
49
+ export const messageZ = z.union([requestZ, responseZ]);
50
+
22
51
  export type Message = z.infer<typeof messageZ>;
23
52
 
24
53
  export interface ChunkParser {
package/src/kv/types.ts CHANGED
@@ -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 { z } from "zod";
10
+ import { z } from "zod/v4";
11
11
 
12
12
  export interface Reader<V = unknown> {
13
13
  /** @returns the value for a given key, or null if the key is not present. */
@@ -8,7 +8,7 @@
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
10
  import { describe, expect, it } from "vitest";
11
- import { z } from "zod";
11
+ import { z } from "zod/v4";
12
12
 
13
13
  import { migrate } from "@/migrate";
14
14
 
@@ -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 { z } from "zod";
10
+ import { z } from "zod/v4";
11
11
 
12
12
  import { compare } from "@/compare";
13
13
  import { type Optional } from "@/optional";
@@ -118,8 +118,8 @@ export type Migration<I extends Migratable, O extends Migratable> = (input: I) =
118
118
  export interface MigrationProps<
119
119
  I extends Migratable,
120
120
  O extends Migratable,
121
- ZI extends z.ZodTypeAny,
122
- ZO extends z.ZodTypeAny,
121
+ ZI extends z.ZodType,
122
+ ZO extends z.ZodType,
123
123
  > {
124
124
  name: string;
125
125
  inputSchema?: ZI;
@@ -131,8 +131,8 @@ export const createMigration =
131
131
  <
132
132
  I extends Migratable,
133
133
  O extends Migratable,
134
- ZI extends z.ZodTypeAny = z.ZodTypeAny,
135
- ZO extends z.ZodTypeAny = z.ZodTypeAny,
134
+ ZI extends z.ZodType = z.ZodType,
135
+ ZO extends z.ZodType = z.ZodType,
136
136
  >({
137
137
  name,
138
138
  migrate,
@@ -155,7 +155,7 @@ export const createMigration =
155
155
  */
156
156
  export type Migrations = Record<string, Migration<any, any>>;
157
157
 
158
- interface MigratorProps<O extends Migratable, ZO extends z.ZodTypeAny = z.ZodTypeAny> {
158
+ interface MigratorProps<O extends Migratable, ZO extends z.ZodType = z.ZodType> {
159
159
  name: string;
160
160
  migrations: Migrations;
161
161
  def: O;
@@ -168,7 +168,7 @@ export type Migrator = <I extends Optional<Migratable, "version">, O>(v: I) => O
168
168
  export const migrator = <
169
169
  I extends Optional<Migratable, "version">,
170
170
  O extends Migratable,
171
- ZO extends z.ZodTypeAny = z.ZodTypeAny,
171
+ ZO extends z.ZodType = z.ZodType,
172
172
  >({
173
173
  name,
174
174
  migrations,
@@ -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 { z } from "zod";
10
+ import { z } from "zod/v4";
11
11
 
12
12
  export const NOTATIONS = ["standard", "scientific", "engineering"] as const;
13
13
  export const notationZ = z.enum(NOTATIONS);
@@ -0,0 +1,10 @@
1
+ // Copyright 2025 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
+ export * as primitive from "@/primitive/primitive";
@@ -0,0 +1,126 @@
1
+ // Copyright 2025 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 { describe, expect, it } from "vitest";
11
+ import { z } from "zod/v4";
12
+
13
+ import { binary } from "@/binary";
14
+ import { primitive } from "@/primitive";
15
+
16
+ class ExampleStringer implements primitive.Stringer {
17
+ readonly value: string;
18
+ constructor(value: string) {
19
+ this.value = value;
20
+ }
21
+
22
+ toString(): string {
23
+ return this.value;
24
+ }
25
+ }
26
+
27
+ describe("primitive", () => {
28
+ describe("isZero", () => {
29
+ interface Spec {
30
+ value: primitive.Value;
31
+ expected: boolean;
32
+ }
33
+ const SPECS: Spec[] = [
34
+ { value: 0, expected: true },
35
+ { value: 1, expected: false },
36
+ { value: 0n, expected: true },
37
+ { value: 12n, expected: false },
38
+ { value: true, expected: false },
39
+ { value: false, expected: true },
40
+ { value: undefined, expected: true },
41
+ { value: new ExampleStringer(""), expected: true },
42
+ { value: new ExampleStringer("cat"), expected: false },
43
+ ];
44
+ SPECS.forEach(({ value, expected }) => {
45
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
46
+ it(`should return ${expected} for ${value} ${typeof value}`, () => {
47
+ expect(primitive.isZero(value)).toEqual(expected);
48
+ });
49
+ });
50
+ });
51
+
52
+ describe("isStringer", () => {
53
+ it("should return true for a stringer", () => {
54
+ expect(primitive.isStringer(new ExampleStringer("cat"))).toEqual(true);
55
+ });
56
+ it("should return false for a non-stringer", () => {
57
+ expect(primitive.isStringer(0)).toEqual(false);
58
+ });
59
+ it("should return false for null", () => {
60
+ expect(primitive.isStringer(null)).toEqual(false);
61
+ });
62
+ });
63
+
64
+ describe("ValueExtension", () => {
65
+ class MyValueExtension extends primitive.ValueExtension<bigint> {
66
+ valueOf(): bigint {
67
+ return this.value;
68
+ }
69
+ toJSON(): bigint {
70
+ return this.value;
71
+ }
72
+ }
73
+
74
+ describe("valueOf", () => {
75
+ it("should return the value", () => {
76
+ const value = new MyValueExtension(12n);
77
+ expect(value.valueOf()).toEqual(12n);
78
+ });
79
+ });
80
+
81
+ describe("toJSON", () => {
82
+ it("should return the value", () => {
83
+ const value = new MyValueExtension(12n);
84
+ expect(value.toJSON()).toEqual(12n);
85
+ });
86
+ });
87
+
88
+ describe("toString", () => {
89
+ it("should return the value", () => {
90
+ const value = new MyValueExtension(12n);
91
+ expect(value.toString()).toEqual("12");
92
+ });
93
+ });
94
+
95
+ describe("encode + decode", () => {
96
+ it("should encode + decode a value extension", () => {
97
+ const v = {
98
+ myDog: new MyValueExtension(12n),
99
+ };
100
+ const encoded = binary.JSON_CODEC.encode(v);
101
+ const decoded = binary.JSON_CODEC.decode(encoded);
102
+ expect(decoded).toEqual({
103
+ myDog: "12",
104
+ });
105
+ });
106
+
107
+ it("should encode + decode a value extension with a schema", () => {
108
+ const v = {
109
+ myDog: new MyValueExtension(12n),
110
+ };
111
+ const schema = z.object({
112
+ myDog: z
113
+ .bigint()
114
+ .or(z.string())
115
+ .transform((v) => new MyValueExtension(BigInt(v))),
116
+ });
117
+ const encoded = binary.JSON_CODEC.encode(v);
118
+ const decoded = binary.JSON_CODEC.decode(encoded, schema);
119
+ expect(decoded).toEqual({
120
+ myDog: new MyValueExtension(12n),
121
+ });
122
+ expect(decoded.myDog).toBeInstanceOf(MyValueExtension);
123
+ });
124
+ });
125
+ });
126
+ });
@@ -0,0 +1,82 @@
1
+ // Copyright 2025 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
+ /** Union of types that are primitive values or can be converted to primitive values */
11
+ export type Value = string | number | bigint | boolean | Stringer | null | undefined;
12
+
13
+ /**
14
+ * ValueExtension is a utility class that can be extended in order to implement objects
15
+ * that pseudo-extend a primitive value with additional functionality.
16
+ */
17
+ export class ValueExtension<V extends NonNullable<Value>> {
18
+ /** The underlying primitive value */
19
+ protected readonly value: V;
20
+
21
+ constructor(value: V) {
22
+ this.value = value;
23
+ }
24
+
25
+ /** Overrides the JS default valueOf() function to return the primitive value. */
26
+ valueOf(): V {
27
+ return this.value;
28
+ }
29
+
30
+ /** toJSON ensures that only the primitive value gets encoded during JSON
31
+ * stringification. */
32
+ toJSON(): V {
33
+ return this.value;
34
+ }
35
+
36
+ /** @returns a string representation of the item. */
37
+ toString(): string {
38
+ return this.value.toString();
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Stringer is a type that implements a toString() method in order to return a string
44
+ * representation of itself.
45
+ */
46
+ export interface Stringer {
47
+ /** @returns a string representation of the item. */
48
+ toString: () => string;
49
+ }
50
+
51
+ /** @returns true if the value implements primitive.Stringer, otherwise returns false. */
52
+ export const isStringer = (value: unknown): boolean =>
53
+ value != null && typeof value === "object" && "toString" in value;
54
+
55
+ /**
56
+ * @returns true if the given primitive is the zero value for its type.
57
+ * For strings value == ""
58
+ * For numbers value == 0
59
+ * For bigints value == 0n
60
+ * For booleans value == false
61
+ * For objects value == null
62
+ * For undefined returns true
63
+ */
64
+ export const isZero = <V extends Value>(value: V): boolean => {
65
+ if (isStringer(value)) return value?.toString().length === 0;
66
+ switch (typeof value) {
67
+ case "string":
68
+ return value.length === 0;
69
+ case "number":
70
+ return value === 0;
71
+ case "bigint":
72
+ return value === 0n;
73
+ case "boolean":
74
+ return !value;
75
+ case "undefined":
76
+ return true;
77
+ case "object":
78
+ return value == null;
79
+ default:
80
+ return false;
81
+ }
82
+ };
package/src/record.ts CHANGED
@@ -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 { z } from "zod";
10
+ import { z } from "zod/v4";
11
11
 
12
12
  export type Key = string | number;
13
13
 
@@ -40,8 +40,6 @@ export const getEntries = <T extends Record<Key, unknown>>(obj: T): Entries<T> =
40
40
 
41
41
  export const mapValues = <T extends Record<Key, unknown>, U>(
42
42
  obj: T,
43
- fn: (value: T[keyof T], key: Key) => U,
43
+ fn: (value: T[keyof T], key: keyof T) => U,
44
44
  ): Record<Key, U> =>
45
- Object.fromEntries(
46
- getEntries(obj).map(([key, value]) => [key, fn(value, key as Key)]),
47
- );
45
+ Object.fromEntries(getEntries(obj).map(([key, value]) => [key, fn(value, key)]));
package/src/renderable.ts CHANGED
@@ -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 { type Stringer } from "@/primitive";
10
+ import { type Stringer } from "@/primitive/primitive";
11
11
 
12
12
  export type PureRenderableValue = string | number | undefined;
13
13
  export type RenderableValue = PureRenderableValue | Stringer;
package/src/replace.ts CHANGED
@@ -1 +1,10 @@
1
+ // Copyright 2025 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
+
1
10
  export type Replace<T, R> = Omit<T, keyof R> & R;
@@ -17,14 +17,12 @@ export type Runtime = "browser" | "node" | "webworker";
17
17
  */
18
18
  export const detect = (): Runtime => {
19
19
  if (
20
-
21
20
  typeof process !== "undefined" &&
22
21
  process.versions != null &&
23
22
  process.versions.node != null
24
23
  )
25
24
  return "node";
26
25
 
27
-
28
26
  if (typeof window === "undefined" || window.document === undefined)
29
27
  return "webworker";
30
28
 
package/src/runtime/os.ts CHANGED
@@ -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 { z } from "zod";
10
+ import { z } from "zod/v4";
11
11
 
12
12
  export const OPERATING_SYSTEMS = ["macOS", "Windows", "Linux"] as const;
13
13
  const LOWERCASE_OPERATING_SYSTEMS = ["macos", "windows", "linux"] as const;
@@ -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 { z } from "zod";
10
+ import { z } from "zod/v4";
11
11
 
12
12
  export const numberCouple = z.tuple([z.number(), z.number()]);
13
13
  export const bigNumberCouple = z.tuple([z.bigint(), z.bigint()]);
@@ -28,16 +28,36 @@ describe("Bounds", () => {
28
28
  expect(bound.upper).toEqual(2);
29
29
  });
30
30
  });
31
+
31
32
  it("should accept two arguments", () => {
32
33
  const bound = bounds.construct(1, 2);
33
34
  expect(bound.lower).toEqual(1);
34
35
  expect(bound.upper).toEqual(2);
35
36
  });
37
+
36
38
  it("should consider a single argument as the upper bound", () => {
37
39
  const bound = bounds.construct(1);
38
40
  expect(bound.lower).toEqual(0);
39
41
  expect(bound.upper).toEqual(1);
40
42
  });
43
+
44
+ describe("makeValid", () => {
45
+ it("should make the bounds valid", () => {
46
+ const bound = bounds.construct<number>(2, 1, { makeValid: true });
47
+ expect(bound.lower).toEqual(1);
48
+ expect(bound.upper).toEqual(2);
49
+ });
50
+ it("should allow for options in a single argument constructor", () => {
51
+ const bound = bounds.construct<number>([2, 1], { makeValid: false });
52
+ expect(bound.lower).toEqual(2);
53
+ expect(bound.upper).toEqual(1);
54
+ });
55
+ it("should not make the bounds valid if makeValid is false", () => {
56
+ const bound = bounds.construct(1, 2, { makeValid: false });
57
+ expect(bound.lower).toEqual(1);
58
+ expect(bound.upper).toEqual(2);
59
+ });
60
+ });
41
61
  });
42
62
  describe("equals", () => {
43
63
  it("should return true if the bounds are equal", () => {