lib0 0.2.112 → 0.2.115-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 (331) hide show
  1. package/README.md +1 -1
  2. package/broadcastchannel.js +1 -1
  3. package/buffer.d.ts +3 -3
  4. package/buffer.d.ts.map +1 -1
  5. package/buffer.js +1 -1
  6. package/coverage/tmp/coverage-27667-1761218530660-0.json +1 -0
  7. package/coverage/tmp/{coverage-20055-1752683207886-0.json → coverage-27668-1761218485882-0.json} +1 -1
  8. package/crypto/aes-gcm.d.ts +4 -4
  9. package/crypto/aes-gcm.d.ts.map +1 -1
  10. package/crypto/aes-gcm.js +6 -6
  11. package/crypto/common.d.ts +1 -1
  12. package/crypto/common.d.ts.map +1 -1
  13. package/crypto/common.js +1 -1
  14. package/crypto/ecdsa.d.ts +2 -2
  15. package/crypto/ecdsa.d.ts.map +1 -1
  16. package/crypto/ecdsa.js +4 -4
  17. package/crypto/rsa-oaep.d.ts +2 -2
  18. package/crypto/rsa-oaep.d.ts.map +1 -1
  19. package/crypto/rsa-oaep.js +3 -3
  20. package/decoding.d.ts +27 -14
  21. package/decoding.d.ts.map +1 -1
  22. package/decoding.js +12 -8
  23. package/delta/abstract-array.d.ts +166 -0
  24. package/delta/abstract-array.d.ts.map +1 -0
  25. package/delta/abstract-array.js +421 -0
  26. package/delta/abstract.d.ts +69 -0
  27. package/delta/abstract.d.ts.map +1 -0
  28. package/delta/abstract.js +102 -0
  29. package/delta/array.d.ts +23 -0
  30. package/delta/array.d.ts.map +1 -0
  31. package/delta/array.js +45 -0
  32. package/delta/array.test.d.ts +2 -0
  33. package/delta/array.test.d.ts.map +1 -0
  34. package/delta/binding.d.ts +105 -0
  35. package/delta/binding.d.ts.map +1 -0
  36. package/delta/binding.js +369 -0
  37. package/delta/binding.test.d.ts +5 -0
  38. package/delta/binding.test.d.ts.map +1 -0
  39. package/delta/d2.d.ts +705 -0
  40. package/delta/d2.d.ts.map +1 -0
  41. package/delta/d2.js +1309 -0
  42. package/delta/d2.test.d.ts +15 -0
  43. package/delta/d2.test.d.ts.map +1 -0
  44. package/delta/index.d.ts +14 -0
  45. package/delta/index.d.ts.map +1 -0
  46. package/delta/index.js +79 -0
  47. package/delta/map.d.ts +230 -0
  48. package/delta/map.d.ts.map +1 -0
  49. package/delta/map.js +304 -0
  50. package/delta/node.d.ts +119 -0
  51. package/delta/node.d.ts.map +1 -0
  52. package/delta/node.js +183 -0
  53. package/delta/node.test.d.ts +4 -0
  54. package/delta/node.test.d.ts.map +1 -0
  55. package/delta/ops.d.ts +466 -0
  56. package/delta/ops.d.ts.map +1 -0
  57. package/delta/ops.js +544 -0
  58. package/delta/readme.md +129 -0
  59. package/delta/text.d.ts +43 -0
  60. package/delta/text.d.ts.map +1 -0
  61. package/delta/text.js +54 -0
  62. package/delta/text.test.d.ts +6 -0
  63. package/delta/text.test.d.ts.map +1 -0
  64. package/delta/transformer.d.ts +164 -0
  65. package/delta/transformer.d.ts.map +1 -0
  66. package/delta/transformer.js +888 -0
  67. package/delta/transformer.test.d.ts +13 -0
  68. package/delta/transformer.test.d.ts.map +1 -0
  69. package/delta/value.d.ts +84 -0
  70. package/delta/value.d.ts.map +1 -0
  71. package/delta/value.js +168 -0
  72. package/dist/abstract-array.cjs +433 -0
  73. package/dist/abstract-array.cjs.map +1 -0
  74. package/dist/abstract.cjs +122 -0
  75. package/dist/abstract.cjs.map +1 -0
  76. package/dist/aes-gcm.cjs +12 -12
  77. package/dist/aes-gcm.cjs.map +1 -1
  78. package/dist/array.cjs +60 -17
  79. package/dist/array.cjs.map +1 -1
  80. package/dist/array2.cjs +26 -0
  81. package/dist/array2.cjs.map +1 -0
  82. package/dist/binding.cjs +398 -0
  83. package/dist/binding.cjs.map +1 -0
  84. package/dist/{broadcastchannel-2c4b0a1c.cjs → broadcastchannel-b4eaea6e.cjs} +4 -4
  85. package/dist/broadcastchannel-b4eaea6e.cjs.map +1 -0
  86. package/dist/broadcastchannel.cjs +12 -12
  87. package/dist/{buffer-a74f7330.cjs → buffer-adc4e6ea.cjs} +7 -7
  88. package/dist/buffer-adc4e6ea.cjs.map +1 -0
  89. package/dist/buffer.cjs +11 -11
  90. package/dist/buffer.d.ts +3 -3
  91. package/dist/buffer.d.ts.map +1 -1
  92. package/dist/cache.cjs +6 -6
  93. package/dist/common.cjs +1 -1
  94. package/dist/common.cjs.map +1 -1
  95. package/dist/component.cjs +14 -9
  96. package/dist/component.cjs.map +1 -1
  97. package/dist/crypto/aes-gcm.d.ts +4 -4
  98. package/dist/crypto/aes-gcm.d.ts.map +1 -1
  99. package/dist/crypto/common.d.ts +1 -1
  100. package/dist/crypto/common.d.ts.map +1 -1
  101. package/dist/crypto/ecdsa.d.ts +2 -2
  102. package/dist/crypto/ecdsa.d.ts.map +1 -1
  103. package/dist/crypto/rsa-oaep.d.ts +2 -2
  104. package/dist/crypto/rsa-oaep.d.ts.map +1 -1
  105. package/dist/d2.cjs +1347 -0
  106. package/dist/d2.cjs.map +1 -0
  107. package/dist/{decoding-2b136346.cjs → decoding-50b9ce38.cjs} +18 -14
  108. package/dist/decoding-50b9ce38.cjs.map +1 -0
  109. package/dist/decoding.cjs +6 -6
  110. package/dist/decoding.d.ts +27 -14
  111. package/dist/decoding.d.ts.map +1 -1
  112. package/dist/delta/abstract-array.d.ts +166 -0
  113. package/dist/delta/abstract-array.d.ts.map +1 -0
  114. package/dist/delta/abstract.d.ts +69 -0
  115. package/dist/delta/abstract.d.ts.map +1 -0
  116. package/dist/delta/array.d.ts +23 -0
  117. package/dist/delta/array.d.ts.map +1 -0
  118. package/dist/delta/array.test.d.ts +2 -0
  119. package/dist/delta/array.test.d.ts.map +1 -0
  120. package/dist/delta/binding.d.ts +105 -0
  121. package/dist/delta/binding.d.ts.map +1 -0
  122. package/dist/delta/binding.test.d.ts +5 -0
  123. package/dist/delta/binding.test.d.ts.map +1 -0
  124. package/dist/delta/d2.d.ts +705 -0
  125. package/dist/delta/d2.d.ts.map +1 -0
  126. package/dist/delta/d2.test.d.ts +15 -0
  127. package/dist/delta/d2.test.d.ts.map +1 -0
  128. package/dist/delta/index.d.ts +14 -0
  129. package/dist/delta/index.d.ts.map +1 -0
  130. package/dist/delta/map.d.ts +230 -0
  131. package/dist/delta/map.d.ts.map +1 -0
  132. package/dist/delta/node.d.ts +119 -0
  133. package/dist/delta/node.d.ts.map +1 -0
  134. package/dist/delta/node.test.d.ts +4 -0
  135. package/dist/delta/node.test.d.ts.map +1 -0
  136. package/dist/delta/ops.d.ts +466 -0
  137. package/dist/delta/ops.d.ts.map +1 -0
  138. package/dist/delta/text.d.ts +43 -0
  139. package/dist/delta/text.d.ts.map +1 -0
  140. package/dist/delta/text.test.d.ts +6 -0
  141. package/dist/delta/text.test.d.ts.map +1 -0
  142. package/dist/delta/transformer.d.ts +164 -0
  143. package/dist/delta/transformer.d.ts.map +1 -0
  144. package/dist/delta/transformer.test.d.ts +13 -0
  145. package/dist/delta/transformer.test.d.ts.map +1 -0
  146. package/dist/delta/value.d.ts +84 -0
  147. package/dist/delta/value.d.ts.map +1 -0
  148. package/dist/{diff-77c4cf8e.cjs → diff-f0776c15.cjs} +2 -2
  149. package/dist/{diff-77c4cf8e.cjs.map → diff-f0776c15.cjs.map} +1 -1
  150. package/dist/diff.cjs +3 -3
  151. package/dist/{dom-16daf1a0.cjs → dom-2b123630.cjs} +31 -2
  152. package/dist/dom-2b123630.cjs.map +1 -0
  153. package/dist/dom.cjs +17 -2
  154. package/dist/dom.cjs.map +1 -1
  155. package/dist/dom.d.ts +17 -0
  156. package/dist/dom.d.ts.map +1 -1
  157. package/dist/ecdsa.cjs +4 -4
  158. package/dist/ecdsa.cjs.map +1 -1
  159. package/dist/{encoding-1acb59c4.cjs → encoding-7f85922c.cjs} +5 -5
  160. package/dist/encoding-7f85922c.cjs.map +1 -0
  161. package/dist/encoding.cjs +4 -4
  162. package/dist/encoding.d.ts +6 -6
  163. package/dist/encoding.d.ts.map +1 -1
  164. package/dist/{environment-2de08e0e.cjs → environment-90227ead.cjs} +4 -4
  165. package/dist/{environment-2de08e0e.cjs.map → environment-90227ead.cjs.map} +1 -1
  166. package/dist/environment.cjs +5 -5
  167. package/dist/{error-8582d695.cjs → error-0c1f634f.cjs} +10 -2
  168. package/dist/error-0c1f634f.cjs.map +1 -0
  169. package/dist/error.cjs +2 -1
  170. package/dist/error.cjs.map +1 -1
  171. package/dist/error.d.ts +1 -0
  172. package/dist/error.d.ts.map +1 -1
  173. package/dist/{eventloop-b299a889.cjs → eventloop-a0168106.cjs} +2 -2
  174. package/dist/{eventloop-b299a889.cjs.map → eventloop-a0168106.cjs.map} +1 -1
  175. package/dist/eventloop.cjs +3 -3
  176. package/dist/{function-09b8292c.cjs → function-e7d18feb.cjs} +2 -2
  177. package/dist/{function-09b8292c.cjs.map → function-e7d18feb.cjs.map} +1 -1
  178. package/dist/function.cjs +2 -2
  179. package/dist/index.cjs +23 -22
  180. package/dist/index.cjs.map +1 -1
  181. package/dist/index2.cjs +71 -0
  182. package/dist/index2.cjs.map +1 -0
  183. package/dist/{indexeddb-0cbb4d6f.cjs → indexeddb-46d1e737.cjs} +3 -3
  184. package/dist/{indexeddb-0cbb4d6f.cjs.map → indexeddb-46d1e737.cjs.map} +1 -1
  185. package/dist/indexeddb.cjs +5 -5
  186. package/dist/indexeddbV2.cjs +2 -1
  187. package/dist/indexeddbV2.cjs.map +1 -1
  188. package/dist/jwt.cjs +12 -12
  189. package/dist/list.cjs +39 -12
  190. package/dist/list.cjs.map +1 -1
  191. package/dist/list.d.ts +13 -3
  192. package/dist/list.d.ts.map +1 -1
  193. package/dist/logging.cjs +11 -9
  194. package/dist/logging.cjs.map +1 -1
  195. package/dist/logging.common.cjs +7 -7
  196. package/dist/logging.node.cjs +7 -7
  197. package/dist/{map-0dabcc55.cjs → map-24d263c0.cjs} +7 -1
  198. package/dist/map-24d263c0.cjs.map +1 -0
  199. package/dist/map.cjs +314 -7
  200. package/dist/map.cjs.map +1 -1
  201. package/dist/map.d.ts +1 -0
  202. package/dist/map.d.ts.map +1 -1
  203. package/dist/map2.cjs +15 -0
  204. package/dist/map2.cjs.map +1 -0
  205. package/dist/{math-08e068f9.cjs → math-96d5e8c4.cjs} +4 -2
  206. package/dist/math-96d5e8c4.cjs.map +1 -0
  207. package/dist/math.cjs +1 -1
  208. package/dist/math.d.ts.map +1 -1
  209. package/dist/metric.cjs +1 -1
  210. package/dist/node.cjs +206 -0
  211. package/dist/node.cjs.map +1 -0
  212. package/dist/{number-466d8922.cjs → number-1fb57bba.cjs} +2 -2
  213. package/dist/{number-466d8922.cjs.map → number-1fb57bba.cjs.map} +1 -1
  214. package/dist/number.cjs +2 -2
  215. package/dist/{object-491858d1.cjs → object-18980796.cjs} +12 -2
  216. package/dist/object-18980796.cjs.map +1 -0
  217. package/dist/object.cjs +3 -1
  218. package/dist/object.cjs.map +1 -1
  219. package/dist/object.d.ts +3 -0
  220. package/dist/object.d.ts.map +1 -1
  221. package/dist/observable.cjs +1 -1
  222. package/dist/ops.cjs +575 -0
  223. package/dist/ops.cjs.map +1 -0
  224. package/dist/patience.cjs +2 -2
  225. package/dist/performance.node.cjs +4 -4
  226. package/dist/pledge.cjs +2 -1
  227. package/dist/pledge.cjs.map +1 -1
  228. package/dist/{prng-24dfe0bf.cjs → prng-004c76e8.cjs} +5 -5
  229. package/dist/{prng-24dfe0bf.cjs.map → prng-004c76e8.cjs.map} +1 -1
  230. package/dist/prng.cjs +12 -12
  231. package/dist/prng.d.ts +1 -1
  232. package/dist/prng.d.ts.map +1 -1
  233. package/dist/{promise-7d13a97c.cjs → promise-cda7b9bb.cjs} +2 -2
  234. package/dist/{promise-7d13a97c.cjs.map → promise-cda7b9bb.cjs.map} +1 -1
  235. package/dist/promise.cjs +3 -3
  236. package/dist/rabin-gf2-polynomial.cjs +11 -11
  237. package/dist/rabin-uncached.cjs +11 -11
  238. package/dist/rabin.cjs +11 -11
  239. package/dist/random.cjs +1 -1
  240. package/dist/rsa-oaep.cjs +3 -3
  241. package/dist/rsa-oaep.cjs.map +1 -1
  242. package/dist/schema.cjs +572 -167
  243. package/dist/schema.cjs.map +1 -1
  244. package/dist/schema.d.ts +326 -122
  245. package/dist/schema.d.ts.map +1 -1
  246. package/dist/schema.test.d.ts +5 -0
  247. package/dist/schema.test.d.ts.map +1 -1
  248. package/dist/{sort-b8702761.cjs → sort-812cc211.cjs} +2 -2
  249. package/dist/{sort-b8702761.cjs.map → sort-812cc211.cjs.map} +1 -1
  250. package/dist/sort.cjs +2 -2
  251. package/dist/{statistics-c2316dca.cjs → statistics-65f6114b.cjs} +2 -2
  252. package/dist/{statistics-c2316dca.cjs.map → statistics-65f6114b.cjs.map} +1 -1
  253. package/dist/statistics.cjs +2 -2
  254. package/dist/{string-b2827a90.cjs → string-fddc5f8b.cjs} +3 -3
  255. package/dist/string-fddc5f8b.cjs.map +1 -0
  256. package/dist/string.cjs +1 -1
  257. package/dist/string.d.ts +3 -3
  258. package/dist/string.d.ts.map +1 -1
  259. package/dist/testing.cjs +16 -16
  260. package/dist/text.cjs +79 -0
  261. package/dist/text.cjs.map +1 -0
  262. package/dist/{time-bc2081b9.cjs → time-d8438852.cjs} +2 -2
  263. package/dist/{time-bc2081b9.cjs.map → time-d8438852.cjs.map} +1 -1
  264. package/dist/time.cjs +2 -2
  265. package/dist/traits.cjs +22 -0
  266. package/dist/traits.cjs.map +1 -1
  267. package/dist/traits.d.ts +1 -0
  268. package/dist/traits.d.ts.map +1 -1
  269. package/dist/traits.test.d.ts.map +1 -1
  270. package/dist/transformer.cjs +930 -0
  271. package/dist/transformer.cjs.map +1 -0
  272. package/dist/url.cjs +2 -1
  273. package/dist/url.cjs.map +1 -1
  274. package/dist/value.cjs +187 -0
  275. package/dist/value.cjs.map +1 -0
  276. package/dist/webcrypto.d.ts +1 -1
  277. package/dist/webcrypto.d.ts.map +1 -1
  278. package/dist/{websocket-40a601d4.cjs → websocket-b073d0fc.cjs} +3 -3
  279. package/dist/{websocket-40a601d4.cjs.map → websocket-b073d0fc.cjs.map} +1 -1
  280. package/dist/websocket.cjs +4 -4
  281. package/dom.d.ts +17 -0
  282. package/dom.d.ts.map +1 -1
  283. package/dom.js +21 -0
  284. package/encoding.d.ts +6 -6
  285. package/encoding.d.ts.map +1 -1
  286. package/encoding.js +1 -1
  287. package/error.d.ts +1 -0
  288. package/error.d.ts.map +1 -1
  289. package/error.js +6 -0
  290. package/list.d.ts +13 -3
  291. package/list.d.ts.map +1 -1
  292. package/list.js +36 -8
  293. package/map.d.ts +1 -0
  294. package/map.d.ts.map +1 -1
  295. package/map.js +6 -0
  296. package/math.d.ts.map +1 -1
  297. package/math.js +3 -1
  298. package/object.d.ts +3 -0
  299. package/object.d.ts.map +1 -1
  300. package/object.js +9 -1
  301. package/package.json +9 -3
  302. package/prng.d.ts +1 -1
  303. package/prng.d.ts.map +1 -1
  304. package/prng.js +1 -1
  305. package/schema.d.ts +326 -122
  306. package/schema.d.ts.map +1 -1
  307. package/schema.js +513 -141
  308. package/schema.test.d.ts +5 -0
  309. package/schema.test.d.ts.map +1 -1
  310. package/string.d.ts +3 -3
  311. package/string.d.ts.map +1 -1
  312. package/string.js +2 -2
  313. package/test.html +1 -0
  314. package/test.js +13 -1
  315. package/traits.d.ts +1 -0
  316. package/traits.d.ts.map +1 -1
  317. package/traits.js +21 -0
  318. package/traits.test.d.ts.map +1 -1
  319. package/webcrypto.d.ts +1 -1
  320. package/webcrypto.d.ts.map +1 -1
  321. package/coverage/tmp/coverage-20054-1752683240888-0.json +0 -1
  322. package/dist/broadcastchannel-2c4b0a1c.cjs.map +0 -1
  323. package/dist/buffer-a74f7330.cjs.map +0 -1
  324. package/dist/decoding-2b136346.cjs.map +0 -1
  325. package/dist/dom-16daf1a0.cjs.map +0 -1
  326. package/dist/encoding-1acb59c4.cjs.map +0 -1
  327. package/dist/error-8582d695.cjs.map +0 -1
  328. package/dist/map-0dabcc55.cjs.map +0 -1
  329. package/dist/math-08e068f9.cjs.map +0 -1
  330. package/dist/object-491858d1.cjs.map +0 -1
  331. package/dist/string-b2827a90.cjs.map +0 -1
package/schema.js CHANGED
@@ -8,6 +8,9 @@ import * as obj from './object.js'
8
8
  import * as arr from './array.js'
9
9
  import * as error from './error.js'
10
10
  import * as env from './environment.js'
11
+ import * as traits from './traits.js'
12
+ import * as fun from './function.js'
13
+ import * as string from './string.js'
11
14
 
12
15
  /**
13
16
  * @typedef {string|number|bigint|boolean|null|undefined} LiteralType
@@ -19,17 +22,22 @@ import * as env from './environment.js'
19
22
 
20
23
  /**
21
24
  * @template T
22
- * @typedef {T extends $Schema<infer X> ? X : T} Unwrap
25
+ * @typedef {T extends Schema<infer X> ? X : T} Unwrap
26
+ */
27
+
28
+ /**
29
+ * @template T
30
+ * @typedef {T extends Schema<infer X> ? X : T} TypeOf
23
31
  */
24
32
 
25
33
  /**
26
34
  * @template {readonly unknown[]} T
27
- * @typedef {T extends readonly [$Schema<infer First>, ...infer Rest] ? [First, ...UnwrapArray<Rest>] : [] } UnwrapArray
35
+ * @typedef {T extends readonly [Schema<infer First>, ...infer Rest] ? [First, ...UnwrapArray<Rest>] : [] } UnwrapArray
28
36
  */
29
37
 
30
38
  /**
31
39
  * @template T
32
- * @typedef {T extends $Schema<infer S> ? $Schema<S> : never} CastToSchema
40
+ * @typedef {T extends Schema<infer S> ? Schema<S> : never} CastToSchema
33
41
  */
34
42
 
35
43
  /**
@@ -56,11 +64,98 @@ import * as env from './environment.js'
56
64
 
57
65
  const schemaSymbol = Symbol('0schema')
58
66
 
67
+ class ValidationError {
68
+ constructor () {
69
+ /**
70
+ * Reverse errors
71
+ * @type {Array<{ path: string?, expected: string, has: string, message: string? }>}
72
+ */
73
+ this._rerrs = []
74
+ }
75
+
76
+ /**
77
+ * @param {string?} path
78
+ * @param {string} expected
79
+ * @param {string} has
80
+ * @param {string?} message
81
+ */
82
+ extend (path, expected, has, message = null) {
83
+ this._rerrs.push({ path, expected, has, message })
84
+ }
85
+
86
+ toString () {
87
+ const s = []
88
+ for (let i = this._rerrs.length - 1; i > 0; i--) {
89
+ const r = this._rerrs[i]
90
+ s.push(string.repeat(' ', (this._rerrs.length - i) * 2) + `${r.path != null ? `[${r.path}] ` : ''}${r.has} doesn't match ${r.expected}. ${r.message}`)
91
+ }
92
+ return s.join('\n')
93
+ }
94
+ }
95
+
96
+ /**
97
+ * @param {any} a
98
+ * @param {any} b
99
+ * @return {boolean}
100
+ */
101
+ const shapeExtends = (a, b) => {
102
+ if (a === b) return true
103
+ if (a == null || b == null || a.constructor !== b.constructor) return false
104
+ if (a[traits.EqualityTraitSymbol]) return traits.equals(a, b) // last resort: check equality (do this before array and obj check which don't implement the equality trait)
105
+ if (arr.isArray(a)) {
106
+ return arr.every(a, aitem =>
107
+ arr.some(b, bitem => shapeExtends(aitem, bitem))
108
+ )
109
+ } else if (obj.isObject(a)) {
110
+ return obj.every(a, (aitem, akey) =>
111
+ shapeExtends(aitem, b[akey])
112
+ )
113
+ }
114
+ /* c8 ignore next */
115
+ return false
116
+ }
117
+
59
118
  /**
60
119
  * @template T
120
+ * @implements {traits.EqualityTrait}
61
121
  */
62
- export class $Schema {
63
- get [schemaSymbol] () { return true }
122
+ export class Schema {
123
+ // this.shape must not be defined on Schema. Otherwise typecheck on metatypes (e.g. $$object) won't work as expected anymore
124
+ /**
125
+ * If true, the more things are added to the shape the more objects this schema will accept (e.g.
126
+ * union). By default, the more objects are added, the the fewer objects this schema will accept.
127
+ * @protected
128
+ */
129
+ static _dilutes = false
130
+
131
+ /**
132
+ * @param {Schema<any>} other
133
+ */
134
+ extends (other) {
135
+ let [a, b] = [/** @type {any} */(this).shape, /** @type {any} */ (other).shape]
136
+ if (/** @type {typeof Schema<any>} */ (this.constructor)._dilutes) [b, a] = [a, b]
137
+ return shapeExtends(a, b)
138
+ }
139
+
140
+ /**
141
+ * Overwrite this when necessary. By default, we only check the `shape` property which every shape
142
+ * should have.
143
+ * @param {Schema<any>} other
144
+ */
145
+ equals (other) {
146
+ // @ts-ignore
147
+ return this.constructor === other.constructor && fun.equalityDeep(this.shape, other.shape)
148
+ }
149
+
150
+ [schemaSymbol] () { return true }
151
+
152
+ /**
153
+ * @param {object} other
154
+ */
155
+ [traits.EqualityTraitSymbol] (other) {
156
+ return this.equals(/** @type {any} */ (other))
157
+ }
158
+
64
159
  /**
65
160
  * Use `schema.validate(obj)` with a typed parameter that is already of typed to be an instance of
66
161
  * Schema. Validate will check the structure of the parameter and return true iff the instance
@@ -78,25 +173,26 @@ export class $Schema {
78
173
  * Similar to validate, but this method accepts untyped parameters.
79
174
  *
80
175
  * @param {any} _o
176
+ * @param {ValidationError} [_err]
81
177
  * @return {_o is T}
82
178
  */
83
- check (_o) {
179
+ check (_o, _err) {
84
180
  error.methodUnimplemented()
85
181
  }
86
182
  /* c8 ignore stop */
87
183
 
88
184
  /**
89
- * @type {$Schema<T?>}
185
+ * @type {Schema<T?>}
90
186
  */
91
187
  get nullable () {
92
- return union(this, null_)
188
+ return $union(this, $null)
93
189
  }
94
190
 
95
191
  /**
96
- * @type {$Optional<$Schema<T>>}
192
+ * @type {$Optional<Schema<T>>}
97
193
  */
98
194
  get optional () {
99
- return new $Optional(/** @type {$Schema<T>} */ (this))
195
+ return new $Optional(/** @type {Schema<T>} */ (this))
100
196
  }
101
197
 
102
198
  /**
@@ -107,20 +203,27 @@ export class $Schema {
107
203
  * **Do not rely on these error messages!**
108
204
  * Performs an assertion check only if not in a production environment.
109
205
  *
110
- * @param {any} o
111
- * @return {o extends T ? T : never}
206
+ * @template OO
207
+ * @param {OO} o
208
+ * @return {Extract<OO, T> extends never ? T : (OO extends Array<never> ? T : Extract<OO,T>)}
112
209
  */
113
210
  cast (o) {
114
211
  assert(o, this)
115
- return o
212
+ return /** @type {any} */ (o)
116
213
  }
117
214
 
118
215
  /**
216
+ * EXPECTO PATRONUM!! 🪄
217
+ * This function protects against type errors. Though it may not work in the real world.
218
+ *
219
+ * "After all this time?"
220
+ * "Always." - Snape, talking about type safety
221
+ *
119
222
  * Ensures that a variable is a a specific type. Returns the value, or throws an exception if the assertion check failed.
120
223
  * Use this if you know that the type is of a specific type and you just want to convince the type
121
224
  * system.
122
225
  *
123
- * Can be useful when defining lambdas: `s.lambda(s.$number, s.$void).ensure((n) => n + 1)`
226
+ * Can be useful when defining lambdas: `s.lambda(s.$number, s.$void).expect((n) => n + 1)`
124
227
  *
125
228
  * **Do not rely on these error messages!**
126
229
  * Performs an assertion check if not in a production environment.
@@ -128,60 +231,115 @@ export class $Schema {
128
231
  * @param {T} o
129
232
  * @return {o extends T ? T : never}
130
233
  */
131
- ensure (o) {
234
+ expect (o) {
132
235
  assert(o, this)
133
236
  return o
134
237
  }
135
238
  }
136
239
 
240
+ /**
241
+ * @template {(new (...args:any[]) => any) | ((...args:any[]) => any)} Constr
242
+ * @typedef {Constr extends ((...args:any[]) => infer T) ? T : (Constr extends (new (...args:any[]) => any) ? InstanceType<Constr> : never)} Instance
243
+ */
244
+
137
245
  /**
138
246
  * @template {(new (...args:any[]) => any) | ((...args:any[]) => any)} C
139
- * @extends {$Schema<C extends ((...args:any[]) => infer T) ? T : (C extends (new (...args:any[]) => any) ? InstanceType<C> : never)>}
247
+ * @extends {Schema<Instance<C>>}
140
248
  */
141
- export class $ConstructedBy extends $Schema {
249
+ export class $ConstructedBy extends Schema {
142
250
  /**
143
251
  * @param {C} c
252
+ * @param {((o:Instance<C>)=>boolean)|null} check
144
253
  */
145
- constructor (c) {
254
+ constructor (c, check) {
146
255
  super()
147
- this.v = c
256
+ this.shape = c
257
+ this._c = check
148
258
  }
149
259
 
150
260
  /**
151
261
  * @param {any} o
262
+ * @param {ValidationError} [err]
152
263
  * @return {o is C extends ((...args:any[]) => infer T) ? T : (C extends (new (...args:any[]) => any) ? InstanceType<C> : never)} o
153
264
  */
154
- check (o) {
155
- return o?.constructor === this.v
265
+ check (o, err = undefined) {
266
+ const c = o?.constructor === this.shape && (this._c == null || this._c(o))
267
+ /* c8 ignore next */
268
+ !c && err?.extend(null, this.shape.name, o?.constructor.name, o?.constructor !== this.shape ? 'Constructor match failed' : 'Check failed')
269
+ return c
156
270
  }
157
271
  }
158
272
 
159
273
  /**
160
274
  * @template {(new (...args:any[]) => any) | ((...args:any[]) => any)} C
161
275
  * @param {C} c
276
+ * @param {((o:Instance<C>) => boolean)|null} check
162
277
  * @return {CastToSchema<$ConstructedBy<C>>}
163
278
  */
164
- export const constructedBy = c => new $ConstructedBy(c)
279
+ export const $constructedBy = (c, check = null) => new $ConstructedBy(c, check)
280
+ export const $$constructedBy = $constructedBy($ConstructedBy)
281
+
282
+ /**
283
+ * Check custom properties on any object. You may want to overwrite the generated Schema<any>.
284
+ *
285
+ * @extends {Schema<any>}
286
+ */
287
+ export class $Custom extends Schema {
288
+ /**
289
+ * @param {(o:any) => boolean} check
290
+ */
291
+ constructor (check) {
292
+ super()
293
+ /**
294
+ * @type {(o:any) => boolean}
295
+ */
296
+ this.shape = check
297
+ }
298
+
299
+ /**
300
+ * @param {any} o
301
+ * @param {ValidationError} err
302
+ * @return {o is any}
303
+ */
304
+ check (o, err) {
305
+ const c = this.shape(o)
306
+ /* c8 ignore next */
307
+ !c && err?.extend(null, 'custom prop', o?.constructor.name, 'failed to check custom prop')
308
+ return c
309
+ }
310
+ }
311
+
312
+ /**
313
+ * @param {(o:any) => boolean} check
314
+ * @return {Schema<any>}
315
+ */
316
+ export const $custom = check => new $Custom(check)
317
+ export const $$custom = $constructedBy($Custom)
165
318
 
166
319
  /**
167
320
  * @template {LiteralType} T
168
- * @extends {$Schema<T>}
321
+ * @extends {Schema<T>}
169
322
  */
170
- export class $Literal extends $Schema {
323
+ export class $Literal extends Schema {
171
324
  /**
172
325
  * @param {Array<T>} literals
173
326
  */
174
327
  constructor (literals) {
175
328
  super()
176
- this.v = literals
329
+ this.shape = literals
177
330
  }
178
331
 
179
332
  /**
333
+ *
180
334
  * @param {any} o
335
+ * @param {ValidationError} [err]
181
336
  * @return {o is T}
182
337
  */
183
- check (o) {
184
- return this.v.some(a => a === o)
338
+ check (o, err) {
339
+ const c = this.shape.some(a => a === o)
340
+ /* c8 ignore next */
341
+ !c && err?.extend(null, this.shape.join(' | '), o.toString())
342
+ return c
185
343
  }
186
344
  }
187
345
 
@@ -190,234 +348,405 @@ export class $Literal extends $Schema {
190
348
  * @param {T} literals
191
349
  * @return {CastToSchema<$Literal<T[number]>>}
192
350
  */
193
- export const literal = (...literals) => new $Literal(literals)
351
+ export const $literal = (...literals) => new $Literal(literals)
352
+ export const $$literal = $constructedBy($Literal)
353
+
354
+ /**
355
+ * @template {Array<string|Schema<string|number>>} Ts
356
+ * @typedef {Ts extends [] ? `` : (Ts extends [infer T] ? (Unwrap<T> extends (string|number) ? Unwrap<T> : never) : (Ts extends [infer T1, ...infer Rest] ? `${Unwrap<T1> extends (string|number) ? Unwrap<T1> : never}${Rest extends Array<string|Schema<string|number>> ? CastStringTemplateArgsToTemplate<Rest> : never}` : never))} CastStringTemplateArgsToTemplate
357
+ */
358
+
359
+ /**
360
+ * @param {string} str
361
+ * @return {string}
362
+ */
363
+ const _regexEscape = /** @type {any} */ (RegExp).escape || /** @type {(str:string) => string} */ (str =>
364
+ str.replace(/[().|&,$^[\]]/g, s => '\\' + s)
365
+ )
366
+
367
+ /**
368
+ * @param {string|Schema<any>} s
369
+ * @return {string[]}
370
+ */
371
+ const _schemaStringTemplateToRegex = s => {
372
+ if ($string.check(s)) {
373
+ return [_regexEscape(s)]
374
+ }
375
+ if ($$literal.check(s)) {
376
+ return s.shape.map(v => v + '')
377
+ }
378
+ if ($$number.check(s)) {
379
+ return ['[+-]?\\d+.?\\d*']
380
+ }
381
+ if ($$string.check(s)) {
382
+ return ['.*']
383
+ }
384
+ if ($$union.check(s)) {
385
+ return s.shape.map(_schemaStringTemplateToRegex).flat(1)
386
+ }
387
+ /* c8 ignore next 2 */
388
+ // unexpected schema structure (only supports unions and string in literal types)
389
+ error.unexpectedCase()
390
+ }
391
+
392
+ /**
393
+ * @template {Array<string|Schema<string|number>>} T
394
+ * @extends {Schema<CastStringTemplateArgsToTemplate<T>>}
395
+ */
396
+ export class $StringTemplate extends Schema {
397
+ /**
398
+ * @param {T} shape
399
+ */
400
+ constructor (shape) {
401
+ super()
402
+ this.shape = shape
403
+ this._r = new RegExp('^' + shape.map(_schemaStringTemplateToRegex).map(opts => `(${opts.join('|')})`).join('') + '$')
404
+ }
405
+
406
+ /**
407
+ * @param {any} o
408
+ * @param {ValidationError} [err]
409
+ * @return {o is CastStringTemplateArgsToTemplate<T>}
410
+ */
411
+ check (o, err) {
412
+ const c = this._r.exec(o) != null
413
+ /* c8 ignore next */
414
+ !c && err?.extend(null, this._r.toString(), o.toString(), 'String doesn\'t match string template.')
415
+ return c
416
+ }
417
+ }
418
+
419
+ /**
420
+ * @template {Array<string|Schema<string|number>>} T
421
+ * @param {T} literals
422
+ * @return {CastToSchema<$StringTemplate<T>>}
423
+ */
424
+ export const $stringTemplate = (...literals) => new $StringTemplate(literals)
425
+ export const $$stringTemplate = $constructedBy($StringTemplate)
194
426
 
195
427
  const isOptionalSymbol = Symbol('optional')
196
428
  /**
197
- * @template {$Schema<any>} S
198
- * @extends $Schema<Unwrap<S>|undefined>
429
+ * @template {Schema<any>} S
430
+ * @extends Schema<Unwrap<S>|undefined>
199
431
  */
200
- class $Optional extends $Schema {
432
+ class $Optional extends Schema {
201
433
  /**
202
- * @param {S} s
434
+ * @param {S} shape
203
435
  */
204
- constructor (s) {
436
+ constructor (shape) {
205
437
  super()
206
- this.s = s
438
+ this.shape = shape
207
439
  }
208
440
 
209
441
  /**
210
442
  * @param {any} o
443
+ * @param {ValidationError} [err]
211
444
  * @return {o is (Unwrap<S>|undefined)}
212
445
  */
213
- check (o) {
214
- return o === undefined || this.s.check(o)
446
+ check (o, err) {
447
+ const c = o === undefined || this.shape.check(o)
448
+ /* c8 ignore next */
449
+ !c && err?.extend(null, 'undefined (optional)', '()')
450
+ return c
215
451
  }
216
452
 
217
453
  get [isOptionalSymbol] () { return true }
218
454
  }
455
+ export const $$optional = $constructedBy($Optional)
456
+
457
+ /**
458
+ * @extends Schema<never>
459
+ */
460
+ class $Never extends Schema {
461
+ /**
462
+ * @param {any} _o
463
+ * @param {ValidationError} [err]
464
+ * @return {_o is never}
465
+ */
466
+ check (_o, err) {
467
+ err?.extend(null, 'never', typeof _o)
468
+ return false
469
+ }
470
+ }
219
471
 
220
472
  /**
221
- * @template {{ [key: string|symbol|number]: $Schema<any> }} S
222
- * @typedef {{ [Key in keyof S as S[Key] extends $Optional<$Schema<any>> ? Key : never]?: S[Key] extends $Optional<$Schema<infer Type>> ? Type : never } & { [Key in keyof S as S[Key] extends $Optional<$Schema<any>> ? never : Key]: S[Key] extends $Schema<infer Type> ? Type : never }} $ObjectToType
473
+ * @type {Schema<never>}
223
474
  */
475
+ export const $never = new $Never()
476
+ export const $$never = $constructedBy($Never)
224
477
 
225
478
  /**
226
- * @template {{[key:string|symbol|number]: $Schema<any>}} S
227
- * @extends {$Schema<$ObjectToType<S>>}
479
+ * @template {{ [key: string|symbol|number]: Schema<any> }} S
480
+ * @typedef {{ [Key in keyof S as S[Key] extends $Optional<Schema<any>> ? Key : never]?: S[Key] extends $Optional<Schema<infer Type>> ? Type : never } & { [Key in keyof S as S[Key] extends $Optional<Schema<any>> ? never : Key]: S[Key] extends Schema<infer Type> ? Type : never }} $ObjectToType
228
481
  */
229
- export class $Object extends $Schema {
482
+
483
+ /**
484
+ * @template {{[key:string|symbol|number]: Schema<any>}} S
485
+ * @extends {Schema<$ObjectToType<S>>}
486
+ */
487
+ export class $Object extends Schema {
230
488
  /**
231
- * @param {S} v
489
+ * @param {S} shape
490
+ * @param {boolean} partial
232
491
  */
233
- constructor (v) {
492
+ constructor (shape, partial = false) {
234
493
  super()
235
- this.v = v
494
+ /**
495
+ * @type {S}
496
+ */
497
+ this.shape = shape
498
+ this._isPartial = partial
499
+ }
500
+
501
+ /**
502
+ * @type {Schema<Partial<$ObjectToType<S>>>}
503
+ */
504
+ get partial () {
505
+ return new $Object(this.shape, true)
236
506
  }
237
507
 
238
508
  /**
239
509
  * @param {any} o
510
+ * @param {ValidationError} err
240
511
  * @return {o is $ObjectToType<S>}
241
512
  */
242
- check (o) {
243
- return o != null && obj.every(this.v, (vv, vk) => vv.check(o[vk]))
513
+ check (o, err) {
514
+ if (o == null) {
515
+ /* c8 ignore next */
516
+ err?.extend(null, 'object', 'null')
517
+ return false
518
+ }
519
+ return obj.every(this.shape, (vv, vk) => {
520
+ const c = (this._isPartial && !obj.hasProperty(o, vk)) || vv.check(o[vk], err)
521
+ !c && err?.extend(vk.toString(), vv.toString(), typeof o[vk], 'Object property does not match')
522
+ return c
523
+ })
244
524
  }
245
525
  }
246
526
 
527
+ /**
528
+ * @template {{ [key:string|symbol|number]: Schema<any> }} S
529
+ * @typedef {Schema<{ [Key in keyof S as S[Key] extends $Optional<Schema<any>> ? Key : never]?: S[Key] extends $Optional<Schema<infer Type>> ? Type : never } & { [Key in keyof S as S[Key] extends $Optional<Schema<any>> ? never : Key]: S[Key] extends Schema<infer Type> ? Type : never }>} _ObjectDefToSchema
530
+ */
531
+
247
532
  // I used an explicit type annotation instead of $ObjectToType, so that the user doesn't see the
248
533
  // weird type definitions when inspecting type definions.
249
534
  /**
250
- * @template {{ [key:string|symbol|number]: $Schema<any> }} S
535
+ * @template {{ [key:string|symbol|number]: Schema<any> }} S
251
536
  * @param {S} def
252
- * @return {$Schema<{ [Key in keyof S as S[Key] extends $Optional<$Schema<any>> ? Key : never]?: S[Key] extends $Optional<$Schema<infer Type>> ? Type : never } & { [Key in keyof S as S[Key] extends $Optional<$Schema<any>> ? never : Key]: S[Key] extends $Schema<infer Type> ? Type : never }>}
537
+ * @return {_ObjectDefToSchema<S> extends Schema<infer S> ? Schema<S> : never}
538
+ */
539
+ export const $object = def => /** @type {any} */ (new $Object(def))
540
+ export const $$object = $constructedBy($Object)
541
+ /**
542
+ * @type {Schema<{[key:string]: any}>}
253
543
  */
254
- export const object = def => /** @type {any} */ (new $Object(def))
544
+ export const $objectAny = $custom(o => o != null && (o.constructor == null || o.constructor === Object))
255
545
 
256
546
  /**
257
- * @template {$Schema<string|number|symbol>} Keys
258
- * @template {$Schema<any>} Values
259
- * @extends {$Schema<Record<Keys extends $Schema<infer K> ? K : never,Values extends $Schema<infer T> ? T : never>>}
547
+ * @template {Schema<string|number|symbol>} Keys
548
+ * @template {Schema<any>} Values
549
+ * @extends {Schema<{ [key in Unwrap<Keys>]: Unwrap<Values> }>}
260
550
  */
261
- export class $Record extends $Schema {
551
+ export class $Record extends Schema {
262
552
  /**
263
553
  * @param {Keys} keys
264
554
  * @param {Values} values
265
555
  */
266
556
  constructor (keys, values) {
267
557
  super()
268
- this.keys = keys
269
- this.values = values
558
+ this.shape = {
559
+ keys, values
560
+ }
270
561
  }
271
562
 
272
563
  /**
273
564
  * @param {any} o
274
- * @return {o is Record<Keys extends $Schema<infer K> ? K : never,Values extends $Schema<infer T> ? T : never>}
565
+ * @param {ValidationError} err
566
+ * @return {o is { [key in Unwrap<Keys>]: Unwrap<Values> }}
275
567
  */
276
- check (o) {
277
- return o != null && obj.every(o, (vv, vk) => this.keys.check(vk) && this.values.check(vv))
568
+ check (o, err) {
569
+ return o != null && obj.every(o, (vv, vk) => {
570
+ const ck = this.shape.keys.check(vk, err)
571
+ /* c8 ignore next */
572
+ !ck && err?.extend(vk + '', 'Record', typeof o, ck ? 'Key doesn\'t match schema' : 'Value doesn\'t match value')
573
+ return ck && this.shape.values.check(vv, err)
574
+ })
278
575
  }
279
576
  }
280
577
 
281
578
  /**
282
- * @template {$Schema<string|number|symbol>} Keys
283
- * @template {$Schema<any>} Values
579
+ * @template {Schema<string|number|symbol>} Keys
580
+ * @template {Schema<any>} Values
284
581
  * @param {Keys} keys
285
582
  * @param {Values} values
286
583
  * @return {CastToSchema<$Record<Keys,Values>>}
287
584
  */
288
- export const record = (keys, values) => new $Record(keys, values)
585
+ export const $record = (keys, values) => new $Record(keys, values)
586
+ export const $$record = $constructedBy($Record)
289
587
 
290
588
  /**
291
- * @template {$Schema<any>[]} S
292
- * @extends {$Schema<{ [Key in keyof S]: S[Key] extends $Schema<infer Type> ? Type : never }>}
589
+ * @template {Schema<any>[]} S
590
+ * @extends {Schema<{ [Key in keyof S]: S[Key] extends Schema<infer Type> ? Type : never }>}
293
591
  */
294
- export class $Tuple extends $Schema {
592
+ export class $Tuple extends Schema {
295
593
  /**
296
- * @param {S} v
594
+ * @param {S} shape
297
595
  */
298
- constructor (v) {
596
+ constructor (shape) {
299
597
  super()
300
- this.v = v
598
+ this.shape = shape
301
599
  }
302
600
 
303
601
  /**
304
602
  * @param {any} o
305
- * @return {o is { [K in keyof S]: S[K] extends $Schema<infer Type> ? Type : never }}
603
+ * @param {ValidationError} err
604
+ * @return {o is { [K in keyof S]: S[K] extends Schema<infer Type> ? Type : never }}
306
605
  */
307
- check (o) {
308
- return o != null && obj.every(this.v, (vv, vk) => /** @type {$Schema<any>} */ (vv).check(o[vk]))
606
+ check (o, err) {
607
+ return o != null && obj.every(this.shape, (vv, vk) => {
608
+ const c = /** @type {Schema<any>} */ (vv).check(o[vk], err)
609
+ /* c8 ignore next */
610
+ !c && err?.extend(vk.toString(), 'Tuple', typeof vv)
611
+ return c
612
+ })
309
613
  }
310
614
  }
311
615
 
312
616
  /**
313
- * @template {Array<$Schema<any>>} T
617
+ * @template {Array<Schema<any>>} T
314
618
  * @param {T} def
315
619
  * @return {CastToSchema<$Tuple<T>>}
316
620
  */
317
- export const tuple = (...def) => new $Tuple(def)
621
+ export const $tuple = (...def) => new $Tuple(def)
622
+ export const $$tuple = $constructedBy($Tuple)
318
623
 
319
624
  /**
320
- * @template {$Schema<any>} S
321
- * @extends {$Schema<Array<S extends $Schema<infer T> ? T : never>>}
625
+ * @template {Schema<any>} S
626
+ * @extends {Schema<Array<S extends Schema<infer T> ? T : never>>}
322
627
  */
323
- export class $Array extends $Schema {
628
+ export class $Array extends Schema {
324
629
  /**
325
630
  * @param {Array<S>} v
326
631
  */
327
632
  constructor (v) {
328
633
  super()
329
634
  /**
330
- * @type {$Schema<S extends $Schema<infer T> ? T : never>}
635
+ * @type {Schema<S extends Schema<infer T> ? T : never>}
331
636
  */
332
- this.v = v.length === 1 ? v[0] : new $Union(v)
637
+ this.shape = v.length === 1 ? v[0] : new $Union(v)
333
638
  }
334
639
 
335
640
  /**
336
641
  * @param {any} o
337
- * @return {o is Array<S extends $Schema<infer T> ? T : never>} o
642
+ * @param {ValidationError} [err]
643
+ * @return {o is Array<S extends Schema<infer T> ? T : never>} o
338
644
  */
339
- check (o) {
340
- return arr.isArray(o) && arr.every(o, oi => this.v.check(oi))
645
+ check (o, err) {
646
+ const c = arr.isArray(o) && arr.every(o, oi => this.shape.check(oi))
647
+ /* c8 ignore next */
648
+ !c && err?.extend(null, 'Array', '')
649
+ return c
341
650
  }
342
651
  }
343
652
 
344
653
  /**
345
- * @template {Array<$Schema<any>>} T
654
+ * @template {Array<Schema<any>>} T
346
655
  * @param {T} def
347
- * @return {$Schema<Array<T extends Array<$Schema<infer S>> ? S : never>>}
656
+ * @return {Schema<Array<T extends Array<Schema<infer S>> ? S : never>>}
657
+ */
658
+ export const $array = (...def) => new $Array(def)
659
+ export const $$array = $constructedBy($Array)
660
+ /**
661
+ * @type {Schema<Array<any>>}
348
662
  */
349
- export const array = (...def) => new $Array(def)
663
+ export const $arrayAny = $custom(o => arr.isArray(o))
350
664
 
351
665
  /**
352
666
  * @template T
353
- * @extends {$Schema<T>}
667
+ * @extends {Schema<T>}
354
668
  */
355
- export class $InstanceOf extends $Schema {
669
+ export class $InstanceOf extends Schema {
356
670
  /**
357
671
  * @param {new (...args:any) => T} constructor
672
+ * @param {((o:T) => boolean)|null} check
358
673
  */
359
- constructor (constructor) {
674
+ constructor (constructor, check) {
360
675
  super()
361
- this.v = constructor
676
+ this.shape = constructor
677
+ this._c = check
362
678
  }
363
679
 
364
680
  /**
365
681
  * @param {any} o
682
+ * @param {ValidationError} err
366
683
  * @return {o is T}
367
684
  */
368
- check (o) {
369
- return o instanceof this.v
685
+ check (o, err) {
686
+ const c = o instanceof this.shape && (this._c == null || this._c(o))
687
+ /* c8 ignore next */
688
+ !c && err?.extend(null, this.shape.name, o?.constructor.name)
689
+ return c
370
690
  }
371
691
  }
372
692
 
373
693
  /**
374
694
  * @template T
375
695
  * @param {new (...args:any) => T} c
376
- * @return {$Schema<T>}
696
+ * @param {((o:T) => boolean)|null} check
697
+ * @return {Schema<T>}
377
698
  */
378
- export const instance = c => new $InstanceOf(c)
699
+ export const $instanceOf = (c, check = null) => new $InstanceOf(c, check)
700
+ export const $$instanceOf = $constructedBy($InstanceOf)
701
+
702
+ export const $$schema = $instanceOf(Schema)
379
703
 
380
704
  /**
381
- * @template {$Schema<any>[]} Args
705
+ * @template {Schema<any>[]} Args
382
706
  * @typedef {(...args:UnwrapArray<TuplePop<Args>>)=>Unwrap<TupleLast<Args>>} _LArgsToLambdaDef
383
707
  */
384
708
 
385
709
  /**
386
- * @template {Array<$Schema<any>>} Args
387
- * @extends {$Schema<_LArgsToLambdaDef<Args>>}
710
+ * @template {Array<Schema<any>>} Args
711
+ * @extends {Schema<_LArgsToLambdaDef<Args>>}
388
712
  */
389
- export class $Lambda extends $Schema {
713
+ export class $Lambda extends Schema {
390
714
  /**
391
715
  * @param {Args} args
392
716
  */
393
717
  constructor (args) {
394
718
  super()
395
719
  this.len = args.length - 1
396
- this.args = tuple(...args.slice(-1))
720
+ this.args = $tuple(...args.slice(-1))
397
721
  this.res = args[this.len]
398
722
  }
399
723
 
400
724
  /**
401
725
  * @param {any} f
726
+ * @param {ValidationError} err
402
727
  * @return {f is _LArgsToLambdaDef<Args>}
403
728
  */
404
- check (f) {
405
- return f.constructor === Function && f.length <= this.len
729
+ check (f, err) {
730
+ const c = f.constructor === Function && f.length <= this.len
731
+ /* c8 ignore next */
732
+ !c && err?.extend(null, 'function', typeof f)
733
+ return c
406
734
  }
407
735
  }
408
736
 
409
737
  /**
410
- * @template {$Schema<any>[]} Args
738
+ * @template {Schema<any>[]} Args
411
739
  * @param {Args} args
412
- * @return {$Schema<(...args:UnwrapArray<TuplePop<Args>>)=>Unwrap<TupleLast<Args>>>}
740
+ * @return {Schema<(...args:UnwrapArray<TuplePop<Args>>)=>Unwrap<TupleLast<Args>>>}
413
741
  */
414
- export const lambda = (...args) => new $Lambda(args.length > 0 ? args : [void_])
742
+ export const $lambda = (...args) => new $Lambda(args.length > 0 ? args : [$void])
743
+ export const $$lambda = $constructedBy($Lambda)
415
744
 
416
745
  /**
417
- * @template {Array<$Schema<any>>} T
418
- * @extends {$Schema<Intersect<UnwrapArray<T>>>}
746
+ * @template {Array<Schema<any>>} T
747
+ * @extends {Schema<Intersect<UnwrapArray<T>>>}
419
748
  */
420
- export class $Intersection extends $Schema {
749
+ export class $Intersection extends Schema {
421
750
  /**
422
751
  * @param {T} v
423
752
  */
@@ -426,111 +755,154 @@ export class $Intersection extends $Schema {
426
755
  /**
427
756
  * @type {T}
428
757
  */
429
- this.v = v
758
+ this.shape = v
430
759
  }
431
760
 
432
761
  /**
433
762
  * @param {any} o
763
+ * @param {ValidationError} [err]
434
764
  * @return {o is Intersect<UnwrapArray<T>>}
435
765
  */
436
- check (o) {
766
+ check (o, err) {
437
767
  // @ts-ignore
438
- return arr.every(this.v, check => check.check(o))
768
+ const c = arr.every(this.shape, check => check.check(o, err))
769
+ /* c8 ignore next */
770
+ !c && err?.extend(null, 'Intersectinon', typeof o)
771
+ return c
439
772
  }
440
773
  }
441
774
 
442
775
  /**
443
- * @template {$Schema<any>[]} T
776
+ * @template {Schema<any>[]} T
444
777
  * @param {T} def
445
778
  * @return {CastToSchema<$Intersection<T>>}
446
779
  */
447
- export const intersect = (...def) => new $Intersection(def)
780
+ export const $intersect = (...def) => new $Intersection(def)
781
+ export const $$intersect = $constructedBy($Intersection, o => o.shape.length > 0) // Intersection with length=0 is considered "any"
448
782
 
449
783
  /**
450
784
  * @template S
451
- * @extends {$Schema<S>}
785
+ * @extends {Schema<S>}
452
786
  */
453
- export class $Union extends $Schema {
787
+ export class $Union extends Schema {
788
+ static _dilutes = true
789
+
454
790
  /**
455
- * @param {Array<$Schema<S>>} v
791
+ * @param {Array<Schema<S>>} v
456
792
  */
457
793
  constructor (v) {
458
794
  super()
459
- this.v = v
795
+ this.shape = v
460
796
  }
461
797
 
462
798
  /**
463
799
  * @param {any} o
800
+ * @param {ValidationError} [err]
464
801
  * @return {o is S}
465
802
  */
466
- check (o) {
467
- return arr.some(this.v, (vv) => vv.check(o))
803
+ check (o, err) {
804
+ const c = arr.some(this.shape, (vv) => vv.check(o, err))
805
+ err?.extend(null, 'Union', typeof o)
806
+ return c
468
807
  }
469
-
470
- static schema = constructedBy($Union)
471
808
  }
472
809
 
473
810
  /**
474
- * @template {Array<$Schema<any>>} T
475
- * @param {T} def
476
- * @return {CastToSchema<$Union<T extends [] ? never : (T extends Array<$Schema<infer S>> ? S : never)>>}
811
+ * @template {Array<Schema<any>>} T
812
+ * @param {T} schemas
813
+ * @return {CastToSchema<$Union<T extends [] ? never : (T extends Array<Schema<infer S>> ? S : never)>>}
477
814
  */
478
- export const union = (...def) => $Union.schema.check(def[0]) ? new $Union([...def[0].v, ...def.slice(1)]) : new $Union(def)
815
+ export const $union = (...schemas) => $$union.check(schemas[0]) ? new $Union([...schemas[0].shape, ...schemas.slice(1)]) : (schemas.length === 1 ? schemas[0] : new $Union(schemas))
816
+ export const $$union = /** @type {Schema<$Union<any>>} */ ($constructedBy($Union))
479
817
 
818
+ const _t = () => true
480
819
  /**
481
- * @type {$Schema<any>}
820
+ * @type {Schema<any>}
482
821
  */
483
- export const any = intersect()
822
+ export const $any = $custom(_t)
823
+ export const $$any = /** @type {Schema<Schema<any>>} */ ($constructedBy($Custom, o => o.shape === _t))
484
824
 
485
825
  /**
486
- * @type {$Schema<bigint>}
826
+ * @type {Schema<bigint>}
487
827
  */
488
- export const bigint = constructedBy(BigInt)
828
+ export const $bigint = $constructedBy(BigInt)
829
+ export const $$bigint = /** @type {Schema<Schema<BigInt>>} */ ($constructedBy($ConstructedBy, o => o.shape === BigInt))
489
830
 
490
831
  /**
491
- * @type {$Schema<Symbol>}
832
+ * @type {Schema<Symbol>}
492
833
  */
493
- export const symbol = constructedBy(Symbol)
834
+ export const $symbol = $constructedBy(Symbol)
835
+ export const $$symbol = /** @type {Schema<Schema<Symbol>>} */ ($constructedBy($ConstructedBy, o => o.shape === Symbol))
494
836
 
495
837
  /**
496
- * @type {$Schema<number>}
838
+ * @type {Schema<number>}
497
839
  */
498
- export const number = constructedBy(Number)
840
+ export const $number = $constructedBy(Number)
841
+ export const $$number = /** @type {Schema<Schema<number>>} */ ($constructedBy($ConstructedBy, o => o.shape === Number))
499
842
 
500
843
  /**
501
- * @type {$Schema<string>}
844
+ * @type {Schema<string>}
502
845
  */
503
- export const string = constructedBy(String)
846
+ export const $string = $constructedBy(String)
847
+ export const $$string = /** @type {Schema<Schema<string>>} */ ($constructedBy($ConstructedBy, o => o.shape === String))
504
848
 
505
849
  /**
506
- * @type {$Schema<undefined>}
850
+ * @type {Schema<boolean>}
507
851
  */
508
- const undefined_ = literal(undefined)
852
+ export const $boolean = $constructedBy(Boolean)
853
+ export const $$boolean = /** @type {Schema<Schema<Boolean>>} */ ($constructedBy($ConstructedBy, o => o.shape === Boolean))
509
854
 
510
855
  /**
511
- * @type {$Schema<void>}
856
+ * @type {Schema<undefined>}
512
857
  */
513
- const void_ = undefined_
858
+ export const $undefined = $literal(undefined)
859
+ export const $$undefined = /** @type {Schema<Schema<undefined>>} */ ($constructedBy($Literal, o => o.shape.length === 1 && o.shape[0] === undefined))
514
860
 
515
861
  /**
516
- * @type {$Schema<null>}
862
+ * @type {Schema<void>}
517
863
  */
518
- const null_ = literal(null)
864
+ export const $void = $literal(undefined)
865
+ export const $$void = /** @type {Schema<Schema<void>>} */ ($$undefined)
519
866
 
520
- export { null_ as null, void_ as void, undefined_ as undefined }
867
+ export const $null = $literal(null)
868
+ export const $$null = /** @type {Schema<Schema<null>>} */ ($constructedBy($Literal, o => o.shape.length === 1 && o.shape[0] === null))
869
+
870
+ /**
871
+ * @type {Schema<number|string|null|boolean>}
872
+ */
873
+ export const $primitive = $union($number, $string, $null, $boolean)
874
+
875
+ /**
876
+ * @typedef {JSON[]} JSONArray
877
+ */
878
+ /**
879
+ * @typedef {Unwrap<$primitive>|JSONArray|{ [key:string]:JSON }} JSON
880
+ */
881
+ /**
882
+ * @type {Schema<null|number|string|boolean|JSON[]|{[key:string]:JSON}>}
883
+ */
884
+ export const $json = (() => {
885
+ const $jsonArr = /** @type {$Array<$any>} */ ($array($any))
886
+ const $jsonRecord = /** @type {$Record<$string,$any>} */ ($record($string, $any))
887
+ const $json = $union($number, $string, $null, $boolean, $jsonArr, $jsonRecord)
888
+ $jsonArr.shape = $json
889
+ $jsonRecord.shape.values = $json
890
+ return $json
891
+ })()
521
892
 
522
893
  /* c8 ignore start */
523
894
  /**
524
895
  * Assert that a variable is of this specific type.
525
896
  * The assertion check is only performed in non-production environments.
526
897
  *
527
- * @type {<T>(o:any,schema:$Schema<T>) => asserts o is T}
898
+ * @type {<T>(o:any,schema:Schema<T>) => asserts o is T}
528
899
  */
529
900
  export const assert = env.production
530
901
  ? () => {}
531
902
  : (o, schema) => {
532
- if (!schema.check(o)) {
533
- throw error.create(`Expected value to be of type ${schema.constructor.name}.`)
903
+ const err = new ValidationError()
904
+ if (!schema.check(o, err)) {
905
+ throw error.create(`Expected value to be of type ${schema.constructor.name}.\n${err.toString()}`)
534
906
  }
535
907
  }
536
908
  /* c8 ignore end */