@versionzero/schema 1.0.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 (401) hide show
  1. package/LICENSE +177 -0
  2. package/README.md +246 -0
  3. package/package.json +84 -0
  4. package/src/compilation/handler-compilation.js +28 -0
  5. package/src/compilation/metadata-compilation.js +35 -0
  6. package/src/compilation/schema-compilation.js +142 -0
  7. package/src/compilation/selection-compilation.js +84 -0
  8. package/src/compilation/union-compilation.js +510 -0
  9. package/src/compilation/values-compilation.js +35 -0
  10. package/src/compiled-schema.js +1709 -0
  11. package/src/constants.js +1 -0
  12. package/src/core-library/index.js +32 -0
  13. package/src/core-library/processors/aggregation-operators.js +75 -0
  14. package/src/core-library/processors/alpha-constraint.js +20 -0
  15. package/src/core-library/processors/alphanum-constraint.js +20 -0
  16. package/src/core-library/processors/array-operator.js +51 -0
  17. package/src/core-library/processors/assert-constraint.js +75 -0
  18. package/src/core-library/processors/base64-constraint.js +26 -0
  19. package/src/core-library/processors/camel-case-operator.js +24 -0
  20. package/src/core-library/processors/capitalize-operator.js +16 -0
  21. package/src/core-library/processors/cardnum-constraint.js +193 -0
  22. package/src/core-library/processors/ceil-operator.js +44 -0
  23. package/src/core-library/processors/collapse-operator.js +29 -0
  24. package/src/core-library/processors/compact-operator.js +34 -0
  25. package/src/core-library/processors/compile-operator.js +65 -0
  26. package/src/core-library/processors/concat-operator.js +51 -0
  27. package/src/core-library/processors/conditional-operators.js +301 -0
  28. package/src/core-library/processors/constant-case-operator.js +16 -0
  29. package/src/core-library/processors/data-size-operator.js +86 -0
  30. package/src/core-library/processors/date-object-operator.js +54 -0
  31. package/src/core-library/processors/date-operator.js +67 -0
  32. package/src/core-library/processors/date-range-constraint.js +76 -0
  33. package/src/core-library/processors/defined-constraint.js +30 -0
  34. package/src/core-library/processors/each-operator.js +57 -0
  35. package/src/core-library/processors/email-constraint.js +112 -0
  36. package/src/core-library/processors/entries-operator.js +25 -0
  37. package/src/core-library/processors/eq-constraint.js +37 -0
  38. package/src/core-library/processors/filter-operator.js +74 -0
  39. package/src/core-library/processors/find-schema-operator.js +45 -0
  40. package/src/core-library/processors/flatten-operator.js +40 -0
  41. package/src/core-library/processors/floor-operator.js +47 -0
  42. package/src/core-library/processors/get-operator.js +44 -0
  43. package/src/core-library/processors/group-by-operator.js +84 -0
  44. package/src/core-library/processors/has-prefix-constraint.js +37 -0
  45. package/src/core-library/processors/has-suffix-constraint.js +35 -0
  46. package/src/core-library/processors/hex-constraint.js +20 -0
  47. package/src/core-library/processors/hostname-constraint.js +22 -0
  48. package/src/core-library/processors/http-url-constraint.js +27 -0
  49. package/src/core-library/processors/in-constraint.js +66 -0
  50. package/src/core-library/processors/index-by-operator.js +98 -0
  51. package/src/core-library/processors/index.js +131 -0
  52. package/src/core-library/processors/input-operator.js +23 -0
  53. package/src/core-library/processors/instanceof-constraint.js +38 -0
  54. package/src/core-library/processors/integer-constraint.js +22 -0
  55. package/src/core-library/processors/invoke-operator.js +33 -0
  56. package/src/core-library/processors/ipv4-constraint.js +188 -0
  57. package/src/core-library/processors/ipv6-constraint.js +205 -0
  58. package/src/core-library/processors/is-array-constraint.js +21 -0
  59. package/src/core-library/processors/is-date-constraint.js +22 -0
  60. package/src/core-library/processors/is-number-constraint.js +21 -0
  61. package/src/core-library/processors/is-object-constraint.js +21 -0
  62. package/src/core-library/processors/is-string-constraint.js +21 -0
  63. package/src/core-library/processors/join-operator.js +41 -0
  64. package/src/core-library/processors/json-constraint.js +22 -0
  65. package/src/core-library/processors/json-decode-operator.js +25 -0
  66. package/src/core-library/processors/json-encode-operator.js +35 -0
  67. package/src/core-library/processors/kebab-case-operator.js +23 -0
  68. package/src/core-library/processors/keys-operator.js +20 -0
  69. package/src/core-library/processors/length-constraint.js +85 -0
  70. package/src/core-library/processors/lookup-operator.js +84 -0
  71. package/src/core-library/processors/lowercase-operator.js +14 -0
  72. package/src/core-library/processors/map-operator.js +84 -0
  73. package/src/core-library/processors/match-operator.js +64 -0
  74. package/src/core-library/processors/matches-constraint.js +54 -0
  75. package/src/core-library/processors/math-operators.js +151 -0
  76. package/src/core-library/processors/merge-deep-operator.js +61 -0
  77. package/src/core-library/processors/merge-operator.js +54 -0
  78. package/src/core-library/processors/metadata-operator.js +100 -0
  79. package/src/core-library/processors/negative-constraint.js +23 -0
  80. package/src/core-library/processors/never-constraint.js +69 -0
  81. package/src/core-library/processors/non-empty-constraint.js +59 -0
  82. package/src/core-library/processors/not-constraint.js +71 -0
  83. package/src/core-library/processors/number-operator.js +24 -0
  84. package/src/core-library/processors/numeric-constraint.js +22 -0
  85. package/src/core-library/processors/object-operator.js +38 -0
  86. package/src/core-library/processors/omit-operator.js +57 -0
  87. package/src/core-library/processors/parallel-operator.js +64 -0
  88. package/src/core-library/processors/pascal-case-operator.js +16 -0
  89. package/src/core-library/processors/phone-constraint.js +235 -0
  90. package/src/core-library/processors/pick-operator.js +62 -0
  91. package/src/core-library/processors/pipeline-operator.js +63 -0
  92. package/src/core-library/processors/port-constraint.js +22 -0
  93. package/src/core-library/processors/positive-constraint.js +23 -0
  94. package/src/core-library/processors/process-operator.js +55 -0
  95. package/src/core-library/processors/property-operator.js +49 -0
  96. package/src/core-library/processors/range-constraint.js +72 -0
  97. package/src/core-library/processors/reference-operator.js +79 -0
  98. package/src/core-library/processors/require-constraint.js +74 -0
  99. package/src/core-library/processors/reverse-operator.js +20 -0
  100. package/src/core-library/processors/round-operator.js +53 -0
  101. package/src/core-library/processors/schema-handler-operators.js +54 -0
  102. package/src/core-library/processors/semver-constraint.js +282 -0
  103. package/src/core-library/processors/sequence-processors.js +406 -0
  104. package/src/core-library/processors/sort-operator.js +52 -0
  105. package/src/core-library/processors/split-operator.js +43 -0
  106. package/src/core-library/processors/string-extra-operators.js +141 -0
  107. package/src/core-library/processors/string-operator.js +34 -0
  108. package/src/core-library/processors/target-operator.js +30 -0
  109. package/src/core-library/processors/template-operator.js +60 -0
  110. package/src/core-library/processors/title-case-operator.js +17 -0
  111. package/src/core-library/processors/trim-operator.js +14 -0
  112. package/src/core-library/processors/truthy-constraint.js +35 -0
  113. package/src/core-library/processors/type-operator.js +24 -0
  114. package/src/core-library/processors/unique-operator.js +21 -0
  115. package/src/core-library/processors/uppercase-operator.js +14 -0
  116. package/src/core-library/processors/url-constraint.js +31 -0
  117. package/src/core-library/processors/url-decode-operator.js +50 -0
  118. package/src/core-library/processors/url-encode-operator.js +44 -0
  119. package/src/core-library/processors/uuid-constraint.js +31 -0
  120. package/src/core-library/processors/values-operator.js +20 -0
  121. package/src/core-library/schemas/any-schema.js +23 -0
  122. package/src/core-library/schemas/array-schema.js +8 -0
  123. package/src/core-library/schemas/boolean-schema.js +10 -0
  124. package/src/core-library/schemas/date-schema.js +12 -0
  125. package/src/core-library/schemas/function-schema.js +40 -0
  126. package/src/core-library/schemas/number-schema.js +9 -0
  127. package/src/core-library/schemas/object-schema.js +10 -0
  128. package/src/core-library/schemas/root-schema.js +21 -0
  129. package/src/core-library/schemas/string-schema.js +9 -0
  130. package/src/core-library-node/index.js +47 -0
  131. package/src/core-library-node/processors/base64-decode-operator.js +20 -0
  132. package/src/core-library-node/processors/base64-encode-operator.js +20 -0
  133. package/src/core-library-node/processors/buffer-operator.js +39 -0
  134. package/src/core-library-node/processors/directory-constraint.js +35 -0
  135. package/src/core-library-node/processors/executable-constraint.js +34 -0
  136. package/src/core-library-node/processors/file-constraint.js +34 -0
  137. package/src/core-library-node/processors/file-size-constraint.js +94 -0
  138. package/src/core-library-node/processors/is-buffer-constraint.js +21 -0
  139. package/src/core-library-node/processors/reachable-constraint.js +28 -0
  140. package/src/core-library-node/processors/readable-constraint.js +34 -0
  141. package/src/core-library-node/processors/writable-constraint.js +59 -0
  142. package/src/core-library-node/schemas/buffer-schema.js +10 -0
  143. package/src/errors.js +209 -0
  144. package/src/executor/array-executor.js +78 -0
  145. package/src/executor/conditional-executor.js +134 -0
  146. package/src/executor/each-executor.js +68 -0
  147. package/src/executor/executor.js +123 -0
  148. package/src/executor/object-executor.js +98 -0
  149. package/src/executor/parallel-executor.js +43 -0
  150. package/src/executor/pipeline-executor.js +65 -0
  151. package/src/executor/sequence-executor.js +206 -0
  152. package/src/executor/serial-executor.js +24 -0
  153. package/src/executor/step-executor.js +68 -0
  154. package/src/helpers/case.js +124 -0
  155. package/src/helpers/data-size.js +144 -0
  156. package/src/helpers/debug-sink.js +15 -0
  157. package/src/helpers/deep.js +280 -0
  158. package/src/helpers/format.js +121 -0
  159. package/src/helpers/has-string-properties.js +30 -0
  160. package/src/helpers/index.js +16 -0
  161. package/src/helpers/object.js +115 -0
  162. package/src/helpers/parse-date.js +75 -0
  163. package/src/helpers/path.js +28 -0
  164. package/src/helpers/regex.js +18 -0
  165. package/src/helpers/stringify.js +309 -0
  166. package/src/helpers/to-data.js +64 -0
  167. package/src/helpers/truthy.js +55 -0
  168. package/src/index.js +29 -0
  169. package/src/schema-compiler.js +531 -0
  170. package/src/schema-location.js +200 -0
  171. package/src/schema-resolver.js +546 -0
  172. package/src/schema.js +1182 -0
  173. package/src/traversal/executors/check-condition.js +42 -0
  174. package/src/traversal/executors/check-input.js +27 -0
  175. package/src/traversal/executors/check-required.js +19 -0
  176. package/src/traversal/executors/check-schema.js +45 -0
  177. package/src/traversal/executors/defaults.js +21 -0
  178. package/src/traversal/executors/enter-existing.js +25 -0
  179. package/src/traversal/executors/enter-input.js +25 -0
  180. package/src/traversal/executors/enter.js +37 -0
  181. package/src/traversal/executors/exit.js +74 -0
  182. package/src/traversal/executors/finalize.js +64 -0
  183. package/src/traversal/executors/index.js +42 -0
  184. package/src/traversal/executors/normalize.js +38 -0
  185. package/src/traversal/executors/prepare-existing.js +27 -0
  186. package/src/traversal/executors/prepare-pending.js +54 -0
  187. package/src/traversal/executors/resolve-union.js +50 -0
  188. package/src/traversal/executors/serialize.js +48 -0
  189. package/src/traversal/executors/transform-early.js +51 -0
  190. package/src/traversal/executors/transform.js +68 -0
  191. package/src/traversal/executors/traversal-state-executor.js +46 -0
  192. package/src/traversal/executors/validate.js +63 -0
  193. package/src/traversal/traversal-context.js +231 -0
  194. package/src/traversal/traversal-state.js +809 -0
  195. package/src/types.js +102 -0
  196. package/src/value-processor/composed-value-processor.js +43 -0
  197. package/src/value-processor/defined-value-processor.js +72 -0
  198. package/src/value-processor/function-value-processor.js +68 -0
  199. package/src/value-processor/parameterized-value-processor.js +45 -0
  200. package/src/value-processor/parameters-value-processor.js +178 -0
  201. package/src/value-processor/spec.js +89 -0
  202. package/src/value-processor/value-processor.js +105 -0
  203. package/types/compilation/handler-compilation.d.ts +13 -0
  204. package/types/compilation/metadata-compilation.d.ts +6 -0
  205. package/types/compilation/schema-compilation.d.ts +32 -0
  206. package/types/compilation/selection-compilation.d.ts +9 -0
  207. package/types/compilation/union-compilation.d.ts +42 -0
  208. package/types/compilation/values-compilation.d.ts +12 -0
  209. package/types/compiled-schema.d.ts +883 -0
  210. package/types/constants.d.ts +1 -0
  211. package/types/core-library/index.d.ts +7 -0
  212. package/types/core-library/processors/aggregation-operators.d.ts +24 -0
  213. package/types/core-library/processors/alpha-constraint.d.ts +9 -0
  214. package/types/core-library/processors/alphanum-constraint.d.ts +9 -0
  215. package/types/core-library/processors/array-operator.d.ts +12 -0
  216. package/types/core-library/processors/assert-constraint.d.ts +30 -0
  217. package/types/core-library/processors/base64-constraint.d.ts +11 -0
  218. package/types/core-library/processors/camel-case-operator.d.ts +17 -0
  219. package/types/core-library/processors/capitalize-operator.d.ts +11 -0
  220. package/types/core-library/processors/cardnum-constraint.d.ts +51 -0
  221. package/types/core-library/processors/ceil-operator.d.ts +30 -0
  222. package/types/core-library/processors/collapse-operator.d.ts +24 -0
  223. package/types/core-library/processors/compact-operator.d.ts +29 -0
  224. package/types/core-library/processors/compile-operator.d.ts +34 -0
  225. package/types/core-library/processors/concat-operator.d.ts +23 -0
  226. package/types/core-library/processors/conditional-operators.d.ts +219 -0
  227. package/types/core-library/processors/constant-case-operator.d.ts +9 -0
  228. package/types/core-library/processors/data-size-operator.d.ts +31 -0
  229. package/types/core-library/processors/date-object-operator.d.ts +16 -0
  230. package/types/core-library/processors/date-operator.d.ts +21 -0
  231. package/types/core-library/processors/date-range-constraint.d.ts +26 -0
  232. package/types/core-library/processors/defined-constraint.d.ts +20 -0
  233. package/types/core-library/processors/each-operator.d.ts +34 -0
  234. package/types/core-library/processors/email-constraint.d.ts +54 -0
  235. package/types/core-library/processors/entries-operator.d.ts +13 -0
  236. package/types/core-library/processors/eq-constraint.d.ts +20 -0
  237. package/types/core-library/processors/filter-operator.d.ts +35 -0
  238. package/types/core-library/processors/find-schema-operator.d.ts +28 -0
  239. package/types/core-library/processors/flatten-operator.d.ts +26 -0
  240. package/types/core-library/processors/floor-operator.d.ts +33 -0
  241. package/types/core-library/processors/get-operator.d.ts +31 -0
  242. package/types/core-library/processors/group-by-operator.d.ts +36 -0
  243. package/types/core-library/processors/has-prefix-constraint.d.ts +22 -0
  244. package/types/core-library/processors/has-suffix-constraint.d.ts +20 -0
  245. package/types/core-library/processors/hex-constraint.d.ts +9 -0
  246. package/types/core-library/processors/hostname-constraint.d.ts +11 -0
  247. package/types/core-library/processors/http-url-constraint.d.ts +9 -0
  248. package/types/core-library/processors/in-constraint.d.ts +27 -0
  249. package/types/core-library/processors/index-by-operator.d.ts +26 -0
  250. package/types/core-library/processors/index.d.ts +8 -0
  251. package/types/core-library/processors/input-operator.d.ts +20 -0
  252. package/types/core-library/processors/instanceof-constraint.d.ts +23 -0
  253. package/types/core-library/processors/integer-constraint.d.ts +9 -0
  254. package/types/core-library/processors/invoke-operator.d.ts +12 -0
  255. package/types/core-library/processors/ipv4-constraint.d.ts +37 -0
  256. package/types/core-library/processors/ipv6-constraint.d.ts +34 -0
  257. package/types/core-library/processors/is-array-constraint.d.ts +10 -0
  258. package/types/core-library/processors/is-date-constraint.d.ts +10 -0
  259. package/types/core-library/processors/is-number-constraint.d.ts +10 -0
  260. package/types/core-library/processors/is-object-constraint.d.ts +10 -0
  261. package/types/core-library/processors/is-string-constraint.d.ts +10 -0
  262. package/types/core-library/processors/join-operator.d.ts +29 -0
  263. package/types/core-library/processors/json-constraint.d.ts +10 -0
  264. package/types/core-library/processors/json-decode-operator.d.ts +9 -0
  265. package/types/core-library/processors/json-encode-operator.d.ts +27 -0
  266. package/types/core-library/processors/kebab-case-operator.d.ts +16 -0
  267. package/types/core-library/processors/keys-operator.d.ts +9 -0
  268. package/types/core-library/processors/length-constraint.d.ts +34 -0
  269. package/types/core-library/processors/lookup-operator.d.ts +36 -0
  270. package/types/core-library/processors/lowercase-operator.d.ts +9 -0
  271. package/types/core-library/processors/map-operator.d.ts +38 -0
  272. package/types/core-library/processors/match-operator.d.ts +34 -0
  273. package/types/core-library/processors/matches-constraint.d.ts +29 -0
  274. package/types/core-library/processors/math-operators.d.ts +91 -0
  275. package/types/core-library/processors/merge-deep-operator.d.ts +32 -0
  276. package/types/core-library/processors/merge-operator.d.ts +26 -0
  277. package/types/core-library/processors/metadata-operator.d.ts +56 -0
  278. package/types/core-library/processors/negative-constraint.d.ts +13 -0
  279. package/types/core-library/processors/never-constraint.d.ts +26 -0
  280. package/types/core-library/processors/non-empty-constraint.d.ts +28 -0
  281. package/types/core-library/processors/not-constraint.d.ts +28 -0
  282. package/types/core-library/processors/number-operator.d.ts +9 -0
  283. package/types/core-library/processors/numeric-constraint.d.ts +10 -0
  284. package/types/core-library/processors/object-operator.d.ts +10 -0
  285. package/types/core-library/processors/omit-operator.d.ts +24 -0
  286. package/types/core-library/processors/parallel-operator.d.ts +41 -0
  287. package/types/core-library/processors/pascal-case-operator.d.ts +9 -0
  288. package/types/core-library/processors/phone-constraint.d.ts +65 -0
  289. package/types/core-library/processors/pick-operator.d.ts +27 -0
  290. package/types/core-library/processors/pipeline-operator.d.ts +40 -0
  291. package/types/core-library/processors/port-constraint.d.ts +11 -0
  292. package/types/core-library/processors/positive-constraint.d.ts +13 -0
  293. package/types/core-library/processors/process-operator.d.ts +37 -0
  294. package/types/core-library/processors/property-operator.d.ts +34 -0
  295. package/types/core-library/processors/range-constraint.d.ts +30 -0
  296. package/types/core-library/processors/reference-operator.d.ts +38 -0
  297. package/types/core-library/processors/require-constraint.d.ts +29 -0
  298. package/types/core-library/processors/reverse-operator.d.ts +9 -0
  299. package/types/core-library/processors/round-operator.d.ts +34 -0
  300. package/types/core-library/processors/schema-handler-operators.d.ts +28 -0
  301. package/types/core-library/processors/semver-constraint.d.ts +43 -0
  302. package/types/core-library/processors/sequence-processors.d.ts +213 -0
  303. package/types/core-library/processors/sort-operator.d.ts +31 -0
  304. package/types/core-library/processors/split-operator.d.ts +33 -0
  305. package/types/core-library/processors/string-extra-operators.d.ts +83 -0
  306. package/types/core-library/processors/string-operator.d.ts +10 -0
  307. package/types/core-library/processors/target-operator.d.ts +27 -0
  308. package/types/core-library/processors/template-operator.d.ts +31 -0
  309. package/types/core-library/processors/title-case-operator.d.ts +12 -0
  310. package/types/core-library/processors/trim-operator.d.ts +9 -0
  311. package/types/core-library/processors/truthy-constraint.d.ts +23 -0
  312. package/types/core-library/processors/type-operator.d.ts +11 -0
  313. package/types/core-library/processors/unique-operator.d.ts +10 -0
  314. package/types/core-library/processors/uppercase-operator.d.ts +9 -0
  315. package/types/core-library/processors/url-constraint.d.ts +20 -0
  316. package/types/core-library/processors/url-decode-operator.d.ts +31 -0
  317. package/types/core-library/processors/url-encode-operator.d.ts +36 -0
  318. package/types/core-library/processors/uuid-constraint.d.ts +20 -0
  319. package/types/core-library/processors/values-operator.d.ts +9 -0
  320. package/types/core-library/schemas/any-schema.d.ts +2 -0
  321. package/types/core-library/schemas/array-schema.d.ts +2 -0
  322. package/types/core-library/schemas/boolean-schema.d.ts +2 -0
  323. package/types/core-library/schemas/date-schema.d.ts +2 -0
  324. package/types/core-library/schemas/function-schema.d.ts +2 -0
  325. package/types/core-library/schemas/number-schema.d.ts +2 -0
  326. package/types/core-library/schemas/object-schema.d.ts +2 -0
  327. package/types/core-library/schemas/root-schema.d.ts +2 -0
  328. package/types/core-library/schemas/string-schema.d.ts +2 -0
  329. package/types/core-library-node/index.d.ts +12 -0
  330. package/types/core-library-node/processors/base64-decode-operator.d.ts +9 -0
  331. package/types/core-library-node/processors/base64-encode-operator.d.ts +9 -0
  332. package/types/core-library-node/processors/buffer-operator.d.ts +15 -0
  333. package/types/core-library-node/processors/directory-constraint.d.ts +14 -0
  334. package/types/core-library-node/processors/executable-constraint.d.ts +17 -0
  335. package/types/core-library-node/processors/file-constraint.d.ts +13 -0
  336. package/types/core-library-node/processors/file-size-constraint.d.ts +43 -0
  337. package/types/core-library-node/processors/is-buffer-constraint.d.ts +10 -0
  338. package/types/core-library-node/processors/reachable-constraint.d.ts +13 -0
  339. package/types/core-library-node/processors/readable-constraint.d.ts +17 -0
  340. package/types/core-library-node/processors/writable-constraint.d.ts +18 -0
  341. package/types/core-library-node/schemas/buffer-schema.d.ts +2 -0
  342. package/types/errors.d.ts +58 -0
  343. package/types/executor/array-executor.d.ts +17 -0
  344. package/types/executor/conditional-executor.d.ts +45 -0
  345. package/types/executor/each-executor.d.ts +15 -0
  346. package/types/executor/executor.d.ts +84 -0
  347. package/types/executor/object-executor.d.ts +14 -0
  348. package/types/executor/parallel-executor.d.ts +27 -0
  349. package/types/executor/pipeline-executor.d.ts +11 -0
  350. package/types/executor/sequence-executor.d.ts +32 -0
  351. package/types/executor/serial-executor.d.ts +16 -0
  352. package/types/executor/step-executor.d.ts +14 -0
  353. package/types/helpers/case.d.ts +30 -0
  354. package/types/helpers/data-size.d.ts +25 -0
  355. package/types/helpers/debug-sink.d.ts +9 -0
  356. package/types/helpers/deep.d.ts +33 -0
  357. package/types/helpers/format.d.ts +14 -0
  358. package/types/helpers/has-string-properties.d.ts +5 -0
  359. package/types/helpers/index.d.ts +13 -0
  360. package/types/helpers/object.d.ts +46 -0
  361. package/types/helpers/parse-date.d.ts +6 -0
  362. package/types/helpers/path.d.ts +13 -0
  363. package/types/helpers/regex.d.ts +7 -0
  364. package/types/helpers/stringify.d.ts +33 -0
  365. package/types/helpers/to-data.d.ts +13 -0
  366. package/types/helpers/truthy.d.ts +26 -0
  367. package/types/index.d.ts +6 -0
  368. package/types/schema-compiler.d.ts +49 -0
  369. package/types/schema-location.d.ts +64 -0
  370. package/types/schema-resolver.d.ts +145 -0
  371. package/types/schema.d.ts +586 -0
  372. package/types/traversal/executors/check-condition.d.ts +8 -0
  373. package/types/traversal/executors/check-input.d.ts +6 -0
  374. package/types/traversal/executors/check-required.d.ts +6 -0
  375. package/types/traversal/executors/check-schema.d.ts +7 -0
  376. package/types/traversal/executors/defaults.d.ts +8 -0
  377. package/types/traversal/executors/enter-existing.d.ts +6 -0
  378. package/types/traversal/executors/enter-input.d.ts +8 -0
  379. package/types/traversal/executors/enter.d.ts +7 -0
  380. package/types/traversal/executors/exit.d.ts +6 -0
  381. package/types/traversal/executors/finalize.d.ts +6 -0
  382. package/types/traversal/executors/index.d.ts +15 -0
  383. package/types/traversal/executors/normalize.d.ts +7 -0
  384. package/types/traversal/executors/prepare-existing.d.ts +6 -0
  385. package/types/traversal/executors/prepare-pending.d.ts +6 -0
  386. package/types/traversal/executors/resolve-union.d.ts +6 -0
  387. package/types/traversal/executors/serialize.d.ts +11 -0
  388. package/types/traversal/executors/transform-early.d.ts +6 -0
  389. package/types/traversal/executors/transform.d.ts +6 -0
  390. package/types/traversal/executors/traversal-state-executor.d.ts +19 -0
  391. package/types/traversal/executors/validate.d.ts +6 -0
  392. package/types/traversal/traversal-context.d.ts +67 -0
  393. package/types/traversal/traversal-state.d.ts +97 -0
  394. package/types/types.d.ts +218 -0
  395. package/types/value-processor/composed-value-processor.d.ts +17 -0
  396. package/types/value-processor/defined-value-processor.d.ts +16 -0
  397. package/types/value-processor/function-value-processor.d.ts +15 -0
  398. package/types/value-processor/parameterized-value-processor.d.ts +14 -0
  399. package/types/value-processor/parameters-value-processor.d.ts +28 -0
  400. package/types/value-processor/spec.d.ts +22 -0
  401. package/types/value-processor/value-processor.d.ts +92 -0
@@ -0,0 +1,76 @@
1
+
2
+ import { ConstraintError } from '../../errors.js';
3
+ import { parseDate } from '../../helpers/parse-date.js';
4
+
5
+ /**
6
+ * ## $date-range
7
+ *
8
+ * Validates that a date value falls within the specified range (inclusive).
9
+ * Can specify minimum, maximum, or both bounds. Bounds are parsed using
10
+ * the same rules as the `date` schema normalizer, so strings, numbers,
11
+ * and Date objects are all accepted.
12
+ *
13
+ * ### Parameters
14
+ * - `min` (optional): Minimum date (inclusive). If omitted, no lower bound.
15
+ * - `max` (optional): Maximum date (inclusive). If omitted, no upper bound.
16
+ *
17
+ * ### Example
18
+ * ```js
19
+ * // Object form with named parameters
20
+ * new Schema('date').validator({'$date-range': {min: '2024-01-01', max: '2024-12-31'}})
21
+ *
22
+ * // Cross-reference: end date must be >= start date
23
+ * new Schema('object')
24
+ * .property('start', new Schema('date'))
25
+ * .property('end', new Schema('date').validator({'$date-range': {min: {$reference: '^start'}}}))
26
+ * ```
27
+ *
28
+ * @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}
29
+ */
30
+ export const DATE_RANGE_CONSTRAINT = {
31
+ keyword: 'date-range',
32
+ parameters: [
33
+ { parameter: 'min', default: undefined },
34
+ { parameter: 'max', default: undefined },
35
+ ],
36
+
37
+ process: (value, _target, _location, options) => {
38
+ const { min, max } = options.args;
39
+
40
+ const dateMs = (value instanceof Date ? value : parseDate(value)).getTime();
41
+
42
+ if (min !== undefined) {
43
+ const minMs = (min instanceof Date ? min : parseDate(min)).getTime();
44
+ if (dateMs < minMs) {
45
+ throw new ConstraintError(`Date must not be before ${new Date(minMs).toISOString()}`);
46
+ }
47
+ }
48
+ if (max !== undefined) {
49
+ const maxMs = (max instanceof Date ? max : parseDate(max)).getTime();
50
+ if (dateMs > maxMs) {
51
+ throw new ConstraintError(`Date must not be after ${new Date(maxMs).toISOString()}`);
52
+ }
53
+ }
54
+ return value;
55
+ },
56
+
57
+ describe: (args) => {
58
+ if (!args) {
59
+ return undefined;
60
+ }
61
+
62
+ const minProcessor = (Array.isArray(args) ? args[0] : args.min);
63
+ const maxProcessor = (Array.isArray(args) ? args[1] : args.max);
64
+
65
+ const min = minProcessor?.description;
66
+ const max = maxProcessor?.description;
67
+
68
+ return min !== undefined && max !== undefined
69
+ ? `${min}..${max}`
70
+ : min !== undefined
71
+ ? `>=${min}`
72
+ : max !== undefined
73
+ ? `<=${max}`
74
+ : undefined;
75
+ }
76
+ };
@@ -0,0 +1,30 @@
1
+ import { ConstraintError } from '../../errors.js';
2
+
3
+ /**
4
+ * ## $defined
5
+ *
6
+ * Allow any value, as long as it's defined.
7
+ *
8
+ * ### Example
9
+ * ```js
10
+ * // Ensure an optional field, when supplied, is not undefined
11
+ * new Schema('any').validator('$defined')
12
+ *
13
+ * // Gate a sub-pipeline: only run if the value is defined
14
+ * new Schema('any').normalizer({$gate: ['$defined', '$trim']})
15
+ *
16
+ * // Require a computed result to be defined
17
+ * new Schema('string').validator({$require: {$get: {path: 'nested.key'}}})
18
+ * ```
19
+ *
20
+ * @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}
21
+ */
22
+ export const DEFINED_CONSTRAINT = {
23
+ keyword: 'defined',
24
+ process: (value) => {
25
+ if (value === undefined) {
26
+ throw new ConstraintError('Must be defined');
27
+ }
28
+ return value;
29
+ }
30
+ };
@@ -0,0 +1,57 @@
1
+ import { EachExecutor } from "../../executor/each-executor.js";
2
+ import { ComposedValueProcessor } from '../../value-processor/composed-value-processor.js';
3
+ import { Executor } from '../../executor/executor.js';
4
+ import { PipelineExecutor } from '../../executor/pipeline-executor.js';
5
+ import { ConstraintError } from '../../errors.js';
6
+
7
+ /**
8
+ * ## $each
9
+ *
10
+ * Applies a processor to each element of an array. The processor can be any valid
11
+ * processor specification (RegExp, function, keyword, or parameterized processor).
12
+ * If any element fails validation, the entire array is rejected.
13
+ *
14
+ * This operator is useful for applying consistent validation or transformation rules
15
+ * across all array elements without requiring explicit array element schemas.
16
+ *
17
+ * ### Parameters
18
+ * - `processor` (any valid processor spec, required): The processor to apply to each element.
19
+ * Can be a RegExp, function, string keyword (e.g., `'$numeric'`), or parameterized processor object.
20
+ *
21
+ * ### Example
22
+ * ```js
23
+ * // Trim whitespace from every string in an array
24
+ * new Schema('array').transformer({$each: '$trim'})
25
+ *
26
+ * // Validate that every element is numeric
27
+ * new Schema('array').validator({$each: '$numeric'})
28
+ *
29
+ * // Validate that each element is within a range
30
+ * new Schema('array').validator({$each: {$range: {min: 0, max: 100}}})
31
+ *
32
+ * // Normalize every tag: trim and lowercase
33
+ * new Schema('object', {
34
+ * tags: new Schema('array').transformer({$each: ['$trim', '$lowercase']}),
35
+ * })
36
+ * ```
37
+ *
38
+ * @type {import('../../value-processor/value-processor.js').ValueProcessorDefinition}
39
+ */
40
+ export const EACH_OPERATOR = {
41
+ keyword: 'each',
42
+ parameters: [{parameter: 'processor', required: true}],
43
+ build: (args) => {
44
+ const processor = (Array.isArray(args)? args[0] : args.processor) ?? new Executor();
45
+ // TODO - wrap the processor in a function that passes the original collection in the options
46
+
47
+ const values = (Array.isArray(args)? args[1] : args.values) ?? new Executor();
48
+
49
+ const spec = {$each: processor.spec};
50
+ const description = processor.description ? `[${processor.description}]...` : 'values...';
51
+
52
+ return new ComposedValueProcessor(new PipelineExecutor([values, new EachExecutor(processor)]), spec, description);
53
+ }
54
+ };
55
+
56
+
57
+
@@ -0,0 +1,112 @@
1
+ import { ConstraintError } from '../../errors.js';
2
+ import { isFalsey } from '../../helpers/truthy.js';
3
+
4
+ // Username: letters, digits, and limited special chars (._%+-)
5
+ // No leading/trailing dot, no consecutive dots
6
+ // Domain: 2+ dot-separated labels of letters/digits/hyphens, ending with 2+ letter TLD
7
+ // No consecutive dots, no leading/trailing hyphens in labels
8
+ const EMAIL_REGEX =
9
+ /^[a-zA-Z0-9_%+-](?:[a-zA-Z0-9_%+.-]*[a-zA-Z0-9_%+-])?@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/;
10
+
11
+ // Additional check: no consecutive dots in local part
12
+ const CONSECUTIVE_DOTS = /\.\./;
13
+
14
+ /**
15
+ * ## $email
16
+ *
17
+ * Validates that a string matches a practical email address format (local-part@domain.tld).
18
+ *
19
+ * **Username (local part):**
20
+ * - Allowed characters: letters, digits, `.`, `_`, `%`, `+`, `-`
21
+ * - Must not start or end with a dot
22
+ * - Must not contain consecutive dots
23
+ *
24
+ * **Domain:**
25
+ * - Must consist of at least two dot-separated labels (e.g. `example.com`)
26
+ * - Labels may contain letters, digits, and hyphens (no leading/trailing hyphens)
27
+ * - Must not contain consecutive dots
28
+ * - Must end in a TLD of 2+ letters
29
+ *
30
+ * **Not supported (by design):** quoted local parts, comments, IP address literals, emoji,
31
+ * non-ASCII characters. This processor is intended to handle addresses as they are typically
32
+ * used. If you need to support all the madness that the official RFC allows, you'll need to
33
+ * write your own version.
34
+ *
35
+ * The default behavior is to convert the address to lower case for consistency, but this
36
+ * can be overridden.
37
+ *
38
+ * ### Parameters
39
+ * - `case` (string, default `'lower'`): Case conversion applied to the domain portion,
40
+ * and (unless overridden by `case-sensitive`) to the username portion as well.
41
+ * Accepts `'lower'` or `'upper'`, or if falsey, doesn't do any conversion.
42
+ * - `case-sensitive` (boolean, default `false`): When `true`, preserve the original case of
43
+ * the username portion. When `false`, the username is converted using the `case` parameter.
44
+ * (Rationale: RFC 5321 technically allows case-sensitive local parts, but virtually all
45
+ * providers treat them as case-insensitive.)
46
+ * - `filter` (boolean, default `false`): When `true`, strip plus-addressing
47
+ * (e.g. `user+tag@` becomes `user@`), and for `gmail.com` domains, additionally remove
48
+ * all dots from the username (since Gmail ignores them).
49
+ *
50
+ * ### Example
51
+ * ```js
52
+ * // Basic validation only
53
+ * new Schema('string').validator('$email')
54
+ *
55
+ * // Normalize to lowercase, strip plus-addressing
56
+ * new Schema('string').validator({'$email': {filter: true}})
57
+ *
58
+ * // Preserve username case
59
+ * new Schema('string').validator({'$email': {'case-sensitive': true}})
60
+ *
61
+ * // Work for the government and like to shout at people?
62
+ * new Schema('string').validator({'$email': {'case': 'upper'}}
63
+ * ```
64
+ *
65
+ * @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}
66
+ */
67
+ export const EMAIL_CONSTRAINT = {
68
+ keyword: 'email',
69
+ parameters: [
70
+ { parameter: 'case', default: 'lower' },
71
+ { parameter: 'case-sensitive', type: 'boolean', default: false },
72
+ { parameter: 'filter', type: 'boolean', default: false },
73
+ ],
74
+
75
+ process: (value, _target, _location, options) => {
76
+ const { 'case': caseParam, 'case-sensitive': caseSensitive, filter } = options.args;
77
+
78
+ if (!EMAIL_REGEX.test(value)) {
79
+ throw new ConstraintError('Invalid email format');
80
+ }
81
+
82
+ const atIndex = value.lastIndexOf('@');
83
+ let username = value.slice(0, atIndex);
84
+ let domain = value.slice(atIndex + 1);
85
+
86
+ // Reject consecutive dots in local part (regex alone can't catch all combos cleanly)
87
+ if (CONSECUTIVE_DOTS.test(username)) {
88
+ throw new ConstraintError('Invalid email format');
89
+ }
90
+
91
+ // Apply filter: strip plus-addressing and gmail dot normalization
92
+ if (filter) {
93
+ const plusIndex = username.indexOf('+');
94
+ if (plusIndex !== -1) {
95
+ username = username.slice(0, plusIndex);
96
+ }
97
+ if (domain.toLowerCase() === 'gmail.com') {
98
+ username = username.replace(/\./g, '');
99
+ }
100
+ }
101
+
102
+ // Apply case conversion
103
+
104
+ const applyCase = isFalsey(caseParam)? (s) => s : (caseParam === 'upper' ? (s) => s.toUpperCase() : (s) => s.toLowerCase());
105
+ domain = applyCase(domain);
106
+ if (!caseSensitive) {
107
+ username = applyCase(username);
108
+ }
109
+
110
+ return `${username}@${domain}`;
111
+ }
112
+ };
@@ -0,0 +1,25 @@
1
+ import { isPlainObject } from '../../helpers/object.js';
2
+ import { ConstraintError } from '../../errors.js';
3
+ import { formatValue } from '../../helpers/format.js';
4
+
5
+ /**
6
+ * ## $entries
7
+ *
8
+ * Returns the enumerable own properties of an object as an array of `[key, value]` pairs,
9
+ * matching the output of `Object.entries()`.
10
+ *
11
+ * The resulting array can be reconstructed back into an object with `$object`.
12
+ *
13
+ * Throws if the input is not a plain object.
14
+ *
15
+ * @type {import('../../value-processor/value-processor.js').ValueProcessorDefinition}
16
+ */
17
+ export const ENTRIES_OPERATOR = {
18
+ keyword: 'entries',
19
+ process: (value, _target, location) => {
20
+ if (!isPlainObject(value)) {
21
+ throw new ConstraintError(`$entries requires a plain object, got ${formatValue(value)}`, {location});
22
+ }
23
+ return Object.entries(value);
24
+ }
25
+ };
@@ -0,0 +1,37 @@
1
+ import { deepEquals } from "../../helpers/deep.js";
2
+ import { ConstraintError } from '../../errors.js';
3
+ import { formatValue } from '../../helpers/format.js';
4
+
5
+ /**
6
+ * ## $eq
7
+ *
8
+ * Do a deep equality check between the value and the provided constraint value.
9
+ *
10
+ * ### Parameters
11
+ * - `value` (any, required): The value to compare against using deep equality.
12
+ *
13
+ * ### Example
14
+ * ```js
15
+ * // Ensure a status field can only be 'active'
16
+ * new Schema('string').validator({$eq: 'active'})
17
+ *
18
+ * // Ensure an object matches an exact structure
19
+ * new Schema('object').validator({$eq: {type: 'config', version: 1}})
20
+ * ```
21
+ *
22
+ * @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}*
23
+ */
24
+ export const EQ_CONSTRAINT = {
25
+ keyword: 'eq',
26
+ parameters: [ { parameter: 'value', required: true }, { parameter: 'compare' } ],
27
+
28
+ process: (value, _target, location, options) => {
29
+ const eqValue = options.args['value'];
30
+ const compare = options.args['compare'] ?? value;
31
+
32
+ if (!deepEquals(eqValue, compare)) {
33
+ throw new ConstraintError(`Value ${formatValue(value)} was not equal to constraint`, {value, location});
34
+ }
35
+ return value;
36
+ }
37
+ }
@@ -0,0 +1,74 @@
1
+ import { ComposedValueProcessor } from '../../value-processor/composed-value-processor.js';
2
+ import { ConditionalExecutor } from '../../executor/conditional-executor.js';
3
+ import { FunctionValueProcessor } from '../../value-processor/function-value-processor.js';
4
+ import { EachExecutor } from '../../executor/each-executor.js';
5
+
6
+ import { SchemaError } from '../../errors.js';
7
+
8
+ /**
9
+ * ## $filter
10
+ *
11
+ * Runs a processor on each element of the input array, keeping elements for which the processor
12
+ * succeeds and returning the processor's output value (consistent with standard processor semantics).
13
+ * Elements are filtered out if the processor throws or returns undefined.
14
+ * (Note that processor results are not checked for truthiness — only for definedness.)
15
+ *
16
+ * Non-arrays are "filtered" as an empty array.
17
+ *
18
+ * ### Parameters
19
+ * - `processor` (any valid processor spec, optional): The processor to apply to each element.
20
+ * Elements where the processor returns undefined or throws are excluded from the result.
21
+ * If omitted, null/undefined elements are removed.
22
+ *
23
+ * ### Example
24
+ * ```js
25
+ * // Remove null and undefined values from an array
26
+ * new Schema('array').transformer('$filter')
27
+ *
28
+ * // Keep only numeric strings
29
+ * new Schema('array').transformer({$filter: '$numeric'})
30
+ *
31
+ * // Keep only values within range
32
+ * new Schema('array').transformer({$filter: {$range: {min: 0, max: 100}}})
33
+ *
34
+ * // Filter out non-email strings from a list
35
+ * new Schema('object', {
36
+ * recipients: new Schema('array').transformer({$filter: '$email'}),
37
+ * })
38
+ * ```
39
+ *
40
+ * @type {import('../../value-processor/value-processor.js').ValueProcessorDefinition}
41
+ */
42
+ export const FILTER_OPERATOR = {
43
+ keyword: 'filter',
44
+ parameters: [{parameter: 'processor', required: false}],
45
+ build: (args) => {
46
+ let processor;
47
+ if (Array.isArray(args)) {
48
+ if (args.length > 1) {
49
+ throw new SchemaError('Expected exactly one argument for $filter operator');
50
+ }
51
+ processor = args[0];
52
+ }
53
+ else if (typeof args === 'object') {
54
+ if (Object.keys(args).length !== 1) {
55
+ throw new SchemaError('Expected only "processor" argument for $filter operator');
56
+ }
57
+ processor = args.processor;
58
+ }
59
+ processor ??= new FunctionValueProcessor(v => (v === undefined || v === null)? undefined : v);
60
+
61
+ return new ComposedValueProcessor(
62
+ new EachExecutor(
63
+ new ConditionalExecutor(processor, {}, [ConditionalExecutor.CHECK_DEFINED, ConditionalExecutor.PASS_RESULT]),
64
+ (inputs) => {
65
+ if (!Array.isArray(inputs)) {
66
+ return [];
67
+ }
68
+ return inputs;
69
+ },
70
+ (results) => (Array.isArray(results)? results.filter(r => r !== undefined) : [])
71
+ ),
72
+ {$filter: processor.spec});
73
+ }
74
+ };
@@ -0,0 +1,45 @@
1
+ import { SchemaError } from '../../errors.js';
2
+ import { formatValue } from '../../helpers/format.js';
3
+
4
+ /**
5
+ * ## $find-schema
6
+ *
7
+ * Find a schema in the schema hierarchy based on a dotted path. Returns the current schema by default.
8
+ * The provided path is interpreted relative to the currently active schema but supports navigation
9
+ * to the root schema using '/' and parent schema using '^'.
10
+ *
11
+ * ### Parameters
12
+ * - `path` (string | number, required): Dot-separated property path or array index.
13
+ *
14
+ * Example paths:
15
+ * - '': The current schema.
16
+ * - '/': The root schema.
17
+ * - 'xyzzy': Find the 'xyzzy' child of the current schema.
18
+ * - 'xyzzy.plugh': Find the 'plugh' child of the 'xyzzy' child of the current schema.
19
+ * - 'child.^': The current schema if and only if the child exists.
20
+ * - `/.foo.bar`: Find the 'bar' property in the 'foo' child of the root.
21
+ * - `^`: Return the parent schema
22
+ * - `^^jim`: Get the grandparent schema's child named 'jim' (uncle jim)
23
+ * - `^.^.jim`: Same thing (extra dots are ignored.)
24
+ *
25
+ * ```js
26
+ * new Schema('any').transformer({'$metadata': {name: 'description', schema: {'$find-schema': '^'}}})
27
+ * ```
28
+ *
29
+ * @type {import('../../value-processor/value-processor.js').ValueProcessorDefinition}
30
+ */
31
+ export const FIND_SCHEMA_OPERATOR = {
32
+ keyword: 'find-schema',
33
+ parameters: [{parameter: 'path', required: false}],
34
+
35
+ process: (value, _target, location, options) => {
36
+ /** @type {string} */
37
+ const path = options.args?.path ?? value ?? '.';
38
+
39
+ if (typeof path !== 'string') {
40
+ throw new SchemaError(`$find-schema "path" must be a string, got ${formatValue(path)}`, {location});
41
+ }
42
+
43
+ return location.relative(path)?.schema;
44
+ }
45
+ };
@@ -0,0 +1,40 @@
1
+ import { ConstraintError } from '../../errors.js';
2
+ import { formatValue } from '../../helpers/format.js';
3
+
4
+ /**
5
+ * ## $flatten
6
+ *
7
+ * Returns a new array with sub-array elements flattened to the specified depth.
8
+ * Throws if the input is not an array.
9
+ *
10
+ * ### Parameters
11
+ * - `depth` (number, optional, default `1`): The depth to flatten. Use `Infinity` to flatten completely.
12
+ *
13
+ * ### Example
14
+ * ```js
15
+ * // Flatten one level of nesting
16
+ * new Schema('array').transformer('$flatten')
17
+ * // [[1, 2], [3, 4]] → [1, 2, 3, 4]
18
+ *
19
+ * // Flatten all levels
20
+ * new Schema('array').transformer({$flatten: {depth: Infinity}})
21
+ * // [1, [2, [3, [4]]]] → [1, 2, 3, 4]
22
+ *
23
+ * // Flatten exactly 2 levels
24
+ * new Schema('array').transformer({$flatten: {depth: 2}})
25
+ * ```
26
+ *
27
+ * @type {import('../../value-processor/value-processor.js').ValueProcessorDefinition}
28
+ */
29
+ export const FLATTEN_OPERATOR = {
30
+ keyword: 'flatten',
31
+ parameters: [ { parameter: 'depth', default: 1 } ],
32
+
33
+ process: (value, _target, location, options) => {
34
+ if (!Array.isArray(value)) {
35
+ throw new ConstraintError(`$flatten requires an array, got ${formatValue(value)}`, {location});
36
+ }
37
+ const depth = options.args?.['depth'] ?? 1;
38
+ return value.flat(depth);
39
+ }
40
+ };
@@ -0,0 +1,47 @@
1
+ /**
2
+ * ## $floor
3
+ *
4
+ * Rounds a numeric value down to the specified number of decimal places.
5
+ * Non-numeric values are passed through unchanged. Safe to use in normalize phase (non-throwing).
6
+ *
7
+ * ### Parameters
8
+ * - `precision` (number, optional): Number of decimal places to preserve. Defaults to 0 (round to integer).
9
+ *
10
+ * **Input/Output Examples**:
11
+ * - `$floor`: `3.7` → `3`, `9.99` → `9`, `-2.3` → `-3`
12
+ * - `{$floor: 2}`: `3.14159` → `3.14`, `99.999` → `99.99`, `5.1` → `5.1`
13
+ * - `{$floor: 1}`: `3.76` → `3.7`, `9.01` → `9.0`
14
+ *
15
+ * ### Example
16
+ * ```js
17
+ * // Truncate to integer (floor toward zero for positive numbers)
18
+ * new Schema('number').transformer('$floor')
19
+ * // 9.99 → 9
20
+ *
21
+ * // Preserve 2 decimal places, discarding extra precision
22
+ * new Schema('number').transformer({$floor: {precision: 2}})
23
+ * // 3.14159 → 3.14
24
+ *
25
+ * // Strip sub-cent precision from a price field
26
+ * new Schema('object', {
27
+ * price: new Schema('number').transformer({$floor: {precision: 2}}),
28
+ * })
29
+ * ```
30
+ *
31
+ * @type {import('../../value-processor/value-processor.js').ValueProcessorDefinition}
32
+ */
33
+ export const FLOOR_OPERATOR = {
34
+ keyword: 'floor',
35
+ parameters: [ { parameter: 'precision', default: 0 } ],
36
+
37
+ process: (value, _target, _location, options) => {
38
+ const num = Number(value);
39
+ if (!Number.isFinite(num)) {
40
+ return value; // Pass through non-numeric values unchanged
41
+ }
42
+ const precision = options.args.precision;
43
+ const multiplier = Math.pow(10, precision);
44
+
45
+ return Math.floor(num * multiplier) / multiplier;
46
+ }
47
+ };
@@ -0,0 +1,44 @@
1
+ import { deepValue } from '../../helpers/deep.js';
2
+
3
+ /**
4
+ * ## $get
5
+ *
6
+ * Extracts a value from the input using a dot-separated path (for objects) or a numeric
7
+ * index (for arrays). Does not require the path to be declared as a schema property —
8
+ * use `$property` when schema-awareness is needed.
9
+ *
10
+ * Returns `undefined` if the path does not resolve.
11
+ *
12
+ * ### Parameters
13
+ * - `path` (string | number, required): Dot-separated property path or array index.
14
+ *
15
+ * ### Example
16
+ * ```js
17
+ * // Extract a nested property from an object
18
+ * new Schema('object').transformer({$get: {path: 'database.host'}})
19
+ * // {database: {host: 'localhost'}} → 'localhost'
20
+ *
21
+ * // Extract an array element by index
22
+ * new Schema('array').transformer({$get: {path: 0}})
23
+ * // ['first', 'second'] → 'first'
24
+ *
25
+ * // Use as a conditional predicate — only proceed if the path exists
26
+ * new Schema('object').transformer({
27
+ * $when: [{$get: {path: 'config.timeout'}}]
28
+ * })
29
+ * ```
30
+ *
31
+ * @type {import('../../value-processor/value-processor.js').ValueProcessorDefinition}
32
+ */
33
+ export const GET_OPERATOR = {
34
+ keyword: 'get',
35
+ parameters: [{parameter: 'path', required: true}],
36
+
37
+ process: (value, _target, _location, options) => {
38
+ const path = options.args?.path;
39
+ if (typeof path === 'number') {
40
+ return Array.isArray(value) ? value[path] : undefined;
41
+ }
42
+ return deepValue(value, path);
43
+ }
44
+ };
@@ -0,0 +1,84 @@
1
+
2
+ import { FunctionValueProcessor } from '../../value-processor/function-value-processor.js';
3
+ import { ComposedValueProcessor } from '../../value-processor/composed-value-processor.js';
4
+ import { EachExecutor } from '../../executor/each-executor.js';
5
+ import { ConstraintError, SchemaError } from '../../errors.js';
6
+ import { formatValue } from '../../helpers/format.js';
7
+
8
+ /**
9
+ * ## $group-by
10
+ *
11
+ * Groups an array of objects by a key, returning an object whose values are arrays of elements
12
+ * that share that key value.
13
+ *
14
+ * - `{'$group-by': 'key'}` — groups by the named property on each element
15
+ * - `{'$group-by': processor}` — groups by the result of executing the processor against each element
16
+ * (any compiled processor spec, e.g. `'$type'`, `{$get: 'field'}`, or a function)
17
+ *
18
+ * Elements where the extracted key is `undefined` are omitted from the result.
19
+ * Insertion order is preserved within each group.
20
+ *
21
+ * ### Parameters
22
+ * - `key` (string or processor, required): Property name to group by, or a processor that extracts
23
+ * the grouping key from each element. Plain strings (no leading `$`) are treated as property names;
24
+ * all other processor specs are executed as extractors.
25
+ *
26
+ * ### Example
27
+ * ```js
28
+ * // Group an array of log entries by their severity level
29
+ * new Schema('array').transformer({'$group-by': 'level'})
30
+ * // [{level:'error', msg:'...'}, {level:'info', msg:'...'}]
31
+ * // → {error: [{level:'error', ...}], info: [{level:'info', ...}]}
32
+ *
33
+ * // Group by a computed key (the JS type of each element)
34
+ * new Schema('array').transformer({'$group-by': '$type'})
35
+ * // [1, 'a', 2, 'b'] → {number: [1, 2], string: ['a', 'b']}
36
+ *
37
+ * // Group by a nested property using $get
38
+ * new Schema('array').transformer({'$group-by': {$get: 'meta.region'}})
39
+ * ```
40
+ *
41
+ * @type {import('../../value-processor/value-processor.js').ValueProcessorDefinition}
42
+ */
43
+ export const GROUP_BY_OPERATOR = {
44
+ keyword: 'group-by',
45
+
46
+ build: (args) => {
47
+ if (!Array.isArray(args) || args.length !== 1) {
48
+ throw new SchemaError('$group-by requires a single key or processor argument');
49
+ }
50
+
51
+ const keyArg = args[0];
52
+ const keySpec = keyArg?.spec;
53
+
54
+ // Plain property name strings (no leading $) → property lookup per element.
55
+ // Processor keywords ($type), complex specs, functions → execute as extractor.
56
+ const keyExtractor = (typeof keySpec === 'string' && !keySpec.startsWith('$'))
57
+ ? new FunctionValueProcessor(element => element?.[keySpec])
58
+ : keyArg;
59
+
60
+ return new ComposedValueProcessor(
61
+ new EachExecutor(
62
+ keyExtractor,
63
+ (input) => {
64
+ if (!Array.isArray(input)) {
65
+ throw new ConstraintError(`$group-by requires an array, got ${formatValue(input)}`);
66
+ }
67
+ return input;
68
+ },
69
+ (keys, input) => {
70
+ const result = {};
71
+ for (let i = 0; i < input.length; i++) {
72
+ const key = keys[i];
73
+ if (key === undefined) continue;
74
+ const groupKey = String(key);
75
+ if (!result[groupKey]) result[groupKey] = [];
76
+ result[groupKey].push(input[i]);
77
+ }
78
+ return result;
79
+ }
80
+ ),
81
+ {'$group-by': keySpec}
82
+ );
83
+ }
84
+ };