@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,235 @@
1
+ import { ConstraintError } from '../../errors.js';
2
+
3
+ /**
4
+ * Built-in country rules. Each entry maps a country calling code to:
5
+ * - `lengths` — accepted subscriber digit counts (after country code)
6
+ * - `validate` — optional regex applied to subscriber digits
7
+ * - `national` — `#`-template for national formatting
8
+ * - `international` — `#`-template for international formatting (after `+CC `)
9
+ *
10
+ * Users can extend via the `countries` parameter; custom entries are merged
11
+ * over these defaults (allowing override). Custom entries do not require
12
+ * `validate` — only `lengths` and templates are needed.
13
+ */
14
+ const DEFAULT_COUNTRY_RULES = {
15
+ // NANP: area code (NPA) and exchange (NXX) cannot start with 0 or 1
16
+ '1': {
17
+ lengths: [10],
18
+ validate: /^[2-9]\d{2}[2-9]\d{6}$/,
19
+ national: '(###) ###-####',
20
+ international: '### ### ####',
21
+ },
22
+ };
23
+
24
+ /**
25
+ * Strip characters commonly used as phone number formatting.
26
+ * Preserves digits and a leading `+`.
27
+ * @param {string} value
28
+ * @returns {string}
29
+ */
30
+ function stripFormatting(value) {
31
+ const trimmed = value.trim();
32
+ if (trimmed.startsWith('+')) {
33
+ return '+' + trimmed.slice(1).replace(/\D/g, '');
34
+ }
35
+ return trimmed.replace(/\D/g, '');
36
+ }
37
+
38
+ /**
39
+ * Replace each `#` in a template with the next digit from `digits`.
40
+ * @param {string} digits
41
+ * @param {string} template
42
+ * @returns {string}
43
+ */
44
+ function applyTemplate(digits, template) {
45
+ let i = 0;
46
+ return template.replace(/#/g, () => digits[i++] ?? '');
47
+ }
48
+
49
+ /**
50
+ * ## $phone
51
+ *
52
+ * Validates and normalizes a phone number string.
53
+ *
54
+ * Strips common formatting (spaces, dashes, dots, parentheses, slashes) and
55
+ * validates the remaining digits against country-specific rules when available,
56
+ * or generic E.164 length rules otherwise.
57
+ *
58
+ * **Output format** is controlled by the `international` parameter:
59
+ * - When `false` (default): national format for the default country
60
+ * (e.g. `(212) 555-1234` for country code `1`).
61
+ * - When `true`: international format with country code prefix
62
+ * (e.g. `+1 212 555 1234`).
63
+ *
64
+ * Numbers without a `+` prefix are assumed to belong to the default `country`.
65
+ * A leading country code without `+` is recognized when it produces a valid
66
+ * subscriber length (e.g. `12125551234` is treated as `+1 2125551234`).
67
+ *
68
+ * **NANP validation (country code `1`):** area codes and exchanges must not
69
+ * start with `0` or `1`, matching North American Numbering Plan rules.
70
+ *
71
+ * **Not supported:** extensions, vanity letters (1-800-FLOWERS), international
72
+ * dialing prefixes (`00`, `011`), short codes, or emergency numbers. This
73
+ * processor targets typical subscriber phone numbers as entered in forms or
74
+ * configuration files.
75
+ *
76
+ * ### Parameters
77
+ * - `international` (boolean, default `false`): When `false`, only numbers
78
+ * matching the default `country` code are accepted, and output uses the
79
+ * national format. When `true`, any valid international number is accepted,
80
+ * and output uses the international format with `+CC` prefix.
81
+ * - `country` (string, default `'1'`): Default country calling code applied
82
+ * to numbers entered without a `+` prefix.
83
+ * - `countries` (object, default `null`): Optional map of country calling
84
+ * codes to rule objects, merged over the built-in rules. Each rule object
85
+ * may contain:
86
+ * - `lengths` (number[]) — accepted subscriber digit counts
87
+ * - `validate` (RegExp, optional) — pattern the subscriber digits must match
88
+ * - `national` (string) — `#`-template for national formatting
89
+ * - `international` (string) — `#`-template for international formatting
90
+ *
91
+ * ### Example
92
+ * ```js
93
+ * // Basic US number validation and national formatting
94
+ * new Schema('string').validator('$phone')
95
+ *
96
+ * // Accept international numbers
97
+ * new Schema('string').validator({'$phone': {international: true}})
98
+ *
99
+ * // Default to UK numbers
100
+ * new Schema('string').validator({'$phone': {
101
+ * country: '44',
102
+ * countries: {
103
+ * '44': {lengths: [10], national: '#### ### ####', international: '#### ### ####'}
104
+ * }
105
+ * }})
106
+ *
107
+ * // Compact storage: compose with space/punctuation stripping
108
+ * new Schema('string').normalizer({$pipeline: ['$trim', '$phone']})
109
+ * ```
110
+ *
111
+ * @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}
112
+ */
113
+ export const PHONE_CONSTRAINT = {
114
+ keyword: 'phone',
115
+ parameters: [
116
+ { parameter: 'international', type: 'boolean', default: false },
117
+ { parameter: 'country', default: '1' },
118
+ { parameter: 'countries', default: null },
119
+ ],
120
+
121
+ process: (value, _target, _location, options) => {
122
+ const { international, country, countries: customCountries } = options.args;
123
+ const rules = customCountries
124
+ ? { ...DEFAULT_COUNTRY_RULES, ...customCountries }
125
+ : DEFAULT_COUNTRY_RULES;
126
+
127
+ const stripped = stripFormatting(value);
128
+
129
+ // After stripping, must be digits with optional leading +
130
+ if (!stripped || !/^\+?\d+$/.test(stripped)) {
131
+ throw new ConstraintError('Invalid phone number format');
132
+ }
133
+
134
+ let countryCode;
135
+ let subscriber = '';
136
+
137
+ if (stripped.startsWith('+')) {
138
+ const digits = stripped.slice(1);
139
+
140
+ // Match known country codes (ITU codes are prefix-free, 1-3 digits)
141
+ let matched = false;
142
+ for (const len of [1, 2, 3]) {
143
+ if (len > digits.length) break;
144
+ const candidate = digits.slice(0, len);
145
+ if (rules[candidate]) {
146
+ countryCode = candidate;
147
+ subscriber = digits.slice(len);
148
+ matched = true;
149
+ break;
150
+ }
151
+ }
152
+
153
+ if (!matched) {
154
+ if (!international) {
155
+ throw new ConstraintError(
156
+ `Phone number country code does not match +${country}`
157
+ );
158
+ }
159
+ // Unknown country — generic E.164 validation (total 7-15 digits)
160
+ if (digits.length < 7 || digits.length > 15) {
161
+ throw new ConstraintError('Invalid phone number length');
162
+ }
163
+ return '+' + digits;
164
+ }
165
+ }
166
+ else {
167
+ // No + prefix — match against default country
168
+ const countryRules = rules[country];
169
+ countryCode = country;
170
+
171
+ if (countryRules) {
172
+ const withCC = countryRules.lengths.map(l => l + country.length);
173
+ if (withCC.includes(stripped.length) && stripped.startsWith(country)) {
174
+ // Leading country code without + (e.g. 12125551234)
175
+ subscriber = stripped.slice(country.length);
176
+ }
177
+ else if (countryRules.lengths.includes(stripped.length)) {
178
+ // National number (e.g. 2125551234)
179
+ subscriber = stripped;
180
+ }
181
+ else {
182
+ throw new ConstraintError(
183
+ `Invalid phone number length for country code +${country}`
184
+ );
185
+ }
186
+ }
187
+ else {
188
+ // No rules for default country — accept digits as subscriber
189
+ subscriber = stripped;
190
+ }
191
+ }
192
+
193
+ // Reject international numbers when not accepted
194
+ if (!international && countryCode !== country) {
195
+ throw new ConstraintError(
196
+ `International numbers not accepted; expected country code +${country}`
197
+ );
198
+ }
199
+
200
+ // Country-specific validation
201
+ const countryRules = rules[countryCode];
202
+ if (countryRules) {
203
+ if (!countryRules.lengths.includes(subscriber.length)) {
204
+ throw new ConstraintError(
205
+ `Invalid phone number length for country code +${countryCode}`
206
+ );
207
+ }
208
+ if (countryRules.validate && !countryRules.validate.test(subscriber)) {
209
+ throw new ConstraintError(
210
+ `Invalid phone number for country code +${countryCode}`
211
+ );
212
+ }
213
+ }
214
+ else {
215
+ // Generic E.164: total digits (cc + subscriber) must be 7-15
216
+ const total = countryCode.length + subscriber.length;
217
+ if (total < 7 || total > 15) {
218
+ throw new ConstraintError('Invalid phone number length');
219
+ }
220
+ }
221
+
222
+ // Format output
223
+ if (international) {
224
+ if (countryRules?.international) {
225
+ return `+${countryCode} ${applyTemplate(subscriber, countryRules.international)}`;
226
+ }
227
+ return `+${countryCode}${subscriber}`;
228
+ }
229
+
230
+ if (countryRules?.national) {
231
+ return applyTemplate(subscriber, countryRules.national);
232
+ }
233
+ return subscriber;
234
+ }
235
+ };
@@ -0,0 +1,62 @@
1
+
2
+ import { ComposedValueProcessor } from '../../value-processor/composed-value-processor.js';
3
+ import { FunctionValueProcessor } from '../../value-processor/function-value-processor.js';
4
+ import { ArrayExecutor } from '../../executor/array-executor.js';
5
+ import { map } from '../../helpers/object.js';
6
+ import { ConstraintError, SchemaError } from '../../errors.js';
7
+
8
+ /**
9
+ * ## $pick
10
+ *
11
+ * Returns a new object or dense array containing only the specified keys/indices from the input.
12
+ * Keys not present in the input are silently omitted from the result.
13
+ * For arrays, numeric indices are selected and the result is a dense (packed) array.
14
+ *
15
+ * ### Parameters
16
+ * - Array of key names or indices (string[]|number[], required): The keys/indices to retain.
17
+ *
18
+ * ### Example
19
+ * ```js
20
+ * // Retain only 'id' and 'name' from an object
21
+ * new Schema('object').transformer({$pick: ['id', 'name']})
22
+ * // {id: 1, name: 'Alice', secret: 'xyz'} → {id: 1, name: 'Alice'}
23
+ *
24
+ * // Select the first and third elements from an array
25
+ * new Schema('array').transformer({$pick: [0, 2]})
26
+ * // ['a', 'b', 'c', 'd'] → ['a', 'c']
27
+ *
28
+ * // Strip sensitive fields from a user record before returning
29
+ * new Schema('object').transformer({$pick: ['id', 'username', 'email', 'role']})
30
+ * ```
31
+ *
32
+ * @type {import('../../value-processor/value-processor.js').ValueProcessorDefinition}
33
+ */
34
+ export const PICK_OPERATOR = {
35
+ keyword: 'pick',
36
+
37
+ build: (args) => {
38
+ if (!Array.isArray(args) || args.length === 0) {
39
+ throw new SchemaError('$pick requires a non-empty array of key names');
40
+ }
41
+
42
+ const argsSpec = map(args, v => v.spec);
43
+
44
+ return new FunctionValueProcessor(
45
+ (value, _target, location, options) => {
46
+ const keys = Array.isArray(options.args) ? options.args : [];
47
+ if (typeof value !== 'object' || value === null) {
48
+ throw new ConstraintError(`$pick requires an object or array input`, {location});
49
+ }
50
+ if (Array.isArray(value)) {
51
+ return keys.filter(k => k >= 0 && k < value.length).map(k => value[k]);
52
+ }
53
+ const result = {};
54
+ for (const k of keys) {
55
+ if (k in value) result[k] = value[k];
56
+ }
57
+ return result;
58
+ },
59
+ new ComposedValueProcessor(new ArrayExecutor(args), argsSpec)
60
+ );
61
+ }
62
+ };
@@ -0,0 +1,63 @@
1
+ import { PipelineExecutor } from '../../executor/pipeline-executor.js';
2
+
3
+ import { ComposedValueProcessor } from '../../value-processor/composed-value-processor.js';
4
+ import { map } from '../../helpers/object.js';
5
+ import { ResolverError } from '../../errors.js';
6
+
7
+ /**
8
+ * @import {ValueProcessorDefinition} from '../../value-processor/value-processor.js'
9
+ */
10
+
11
+ /**
12
+ * ## $pipeline
13
+ *
14
+ * Executes a sequence of processors in order, passing the output of each processor
15
+ * as input to the next. The final processor's output becomes the result.
16
+ *
17
+ * **Note**: Handler arrays (normalizers, validators, etc.) implicitly create pipelines,
18
+ * so this processor is rarely used directly. It's primarily used internally by the
19
+ * schema compiler to aggregate handler arrays into single compiled processors.
20
+ *
21
+ * ### Parameters
22
+ * - `processors` (`Array<ProcessorSpec>`, required): Array of processor specifications to execute in sequence.
23
+ * Each element can be a string keyword (e.g., `'$trim'`), a parameterized processor object
24
+ * (e.g., `{$range: {min: 0}}`), a RegExp, or a function.
25
+ *
26
+ * **Behavior**: Processors execute left-to-right. If any processor throws an error, the pipeline
27
+ * stops and the error propagates. Each processor receives the output of the previous processor
28
+ * as its input value.
29
+ *
30
+ * ### Example
31
+ * ```js
32
+ * // Explicit pipeline (equivalent to passing an array to .normalizer())
33
+ * new Schema('string').normalizer({$pipeline: ['$trim', '$lowercase', '$alphanum']})
34
+ *
35
+ * // Use $pipeline inside a conditional to chain processors on a branch
36
+ * new Schema('string').transformer({
37
+ * $if: [
38
+ * '$numeric',
39
+ * {$pipeline: ['$number', {$clamp: {min: 0, max: 100}}]},
40
+ * ]
41
+ * })
42
+ * ```
43
+ *
44
+ * @type {ValueProcessorDefinition}
45
+ */
46
+ export const PIPELINE_OPERATOR = {
47
+ keyword: 'pipeline',
48
+ build: (args) => {
49
+ if (!Array.isArray(args)) {
50
+ throw new ResolverError('$pipeline requires an array of processors');
51
+ }
52
+
53
+ const descriptions = args.map(arg => arg.description ?? '').filter(Boolean);
54
+ const description = descriptions.length > 1
55
+ ? descriptions.map(d => (d.includes('|') || d.includes('&')) ? `(${d})` : d).join(' >> ')
56
+ : descriptions[0]
57
+ const spec = {$pipeline: map(args, arg => arg.spec)}
58
+
59
+ return new ComposedValueProcessor(new PipelineExecutor(args), spec, description);
60
+ }
61
+ }
62
+
63
+
@@ -0,0 +1,22 @@
1
+ import { ConstraintError } from '../../errors.js';
2
+
3
+ /**
4
+ * ## $port
5
+ *
6
+ * Validates that a value is a valid TCP/UDP port number (1-65535).
7
+ * Accepts numeric values or strings that can be converted to numbers.
8
+ * Returns the value as a number or a string, depending on the underlying schema.
9
+ * (defaults to a number).
10
+ *
11
+ * @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}
12
+ */
13
+ export const PORT_CONSTRAINT = {
14
+ keyword: 'port',
15
+ process: (value, _target, location) => {
16
+ const num = Number(value);
17
+ if (!(Number.isInteger(num) && num >= 1 && num <= 65535)) {
18
+ throw new ConstraintError('Port must be between 1 and 65535');
19
+ }
20
+ return location.schema.options.type === 'string'? `${num}` : num;
21
+ }
22
+ };
@@ -0,0 +1,23 @@
1
+ import { ConstraintError } from '../../errors.js';
2
+
3
+ /**
4
+ * ## $positive
5
+ *
6
+ * Validates that a numeric value is positive (greater than 0).
7
+ * Input must already be a number; use `$number` in a prior normalizer if coercion from string is needed.
8
+ *
9
+ * See also:
10
+ * - `$negative` to enforce the opposite constraint
11
+ * - `$range` if you want "non-negative" ( greater than or equal to 0) semantics.
12
+ *
13
+ * @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}
14
+ */
15
+ export const POSITIVE_CONSTRAINT = {
16
+ keyword: 'positive',
17
+ process: (value) => {
18
+ if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {
19
+ throw new ConstraintError('Must be a positive number');
20
+ }
21
+ return value;
22
+ }
23
+ };
@@ -0,0 +1,55 @@
1
+ import { CompiledSchema } from '../../compiled-schema.js';
2
+ import { SchemaError } from '../../errors.js';
3
+ import { formatValue } from '../../helpers/format.js';
4
+
5
+ /**
6
+ * ## $process
7
+ *
8
+ * Process the incoming value according to the provided schema
9
+ *
10
+ * Important note: the provided schema is run in isolation in a private local context, which means
11
+ * that it (and its handlers) have no access to the outer schema or the global target value, and all
12
+ * paths are relative to the root of the provided schema.
13
+ *
14
+ * ### Parameters
15
+ * - `schema` (CompiledSchema, required): the compiled schema to apply to the input value.
16
+ * Any `Schema` found in a handler pipeline will be automatically compiled;
17
+ * Use `$compile` to produce a `CompiledSchema` from a `Schema` literal value.
18
+ *
19
+ * ### Example
20
+ * ```js
21
+ * import { Schema, SchemaResolver } from '@versionzero/schema';
22
+ *
23
+ * // Compile a reusable sub-schema and run values through it
24
+ * const resolver = new SchemaResolver();
25
+ * const portSchema = await resolver.compile(
26
+ * new Schema('number').validator({$range: {min: 1, max: 65535}})
27
+ * );
28
+ *
29
+ * // portSchema is automatically compiled:
30
+ * new Schema('object', {
31
+ * port: new Schema('any').validator({$process: {schema: portSchema}}),
32
+ * })
33
+ *
34
+ * // Use $compile inline to compile-then-process in a single pipeline
35
+ * const mySchema = new Schema('string').validator('$non-empty');
36
+ * new Schema('any').normalizer([{$compile: {$literal: mySchema}}, '$process'])
37
+ * ```
38
+ *
39
+ * @type {import('../../value-processor/value-processor.js').ValueProcessorDefinition}
40
+ */
41
+ export const PROCESS_OPERATOR = {
42
+ keyword: 'process',
43
+ parameters: [ { parameter: 'schema', required: true } ],
44
+
45
+ process: (value, _target, location, options) => {
46
+
47
+ const schema = options.args.schema;
48
+
49
+ if (!(schema instanceof CompiledSchema)) {
50
+ throw new SchemaError(`Schema argument must be an instance of CompiledSchema, got ${formatValue(schema)})`, {location});
51
+ }
52
+
53
+ return schema._process(value); // do not pass options, or outer schema context/paths will leak in!
54
+ }
55
+ };
@@ -0,0 +1,49 @@
1
+ import { SchemaError } from '../../errors.js';
2
+
3
+ /**
4
+ * ## $property
5
+ *
6
+ * Extracts a named property value from an object. This operator is useful for accessing
7
+ * nested properties or extracting specific fields during processing pipelines.
8
+ *
9
+ * Returns `undefined` if the current value is not an object or if the property doesn't exist.
10
+ * Throws a `SchemaError` if the specified property name is not defined in the schema.
11
+ *
12
+ * ### Parameters
13
+ * - `name` (string, required): The name of the schema-defined property to extract from the input object.
14
+ * The property must be declared in the current schema; use `$get` for arbitrary path access without
15
+ * schema awareness.
16
+ *
17
+ * ### Example
18
+ * ```js
19
+ * // Conditionally require 'apiKey' only when 'useApiKey' is true
20
+ * new Schema('object', {
21
+ * useApiKey: new Schema('boolean'),
22
+ * apiKey: new Schema('string').validator({
23
+ * $if: [{$property: 'useApiKey'}, '$non-empty']
24
+ * }),
25
+ * })
26
+ *
27
+ * // Discriminate a union using a schema property value
28
+ * new Schema('object', {
29
+ * type: new Schema('string'),
30
+ * config: new Schema('any'),
31
+ * }).discriminator({$property: 'type'})
32
+ * ```
33
+ *
34
+ * @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}
35
+ */
36
+ export const PROPERTY_OPERATOR = {
37
+ keyword: 'property',
38
+ parameters: [{parameter: 'name', required: true}],
39
+ process: (value, _target, location, options) => {
40
+ const propertyName = options.args.name;
41
+ if (propertyName === undefined) {
42
+ throw new SchemaError('$property expects a property name', {location})
43
+ }
44
+ if (location.schema.getPropertySchema(propertyName) === undefined) {
45
+ throw new SchemaError(`Unknown $property ${propertyName}`, {location});
46
+ }
47
+ return (typeof value === 'object' && value !== null)? value[propertyName] : undefined;
48
+ }
49
+ };
@@ -0,0 +1,72 @@
1
+
2
+ import { ConstraintError, ResolverError } from '../../errors.js';
3
+
4
+ /**
5
+ * ## $range
6
+ *
7
+ * Validates that a numeric value falls within the specified range (inclusive).
8
+ * Can specify minimum, maximum, or both bounds.
9
+ *
10
+ * ### Parameters
11
+ * - `min` (number, optional): Minimum value (inclusive). If omitted, no lower bound.
12
+ * - `max` (number, optional): Maximum value (inclusive). If omitted, no upper bound.
13
+ *
14
+ * ### Example
15
+ * ```js
16
+ * // Object form with named parameters
17
+ * new Schema('number').validator({$range: {min: 1, max: 100}})
18
+ *
19
+ * // Array form [min, max]
20
+ * new Schema('number').validator({$range: [1, 65535]})
21
+ *
22
+ * // Only a lower bound (percentage, must be non-negative)
23
+ * new Schema('number').validator({$range: {min: 0}})
24
+ *
25
+ * // Only an upper bound
26
+ * new Schema('number').validator({$range: {max: 255}})
27
+ * ```
28
+ *
29
+ * See also: `$positive` and `$negative` for common named ranges.
30
+ *
31
+ * @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}
32
+ */
33
+ export const RANGE_CONSTRAINT = {
34
+ keyword: 'range',
35
+ parameters: [ { parameter: 'min', type: 'number', default: undefined }, { parameter: 'max', type: 'number', default: undefined } ],
36
+
37
+ process: (value, _target, _location, options) => {
38
+ const { min, max } = options.args;
39
+
40
+ const num = Number(value);
41
+ if (!Number.isFinite(num)) {
42
+ throw new ConstraintError('Value must be a number');
43
+ }
44
+ if (min !== undefined && num < min) {
45
+ throw new ConstraintError(`Value must be at least ${min}`);
46
+ }
47
+ if (max !== undefined && num > max) {
48
+ throw new ConstraintError(`Value must be at most ${max}`);
49
+ }
50
+ return value;
51
+ },
52
+ describe: (args) => {
53
+
54
+ if (!args) {
55
+ return undefined; // should never happen
56
+ }
57
+
58
+ const minProcessor = (Array.isArray(args)? args[0] : args.min);
59
+ const maxProcessor = (Array.isArray(args)? args[1] : args.max);
60
+
61
+ const min = minProcessor?.description;
62
+ const max = maxProcessor?.description;
63
+
64
+ return min !== undefined && max !== undefined
65
+ ? `${min}-${max}`
66
+ : min !== undefined
67
+ ? `≥${min}`
68
+ : max !== undefined
69
+ ? `≤${max}`
70
+ : undefined
71
+ }
72
+ };
@@ -0,0 +1,79 @@
1
+ import { deepValue } from '../../helpers/deep.js';
2
+
3
+ import { SchemaError } from '../../errors.js';
4
+
5
+ /**
6
+ * ## $reference
7
+ *
8
+ * Returns the value at the referenced path (relative to the current schema) in the target data, or undefined if not set.
9
+ *
10
+ * Throws a `SchemaError` if the specified path is not defined in the schema.
11
+ *
12
+ * ### Parameters
13
+ * - `path` (string, required): path from the current schema into the top-level target object; must be a valid
14
+ * schema path (dot-separated, supports / for absolute or ^ for parents).
15
+ * - `pending` (boolean, optional, default: false): If true will fall back to any pending value not yet in the target data.
16
+ * - `completed` (boolean, optional, default: false): If true, will only return a value if the reference is completed (useful for checking if all children are handled).
17
+ *
18
+ * ### Example
19
+ * ```js
20
+ * // Validate 'port' is within range only when 'ssl' is enabled at the top level
21
+ * new Schema('object', {
22
+ * ssl: new Schema('boolean'),
23
+ * port: new Schema('number').validator({
24
+ * $if: [{$reference: 'ssl'}, {$range: {min: 443, max: 443}}]
25
+ * }),
26
+ * })
27
+ *
28
+ * // Cross-field consistency: confirm 'passwordConfirm' matches 'password'
29
+ * new Schema('object', {
30
+ * password: new Schema('string'),
31
+ * passwordConfirm: new Schema('string').validator(
32
+ * (value, target) => value === target.password || undefined
33
+ * ),
34
+ * })
35
+ * ```
36
+ * ### See Also
37
+ * - Use `$property` for getting a named child value.
38
+ * - Use `$get` for getting values under the input value (without the path needing to be in the schema.)
39
+ *
40
+ * @type {import("../../value-processor/value-processor.js").ValueProcessorDefinition}
41
+ */
42
+ export const REFERENCE_OPERATOR = {
43
+ keyword: 'reference',
44
+ parameters: [{parameter: 'path', required: true}, {parameter: 'pending', required: false, default: false}, {parameter: 'completed', required: false, type: 'boolean', default: false}],
45
+ process: (_, target, location, options) => {
46
+ const path = options.args.path;
47
+ if (path === undefined) {
48
+ throw new SchemaError('$reference expects a path')
49
+ }
50
+ const state = options.state.getRelativeState(path);
51
+
52
+ const requireCompleted = options.args.completed;
53
+
54
+ if (state === undefined) {
55
+ if (requireCompleted) {
56
+ return undefined; // welp.
57
+ }
58
+ // We're lost. Maybe we can find it in the target data?
59
+ const resolvedLocation = location.relative(path);
60
+ return resolvedLocation? deepValue(target, resolvedLocation.path) : undefined;
61
+ }
62
+ if (requireCompleted && !state.completed) {
63
+ return undefined;
64
+ }
65
+ if (state.value !== undefined) {
66
+ return state.value;
67
+ }
68
+ if (options.args.pending) {
69
+ return state.pending;
70
+ }
71
+ return undefined;
72
+ },
73
+ /*
74
+ description: `${path}`
75
+ };
76
+ }
77
+
78
+ */
79
+ };