@warlock.js/seal 4.0.174 → 4.1.1

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 (1226) hide show
  1. package/cjs/index.cjs +8900 -0
  2. package/cjs/index.cjs.map +1 -0
  3. package/esm/config.d.mts +47 -0
  4. package/esm/config.d.mts.map +1 -0
  5. package/esm/config.mjs +40 -0
  6. package/esm/config.mjs.map +1 -0
  7. package/esm/factory/index.d.mts +2 -0
  8. package/esm/factory/index.mjs +4 -0
  9. package/esm/factory/validate.d.mts +16 -0
  10. package/esm/factory/validate.d.mts.map +1 -0
  11. package/esm/factory/validate.mjs +29 -0
  12. package/esm/factory/validate.mjs.map +1 -0
  13. package/esm/factory/validators.d.mts +75 -0
  14. package/esm/factory/validators.d.mts.map +1 -0
  15. package/esm/factory/validators.mjs +132 -0
  16. package/esm/factory/validators.mjs.map +1 -0
  17. package/esm/helpers/date-helpers.d.mts +19 -0
  18. package/esm/helpers/date-helpers.d.mts.map +1 -0
  19. package/esm/helpers/date-helpers.mjs +24 -0
  20. package/esm/helpers/date-helpers.mjs.map +1 -0
  21. package/esm/helpers/file.utils.d.mts +12 -0
  22. package/esm/helpers/file.utils.d.mts.map +1 -0
  23. package/esm/helpers/file.utils.mjs +33 -0
  24. package/esm/helpers/file.utils.mjs.map +1 -0
  25. package/esm/helpers/get-field-value.d.mts +42 -0
  26. package/esm/helpers/get-field-value.d.mts.map +1 -0
  27. package/esm/helpers/get-field-value.mjs +45 -0
  28. package/esm/helpers/get-field-value.mjs.map +1 -0
  29. package/esm/helpers/index.mjs +7 -0
  30. package/esm/helpers/is-empty-value.mjs +10 -0
  31. package/esm/helpers/is-empty-value.mjs.map +1 -0
  32. package/esm/helpers/path-helpers.d.mts +8 -0
  33. package/esm/helpers/path-helpers.d.mts.map +1 -0
  34. package/esm/helpers/path-helpers.mjs +12 -0
  35. package/esm/helpers/path-helpers.mjs.map +1 -0
  36. package/esm/helpers/validation-helpers.d.mts +36 -0
  37. package/esm/helpers/validation-helpers.d.mts.map +1 -0
  38. package/esm/helpers/validation-helpers.mjs +72 -0
  39. package/esm/helpers/validation-helpers.mjs.map +1 -0
  40. package/esm/index.d.mts +96 -0
  41. package/esm/index.mjs +92 -0
  42. package/esm/mutators/array-mutators.d.mts +16 -0
  43. package/esm/mutators/array-mutators.d.mts.map +1 -0
  44. package/esm/mutators/array-mutators.mjs +40 -0
  45. package/esm/mutators/array-mutators.mjs.map +1 -0
  46. package/esm/mutators/date-mutators.d.mts +43 -0
  47. package/esm/mutators/date-mutators.d.mts.map +1 -0
  48. package/esm/mutators/date-mutators.mjs +113 -0
  49. package/esm/mutators/date-mutators.mjs.map +1 -0
  50. package/esm/mutators/index.mjs +8 -0
  51. package/esm/mutators/number-mutators.d.mts +26 -0
  52. package/esm/mutators/number-mutators.d.mts.map +1 -0
  53. package/esm/mutators/number-mutators.mjs +53 -0
  54. package/esm/mutators/number-mutators.mjs.map +1 -0
  55. package/esm/mutators/object-mutators.d.mts +12 -0
  56. package/esm/mutators/object-mutators.d.mts.map +1 -0
  57. package/esm/mutators/object-mutators.mjs +37 -0
  58. package/esm/mutators/object-mutators.mjs.map +1 -0
  59. package/esm/mutators/scalar-mutators.d.mts +7 -0
  60. package/esm/mutators/scalar-mutators.d.mts.map +1 -0
  61. package/esm/mutators/scalar-mutators.mjs +9 -0
  62. package/esm/mutators/scalar-mutators.mjs.map +1 -0
  63. package/esm/mutators/string-mutators.d.mts +76 -0
  64. package/esm/mutators/string-mutators.d.mts.map +1 -0
  65. package/esm/mutators/string-mutators.mjs +169 -0
  66. package/esm/mutators/string-mutators.mjs.map +1 -0
  67. package/esm/plugins/plugin-system.d.mts +71 -0
  68. package/esm/plugins/plugin-system.d.mts.map +1 -0
  69. package/esm/plugins/plugin-system.mjs +64 -0
  70. package/esm/plugins/plugin-system.mjs.map +1 -0
  71. package/esm/rules/array/array-rules.d.mts +16 -0
  72. package/esm/rules/array/array-rules.d.mts.map +1 -0
  73. package/esm/rules/array/array-rules.mjs +41 -0
  74. package/esm/rules/array/array-rules.mjs.map +1 -0
  75. package/esm/rules/array/index.mjs +3 -0
  76. package/esm/rules/color/color-rules.d.mts +34 -0
  77. package/esm/rules/color/color-rules.d.mts.map +1 -0
  78. package/esm/rules/color/color-rules.mjs +104 -0
  79. package/esm/rules/color/color-rules.mjs.map +1 -0
  80. package/esm/rules/color/index.mjs +3 -0
  81. package/esm/rules/common/enum.d.mts +30 -0
  82. package/esm/rules/common/enum.d.mts.map +1 -0
  83. package/esm/rules/common/enum.mjs +77 -0
  84. package/esm/rules/common/enum.mjs.map +1 -0
  85. package/esm/rules/common/equals-field-rules.d.mts +22 -0
  86. package/esm/rules/common/equals-field-rules.d.mts.map +1 -0
  87. package/esm/rules/common/equals-field-rules.mjs +42 -0
  88. package/esm/rules/common/equals-field-rules.mjs.map +1 -0
  89. package/esm/rules/common/index.mjs +8 -0
  90. package/esm/rules/common/instanceof.d.mts +16 -0
  91. package/esm/rules/common/instanceof.d.mts.map +1 -0
  92. package/esm/rules/common/instanceof.mjs +23 -0
  93. package/esm/rules/common/instanceof.mjs.map +1 -0
  94. package/esm/rules/common/literal.d.mts +16 -0
  95. package/esm/rules/common/literal.d.mts.map +1 -0
  96. package/esm/rules/common/literal.mjs +29 -0
  97. package/esm/rules/common/literal.mjs.map +1 -0
  98. package/esm/rules/common/type-rules.d.mts +42 -0
  99. package/esm/rules/common/type-rules.d.mts.map +1 -0
  100. package/esm/rules/common/type-rules.mjs +112 -0
  101. package/esm/rules/common/type-rules.mjs.map +1 -0
  102. package/esm/rules/common/unknown-key.d.mts +14 -0
  103. package/esm/rules/common/unknown-key.d.mts.map +1 -0
  104. package/esm/rules/common/unknown-key.mjs +25 -0
  105. package/esm/rules/common/unknown-key.mjs.map +1 -0
  106. package/esm/rules/conditional/forbidden-if-rules.d.mts +58 -0
  107. package/esm/rules/conditional/forbidden-if-rules.d.mts.map +1 -0
  108. package/esm/rules/conditional/forbidden-if-rules.mjs +116 -0
  109. package/esm/rules/conditional/forbidden-if-rules.mjs.map +1 -0
  110. package/esm/rules/conditional/index.mjs +12 -0
  111. package/esm/rules/conditional/present-if-rules.d.mts +49 -0
  112. package/esm/rules/conditional/present-if-rules.d.mts.map +1 -0
  113. package/esm/rules/conditional/present-if-rules.mjs +97 -0
  114. package/esm/rules/conditional/present-if-rules.mjs.map +1 -0
  115. package/esm/rules/conditional/present-unless-rules.d.mts +15 -0
  116. package/esm/rules/conditional/present-unless-rules.d.mts.map +1 -0
  117. package/esm/rules/conditional/present-unless-rules.mjs +30 -0
  118. package/esm/rules/conditional/present-unless-rules.mjs.map +1 -0
  119. package/esm/rules/conditional/present-with-rules.d.mts +30 -0
  120. package/esm/rules/conditional/present-with-rules.d.mts.map +1 -0
  121. package/esm/rules/conditional/present-with-rules.mjs +75 -0
  122. package/esm/rules/conditional/present-with-rules.mjs.map +1 -0
  123. package/esm/rules/conditional/present-without-rules.d.mts +30 -0
  124. package/esm/rules/conditional/present-without-rules.d.mts.map +1 -0
  125. package/esm/rules/conditional/present-without-rules.mjs +75 -0
  126. package/esm/rules/conditional/present-without-rules.mjs.map +1 -0
  127. package/esm/rules/conditional/required-if-rules.d.mts +81 -0
  128. package/esm/rules/conditional/required-if-rules.d.mts.map +1 -0
  129. package/esm/rules/conditional/required-if-rules.mjs +203 -0
  130. package/esm/rules/conditional/required-if-rules.mjs.map +1 -0
  131. package/esm/rules/conditional/required-unless-rules.d.mts +15 -0
  132. package/esm/rules/conditional/required-unless-rules.d.mts.map +1 -0
  133. package/esm/rules/conditional/required-unless-rules.mjs +31 -0
  134. package/esm/rules/conditional/required-unless-rules.mjs.map +1 -0
  135. package/esm/rules/conditional/required-when-rule.d.mts +23 -0
  136. package/esm/rules/conditional/required-when-rule.d.mts.map +1 -0
  137. package/esm/rules/conditional/required-when-rule.mjs +32 -0
  138. package/esm/rules/conditional/required-when-rule.mjs.map +1 -0
  139. package/esm/rules/conditional/required-with-rules.d.mts +30 -0
  140. package/esm/rules/conditional/required-with-rules.d.mts.map +1 -0
  141. package/esm/rules/conditional/required-with-rules.mjs +66 -0
  142. package/esm/rules/conditional/required-with-rules.mjs.map +1 -0
  143. package/esm/rules/conditional/required-without-rules.d.mts +30 -0
  144. package/esm/rules/conditional/required-without-rules.d.mts.map +1 -0
  145. package/esm/rules/conditional/required-without-rules.mjs +66 -0
  146. package/esm/rules/conditional/required-without-rules.mjs.map +1 -0
  147. package/esm/rules/core/equal.d.mts +12 -0
  148. package/esm/rules/core/equal.d.mts.map +1 -0
  149. package/esm/rules/core/equal.mjs +22 -0
  150. package/esm/rules/core/equal.mjs.map +1 -0
  151. package/esm/rules/core/forbidden.d.mts +10 -0
  152. package/esm/rules/core/forbidden.d.mts.map +1 -0
  153. package/esm/rules/core/forbidden.mjs +20 -0
  154. package/esm/rules/core/forbidden.mjs.map +1 -0
  155. package/esm/rules/core/index.mjs +7 -0
  156. package/esm/rules/core/required.d.mts +15 -0
  157. package/esm/rules/core/required.d.mts.map +1 -0
  158. package/esm/rules/core/required.mjs +36 -0
  159. package/esm/rules/core/required.mjs.map +1 -0
  160. package/esm/rules/core/union.d.mts +13 -0
  161. package/esm/rules/core/union.d.mts.map +1 -0
  162. package/esm/rules/core/union.mjs +30 -0
  163. package/esm/rules/core/union.mjs.map +1 -0
  164. package/esm/rules/core/when.d.mts +11 -0
  165. package/esm/rules/core/when.d.mts.map +1 -0
  166. package/esm/rules/core/when.mjs +36 -0
  167. package/esm/rules/core/when.mjs.map +1 -0
  168. package/esm/rules/date/date-comparison-rules.d.mts +29 -0
  169. package/esm/rules/date/date-comparison-rules.d.mts.map +1 -0
  170. package/esm/rules/date/date-comparison-rules.mjs +78 -0
  171. package/esm/rules/date/date-comparison-rules.mjs.map +1 -0
  172. package/esm/rules/date/date-day-rules.d.mts +25 -0
  173. package/esm/rules/date/date-day-rules.d.mts.map +1 -0
  174. package/esm/rules/date/date-day-rules.mjs +61 -0
  175. package/esm/rules/date/date-day-rules.mjs.map +1 -0
  176. package/esm/rules/date/date-field-comparison-rules.d.mts +32 -0
  177. package/esm/rules/date/date-field-comparison-rules.d.mts.map +1 -0
  178. package/esm/rules/date/date-field-comparison-rules.mjs +81 -0
  179. package/esm/rules/date/date-field-comparison-rules.mjs.map +1 -0
  180. package/esm/rules/date/date-period-rules.d.mts +127 -0
  181. package/esm/rules/date/date-period-rules.d.mts.map +1 -0
  182. package/esm/rules/date/date-period-rules.mjs +398 -0
  183. package/esm/rules/date/date-period-rules.mjs.map +1 -0
  184. package/esm/rules/date/date-relative-rules.d.mts +24 -0
  185. package/esm/rules/date/date-relative-rules.d.mts.map +1 -0
  186. package/esm/rules/date/date-relative-rules.mjs +55 -0
  187. package/esm/rules/date/date-relative-rules.mjs.map +1 -0
  188. package/esm/rules/date/date-special-rules.d.mts +24 -0
  189. package/esm/rules/date/date-special-rules.d.mts.map +1 -0
  190. package/esm/rules/date/date-special-rules.mjs +58 -0
  191. package/esm/rules/date/date-special-rules.mjs.map +1 -0
  192. package/esm/rules/date/date.d.mts +97 -0
  193. package/esm/rules/date/date.d.mts.map +1 -0
  194. package/esm/rules/date/date.mjs +234 -0
  195. package/esm/rules/date/date.mjs.map +1 -0
  196. package/esm/rules/date/index.mjs +9 -0
  197. package/esm/rules/file/dimensions.d.mts +30 -0
  198. package/esm/rules/file/dimensions.d.mts.map +1 -0
  199. package/esm/rules/file/dimensions.mjs +56 -0
  200. package/esm/rules/file/dimensions.mjs.map +1 -0
  201. package/esm/rules/file/file-size.d.mts +18 -0
  202. package/esm/rules/file/file-size.d.mts.map +1 -0
  203. package/esm/rules/file/file-size.mjs +33 -0
  204. package/esm/rules/file/file-size.mjs.map +1 -0
  205. package/esm/rules/file/index.mjs +4 -0
  206. package/esm/rules/index.mjs +57 -0
  207. package/esm/rules/length/index.mjs +3 -0
  208. package/esm/rules/length/length-rules.d.mts +53 -0
  209. package/esm/rules/length/length-rules.d.mts.map +1 -0
  210. package/esm/rules/length/length-rules.mjs +98 -0
  211. package/esm/rules/length/length-rules.mjs.map +1 -0
  212. package/esm/rules/number/index.mjs +3 -0
  213. package/esm/rules/number/number-rules.d.mts +69 -0
  214. package/esm/rules/number/number-rules.d.mts.map +1 -0
  215. package/esm/rules/number/number-rules.mjs +196 -0
  216. package/esm/rules/number/number-rules.mjs.map +1 -0
  217. package/esm/rules/scalar/accepted-rule.mjs +116 -0
  218. package/esm/rules/scalar/accepted-rule.mjs.map +1 -0
  219. package/esm/rules/scalar/declined-rule.mjs +116 -0
  220. package/esm/rules/scalar/declined-rule.mjs.map +1 -0
  221. package/esm/rules/scalar/index.mjs +4 -0
  222. package/esm/rules/string/alpha.d.mts +18 -0
  223. package/esm/rules/string/alpha.d.mts.map +1 -0
  224. package/esm/rules/string/alpha.mjs +41 -0
  225. package/esm/rules/string/alpha.mjs.map +1 -0
  226. package/esm/rules/string/credit-card.d.mts +10 -0
  227. package/esm/rules/string/credit-card.d.mts.map +1 -0
  228. package/esm/rules/string/credit-card.mjs +32 -0
  229. package/esm/rules/string/credit-card.mjs.map +1 -0
  230. package/esm/rules/string/email.d.mts +10 -0
  231. package/esm/rules/string/email.d.mts.map +1 -0
  232. package/esm/rules/string/email.mjs +20 -0
  233. package/esm/rules/string/email.mjs.map +1 -0
  234. package/esm/rules/string/id-formats.d.mts +54 -0
  235. package/esm/rules/string/id-formats.d.mts.map +1 -0
  236. package/esm/rules/string/id-formats.mjs +104 -0
  237. package/esm/rules/string/id-formats.mjs.map +1 -0
  238. package/esm/rules/string/index.mjs +13 -0
  239. package/esm/rules/string/ip.d.mts +18 -0
  240. package/esm/rules/string/ip.d.mts.map +1 -0
  241. package/esm/rules/string/ip.mjs +42 -0
  242. package/esm/rules/string/ip.mjs.map +1 -0
  243. package/esm/rules/string/matches.d.mts +12 -0
  244. package/esm/rules/string/matches.d.mts.map +1 -0
  245. package/esm/rules/string/matches.mjs +21 -0
  246. package/esm/rules/string/matches.mjs.map +1 -0
  247. package/esm/rules/string/pattern.d.mts +12 -0
  248. package/esm/rules/string/pattern.d.mts.map +1 -0
  249. package/esm/rules/string/pattern.mjs +20 -0
  250. package/esm/rules/string/pattern.mjs.map +1 -0
  251. package/esm/rules/string/string-comparison.d.mts +30 -0
  252. package/esm/rules/string/string-comparison.d.mts.map +1 -0
  253. package/esm/rules/string/string-comparison.mjs +56 -0
  254. package/esm/rules/string/string-comparison.mjs.map +1 -0
  255. package/esm/rules/string/strong-password-rule.d.mts +18 -0
  256. package/esm/rules/string/strong-password-rule.d.mts.map +1 -0
  257. package/esm/rules/string/strong-password-rule.mjs +31 -0
  258. package/esm/rules/string/strong-password-rule.mjs.map +1 -0
  259. package/esm/rules/string/url.d.mts +10 -0
  260. package/esm/rules/string/url.d.mts.map +1 -0
  261. package/esm/rules/string/url.mjs +23 -0
  262. package/esm/rules/string/url.mjs.map +1 -0
  263. package/esm/rules/string/without-whitespace.d.mts +10 -0
  264. package/esm/rules/string/without-whitespace.d.mts.map +1 -0
  265. package/esm/rules/string/without-whitespace.mjs +19 -0
  266. package/esm/rules/string/without-whitespace.mjs.map +1 -0
  267. package/esm/standard-schema/json-schema.d.mts +65 -0
  268. package/esm/standard-schema/json-schema.d.mts.map +1 -0
  269. package/esm/standard-schema/json-schema.mjs +81 -0
  270. package/esm/standard-schema/json-schema.mjs.map +1 -0
  271. package/esm/standard-schema/map-result.d.mts +22 -0
  272. package/esm/standard-schema/map-result.d.mts.map +1 -0
  273. package/esm/standard-schema/map-result.mjs +26 -0
  274. package/esm/standard-schema/map-result.mjs.map +1 -0
  275. package/esm/standard-schema/types.d.mts +96 -0
  276. package/esm/standard-schema/types.d.mts.map +1 -0
  277. package/esm/types/conditional-types.d.mts +15 -0
  278. package/esm/types/conditional-types.d.mts.map +1 -0
  279. package/esm/types/context-types.d.mts +41 -0
  280. package/esm/types/context-types.d.mts.map +1 -0
  281. package/esm/types/data-transformer-types.d.mts +29 -0
  282. package/esm/types/data-transformer-types.d.mts.map +1 -0
  283. package/esm/types/date-types.d.mts +12 -0
  284. package/esm/types/date-types.d.mts.map +1 -0
  285. package/esm/types/date-types.mjs +17 -0
  286. package/esm/types/date-types.mjs.map +1 -0
  287. package/esm/types/file.types.d.mts +8 -0
  288. package/esm/types/file.types.d.mts.map +1 -0
  289. package/esm/types/inference-types.d.mts +178 -0
  290. package/esm/types/inference-types.d.mts.map +1 -0
  291. package/esm/types/mutator-types.d.mts +27 -0
  292. package/esm/types/mutator-types.d.mts.map +1 -0
  293. package/esm/types/result-types.d.mts +16 -0
  294. package/esm/types/result-types.d.mts.map +1 -0
  295. package/esm/types/rule-types.d.mts +52 -0
  296. package/esm/types/rule-types.d.mts.map +1 -0
  297. package/esm/types/schema-types.d.mts +10 -0
  298. package/esm/types/schema-types.d.mts.map +1 -0
  299. package/esm/validators/any-validator.d.mts +33 -0
  300. package/esm/validators/any-validator.d.mts.map +1 -0
  301. package/esm/validators/any-validator.mjs +35 -0
  302. package/esm/validators/any-validator.mjs.map +1 -0
  303. package/esm/validators/array-validator.d.mts +82 -0
  304. package/esm/validators/array-validator.d.mts.map +1 -0
  305. package/esm/validators/array-validator.mjs +176 -0
  306. package/esm/validators/array-validator.mjs.map +1 -0
  307. package/esm/validators/base-validator.d.mts +491 -0
  308. package/esm/validators/base-validator.d.mts.map +1 -0
  309. package/esm/validators/base-validator.mjs +656 -0
  310. package/esm/validators/base-validator.mjs.map +1 -0
  311. package/esm/validators/boolean-validator.d.mts +71 -0
  312. package/esm/validators/boolean-validator.d.mts.map +1 -0
  313. package/esm/validators/boolean-validator.mjs +126 -0
  314. package/esm/validators/boolean-validator.mjs.map +1 -0
  315. package/esm/validators/computed-validator.d.mts +80 -0
  316. package/esm/validators/computed-validator.d.mts.map +1 -0
  317. package/esm/validators/computed-validator.mjs +116 -0
  318. package/esm/validators/computed-validator.mjs.map +1 -0
  319. package/esm/validators/date-validator.d.mts +336 -0
  320. package/esm/validators/date-validator.d.mts.map +1 -0
  321. package/esm/validators/date-validator.mjs +637 -0
  322. package/esm/validators/date-validator.mjs.map +1 -0
  323. package/esm/validators/discriminated-union-validator.d.mts +67 -0
  324. package/esm/validators/discriminated-union-validator.d.mts.map +1 -0
  325. package/esm/validators/discriminated-union-validator.mjs +125 -0
  326. package/esm/validators/discriminated-union-validator.mjs.map +1 -0
  327. package/esm/validators/float-validator.d.mts +12 -0
  328. package/esm/validators/float-validator.d.mts.map +1 -0
  329. package/esm/validators/float-validator.mjs +18 -0
  330. package/esm/validators/float-validator.mjs.map +1 -0
  331. package/esm/validators/index.d.mts +22 -0
  332. package/esm/validators/index.mjs +28 -0
  333. package/esm/validators/instanceof-validator.d.mts +48 -0
  334. package/esm/validators/instanceof-validator.d.mts.map +1 -0
  335. package/esm/validators/instanceof-validator.mjs +63 -0
  336. package/esm/validators/instanceof-validator.mjs.map +1 -0
  337. package/esm/validators/int-validator.d.mts +23 -0
  338. package/esm/validators/int-validator.d.mts.map +1 -0
  339. package/esm/validators/int-validator.mjs +30 -0
  340. package/esm/validators/int-validator.mjs.map +1 -0
  341. package/esm/validators/lazy-validator.d.mts +70 -0
  342. package/esm/validators/lazy-validator.d.mts.map +1 -0
  343. package/esm/validators/lazy-validator.mjs +85 -0
  344. package/esm/validators/lazy-validator.mjs.map +1 -0
  345. package/esm/validators/literal-validator.d.mts +52 -0
  346. package/esm/validators/literal-validator.d.mts.map +1 -0
  347. package/esm/validators/literal-validator.mjs +67 -0
  348. package/esm/validators/literal-validator.mjs.map +1 -0
  349. package/esm/validators/managed-validator.d.mts +42 -0
  350. package/esm/validators/managed-validator.d.mts.map +1 -0
  351. package/esm/validators/managed-validator.mjs +39 -0
  352. package/esm/validators/managed-validator.mjs.map +1 -0
  353. package/esm/validators/methods/equality-conditional-methods.d.mts +90 -0
  354. package/esm/validators/methods/equality-conditional-methods.d.mts.map +1 -0
  355. package/esm/validators/methods/equality-conditional-methods.mjs +129 -0
  356. package/esm/validators/methods/equality-conditional-methods.mjs.map +1 -0
  357. package/esm/validators/methods/forbidden-methods.d.mts +58 -0
  358. package/esm/validators/methods/forbidden-methods.d.mts.map +1 -0
  359. package/esm/validators/methods/forbidden-methods.mjs +131 -0
  360. package/esm/validators/methods/forbidden-methods.mjs.map +1 -0
  361. package/esm/validators/methods/present-methods.d.mts +102 -0
  362. package/esm/validators/methods/present-methods.d.mts.map +1 -0
  363. package/esm/validators/methods/present-methods.mjs +235 -0
  364. package/esm/validators/methods/present-methods.mjs.map +1 -0
  365. package/esm/validators/methods/required-methods.d.mts +193 -0
  366. package/esm/validators/methods/required-methods.d.mts.map +1 -0
  367. package/esm/validators/methods/required-methods.mjs +347 -0
  368. package/esm/validators/methods/required-methods.mjs.map +1 -0
  369. package/esm/validators/number-validator.d.mts +170 -0
  370. package/esm/validators/number-validator.d.mts.map +1 -0
  371. package/esm/validators/number-validator.mjs +303 -0
  372. package/esm/validators/number-validator.mjs.map +1 -0
  373. package/esm/validators/numeric-validator.d.mts +19 -0
  374. package/esm/validators/numeric-validator.d.mts.map +1 -0
  375. package/esm/validators/numeric-validator.mjs +27 -0
  376. package/esm/validators/numeric-validator.mjs.map +1 -0
  377. package/esm/validators/object-validator.d.mts +253 -0
  378. package/esm/validators/object-validator.d.mts.map +1 -0
  379. package/esm/validators/object-validator.mjs +440 -0
  380. package/esm/validators/object-validator.mjs.map +1 -0
  381. package/esm/validators/primitive-validator.d.mts +74 -0
  382. package/esm/validators/primitive-validator.d.mts.map +1 -0
  383. package/esm/validators/primitive-validator.mjs +89 -0
  384. package/esm/validators/primitive-validator.mjs.map +1 -0
  385. package/esm/validators/record-validator.d.mts +63 -0
  386. package/esm/validators/record-validator.d.mts.map +1 -0
  387. package/esm/validators/record-validator.mjs +111 -0
  388. package/esm/validators/record-validator.mjs.map +1 -0
  389. package/esm/validators/scalar-validator.d.mts +97 -0
  390. package/esm/validators/scalar-validator.d.mts.map +1 -0
  391. package/esm/validators/scalar-validator.mjs +172 -0
  392. package/esm/validators/scalar-validator.mjs.map +1 -0
  393. package/esm/validators/string-validator.d.mts +224 -0
  394. package/esm/validators/string-validator.d.mts.map +1 -0
  395. package/esm/validators/string-validator.mjs +443 -0
  396. package/esm/validators/string-validator.mjs.map +1 -0
  397. package/esm/validators/tuple-validator.d.mts +66 -0
  398. package/esm/validators/tuple-validator.d.mts.map +1 -0
  399. package/esm/validators/tuple-validator.mjs +133 -0
  400. package/esm/validators/tuple-validator.mjs.map +1 -0
  401. package/esm/validators/union-validator.d.mts +59 -0
  402. package/esm/validators/union-validator.d.mts.map +1 -0
  403. package/esm/validators/union-validator.mjs +66 -0
  404. package/esm/validators/union-validator.mjs.map +1 -0
  405. package/llms-full.txt +2175 -0
  406. package/llms.txt +17 -0
  407. package/package.json +37 -48
  408. package/skills/bridge-standard-schema/SKILL.md +138 -0
  409. package/skills/compose-seal-modifiers/SKILL.md +271 -0
  410. package/skills/define-structural-shape/SKILL.md +138 -0
  411. package/skills/define-structural-shape/array-methods.md +78 -0
  412. package/skills/define-structural-shape/object-methods.md +166 -0
  413. package/skills/extend-seal-with-plugins/SKILL.md +178 -0
  414. package/skills/generate-json-schema/SKILL.md +143 -0
  415. package/skills/handle-seal-errors/SKILL.md +148 -0
  416. package/skills/overview/SKILL.md +72 -0
  417. package/skills/pick-seal-primitive/SKILL.md +133 -0
  418. package/skills/pick-seal-primitive/boolean-methods.md +71 -0
  419. package/skills/pick-seal-primitive/date-methods.md +175 -0
  420. package/skills/pick-seal-primitive/number-methods.md +123 -0
  421. package/skills/pick-seal-primitive/string-methods.md +169 -0
  422. package/skills/seal-basics/SKILL.md +106 -0
  423. package/cjs/config.d.ts +0 -48
  424. package/cjs/config.d.ts.map +0 -1
  425. package/cjs/config.js +0 -42
  426. package/cjs/config.js.map +0 -1
  427. package/cjs/factory/index.d.ts +0 -3
  428. package/cjs/factory/index.d.ts.map +0 -1
  429. package/cjs/factory/validate.d.ts +0 -8
  430. package/cjs/factory/validate.d.ts.map +0 -1
  431. package/cjs/factory/validate.js +0 -23
  432. package/cjs/factory/validate.js.map +0 -1
  433. package/cjs/factory/validators.d.ts +0 -56
  434. package/cjs/factory/validators.d.ts.map +0 -1
  435. package/cjs/factory/validators.js +0 -47
  436. package/cjs/factory/validators.js.map +0 -1
  437. package/cjs/helpers/date-helpers.d.ts +0 -16
  438. package/cjs/helpers/date-helpers.d.ts.map +0 -1
  439. package/cjs/helpers/date-helpers.js +0 -20
  440. package/cjs/helpers/date-helpers.js.map +0 -1
  441. package/cjs/helpers/file.utils.d.ts +0 -8
  442. package/cjs/helpers/file.utils.d.ts.map +0 -1
  443. package/cjs/helpers/file.utils.js +0 -29
  444. package/cjs/helpers/file.utils.js.map +0 -1
  445. package/cjs/helpers/get-field-value.d.ts +0 -37
  446. package/cjs/helpers/get-field-value.d.ts.map +0 -1
  447. package/cjs/helpers/get-field-value.js +0 -40
  448. package/cjs/helpers/get-field-value.js.map +0 -1
  449. package/cjs/helpers/index.d.ts +0 -6
  450. package/cjs/helpers/index.d.ts.map +0 -1
  451. package/cjs/helpers/is-empty-value.d.ts +0 -2
  452. package/cjs/helpers/is-empty-value.d.ts.map +0 -1
  453. package/cjs/helpers/is-empty-value.js +0 -3
  454. package/cjs/helpers/is-empty-value.js.map +0 -1
  455. package/cjs/helpers/path-helpers.d.ts +0 -5
  456. package/cjs/helpers/path-helpers.d.ts.map +0 -1
  457. package/cjs/helpers/path-helpers.js +0 -8
  458. package/cjs/helpers/path-helpers.js.map +0 -1
  459. package/cjs/helpers/validation-helpers.d.ts +0 -26
  460. package/cjs/helpers/validation-helpers.d.ts.map +0 -1
  461. package/cjs/helpers/validation-helpers.js +0 -74
  462. package/cjs/helpers/validation-helpers.js.map +0 -1
  463. package/cjs/index.d.ts +0 -30
  464. package/cjs/index.d.ts.map +0 -1
  465. package/cjs/index.js +0 -1
  466. package/cjs/index.js.map +0 -1
  467. package/cjs/mutators/array-mutators.d.ts +0 -12
  468. package/cjs/mutators/array-mutators.d.ts.map +0 -1
  469. package/cjs/mutators/array-mutators.js +0 -37
  470. package/cjs/mutators/array-mutators.js.map +0 -1
  471. package/cjs/mutators/date-mutators.d.ts +0 -39
  472. package/cjs/mutators/date-mutators.d.ts.map +0 -1
  473. package/cjs/mutators/date-mutators.js +0 -120
  474. package/cjs/mutators/date-mutators.js.map +0 -1
  475. package/cjs/mutators/index.d.ts +0 -7
  476. package/cjs/mutators/index.d.ts.map +0 -1
  477. package/cjs/mutators/number-mutators.d.ts +0 -22
  478. package/cjs/mutators/number-mutators.d.ts.map +0 -1
  479. package/cjs/mutators/number-mutators.js +0 -53
  480. package/cjs/mutators/number-mutators.js.map +0 -1
  481. package/cjs/mutators/object-mutators.d.ts +0 -8
  482. package/cjs/mutators/object-mutators.d.ts.map +0 -1
  483. package/cjs/mutators/object-mutators.js +0 -48
  484. package/cjs/mutators/object-mutators.js.map +0 -1
  485. package/cjs/mutators/scalar-mutators.d.ts +0 -3
  486. package/cjs/mutators/scalar-mutators.d.ts.map +0 -1
  487. package/cjs/mutators/scalar-mutators.js +0 -6
  488. package/cjs/mutators/scalar-mutators.js.map +0 -1
  489. package/cjs/mutators/string-mutators.d.ts +0 -72
  490. package/cjs/mutators/string-mutators.d.ts.map +0 -1
  491. package/cjs/mutators/string-mutators.js +0 -193
  492. package/cjs/mutators/string-mutators.js.map +0 -1
  493. package/cjs/plugins/index.d.ts +0 -7
  494. package/cjs/plugins/index.d.ts.map +0 -1
  495. package/cjs/plugins/plugin-system.d.ts +0 -71
  496. package/cjs/plugins/plugin-system.d.ts.map +0 -1
  497. package/cjs/plugins/plugin-system.js +0 -67
  498. package/cjs/plugins/plugin-system.js.map +0 -1
  499. package/cjs/rules/array/array-rules.d.ts +0 -12
  500. package/cjs/rules/array/array-rules.d.ts.map +0 -1
  501. package/cjs/rules/array/array-rules.js +0 -45
  502. package/cjs/rules/array/array-rules.js.map +0 -1
  503. package/cjs/rules/array/index.d.ts +0 -2
  504. package/cjs/rules/array/index.d.ts.map +0 -1
  505. package/cjs/rules/color/color-rules.d.ts +0 -30
  506. package/cjs/rules/color/color-rules.d.ts.map +0 -1
  507. package/cjs/rules/color/color-rules.js +0 -120
  508. package/cjs/rules/color/color-rules.js.map +0 -1
  509. package/cjs/rules/color/index.d.ts +0 -2
  510. package/cjs/rules/color/index.d.ts.map +0 -1
  511. package/cjs/rules/common/enum.d.ts +0 -26
  512. package/cjs/rules/common/enum.d.ts.map +0 -1
  513. package/cjs/rules/common/enum.js +0 -69
  514. package/cjs/rules/common/enum.js.map +0 -1
  515. package/cjs/rules/common/equals-field-rules.d.ts +0 -18
  516. package/cjs/rules/common/equals-field-rules.d.ts.map +0 -1
  517. package/cjs/rules/common/equals-field-rules.js +0 -39
  518. package/cjs/rules/common/equals-field-rules.js.map +0 -1
  519. package/cjs/rules/common/index.d.ts +0 -5
  520. package/cjs/rules/common/index.d.ts.map +0 -1
  521. package/cjs/rules/common/type-rules.d.ts +0 -38
  522. package/cjs/rules/common/type-rules.d.ts.map +0 -1
  523. package/cjs/rules/common/type-rules.js +0 -117
  524. package/cjs/rules/common/type-rules.js.map +0 -1
  525. package/cjs/rules/common/unknown-key.d.ts +0 -9
  526. package/cjs/rules/common/unknown-key.d.ts.map +0 -1
  527. package/cjs/rules/common/unknown-key.js +0 -17
  528. package/cjs/rules/common/unknown-key.js.map +0 -1
  529. package/cjs/rules/conditional/forbidden-if-rules.d.ts +0 -54
  530. package/cjs/rules/conditional/forbidden-if-rules.d.ts.map +0 -1
  531. package/cjs/rules/conditional/forbidden-if-rules.js +0 -118
  532. package/cjs/rules/conditional/forbidden-if-rules.js.map +0 -1
  533. package/cjs/rules/conditional/index.d.ts +0 -11
  534. package/cjs/rules/conditional/index.d.ts.map +0 -1
  535. package/cjs/rules/conditional/present-if-rules.d.ts +0 -45
  536. package/cjs/rules/conditional/present-if-rules.d.ts.map +0 -1
  537. package/cjs/rules/conditional/present-if-rules.js +0 -100
  538. package/cjs/rules/conditional/present-if-rules.js.map +0 -1
  539. package/cjs/rules/conditional/present-unless-rules.d.ts +0 -11
  540. package/cjs/rules/conditional/present-unless-rules.d.ts.map +0 -1
  541. package/cjs/rules/conditional/present-unless-rules.js +0 -22
  542. package/cjs/rules/conditional/present-unless-rules.js.map +0 -1
  543. package/cjs/rules/conditional/present-with-rules.d.ts +0 -26
  544. package/cjs/rules/conditional/present-with-rules.d.ts.map +0 -1
  545. package/cjs/rules/conditional/present-with-rules.js +0 -70
  546. package/cjs/rules/conditional/present-with-rules.js.map +0 -1
  547. package/cjs/rules/conditional/present-without-rules.d.ts +0 -26
  548. package/cjs/rules/conditional/present-without-rules.d.ts.map +0 -1
  549. package/cjs/rules/conditional/present-without-rules.js +0 -70
  550. package/cjs/rules/conditional/present-without-rules.js.map +0 -1
  551. package/cjs/rules/conditional/required-if-rules.d.ts +0 -77
  552. package/cjs/rules/conditional/required-if-rules.d.ts.map +0 -1
  553. package/cjs/rules/conditional/required-if-rules.js +0 -205
  554. package/cjs/rules/conditional/required-if-rules.js.map +0 -1
  555. package/cjs/rules/conditional/required-unless-rules.d.ts +0 -11
  556. package/cjs/rules/conditional/required-unless-rules.d.ts.map +0 -1
  557. package/cjs/rules/conditional/required-unless-rules.js +0 -22
  558. package/cjs/rules/conditional/required-unless-rules.js.map +0 -1
  559. package/cjs/rules/conditional/required-when-rule.d.ts +0 -18
  560. package/cjs/rules/conditional/required-when-rule.d.ts.map +0 -1
  561. package/cjs/rules/conditional/required-when-rule.js +0 -26
  562. package/cjs/rules/conditional/required-when-rule.js.map +0 -1
  563. package/cjs/rules/conditional/required-with-rules.d.ts +0 -26
  564. package/cjs/rules/conditional/required-with-rules.d.ts.map +0 -1
  565. package/cjs/rules/conditional/required-with-rules.js +0 -64
  566. package/cjs/rules/conditional/required-with-rules.js.map +0 -1
  567. package/cjs/rules/conditional/required-without-rules.d.ts +0 -26
  568. package/cjs/rules/conditional/required-without-rules.d.ts.map +0 -1
  569. package/cjs/rules/conditional/required-without-rules.js +0 -64
  570. package/cjs/rules/conditional/required-without-rules.js.map +0 -1
  571. package/cjs/rules/core/equal.d.ts +0 -8
  572. package/cjs/rules/core/equal.d.ts.map +0 -1
  573. package/cjs/rules/core/equal.js +0 -14
  574. package/cjs/rules/core/equal.js.map +0 -1
  575. package/cjs/rules/core/forbidden.d.ts +0 -6
  576. package/cjs/rules/core/forbidden.d.ts.map +0 -1
  577. package/cjs/rules/core/forbidden.js +0 -13
  578. package/cjs/rules/core/forbidden.js.map +0 -1
  579. package/cjs/rules/core/index.d.ts +0 -6
  580. package/cjs/rules/core/index.d.ts.map +0 -1
  581. package/cjs/rules/core/required.d.ts +0 -11
  582. package/cjs/rules/core/required.d.ts.map +0 -1
  583. package/cjs/rules/core/required.js +0 -31
  584. package/cjs/rules/core/required.js.map +0 -1
  585. package/cjs/rules/core/union.d.ts +0 -9
  586. package/cjs/rules/core/union.d.ts.map +0 -1
  587. package/cjs/rules/core/union.js +0 -40
  588. package/cjs/rules/core/union.js.map +0 -1
  589. package/cjs/rules/core/when.d.ts +0 -6
  590. package/cjs/rules/core/when.d.ts.map +0 -1
  591. package/cjs/rules/core/when.js +0 -40
  592. package/cjs/rules/core/when.js.map +0 -1
  593. package/cjs/rules/date/date-comparison-rules.d.ts +0 -25
  594. package/cjs/rules/date/date-comparison-rules.d.ts.map +0 -1
  595. package/cjs/rules/date/date-comparison-rules.js +0 -80
  596. package/cjs/rules/date/date-comparison-rules.js.map +0 -1
  597. package/cjs/rules/date/date-day-rules.d.ts +0 -21
  598. package/cjs/rules/date/date-day-rules.d.ts.map +0 -1
  599. package/cjs/rules/date/date-day-rules.js +0 -68
  600. package/cjs/rules/date/date-day-rules.js.map +0 -1
  601. package/cjs/rules/date/date-field-comparison-rules.d.ts +0 -28
  602. package/cjs/rules/date/date-field-comparison-rules.d.ts.map +0 -1
  603. package/cjs/rules/date/date-field-comparison-rules.js +0 -94
  604. package/cjs/rules/date/date-field-comparison-rules.js.map +0 -1
  605. package/cjs/rules/date/date-period-rules.d.ts +0 -124
  606. package/cjs/rules/date/date-period-rules.d.ts.map +0 -1
  607. package/cjs/rules/date/date-period-rules.js +0 -605
  608. package/cjs/rules/date/date-period-rules.js.map +0 -1
  609. package/cjs/rules/date/date-relative-rules.d.ts +0 -20
  610. package/cjs/rules/date/date-relative-rules.d.ts.map +0 -1
  611. package/cjs/rules/date/date-relative-rules.js +0 -60
  612. package/cjs/rules/date/date-relative-rules.js.map +0 -1
  613. package/cjs/rules/date/date-special-rules.d.ts +0 -20
  614. package/cjs/rules/date/date-special-rules.d.ts.map +0 -1
  615. package/cjs/rules/date/date-special-rules.js +0 -71
  616. package/cjs/rules/date/date-special-rules.js.map +0 -1
  617. package/cjs/rules/date/date.d.ts +0 -93
  618. package/cjs/rules/date/date.d.ts.map +0 -1
  619. package/cjs/rules/date/date.js +0 -288
  620. package/cjs/rules/date/date.js.map +0 -1
  621. package/cjs/rules/date/index.d.ts +0 -8
  622. package/cjs/rules/date/index.d.ts.map +0 -1
  623. package/cjs/rules/file/dimensions.d.ts +0 -26
  624. package/cjs/rules/file/dimensions.d.ts.map +0 -1
  625. package/cjs/rules/file/dimensions.js +0 -60
  626. package/cjs/rules/file/dimensions.js.map +0 -1
  627. package/cjs/rules/file/file-size.d.ts +0 -14
  628. package/cjs/rules/file/file-size.d.ts.map +0 -1
  629. package/cjs/rules/file/file-size.js +0 -30
  630. package/cjs/rules/file/file-size.js.map +0 -1
  631. package/cjs/rules/file/index.d.ts +0 -11
  632. package/cjs/rules/file/index.d.ts.map +0 -1
  633. package/cjs/rules/index.d.ts +0 -19
  634. package/cjs/rules/index.d.ts.map +0 -1
  635. package/cjs/rules/length/index.d.ts +0 -2
  636. package/cjs/rules/length/index.d.ts.map +0 -1
  637. package/cjs/rules/length/length-rules.d.ts +0 -49
  638. package/cjs/rules/length/length-rules.d.ts.map +0 -1
  639. package/cjs/rules/length/length-rules.js +0 -107
  640. package/cjs/rules/length/length-rules.js.map +0 -1
  641. package/cjs/rules/number/index.d.ts +0 -2
  642. package/cjs/rules/number/index.d.ts.map +0 -1
  643. package/cjs/rules/number/number-rules.d.ts +0 -65
  644. package/cjs/rules/number/number-rules.d.ts.map +0 -1
  645. package/cjs/rules/number/number-rules.js +0 -245
  646. package/cjs/rules/number/number-rules.js.map +0 -1
  647. package/cjs/rules/scalar/accepted-rule.d.ts +0 -39
  648. package/cjs/rules/scalar/accepted-rule.d.ts.map +0 -1
  649. package/cjs/rules/scalar/accepted-rule.js +0 -117
  650. package/cjs/rules/scalar/accepted-rule.js.map +0 -1
  651. package/cjs/rules/scalar/declined-rule.d.ts +0 -39
  652. package/cjs/rules/scalar/declined-rule.d.ts.map +0 -1
  653. package/cjs/rules/scalar/declined-rule.js +0 -117
  654. package/cjs/rules/scalar/declined-rule.js.map +0 -1
  655. package/cjs/rules/scalar/index.d.ts +0 -3
  656. package/cjs/rules/scalar/index.d.ts.map +0 -1
  657. package/cjs/rules/string/alpha.d.ts +0 -14
  658. package/cjs/rules/string/alpha.d.ts.map +0 -1
  659. package/cjs/rules/string/alpha.js +0 -39
  660. package/cjs/rules/string/alpha.js.map +0 -1
  661. package/cjs/rules/string/credit-card.d.ts +0 -6
  662. package/cjs/rules/string/credit-card.d.ts.map +0 -1
  663. package/cjs/rules/string/credit-card.js +0 -31
  664. package/cjs/rules/string/credit-card.js.map +0 -1
  665. package/cjs/rules/string/email.d.ts +0 -6
  666. package/cjs/rules/string/email.d.ts.map +0 -1
  667. package/cjs/rules/string/email.js +0 -13
  668. package/cjs/rules/string/email.js.map +0 -1
  669. package/cjs/rules/string/index.d.ts +0 -17
  670. package/cjs/rules/string/index.d.ts.map +0 -1
  671. package/cjs/rules/string/ip.d.ts +0 -14
  672. package/cjs/rules/string/ip.d.ts.map +0 -1
  673. package/cjs/rules/string/ip.js +0 -39
  674. package/cjs/rules/string/ip.js.map +0 -1
  675. package/cjs/rules/string/matches.d.ts +0 -8
  676. package/cjs/rules/string/matches.d.ts.map +0 -1
  677. package/cjs/rules/string/matches.js +0 -15
  678. package/cjs/rules/string/matches.js.map +0 -1
  679. package/cjs/rules/string/pattern.d.ts +0 -8
  680. package/cjs/rules/string/pattern.d.ts.map +0 -1
  681. package/cjs/rules/string/pattern.js +0 -14
  682. package/cjs/rules/string/pattern.js.map +0 -1
  683. package/cjs/rules/string/string-comparison.d.ts +0 -26
  684. package/cjs/rules/string/string-comparison.d.ts.map +0 -1
  685. package/cjs/rules/string/string-comparison.js +0 -56
  686. package/cjs/rules/string/string-comparison.js.map +0 -1
  687. package/cjs/rules/string/strong-password-rule.d.ts +0 -14
  688. package/cjs/rules/string/strong-password-rule.d.ts.map +0 -1
  689. package/cjs/rules/string/strong-password-rule.js +0 -38
  690. package/cjs/rules/string/strong-password-rule.js.map +0 -1
  691. package/cjs/rules/string/url.d.ts +0 -6
  692. package/cjs/rules/string/url.d.ts.map +0 -1
  693. package/cjs/rules/string/url.js +0 -16
  694. package/cjs/rules/string/url.js.map +0 -1
  695. package/cjs/rules/string/without-whitespace.d.ts +0 -6
  696. package/cjs/rules/string/without-whitespace.d.ts.map +0 -1
  697. package/cjs/rules/string/without-whitespace.js +0 -13
  698. package/cjs/rules/string/without-whitespace.js.map +0 -1
  699. package/cjs/standard-schema/index.d.ts +0 -4
  700. package/cjs/standard-schema/index.d.ts.map +0 -1
  701. package/cjs/standard-schema/json-schema.d.ts +0 -61
  702. package/cjs/standard-schema/json-schema.d.ts.map +0 -1
  703. package/cjs/standard-schema/json-schema.js +0 -85
  704. package/cjs/standard-schema/json-schema.js.map +0 -1
  705. package/cjs/standard-schema/map-result.d.ts +0 -18
  706. package/cjs/standard-schema/map-result.d.ts.map +0 -1
  707. package/cjs/standard-schema/map-result.js +0 -27
  708. package/cjs/standard-schema/map-result.js.map +0 -1
  709. package/cjs/standard-schema/types.d.ts +0 -93
  710. package/cjs/standard-schema/types.d.ts.map +0 -1
  711. package/cjs/types/conditional-types.d.ts +0 -15
  712. package/cjs/types/conditional-types.d.ts.map +0 -1
  713. package/cjs/types/context-types.d.ts +0 -47
  714. package/cjs/types/context-types.d.ts.map +0 -1
  715. package/cjs/types/data-transformer-types.d.ts +0 -25
  716. package/cjs/types/data-transformer-types.d.ts.map +0 -1
  717. package/cjs/types/date-types.d.ts +0 -9
  718. package/cjs/types/date-types.d.ts.map +0 -1
  719. package/cjs/types/date-types.js +0 -12
  720. package/cjs/types/date-types.js.map +0 -1
  721. package/cjs/types/file.types.d.ts +0 -5
  722. package/cjs/types/file.types.d.ts.map +0 -1
  723. package/cjs/types/index.d.ts +0 -11
  724. package/cjs/types/index.d.ts.map +0 -1
  725. package/cjs/types/inference-types.d.ts +0 -32
  726. package/cjs/types/inference-types.d.ts.map +0 -1
  727. package/cjs/types/mutator-types.d.ts +0 -27
  728. package/cjs/types/mutator-types.d.ts.map +0 -1
  729. package/cjs/types/result-types.d.ts +0 -19
  730. package/cjs/types/result-types.d.ts.map +0 -1
  731. package/cjs/types/rule-types.d.ts +0 -58
  732. package/cjs/types/rule-types.d.ts.map +0 -1
  733. package/cjs/types/schema-types.d.ts +0 -6
  734. package/cjs/types/schema-types.d.ts.map +0 -1
  735. package/cjs/validators/any-validator.d.ts +0 -29
  736. package/cjs/validators/any-validator.d.ts.map +0 -1
  737. package/cjs/validators/any-validator.js +0 -31
  738. package/cjs/validators/any-validator.js.map +0 -1
  739. package/cjs/validators/array-validator.d.ts +0 -72
  740. package/cjs/validators/array-validator.d.ts.map +0 -1
  741. package/cjs/validators/array-validator.js +0 -162
  742. package/cjs/validators/array-validator.js.map +0 -1
  743. package/cjs/validators/base-validator.d.ts +0 -425
  744. package/cjs/validators/base-validator.d.ts.map +0 -1
  745. package/cjs/validators/base-validator.js +0 -637
  746. package/cjs/validators/base-validator.js.map +0 -1
  747. package/cjs/validators/boolean-validator.d.ts +0 -67
  748. package/cjs/validators/boolean-validator.d.ts.map +0 -1
  749. package/cjs/validators/boolean-validator.js +0 -105
  750. package/cjs/validators/boolean-validator.js.map +0 -1
  751. package/cjs/validators/computed-validator.d.ts +0 -75
  752. package/cjs/validators/computed-validator.d.ts.map +0 -1
  753. package/cjs/validators/computed-validator.js +0 -124
  754. package/cjs/validators/computed-validator.js.map +0 -1
  755. package/cjs/validators/date-validator.d.ts +0 -330
  756. package/cjs/validators/date-validator.d.ts.map +0 -1
  757. package/cjs/validators/date-validator.js +0 -614
  758. package/cjs/validators/date-validator.js.map +0 -1
  759. package/cjs/validators/float-validator.d.ts +0 -8
  760. package/cjs/validators/float-validator.d.ts.map +0 -1
  761. package/cjs/validators/float-validator.js +0 -9
  762. package/cjs/validators/float-validator.js.map +0 -1
  763. package/cjs/validators/index.d.ts +0 -31
  764. package/cjs/validators/index.d.ts.map +0 -1
  765. package/cjs/validators/int-validator.d.ts +0 -19
  766. package/cjs/validators/int-validator.d.ts.map +0 -1
  767. package/cjs/validators/int-validator.js +0 -21
  768. package/cjs/validators/int-validator.js.map +0 -1
  769. package/cjs/validators/managed-validator.d.ts +0 -38
  770. package/cjs/validators/managed-validator.d.ts.map +0 -1
  771. package/cjs/validators/managed-validator.js +0 -34
  772. package/cjs/validators/managed-validator.js.map +0 -1
  773. package/cjs/validators/methods/equality-conditional-methods.d.ts +0 -88
  774. package/cjs/validators/methods/equality-conditional-methods.d.ts.map +0 -1
  775. package/cjs/validators/methods/equality-conditional-methods.js +0 -118
  776. package/cjs/validators/methods/equality-conditional-methods.js.map +0 -1
  777. package/cjs/validators/methods/forbidden-methods.d.ts +0 -58
  778. package/cjs/validators/methods/forbidden-methods.d.ts.map +0 -1
  779. package/cjs/validators/methods/forbidden-methods.js +0 -122
  780. package/cjs/validators/methods/forbidden-methods.js.map +0 -1
  781. package/cjs/validators/methods/present-methods.d.ts +0 -102
  782. package/cjs/validators/methods/present-methods.d.ts.map +0 -1
  783. package/cjs/validators/methods/present-methods.js +0 -229
  784. package/cjs/validators/methods/present-methods.js.map +0 -1
  785. package/cjs/validators/methods/required-methods.d.ts +0 -174
  786. package/cjs/validators/methods/required-methods.d.ts.map +0 -1
  787. package/cjs/validators/methods/required-methods.js +0 -246
  788. package/cjs/validators/methods/required-methods.js.map +0 -1
  789. package/cjs/validators/number-validator.d.ts +0 -166
  790. package/cjs/validators/number-validator.d.ts.map +0 -1
  791. package/cjs/validators/number-validator.js +0 -307
  792. package/cjs/validators/number-validator.js.map +0 -1
  793. package/cjs/validators/numeric-validator.d.ts +0 -15
  794. package/cjs/validators/numeric-validator.d.ts.map +0 -1
  795. package/cjs/validators/numeric-validator.js +0 -18
  796. package/cjs/validators/numeric-validator.js.map +0 -1
  797. package/cjs/validators/object-validator.d.ts +0 -233
  798. package/cjs/validators/object-validator.d.ts.map +0 -1
  799. package/cjs/validators/object-validator.js +0 -517
  800. package/cjs/validators/object-validator.js.map +0 -1
  801. package/cjs/validators/primitive-validator.d.ts +0 -70
  802. package/cjs/validators/primitive-validator.d.ts.map +0 -1
  803. package/cjs/validators/primitive-validator.js +0 -80
  804. package/cjs/validators/primitive-validator.js.map +0 -1
  805. package/cjs/validators/record-validator.d.ts +0 -54
  806. package/cjs/validators/record-validator.d.ts.map +0 -1
  807. package/cjs/validators/record-validator.js +0 -100
  808. package/cjs/validators/record-validator.js.map +0 -1
  809. package/cjs/validators/scalar-validator.d.ts +0 -93
  810. package/cjs/validators/scalar-validator.d.ts.map +0 -1
  811. package/cjs/validators/scalar-validator.js +0 -149
  812. package/cjs/validators/scalar-validator.js.map +0 -1
  813. package/cjs/validators/string-validator.d.ts +0 -189
  814. package/cjs/validators/string-validator.d.ts.map +0 -1
  815. package/cjs/validators/string-validator.js +0 -387
  816. package/cjs/validators/string-validator.js.map +0 -1
  817. package/cjs/validators/tuple-validator.d.ts +0 -56
  818. package/cjs/validators/tuple-validator.d.ts.map +0 -1
  819. package/cjs/validators/tuple-validator.js +0 -121
  820. package/cjs/validators/tuple-validator.js.map +0 -1
  821. package/cjs/validators/union-validator.d.ts +0 -55
  822. package/cjs/validators/union-validator.d.ts.map +0 -1
  823. package/cjs/validators/union-validator.js +0 -60
  824. package/cjs/validators/union-validator.js.map +0 -1
  825. package/esm/config.d.ts +0 -48
  826. package/esm/config.d.ts.map +0 -1
  827. package/esm/config.js +0 -42
  828. package/esm/config.js.map +0 -1
  829. package/esm/factory/index.d.ts +0 -3
  830. package/esm/factory/index.d.ts.map +0 -1
  831. package/esm/factory/validate.d.ts +0 -8
  832. package/esm/factory/validate.d.ts.map +0 -1
  833. package/esm/factory/validate.js +0 -23
  834. package/esm/factory/validate.js.map +0 -1
  835. package/esm/factory/validators.d.ts +0 -56
  836. package/esm/factory/validators.d.ts.map +0 -1
  837. package/esm/factory/validators.js +0 -47
  838. package/esm/factory/validators.js.map +0 -1
  839. package/esm/helpers/date-helpers.d.ts +0 -16
  840. package/esm/helpers/date-helpers.d.ts.map +0 -1
  841. package/esm/helpers/date-helpers.js +0 -20
  842. package/esm/helpers/date-helpers.js.map +0 -1
  843. package/esm/helpers/file.utils.d.ts +0 -8
  844. package/esm/helpers/file.utils.d.ts.map +0 -1
  845. package/esm/helpers/file.utils.js +0 -29
  846. package/esm/helpers/file.utils.js.map +0 -1
  847. package/esm/helpers/get-field-value.d.ts +0 -37
  848. package/esm/helpers/get-field-value.d.ts.map +0 -1
  849. package/esm/helpers/get-field-value.js +0 -40
  850. package/esm/helpers/get-field-value.js.map +0 -1
  851. package/esm/helpers/index.d.ts +0 -6
  852. package/esm/helpers/index.d.ts.map +0 -1
  853. package/esm/helpers/is-empty-value.d.ts +0 -2
  854. package/esm/helpers/is-empty-value.d.ts.map +0 -1
  855. package/esm/helpers/is-empty-value.js +0 -3
  856. package/esm/helpers/is-empty-value.js.map +0 -1
  857. package/esm/helpers/path-helpers.d.ts +0 -5
  858. package/esm/helpers/path-helpers.d.ts.map +0 -1
  859. package/esm/helpers/path-helpers.js +0 -8
  860. package/esm/helpers/path-helpers.js.map +0 -1
  861. package/esm/helpers/validation-helpers.d.ts +0 -26
  862. package/esm/helpers/validation-helpers.d.ts.map +0 -1
  863. package/esm/helpers/validation-helpers.js +0 -74
  864. package/esm/helpers/validation-helpers.js.map +0 -1
  865. package/esm/index.d.ts +0 -30
  866. package/esm/index.d.ts.map +0 -1
  867. package/esm/index.js +0 -1
  868. package/esm/index.js.map +0 -1
  869. package/esm/mutators/array-mutators.d.ts +0 -12
  870. package/esm/mutators/array-mutators.d.ts.map +0 -1
  871. package/esm/mutators/array-mutators.js +0 -37
  872. package/esm/mutators/array-mutators.js.map +0 -1
  873. package/esm/mutators/date-mutators.d.ts +0 -39
  874. package/esm/mutators/date-mutators.d.ts.map +0 -1
  875. package/esm/mutators/date-mutators.js +0 -120
  876. package/esm/mutators/date-mutators.js.map +0 -1
  877. package/esm/mutators/index.d.ts +0 -7
  878. package/esm/mutators/index.d.ts.map +0 -1
  879. package/esm/mutators/number-mutators.d.ts +0 -22
  880. package/esm/mutators/number-mutators.d.ts.map +0 -1
  881. package/esm/mutators/number-mutators.js +0 -53
  882. package/esm/mutators/number-mutators.js.map +0 -1
  883. package/esm/mutators/object-mutators.d.ts +0 -8
  884. package/esm/mutators/object-mutators.d.ts.map +0 -1
  885. package/esm/mutators/object-mutators.js +0 -48
  886. package/esm/mutators/object-mutators.js.map +0 -1
  887. package/esm/mutators/scalar-mutators.d.ts +0 -3
  888. package/esm/mutators/scalar-mutators.d.ts.map +0 -1
  889. package/esm/mutators/scalar-mutators.js +0 -6
  890. package/esm/mutators/scalar-mutators.js.map +0 -1
  891. package/esm/mutators/string-mutators.d.ts +0 -72
  892. package/esm/mutators/string-mutators.d.ts.map +0 -1
  893. package/esm/mutators/string-mutators.js +0 -193
  894. package/esm/mutators/string-mutators.js.map +0 -1
  895. package/esm/plugins/index.d.ts +0 -7
  896. package/esm/plugins/index.d.ts.map +0 -1
  897. package/esm/plugins/plugin-system.d.ts +0 -71
  898. package/esm/plugins/plugin-system.d.ts.map +0 -1
  899. package/esm/plugins/plugin-system.js +0 -67
  900. package/esm/plugins/plugin-system.js.map +0 -1
  901. package/esm/rules/array/array-rules.d.ts +0 -12
  902. package/esm/rules/array/array-rules.d.ts.map +0 -1
  903. package/esm/rules/array/array-rules.js +0 -45
  904. package/esm/rules/array/array-rules.js.map +0 -1
  905. package/esm/rules/array/index.d.ts +0 -2
  906. package/esm/rules/array/index.d.ts.map +0 -1
  907. package/esm/rules/color/color-rules.d.ts +0 -30
  908. package/esm/rules/color/color-rules.d.ts.map +0 -1
  909. package/esm/rules/color/color-rules.js +0 -120
  910. package/esm/rules/color/color-rules.js.map +0 -1
  911. package/esm/rules/color/index.d.ts +0 -2
  912. package/esm/rules/color/index.d.ts.map +0 -1
  913. package/esm/rules/common/enum.d.ts +0 -26
  914. package/esm/rules/common/enum.d.ts.map +0 -1
  915. package/esm/rules/common/enum.js +0 -69
  916. package/esm/rules/common/enum.js.map +0 -1
  917. package/esm/rules/common/equals-field-rules.d.ts +0 -18
  918. package/esm/rules/common/equals-field-rules.d.ts.map +0 -1
  919. package/esm/rules/common/equals-field-rules.js +0 -39
  920. package/esm/rules/common/equals-field-rules.js.map +0 -1
  921. package/esm/rules/common/index.d.ts +0 -5
  922. package/esm/rules/common/index.d.ts.map +0 -1
  923. package/esm/rules/common/type-rules.d.ts +0 -38
  924. package/esm/rules/common/type-rules.d.ts.map +0 -1
  925. package/esm/rules/common/type-rules.js +0 -117
  926. package/esm/rules/common/type-rules.js.map +0 -1
  927. package/esm/rules/common/unknown-key.d.ts +0 -9
  928. package/esm/rules/common/unknown-key.d.ts.map +0 -1
  929. package/esm/rules/common/unknown-key.js +0 -17
  930. package/esm/rules/common/unknown-key.js.map +0 -1
  931. package/esm/rules/conditional/forbidden-if-rules.d.ts +0 -54
  932. package/esm/rules/conditional/forbidden-if-rules.d.ts.map +0 -1
  933. package/esm/rules/conditional/forbidden-if-rules.js +0 -118
  934. package/esm/rules/conditional/forbidden-if-rules.js.map +0 -1
  935. package/esm/rules/conditional/index.d.ts +0 -11
  936. package/esm/rules/conditional/index.d.ts.map +0 -1
  937. package/esm/rules/conditional/present-if-rules.d.ts +0 -45
  938. package/esm/rules/conditional/present-if-rules.d.ts.map +0 -1
  939. package/esm/rules/conditional/present-if-rules.js +0 -100
  940. package/esm/rules/conditional/present-if-rules.js.map +0 -1
  941. package/esm/rules/conditional/present-unless-rules.d.ts +0 -11
  942. package/esm/rules/conditional/present-unless-rules.d.ts.map +0 -1
  943. package/esm/rules/conditional/present-unless-rules.js +0 -22
  944. package/esm/rules/conditional/present-unless-rules.js.map +0 -1
  945. package/esm/rules/conditional/present-with-rules.d.ts +0 -26
  946. package/esm/rules/conditional/present-with-rules.d.ts.map +0 -1
  947. package/esm/rules/conditional/present-with-rules.js +0 -70
  948. package/esm/rules/conditional/present-with-rules.js.map +0 -1
  949. package/esm/rules/conditional/present-without-rules.d.ts +0 -26
  950. package/esm/rules/conditional/present-without-rules.d.ts.map +0 -1
  951. package/esm/rules/conditional/present-without-rules.js +0 -70
  952. package/esm/rules/conditional/present-without-rules.js.map +0 -1
  953. package/esm/rules/conditional/required-if-rules.d.ts +0 -77
  954. package/esm/rules/conditional/required-if-rules.d.ts.map +0 -1
  955. package/esm/rules/conditional/required-if-rules.js +0 -205
  956. package/esm/rules/conditional/required-if-rules.js.map +0 -1
  957. package/esm/rules/conditional/required-unless-rules.d.ts +0 -11
  958. package/esm/rules/conditional/required-unless-rules.d.ts.map +0 -1
  959. package/esm/rules/conditional/required-unless-rules.js +0 -22
  960. package/esm/rules/conditional/required-unless-rules.js.map +0 -1
  961. package/esm/rules/conditional/required-when-rule.d.ts +0 -18
  962. package/esm/rules/conditional/required-when-rule.d.ts.map +0 -1
  963. package/esm/rules/conditional/required-when-rule.js +0 -26
  964. package/esm/rules/conditional/required-when-rule.js.map +0 -1
  965. package/esm/rules/conditional/required-with-rules.d.ts +0 -26
  966. package/esm/rules/conditional/required-with-rules.d.ts.map +0 -1
  967. package/esm/rules/conditional/required-with-rules.js +0 -64
  968. package/esm/rules/conditional/required-with-rules.js.map +0 -1
  969. package/esm/rules/conditional/required-without-rules.d.ts +0 -26
  970. package/esm/rules/conditional/required-without-rules.d.ts.map +0 -1
  971. package/esm/rules/conditional/required-without-rules.js +0 -64
  972. package/esm/rules/conditional/required-without-rules.js.map +0 -1
  973. package/esm/rules/core/equal.d.ts +0 -8
  974. package/esm/rules/core/equal.d.ts.map +0 -1
  975. package/esm/rules/core/equal.js +0 -14
  976. package/esm/rules/core/equal.js.map +0 -1
  977. package/esm/rules/core/forbidden.d.ts +0 -6
  978. package/esm/rules/core/forbidden.d.ts.map +0 -1
  979. package/esm/rules/core/forbidden.js +0 -13
  980. package/esm/rules/core/forbidden.js.map +0 -1
  981. package/esm/rules/core/index.d.ts +0 -6
  982. package/esm/rules/core/index.d.ts.map +0 -1
  983. package/esm/rules/core/required.d.ts +0 -11
  984. package/esm/rules/core/required.d.ts.map +0 -1
  985. package/esm/rules/core/required.js +0 -31
  986. package/esm/rules/core/required.js.map +0 -1
  987. package/esm/rules/core/union.d.ts +0 -9
  988. package/esm/rules/core/union.d.ts.map +0 -1
  989. package/esm/rules/core/union.js +0 -40
  990. package/esm/rules/core/union.js.map +0 -1
  991. package/esm/rules/core/when.d.ts +0 -6
  992. package/esm/rules/core/when.d.ts.map +0 -1
  993. package/esm/rules/core/when.js +0 -40
  994. package/esm/rules/core/when.js.map +0 -1
  995. package/esm/rules/date/date-comparison-rules.d.ts +0 -25
  996. package/esm/rules/date/date-comparison-rules.d.ts.map +0 -1
  997. package/esm/rules/date/date-comparison-rules.js +0 -80
  998. package/esm/rules/date/date-comparison-rules.js.map +0 -1
  999. package/esm/rules/date/date-day-rules.d.ts +0 -21
  1000. package/esm/rules/date/date-day-rules.d.ts.map +0 -1
  1001. package/esm/rules/date/date-day-rules.js +0 -68
  1002. package/esm/rules/date/date-day-rules.js.map +0 -1
  1003. package/esm/rules/date/date-field-comparison-rules.d.ts +0 -28
  1004. package/esm/rules/date/date-field-comparison-rules.d.ts.map +0 -1
  1005. package/esm/rules/date/date-field-comparison-rules.js +0 -94
  1006. package/esm/rules/date/date-field-comparison-rules.js.map +0 -1
  1007. package/esm/rules/date/date-period-rules.d.ts +0 -124
  1008. package/esm/rules/date/date-period-rules.d.ts.map +0 -1
  1009. package/esm/rules/date/date-period-rules.js +0 -605
  1010. package/esm/rules/date/date-period-rules.js.map +0 -1
  1011. package/esm/rules/date/date-relative-rules.d.ts +0 -20
  1012. package/esm/rules/date/date-relative-rules.d.ts.map +0 -1
  1013. package/esm/rules/date/date-relative-rules.js +0 -60
  1014. package/esm/rules/date/date-relative-rules.js.map +0 -1
  1015. package/esm/rules/date/date-special-rules.d.ts +0 -20
  1016. package/esm/rules/date/date-special-rules.d.ts.map +0 -1
  1017. package/esm/rules/date/date-special-rules.js +0 -71
  1018. package/esm/rules/date/date-special-rules.js.map +0 -1
  1019. package/esm/rules/date/date.d.ts +0 -93
  1020. package/esm/rules/date/date.d.ts.map +0 -1
  1021. package/esm/rules/date/date.js +0 -288
  1022. package/esm/rules/date/date.js.map +0 -1
  1023. package/esm/rules/date/index.d.ts +0 -8
  1024. package/esm/rules/date/index.d.ts.map +0 -1
  1025. package/esm/rules/file/dimensions.d.ts +0 -26
  1026. package/esm/rules/file/dimensions.d.ts.map +0 -1
  1027. package/esm/rules/file/dimensions.js +0 -60
  1028. package/esm/rules/file/dimensions.js.map +0 -1
  1029. package/esm/rules/file/file-size.d.ts +0 -14
  1030. package/esm/rules/file/file-size.d.ts.map +0 -1
  1031. package/esm/rules/file/file-size.js +0 -30
  1032. package/esm/rules/file/file-size.js.map +0 -1
  1033. package/esm/rules/file/index.d.ts +0 -11
  1034. package/esm/rules/file/index.d.ts.map +0 -1
  1035. package/esm/rules/index.d.ts +0 -19
  1036. package/esm/rules/index.d.ts.map +0 -1
  1037. package/esm/rules/length/index.d.ts +0 -2
  1038. package/esm/rules/length/index.d.ts.map +0 -1
  1039. package/esm/rules/length/length-rules.d.ts +0 -49
  1040. package/esm/rules/length/length-rules.d.ts.map +0 -1
  1041. package/esm/rules/length/length-rules.js +0 -107
  1042. package/esm/rules/length/length-rules.js.map +0 -1
  1043. package/esm/rules/number/index.d.ts +0 -2
  1044. package/esm/rules/number/index.d.ts.map +0 -1
  1045. package/esm/rules/number/number-rules.d.ts +0 -65
  1046. package/esm/rules/number/number-rules.d.ts.map +0 -1
  1047. package/esm/rules/number/number-rules.js +0 -245
  1048. package/esm/rules/number/number-rules.js.map +0 -1
  1049. package/esm/rules/scalar/accepted-rule.d.ts +0 -39
  1050. package/esm/rules/scalar/accepted-rule.d.ts.map +0 -1
  1051. package/esm/rules/scalar/accepted-rule.js +0 -117
  1052. package/esm/rules/scalar/accepted-rule.js.map +0 -1
  1053. package/esm/rules/scalar/declined-rule.d.ts +0 -39
  1054. package/esm/rules/scalar/declined-rule.d.ts.map +0 -1
  1055. package/esm/rules/scalar/declined-rule.js +0 -117
  1056. package/esm/rules/scalar/declined-rule.js.map +0 -1
  1057. package/esm/rules/scalar/index.d.ts +0 -3
  1058. package/esm/rules/scalar/index.d.ts.map +0 -1
  1059. package/esm/rules/string/alpha.d.ts +0 -14
  1060. package/esm/rules/string/alpha.d.ts.map +0 -1
  1061. package/esm/rules/string/alpha.js +0 -39
  1062. package/esm/rules/string/alpha.js.map +0 -1
  1063. package/esm/rules/string/credit-card.d.ts +0 -6
  1064. package/esm/rules/string/credit-card.d.ts.map +0 -1
  1065. package/esm/rules/string/credit-card.js +0 -31
  1066. package/esm/rules/string/credit-card.js.map +0 -1
  1067. package/esm/rules/string/email.d.ts +0 -6
  1068. package/esm/rules/string/email.d.ts.map +0 -1
  1069. package/esm/rules/string/email.js +0 -13
  1070. package/esm/rules/string/email.js.map +0 -1
  1071. package/esm/rules/string/index.d.ts +0 -17
  1072. package/esm/rules/string/index.d.ts.map +0 -1
  1073. package/esm/rules/string/ip.d.ts +0 -14
  1074. package/esm/rules/string/ip.d.ts.map +0 -1
  1075. package/esm/rules/string/ip.js +0 -39
  1076. package/esm/rules/string/ip.js.map +0 -1
  1077. package/esm/rules/string/matches.d.ts +0 -8
  1078. package/esm/rules/string/matches.d.ts.map +0 -1
  1079. package/esm/rules/string/matches.js +0 -15
  1080. package/esm/rules/string/matches.js.map +0 -1
  1081. package/esm/rules/string/pattern.d.ts +0 -8
  1082. package/esm/rules/string/pattern.d.ts.map +0 -1
  1083. package/esm/rules/string/pattern.js +0 -14
  1084. package/esm/rules/string/pattern.js.map +0 -1
  1085. package/esm/rules/string/string-comparison.d.ts +0 -26
  1086. package/esm/rules/string/string-comparison.d.ts.map +0 -1
  1087. package/esm/rules/string/string-comparison.js +0 -56
  1088. package/esm/rules/string/string-comparison.js.map +0 -1
  1089. package/esm/rules/string/strong-password-rule.d.ts +0 -14
  1090. package/esm/rules/string/strong-password-rule.d.ts.map +0 -1
  1091. package/esm/rules/string/strong-password-rule.js +0 -38
  1092. package/esm/rules/string/strong-password-rule.js.map +0 -1
  1093. package/esm/rules/string/url.d.ts +0 -6
  1094. package/esm/rules/string/url.d.ts.map +0 -1
  1095. package/esm/rules/string/url.js +0 -16
  1096. package/esm/rules/string/url.js.map +0 -1
  1097. package/esm/rules/string/without-whitespace.d.ts +0 -6
  1098. package/esm/rules/string/without-whitespace.d.ts.map +0 -1
  1099. package/esm/rules/string/without-whitespace.js +0 -13
  1100. package/esm/rules/string/without-whitespace.js.map +0 -1
  1101. package/esm/standard-schema/index.d.ts +0 -4
  1102. package/esm/standard-schema/index.d.ts.map +0 -1
  1103. package/esm/standard-schema/json-schema.d.ts +0 -61
  1104. package/esm/standard-schema/json-schema.d.ts.map +0 -1
  1105. package/esm/standard-schema/json-schema.js +0 -85
  1106. package/esm/standard-schema/json-schema.js.map +0 -1
  1107. package/esm/standard-schema/map-result.d.ts +0 -18
  1108. package/esm/standard-schema/map-result.d.ts.map +0 -1
  1109. package/esm/standard-schema/map-result.js +0 -27
  1110. package/esm/standard-schema/map-result.js.map +0 -1
  1111. package/esm/standard-schema/types.d.ts +0 -93
  1112. package/esm/standard-schema/types.d.ts.map +0 -1
  1113. package/esm/types/conditional-types.d.ts +0 -15
  1114. package/esm/types/conditional-types.d.ts.map +0 -1
  1115. package/esm/types/context-types.d.ts +0 -47
  1116. package/esm/types/context-types.d.ts.map +0 -1
  1117. package/esm/types/data-transformer-types.d.ts +0 -25
  1118. package/esm/types/data-transformer-types.d.ts.map +0 -1
  1119. package/esm/types/date-types.d.ts +0 -9
  1120. package/esm/types/date-types.d.ts.map +0 -1
  1121. package/esm/types/date-types.js +0 -12
  1122. package/esm/types/date-types.js.map +0 -1
  1123. package/esm/types/file.types.d.ts +0 -5
  1124. package/esm/types/file.types.d.ts.map +0 -1
  1125. package/esm/types/index.d.ts +0 -11
  1126. package/esm/types/index.d.ts.map +0 -1
  1127. package/esm/types/inference-types.d.ts +0 -32
  1128. package/esm/types/inference-types.d.ts.map +0 -1
  1129. package/esm/types/mutator-types.d.ts +0 -27
  1130. package/esm/types/mutator-types.d.ts.map +0 -1
  1131. package/esm/types/result-types.d.ts +0 -19
  1132. package/esm/types/result-types.d.ts.map +0 -1
  1133. package/esm/types/rule-types.d.ts +0 -58
  1134. package/esm/types/rule-types.d.ts.map +0 -1
  1135. package/esm/types/schema-types.d.ts +0 -6
  1136. package/esm/types/schema-types.d.ts.map +0 -1
  1137. package/esm/validators/any-validator.d.ts +0 -29
  1138. package/esm/validators/any-validator.d.ts.map +0 -1
  1139. package/esm/validators/any-validator.js +0 -31
  1140. package/esm/validators/any-validator.js.map +0 -1
  1141. package/esm/validators/array-validator.d.ts +0 -72
  1142. package/esm/validators/array-validator.d.ts.map +0 -1
  1143. package/esm/validators/array-validator.js +0 -162
  1144. package/esm/validators/array-validator.js.map +0 -1
  1145. package/esm/validators/base-validator.d.ts +0 -425
  1146. package/esm/validators/base-validator.d.ts.map +0 -1
  1147. package/esm/validators/base-validator.js +0 -637
  1148. package/esm/validators/base-validator.js.map +0 -1
  1149. package/esm/validators/boolean-validator.d.ts +0 -67
  1150. package/esm/validators/boolean-validator.d.ts.map +0 -1
  1151. package/esm/validators/boolean-validator.js +0 -105
  1152. package/esm/validators/boolean-validator.js.map +0 -1
  1153. package/esm/validators/computed-validator.d.ts +0 -75
  1154. package/esm/validators/computed-validator.d.ts.map +0 -1
  1155. package/esm/validators/computed-validator.js +0 -124
  1156. package/esm/validators/computed-validator.js.map +0 -1
  1157. package/esm/validators/date-validator.d.ts +0 -330
  1158. package/esm/validators/date-validator.d.ts.map +0 -1
  1159. package/esm/validators/date-validator.js +0 -614
  1160. package/esm/validators/date-validator.js.map +0 -1
  1161. package/esm/validators/float-validator.d.ts +0 -8
  1162. package/esm/validators/float-validator.d.ts.map +0 -1
  1163. package/esm/validators/float-validator.js +0 -9
  1164. package/esm/validators/float-validator.js.map +0 -1
  1165. package/esm/validators/index.d.ts +0 -31
  1166. package/esm/validators/index.d.ts.map +0 -1
  1167. package/esm/validators/int-validator.d.ts +0 -19
  1168. package/esm/validators/int-validator.d.ts.map +0 -1
  1169. package/esm/validators/int-validator.js +0 -21
  1170. package/esm/validators/int-validator.js.map +0 -1
  1171. package/esm/validators/managed-validator.d.ts +0 -38
  1172. package/esm/validators/managed-validator.d.ts.map +0 -1
  1173. package/esm/validators/managed-validator.js +0 -34
  1174. package/esm/validators/managed-validator.js.map +0 -1
  1175. package/esm/validators/methods/equality-conditional-methods.d.ts +0 -88
  1176. package/esm/validators/methods/equality-conditional-methods.d.ts.map +0 -1
  1177. package/esm/validators/methods/equality-conditional-methods.js +0 -118
  1178. package/esm/validators/methods/equality-conditional-methods.js.map +0 -1
  1179. package/esm/validators/methods/forbidden-methods.d.ts +0 -58
  1180. package/esm/validators/methods/forbidden-methods.d.ts.map +0 -1
  1181. package/esm/validators/methods/forbidden-methods.js +0 -122
  1182. package/esm/validators/methods/forbidden-methods.js.map +0 -1
  1183. package/esm/validators/methods/present-methods.d.ts +0 -102
  1184. package/esm/validators/methods/present-methods.d.ts.map +0 -1
  1185. package/esm/validators/methods/present-methods.js +0 -229
  1186. package/esm/validators/methods/present-methods.js.map +0 -1
  1187. package/esm/validators/methods/required-methods.d.ts +0 -174
  1188. package/esm/validators/methods/required-methods.d.ts.map +0 -1
  1189. package/esm/validators/methods/required-methods.js +0 -246
  1190. package/esm/validators/methods/required-methods.js.map +0 -1
  1191. package/esm/validators/number-validator.d.ts +0 -166
  1192. package/esm/validators/number-validator.d.ts.map +0 -1
  1193. package/esm/validators/number-validator.js +0 -307
  1194. package/esm/validators/number-validator.js.map +0 -1
  1195. package/esm/validators/numeric-validator.d.ts +0 -15
  1196. package/esm/validators/numeric-validator.d.ts.map +0 -1
  1197. package/esm/validators/numeric-validator.js +0 -18
  1198. package/esm/validators/numeric-validator.js.map +0 -1
  1199. package/esm/validators/object-validator.d.ts +0 -233
  1200. package/esm/validators/object-validator.d.ts.map +0 -1
  1201. package/esm/validators/object-validator.js +0 -517
  1202. package/esm/validators/object-validator.js.map +0 -1
  1203. package/esm/validators/primitive-validator.d.ts +0 -70
  1204. package/esm/validators/primitive-validator.d.ts.map +0 -1
  1205. package/esm/validators/primitive-validator.js +0 -80
  1206. package/esm/validators/primitive-validator.js.map +0 -1
  1207. package/esm/validators/record-validator.d.ts +0 -54
  1208. package/esm/validators/record-validator.d.ts.map +0 -1
  1209. package/esm/validators/record-validator.js +0 -100
  1210. package/esm/validators/record-validator.js.map +0 -1
  1211. package/esm/validators/scalar-validator.d.ts +0 -93
  1212. package/esm/validators/scalar-validator.d.ts.map +0 -1
  1213. package/esm/validators/scalar-validator.js +0 -149
  1214. package/esm/validators/scalar-validator.js.map +0 -1
  1215. package/esm/validators/string-validator.d.ts +0 -189
  1216. package/esm/validators/string-validator.d.ts.map +0 -1
  1217. package/esm/validators/string-validator.js +0 -387
  1218. package/esm/validators/string-validator.js.map +0 -1
  1219. package/esm/validators/tuple-validator.d.ts +0 -56
  1220. package/esm/validators/tuple-validator.d.ts.map +0 -1
  1221. package/esm/validators/tuple-validator.js +0 -121
  1222. package/esm/validators/tuple-validator.js.map +0 -1
  1223. package/esm/validators/union-validator.d.ts +0 -55
  1224. package/esm/validators/union-validator.d.ts.map +0 -1
  1225. package/esm/validators/union-validator.js +0 -60
  1226. package/esm/validators/union-validator.js.map +0 -1
package/llms-full.txt ADDED
@@ -0,0 +1,2175 @@
1
+ # Warlock Seal — full skills
2
+
3
+ > Package: `@warlock.js/seal`
4
+
5
+ > Generated artifact. Concatenates every SKILL.md and reference file under `@warlock.js/seal/skills/`. Re-run `node scripts/generate-llms.mjs` after any change.
6
+
7
+ ## bridge-standard-schema `@warlock.js/seal/bridge-standard-schema/SKILL.md`
8
+
9
+ ---
10
+ name: bridge-standard-schema
11
+ description: 'Diagnose `StandardSchemaV1` interop — phantom-intersection at the `v` factory return, why typed slots reject a schema, cascade `Model<TSchema>` variance. Triggers: `StandardSchemaV1`, `~standard`, `Infer`, `ObjectValidator`, `StringValidator`, `LiteralValidator`, `BaseValidator`, `Model<TSchema>`, `StandardJSONSchemaV1`, `Result<unknown>`; "StandardSchemaV1 slot rejecting my schema", "Result<unknown> error", "drop as unknown as cast", "cascade Model schema variance"; typical import `import { v, type Infer } from "@warlock.js/seal"`. Skip: foundations — `@warlock.js/seal/seal-basics/SKILL.md`; JSON Schema gen — `@warlock.js/seal/generate-json-schema/SKILL.md`; competing spec `@standard-schema/spec`.'
12
+ ---
13
+
14
+ # The Standard Schema bridge
15
+
16
+ Seal validators implement [Standard Schema V1](https://standardschema.dev) — every validator exposes a `~standard` member with `validate()`, JSON Schema metadata, and inferred types. Any consumer that accepts `StandardSchemaV1<T>` (`@warlock.js/ai` supervisor `output`, ai tool `input`, LangGraph state, OpenAI structured outputs, TanStack Form, Conform) accepts a seal schema directly.
17
+
18
+ This skill is about the **typing** of that interop — the phantom intersection that makes `v.object({...})` satisfy `StandardSchemaV1<T>` without `as unknown as` casts.
19
+
20
+ ## The shape of the bridge
21
+
22
+ The `v` factory returns aren't bare validator classes. Each factory widens its return with a phantom intersection:
23
+
24
+ ```ts
25
+ // Inside seal's factory:
26
+ object: <T extends Schema>(schema: T) =>
27
+ new ObjectValidator<T>(schema) as ObjectValidator<T>
28
+ & StandardSchemaV1<Infer<ObjectValidator<T>>>;
29
+
30
+ string: () =>
31
+ new StringValidator() as StringValidator & StandardSchemaV1<string>;
32
+
33
+ literal: <T extends readonly [...] >(...values: T) =>
34
+ new LiteralValidator<T>(values) as LiteralValidator<T> & StandardSchemaV1<T[number]>;
35
+
36
+ // ...one intersection per factory.
37
+ ```
38
+
39
+ The intersection is **only on the factory return type** — the `BaseValidator` and `ObjectValidator` *class* shapes are unchanged. That distinction is load-bearing: putting `Infer<this>` directly on `BaseValidator['~standard']` breaks `@warlock.js/cascade`'s `Model<TSchema>` because `ObjectValidator` becomes invariant when its members vary with `TSchema`. The factory-side intersection avoids that — bare classes in `Model.schema: ObjectValidator<TSchema>` slots are still structurally compatible with the typed factory return.
40
+
41
+ ## What this means for app code
42
+
43
+ You write the schema once, you use it anywhere a `StandardSchemaV1<T>` is expected, you never cast:
44
+
45
+ ```ts
46
+ import { v, validate, type Infer } from "@warlock.js/seal";
47
+ import { ai } from "@warlock.js/ai";
48
+
49
+ const userSchema = v.object({
50
+ email: v.string().email(),
51
+ age: v.int().optional(),
52
+ });
53
+
54
+ type User = Infer<typeof userSchema>;
55
+
56
+ // ✅ ai-side slot — no cast
57
+ ai.tool({
58
+ name: "create_user",
59
+ description: "Create a new user",
60
+ input: userSchema,
61
+ execute: async input => createUser(input),
62
+ });
63
+
64
+ // ✅ supervisor output — no cast
65
+ ai.supervisor({
66
+ name: "user-flow",
67
+ output: userSchema,
68
+ // ...
69
+ });
70
+
71
+ // ✅ direct validation — call ~standard
72
+ const result = await userSchema["~standard"].validate(rawData);
73
+ ```
74
+
75
+ ## `Infer<typeof schema>` vs hand-rolled types
76
+
77
+ Use `Infer<>`. Always:
78
+
79
+ ```ts
80
+ const schema = v.object({
81
+ email: v.string(),
82
+ blocks: v.array(v.literal("text", "image")).optional(),
83
+ });
84
+
85
+ type Output = Infer<typeof schema>;
86
+ // { email: string; blocks?: ("text" | "image")[] }
87
+ ```
88
+
89
+ Hand-rolled parallel types drift the moment a field changes — and seal's tightened typing now catches that drift at compile time. The old loose typing hid the mismatch; the bridge surfaces it.
90
+
91
+ ## When the bridge "fails"
92
+
93
+ Three failure modes you'll see in real projects:
94
+
95
+ ### 1. You annotated the schema with the bare class type
96
+
97
+ ```ts
98
+ // ❌ Discards the phantom intersection
99
+ const schema: ObjectValidator<{ email: StringValidator }> = v.object({...});
100
+
101
+ // ✅ Let inference run
102
+ const schema = v.object({...});
103
+ ```
104
+
105
+ The annotation strips `& StandardSchemaV1<...>` from the type. The schema stops fitting `StandardSchemaV1<T>` slots. Fix: remove the annotation. If you need the value type, use `Infer<typeof schema>`.
106
+
107
+ ### 2. The schema's inferred shape doesn't match the target type
108
+
109
+ ```ts
110
+ ai.supervisor<MyOutput, ...>({
111
+ output: schema, // ❌ schema infers differently from MyOutput
112
+ });
113
+ ```
114
+
115
+ The supervisor's explicit `<MyOutput>` generic is a constraint the schema must satisfy. If they diverge, TS rightly rejects. Two fixes:
116
+
117
+ - **Drop the explicit generic** — let the supervisor infer output type from the schema. The hand-rolled type was probably documentation-only anyway.
118
+ - **Align them** — if the hand-rolled type is the source of truth (e.g. a domain type from elsewhere), make the schema match.
119
+
120
+ ### 3. The error says `Result<unknown>` even though `Infer<>` resolves correctly
121
+
122
+ This is a TypeScript reporting quirk, not a bridge bug. When a `StandardSchemaV1<T>` slot rejects a schema, TS picks the simplest mismatch chain to report — often it falls through `BaseValidator['~standard'].validate`'s wider `Result<unknown>` declaration before reaching the factory-side narrower one. The intersection *is* there structurally, but the error message mentions `unknown`.
123
+
124
+ If you see this, ignore the `unknown` and ask: does `Infer<typeof schema>` match the slot's expected `T`? Probe with:
125
+
126
+ ```ts
127
+ type _Probe = Infer<typeof schema>;
128
+ const _force: { __nope: 1 } = null as unknown as _Probe;
129
+ // Hover the error to see the resolved shape, then compare to the slot's T.
130
+ ```
131
+
132
+ That's the real mismatch.
133
+
134
+ ## Why not `Omit<class, "~standard"> & StandardSchemaV1<T>`?
135
+
136
+ Tempting — it would force the factory's `~standard` to fully replace the class's wider one, fixing the misleading `Result<unknown>` error message. **Don't do it.** `Omit` on a class instance type triggers the same variance trap as putting `Infer<this>` on the class itself: cascade explodes with hundreds of `ObjectValidator<{specific}>` vs `ObjectValidator<TSchema>` errors. The phantom intersection is the only shape that satisfies both ends — narrower for typed slots, structurally identical to the class for cascade's invariant generic positions.
137
+
138
+ ## Why not import `@standard-schema/spec` instead of forking the types?
139
+
140
+ Seal forks the types locally. Reasons:
141
+
142
+ - Seal extends the spec with `StandardJSONSchemaV1` (JSON Schema converter on `~standard.jsonSchema`). The package doesn't have this — half-importing is the worst of both worlds.
143
+ - V1 spec is locked. The fork is ~70 lines and updates rarely.
144
+ - Avoids version-coupling pain across `@warlock.js/*` packages.
145
+
146
+ If V2 lands, re-fork. Until then the local copy is the right call.
147
+
148
+
149
+ ## compose-seal-modifiers `@warlock.js/seal/compose-seal-modifiers/SKILL.md`
150
+
151
+ ---
152
+ name: compose-seal-modifiers
153
+ description: 'Apply cross-cutting modifiers — `.optional` / `.nullable` / `.default` / `.catch` / `.omit` / membership rules — plus the mutator-vs-transformer pipeline and `Infer.Input` vs `Infer.Output`. Triggers: `.optional`, `.required`, `.nullable`, `.default`, `.catch`, `.present`, `.requiredIf`, `.requiredWith`, `.in`, `.oneOf`, `.notIn`, `.omit`, `.attribute`, `.mutable`, `.addMutator`, `Infer.Input`, `Infer.Output`; "mark field optional in seal", "default value in schema", "mutator vs transformer", "when does .catch fire"; typical import `import { v, type Infer } from "@warlock.js/seal"`. Skip: primitives — `@warlock.js/seal/pick-seal-primitive/SKILL.md`; containers — `@warlock.js/seal/define-structural-shape/SKILL.md`; errors — `@warlock.js/seal/handle-seal-errors/SKILL.md`; competing `zod` `.optional`/`.default`.'
154
+ ---
155
+
156
+ # Cross-cutting modifiers + the pipeline
157
+
158
+ This skill covers methods that work on **every** validator. Type-specific methods (`.email()`, `.min()` on strings, `.between()` on numbers, `.weekDay()` on dates, etc.) live in the per-type method references — see [`@warlock.js/seal/pick-seal-primitive/SKILL.md`](@warlock.js/seal/pick-seal-primitive/SKILL.md) and [`@warlock.js/seal/define-structural-shape/SKILL.md`](@warlock.js/seal/define-structural-shape/SKILL.md).
159
+
160
+ ## The pipeline
161
+
162
+ When `validate()` runs against a value, the order is:
163
+
164
+ ```
165
+ 1. default — fills if input is undefined
166
+ 2. mutators — reshape value (string → Date, .trim(), .toUTC())
167
+ 3. optional/required check — decide whether to run rules
168
+ 4. requiredRule — required-condition rule (.requiredIf, .requiredWith, etc.)
169
+ 5. rules — every other rule, in declaration order
170
+ 6. transformers — reshape value into data (.toISOString, .toLowerCase)
171
+ ```
172
+
173
+ If a rule fails, transformers don't run for that field.
174
+
175
+ **Mutator vs transformer mental model:**
176
+ - **Mutator** = pre-validation reshape. `v.date()` ships one that parses strings. Use when you want rules to see the reshaped value.
177
+ - **Transformer** = post-validation reshape. Lands in `data`. Use when you only care about the output form.
178
+
179
+ ```ts
180
+ // trim BEFORE length check — use a mutator
181
+ v.string().addMutator(s => s.trim()).min(3)
182
+ // " Hi " → mutator trims → "Hi" → fails min(3)
183
+
184
+ // trim only the OUTPUT — use a transformer (.trim() on string is a transformer)
185
+ v.string().min(3).trim()
186
+ // " Hi " → rules see " Hi " (length 6, passes min(3)) → trim → data = "Hi"
187
+ ```
188
+
189
+ ## `.required()` / `.optional()` / `.present()`
190
+
191
+ ```ts
192
+ v.string() // already required inside v.object — no need to call .required()
193
+ v.string().optional() // type: string | undefined — { isOptional: true } brand
194
+ v.string().present() // must exist, may be "" / null
195
+ v.string().required() // explicit form — same behavior, redundant
196
+ ```
197
+
198
+ **Required is the default inside `v.object`.** Most schemas read cleaner without `.required()` — `Infer<>` already shows what's required (no `?`) vs optional (`?`). Calling `.required()` explicitly is harmless and accepted, but the canonical seal style is to skip it. Keep `.optional()` explicit (it changes behavior); skip `.required()` (it doesn't).
199
+
200
+ The `{ isOptional: true }` brand survives chaining (`.optional().min(3)` is still optional) and `Infer<>` reads it to make the key optional.
201
+
202
+ **When `.required()` is still useful:**
203
+ - Visual contrast next to `.optional()` siblings when you want the asymmetry to be loud — style call.
204
+ - It's not needed for conditional rules — `.requiredIf(field, value)` and friends *replace* the default required-condition slot, so they work standalone.
205
+
206
+ Conditional variants (run inside `v.object` only):
207
+ - `.requiredIf(field, value)` / `.requiredIfSibling(field, value)`
208
+ - `.requiredWith(field)` / `.requiredWithSibling(field)`
209
+ - `.requiredWithout(field)` / `.requiredWithoutSibling(field)`
210
+ - `.requiredUnless(field, value)`
211
+ - `.requiredWhen(callback)` — predicate
212
+ - `.present()` / `.presentIf(field, value)` / `.presentUnless(field, value)`
213
+ - `.forbidden()` / `.forbiddenIf(field, value)` — opposite of present
214
+
215
+ ## `.nullable()` / `.notNullable()` / `.nullish()`
216
+
217
+ ```ts
218
+ v.string().nullable() // type: string | null
219
+ v.string().nullish() // sugar for .optional().nullable()
220
+ ```
221
+
222
+ Independent of optional — a field can be required *and* nullable. Defaults to non-nullable. The `{ isNullable: true }` brand widens both `Infer.Input` and `Infer.Output` with `| null`.
223
+
224
+ ## `.default(value | callback)`
225
+
226
+ ```ts
227
+ v.string().default("guest")
228
+ v.int().default(0)
229
+ v.date().default(() => new Date()) // lazy — fresh each validation
230
+ v.array(v.string()).default([])
231
+ ```
232
+
233
+ If input is `undefined` (or missing), the default is used and rules run against it. Pass a callback for fresh-per-run values. The default fires *before* rules — so `v.string().min(3).default("a")` fails because `"a"` is shorter than 3.
234
+
235
+ Date sugar: `v.date().defaultNow()` ≡ `.default(() => new Date())`.
236
+
237
+ The `{ hasDefault: true }` brand makes the key optional in `Infer.Input` (caller doesn't have to send it) and required in `Infer.Output` (data always has it).
238
+
239
+ ## `.catch(fallback)`
240
+
241
+ Rescues *failed* validation by substituting a fallback. Complement to `.default()`:
242
+
243
+ - `.default(x)` fires when input is **absent**
244
+ - `.catch(y)` fires when input is **present but invalid**
245
+
246
+ ```ts
247
+ const config = v.object({
248
+ retries: v.int().min(0).catch(3),
249
+ region: v.string().in(["us", "eu"]).catch("us"),
250
+ features: v.array(v.string()).catch([]),
251
+ });
252
+
253
+ await validate(config, { retries: "five", region: null, features: "x" });
254
+ // { isValid: true, data: { retries: 3, region: "us", features: [] } }
255
+ ```
256
+
257
+ The fallback can be a value or a callback `(errors, originalInput) => fallback` — the callback variant is the only side-channel for the swallowed errors. Use it to log/alert before substituting.
258
+
259
+ **Scope (v1).** Catch is honoured for **leaf validators** (string, number, boolean, date, …) and for fields inside containers. It is a **no-op on container validators themselves** (`v.object`, `v.array`, `v.record`, `v.tuple`, `v.discriminatedUnion`) — those use their own iteration logic that bypasses the catch hook. To rescue a whole-container failure, wrap the call site in your own try/catch instead.
260
+
261
+ **Best used for:** LLM output parsing, third-party API responses, config files, any data where the cost of failure is higher than the cost of a wrong value. Overuse masks real bugs — reach for it deliberately.
262
+
263
+ The `{ hasCatch: true }` brand has the same effect on `Infer.Input`/`Infer.Output` as `{ hasDefault: true }`.
264
+
265
+ ## `Infer.Input` vs `Infer.Output`
266
+
267
+ The two inference helpers describe the two halves of the pipeline:
268
+
269
+ ```ts
270
+ const schema = v.object({
271
+ bio: v.string().optional(),
272
+ status: v.enum(Status).optional().default(Status.ACTIVE),
273
+ retries: v.int().catch(3),
274
+ });
275
+
276
+ type In = Infer.Input<typeof schema>;
277
+ // {
278
+ // bio?: string;
279
+ // status?: Status; ← default makes caller optional
280
+ // retries?: number; ← catch makes caller optional
281
+ // }
282
+
283
+ type Out = Infer.Output<typeof schema>;
284
+ // {
285
+ // bio?: string;
286
+ // status: Status; ← default guarantees a value
287
+ // retries: number; ← catch guarantees a value
288
+ // }
289
+
290
+ type Default = Infer<typeof schema>; // alias for Infer.Input
291
+ ```
292
+
293
+ **When to reach for which:**
294
+ - `Infer.Input<T>` (or bare `Infer<T>`) — for HTTP request bodies, form payloads, DTOs, anything pre-validation. **The common case in HTTP-shaped code.**
295
+ - `Infer.Output<T>` — for Cascade `Model<>` params, validated state, anywhere downstream of `validate()`.
296
+
297
+ Both widen with `| null` when `.nullable()` is set.
298
+
299
+ ## Absent vs empty vs invalid — what `data` actually contains
300
+
301
+ Three failure modes, three different rescue mechanisms:
302
+
303
+ | Input state | Rescued by | What appears in `data` |
304
+ | --- | --- | --- |
305
+ | Field absent | `.default(x)` | `x` |
306
+ | Field absent (no default) | `.optional()` | Key omitted entirely |
307
+ | Field present and invalid | `.catch(y)` | `y` |
308
+ | Field is `null` | `.nullable()` | `null` |
309
+ | Field present, empty (`""`, `[]`, `{}`) | (none needed — empty is a valid value) | Preserved as-is |
310
+
311
+ Full truth table for an `.optional()` field inside `v.object(…)`:
312
+
313
+ | Input | What appears in `data` |
314
+ | --- | --- |
315
+ | Field absent | Key **omitted entirely** (not `undefined`-valued) |
316
+ | Field is explicit `undefined` | Key omitted (treated identically to absent) |
317
+ | Field is `null` (no `.nullable()`) | Key omitted — for an **optional** field, `null` coalesces to empty and the (cleared) required rule doesn't fire. On a **required** field the same `null` triggers a validation error. |
318
+ | Field is `null` with `.nullable()` | Key is `null` |
319
+ | Field present and empty (`""`, `[]`, `{}`) | Preserved as-is — empty ≠ absent |
320
+ | Field is `.default(x)` and absent | Key is `x` (default fires, then rules run on `x`) |
321
+ | Field is `.default(x)` and present | Caller value wins; default is unused |
322
+ | Field is `.catch(y)` and validation fails | Key is `y` (catch rescues) |
323
+
324
+ ```ts
325
+ const schema = v.object({
326
+ metadata: v.record(v.string()).optional(),
327
+ embedding: v.array(v.number()).optional(),
328
+ });
329
+
330
+ (await validate(schema, {})).data
331
+ // → {} — neither key appears
332
+ // (NOT { metadata: {}, embedding: [] })
333
+
334
+ (await validate(schema, { metadata: {}, embedding: [] })).data
335
+ // → { metadata: {}, embedding: [] } — present-empty is preserved
336
+ ```
337
+
338
+ **Why the distinction matters.** Persistence layers see `key in data` as "user touched this column". Synthesizing `{}` / `[]` for absent input would write empty values to the DB, defeat `$exists` filters, and confuse "I cleared this" vs "I never set this" downstream. Cascade models, Standard-Schema consumers, and JSON serializers all depend on this contract.
339
+
340
+ Collection validators (`v.record`, `v.array`, `v.tuple`) explicitly honor this — they used to coerce absent input to empty containers (a long-standing bug), but now propagate `undefined` so the parent `v.object` correctly omits the key.
341
+
342
+ ## Membership rules (inherited by every primitive)
343
+
344
+ Available on `v.string()`, `v.number()`, `v.int()`, `v.float()`, `v.boolean()`, `v.scalar()`:
345
+
346
+ ```ts
347
+ v.string().in(["admin", "user", "guest"]) // value must match one
348
+ v.string().oneOf(["a", "b"]) // alias for .in
349
+ v.string().notIn(["banned", "blocked"]) // value must NOT match
350
+ v.string().forbids(["banned"]) // alias for .notIn
351
+ v.number().allowsOnly([1, 2, 3]) // stricter — explicit allowlist
352
+ v.string().enum(MyTSEnum) // accepts a TS enum object via Object.values
353
+ ```
354
+
355
+ For literal-typed narrowing (`"admin" | "user" | "guest"` instead of `string`), use `v.literal(...)` instead — `oneOf` keeps the broader primitive type.
356
+
357
+ ## `.omit()` / `.exclude()`
358
+
359
+ ```ts
360
+ v.object({
361
+ email: v.string(),
362
+ password: v.string(),
363
+ passwordConfirm: v.string().sameAs("password").omit(),
364
+ })
365
+ ```
366
+
367
+ `.omit()` keeps the field in *validation* but drops it from `data` and from `Infer<>`. Use for confirmation/checksum fields that exist only for cross-field rules. `.exclude()` is the same idea, used internally for managed/computed plumbing.
368
+
369
+ ## `.label("Display Name")` — field display name
370
+
371
+ To control the `:input` placeholder in a field's own messages, call `.label()` on the field validator:
372
+
373
+ ```ts
374
+ v.object({
375
+ email_address: v.string().label("Email Address"),
376
+ })
377
+ // Error message: "The Email Address is required" (instead of "The email_address is required")
378
+ ```
379
+
380
+ `.label(x)` sets the field's `:input` attribute, so every rule message for that field renders the friendly name.
381
+
382
+ ### `.attributes({ ... })` is a different tool
383
+
384
+ `.attributes()` does NOT relabel a field's own `:input`. It supplies named substitution values consumed by the translation layer and by rules that reference *other* fields (e.g. `matches`):
385
+
386
+ ```ts
387
+ v.string().sameAs("confirmPassword").attributes({
388
+ matches: { confirmPassword: "Confirm Password" },
389
+ })
390
+ ```
391
+
392
+ For per-field display names use `.label()`; for translated messages wire the `translateRule` / `translateAttribute` hooks via `configureSeal()`.
393
+
394
+ ## Mutability — `.mutable` / `.immutable`
395
+
396
+ Validators are **immutable by default**. Every chain method returns a clone:
397
+
398
+ ```ts
399
+ const baseString = v.string();
400
+ const required = baseString.required();
401
+ // baseString is unchanged
402
+ ```
403
+
404
+ This matters because schemas are often shared (`Model.schema = v.object({...})`). If chaining mutated, every reuse would carry forward the previous chain's state.
405
+
406
+ Toggle in-place with the `.mutable` getter (rare):
407
+
408
+ ```ts
409
+ const schema = v.string().mutable.required().min(3);
410
+ // Same instance throughout — useful when building dynamically
411
+ ```
412
+
413
+ Switch back with `.immutable`. Default is fine 99% of the time. Reach for `.mutable` only when you've thought about who else holds a reference.
414
+
415
+ ## Things NOT to do
416
+
417
+ - Don't put a transformer where a mutator belongs — `.trim()` is a transformer; if you need trimming *before* `.min()`, use `.addMutator(s => s.trim())`.
418
+ - Don't combine `.required()` and `.optional()` on the same chain — last wins, but the intent is unclear; pick one.
419
+ - Don't chain `.default("a")` with `.min(3)` and expect `"a"` to pass — the default goes through rules.
420
+ - Don't expect `.requiredIf()` to work on a standalone validator outside `v.object` — sibling resolution silently passes.
421
+ - Don't mutate a schema you handed to a Model. Default immutability protects you; opting into `.mutable` on shared schemas is asking for confusion.
422
+
423
+
424
+ ## define-structural-shape `@warlock.js/seal/define-structural-shape/SKILL.md`
425
+
426
+ ---
427
+ name: define-structural-shape
428
+ description: 'Compose `v.object` / `v.array` / `v.record` / `v.tuple` / `v.union` / `v.discriminatedUnion` / `v.lazy`. Triggers: `v.object`, `v.array`, `v.record`, `v.tuple`, `v.union`, `v.discriminatedUnion`, `v.lazy`, `ObjectValidator`; "how do I build an object schema", "dynamic-keyed record", "tagged union with discriminator", "recursive schema", "self-referencing schema"; typical import `import { v, type Infer } from "@warlock.js/seal"`. Skip: leaf primitives — `@warlock.js/seal/pick-seal-primitive/SKILL.md`; modifiers — `@warlock.js/seal/compose-seal-modifiers/SKILL.md`; standard-schema bridge — `@warlock.js/seal/bridge-standard-schema/SKILL.md`; competing libs `zod`, `valibot`.'
429
+ ---
430
+
431
+ # Structural validators — picking guide
432
+
433
+ The five structural factories. Each composes — pass leaf primitives or other structural validators inside, infer with `Infer<typeof schema>`. **Method surface for `v.object` and `v.array` lives in `object-methods.md` and `array-methods.md`** — this file is just orientation.
434
+
435
+ ## `v.object` — fixed-key records
436
+
437
+ ```ts
438
+ v.object({
439
+ email: v.string().email(),
440
+ age: v.int().min(13).optional(),
441
+ role: v.literal("admin", "user", "guest"),
442
+ })
443
+ ```
444
+
445
+ - **Required by default.** `.optional()` to opt out — the `{ isOptional: true }` brand makes the key optional in `Infer<>`.
446
+ - **Unknown keys policy.** By default extra keys are silently dropped from `data`. Toggle with `.allowUnknown()` (forward as-is), `.stripUnknown()` (explicit drop), or `.allow(...keys)` (whitelist specific extras). See [`object-methods.md`](./object-methods.md).
447
+ - **Schema composition.** `.extend(schema)`, `.merge(other)`, `.pick(...keys)`, `.without(...keys)`, `.partial(...keys)`, `.requiredFields(...keys)` — all in [`object-methods.md`](./object-methods.md).
448
+ - **Cross-field rules** (`sameAs`, `requiredIf`, `requiredWith`) attach to fields *inside* a `v.object`. Without a parent, sibling resolution silently passes.
449
+
450
+ ## `v.array` — homogeneous lists
451
+
452
+ ```ts
453
+ v.array(v.string()) // type: string[]
454
+ v.array(userSchema) // type: User[]
455
+ v.array(v.array(v.int())) // type: number[][] — recursive inference
456
+ ```
457
+
458
+ The inner validator runs against each element; failure on any element fails the array. Method surface (`.min`, `.max`, `.unique`, `.sorted`, `.flip`, …) in [`array-methods.md`](./array-methods.md).
459
+
460
+ ## `v.record` — homogeneous values, dynamic keys
461
+
462
+ ```ts
463
+ v.record(v.int()) // type: Record<string, number>
464
+ v.record(v.object({ count: v.int() })) // type: Record<string, { count: number }>
465
+ v.record() // type: Record<string, any>
466
+ ```
467
+
468
+ Reach for `v.record` when keys are dynamic (user-provided, dictionary-style) but values share a schema. If keys are also constrained (e.g. only `"draft" | "published"`), use `v.object` with literal keys instead — the constraint lives in the type.
469
+
470
+ ## `v.tuple` — positional types
471
+
472
+ ```ts
473
+ v.tuple([v.string(), v.int(), v.boolean()]) // type: [string, number, boolean]
474
+ v.tuple([v.literal("ok"), v.string()]) // type: ["ok", string]
475
+ ```
476
+
477
+ Each position has its own validator; the array length must match the tuple length. Pair with `v.literal` at position 0 for result-tuple patterns (`["ok", data]` vs `["error", message]`).
478
+
479
+ ## `v.union` — one of N validators (untagged)
480
+
481
+ ```ts
482
+ v.union([v.string(), v.int()]) // type: string | number
483
+ ```
484
+
485
+ The first type-matching validator wins, picked via each branch's `matchesType()`. Use for unions of **scalar** types (string vs number, etc.) where `matchesType` is enough to disambiguate. For object-vs-object unions, reach for `v.discriminatedUnion` instead — `matchesType` can't distinguish two object branches and you'll get errors from the wrong branch.
486
+
487
+ ## `v.discriminatedUnion` — tagged unions (recommended for objects)
488
+
489
+ ```ts
490
+ const email = v.object({ type: v.literal("email"), email: v.string().email() });
491
+ const sms = v.object({ type: v.literal("sms"), phone: v.string() });
492
+ const push = v.object({ type: v.literal("push"), deviceId: v.string() });
493
+
494
+ const notif = v.discriminatedUnion("type", [email, sms, push]);
495
+
496
+ type Notif = Infer<typeof notif>;
497
+ // { type: "email"; email: string }
498
+ // | { type: "sms"; phone: string }
499
+ // | { type: "push"; deviceId: string }
500
+ ```
501
+
502
+ Routes payloads by reading the discriminator field (here `type`), looking it up in a key→branch map built at construction time, and delegating to the matching branch only. Benefits over plain `v.union`:
503
+
504
+ - **Precise errors.** Failures come from the matched branch, not from every branch.
505
+ - **O(1) routing** instead of trial-and-error.
506
+ - **Exact TS inference** — discriminated union with narrowing inside `if (x.type === "email")` blocks.
507
+ - **Cleaner JSON Schema** — `oneOf` with literal discriminators; OpenAI-strict accepts it.
508
+
509
+ Construction-time validation throws on:
510
+
511
+ - Missing discriminator field in any branch
512
+ - Non-literal discriminator (must be `v.literal(...)`)
513
+ - Duplicate discriminator values across branches
514
+
515
+ So misconfigurations surface at schema-build time, not runtime.
516
+
517
+ ## `v.lazy` — recursive and forward-referenced schemas
518
+
519
+ ```ts
520
+ type Category = { name: string; children: Category[] };
521
+
522
+ const categorySchema: ObjectValidator<...> = v.object({
523
+ name: v.string(),
524
+ children: v.array(v.lazy(() => categorySchema)),
525
+ });
526
+
527
+ type T = Infer<typeof categorySchema>;
528
+ // { name: string; children: T[] } ← recursive type
529
+ ```
530
+
531
+ Defers resolution of the inner validator until validate-time. JavaScript evaluates the object literal before the `const` binding completes, so the inner reference would normally fail with `ReferenceError`. The thunk is invoked only when `validate()` runs, by which time the binding exists.
532
+
533
+ **Memoised.** The thunk fires once on first use; subsequent calls reuse the cached validator.
534
+
535
+ **JSON Schema caveat.** Simple-resolve in v1 — recursive shapes will infinite-loop in `toJsonSchema()`. If you need JSON Schema for a recursive shape, generate it manually with `$defs` + `$ref` until v2 lands.
536
+
537
+ **TS inference requires a recursive type alias.** TS can't infer `Category = { name: string; children: Category[] }` from the schema alone — declare the type explicitly and annotate the schema variable with `ObjectValidator<...>` or similar (same pattern as Zod's `z.ZodType<Category>`).
538
+
539
+ Use for: trees (categories, file systems), threaded data (comment chains), mutually recursive schemas (`A` references `B` references `A`), and forward references (a schema needs to use one defined later in the file).
540
+
541
+ ## Quick map
542
+
543
+ | Want | Reach for |
544
+ | --- | --- |
545
+ | Fixed-shape record | `v.object({...})` |
546
+ | Dynamic keys, same value shape | `v.record(valueSchema)` |
547
+ | List of items | `v.array(itemSchema)` |
548
+ | Position-typed array | `v.tuple([a, b, c])` |
549
+ | One of N scalar types | `v.union([...])` |
550
+ | One of N object shapes with a tag field | `v.discriminatedUnion(key, [...])` |
551
+ | Self-referencing or forward reference | `v.lazy(() => schema)` |
552
+ | One of N constants | `v.literal(...values)` (not structural — see [`@warlock.js/seal/pick-seal-primitive/SKILL.md`](@warlock.js/seal/pick-seal-primitive/SKILL.md)) |
553
+
554
+ ## A note on cascade Models
555
+
556
+ `@warlock.js/cascade` Models declare `static schema: ObjectValidator<TSchema>`. Passing a `v.object({...})` works directly — the factory return widens to fit the Model's invariant generic without breaking type checking. If TS complains *"`ObjectValidator<{specific}>` is not assignable to `ObjectValidator<TSchema>`"*, that's the variance trap and the answer isn't to widen the schema — it's almost always that `Model<TSchema>` was parameterized with a hand-rolled type that drifted from the schema's inferred shape. Fix the type, not the schema. See [`@warlock.js/seal/bridge-standard-schema/SKILL.md`](@warlock.js/seal/bridge-standard-schema/SKILL.md).
557
+
558
+ ## Method-surface reference
559
+
560
+ - [`object-methods.md`](./object-methods.md) — `.extend` / `.merge` / `.pick` / `.without` / `.partial` / `.requiredFields` / `.allowUnknown` / `.stripUnknown` / `.allow` / `.trim`.
561
+ - [`array-methods.md`](./array-methods.md) — `.minLength` / `.maxLength` / `.length` / `.between` / `.unique` / `.sorted` / `.flip` / `.sort` / `.onlyUnique`.
562
+
563
+ `v.record` and `v.tuple` share the array-style length surface. `v.union` and `v.discriminatedUnion` have no chainable methods beyond what's shown above. `v.lazy` is a single-call factory.
564
+
565
+
566
+ ### define-structural-shape/array-methods.md `@warlock.js/seal/define-structural-shape/array-methods.md`
567
+
568
+ # `v.array(itemValidator)` — method reference
569
+
570
+ The inner validator runs against each element. Failure on any element fails the array. Picking guide (array vs tuple vs record) is in [`@warlock.js/seal/define-structural-shape/SKILL.md`](@warlock.js/seal/define-structural-shape/SKILL.md).
571
+
572
+ ## Length
573
+
574
+ | Method | Args | JSON Schema | Example |
575
+ |---|---|---|---|
576
+ | `.min(n, msg?)` | n/a — see note below | — | use `.minLength(n)` |
577
+ | `.minLength(n, msg?)` | inclusive lower bound | `minItems: n` | `v.array(v.string()).minLength(1)` |
578
+ | `.maxLength(n, msg?)` | inclusive upper bound | `maxItems: n` | `v.array(v.string()).maxLength(10)` |
579
+ | `.length(n, msg?)` | exact length | `minItems=maxItems=n` | `v.array(v.string()).length(3)` |
580
+ | `.between(a, b, msg?)` | inclusive range | `minItems: a, maxItems: b` | `v.array(v.string()).between(1, 10)` |
581
+ | `.lengthBetween(a, b, msg?)` | alias for `.between()` | `minItems: a, maxItems: b` | — |
582
+
583
+ **Note on `.min`/`.max`:** the array validator does not expose `.min`/`.max` directly — use `.minLength`/`.maxLength` (or `.between`/`.length`). This is intentional: `.min`/`.max` would conflict with primitive value-comparison semantics if they ever bled into here.
584
+
585
+ ## Uniqueness & sort
586
+
587
+ | Method | Args | Effect |
588
+ |---|---|---|
589
+ | `.unique(msg?)` | — | every element is distinct |
590
+ | `.sorted(direction?, msg?)` | `"asc"` (default) or `"desc"` | array is monotonically sorted |
591
+
592
+ ## Mutators (pre-validation reshape)
593
+
594
+ | Method | Args | Effect |
595
+ |---|---|---|
596
+ | `.flip()` | — | reverse the array |
597
+ | `.reverse()` | — | alias for `.flip()` |
598
+ | `.onlyUnique()` | — | dedupe before validation |
599
+ | `.sort(direction?, key?)` | `"asc"` (default) or `"desc"`; optional sort key for object items | sort before validation |
600
+
601
+ `onlyUnique()` and `unique()` differ: the mutator silently dedupes; the rule fails when duplicates are present. Pick by intent — coerce vs reject.
602
+
603
+ ## Inner validator notes
604
+
605
+ ```ts
606
+ v.array(v.string().email()) // every element must be a valid email
607
+ v.array(userSchema) // every element must satisfy userSchema
608
+ v.array(v.array(v.int())) // matrix-ish — Infer is recursive
609
+ ```
610
+
611
+ Element validators run with element-level context. `path` becomes `${parent}.${index}` for error messages. Cross-field rules inside element schemas resolve to that element's fields, not the array.
612
+
613
+ ## JSON Schema mapping
614
+
615
+ - `v.array(item)` → `{ type: "array", items: <item.toJsonSchema()> }`
616
+ - `.minLength(n)` → `minItems: n`
617
+ - `.maxLength(n)` → `maxItems: n`
618
+ - `.length(n)` → `minItems: n, maxItems: n`
619
+ - `.between(a, b)` → `minItems: a, maxItems: b`
620
+ - `.unique()` and `.sorted()` are NOT representable — silently omitted
621
+
622
+ ## Common chains
623
+
624
+ ```ts
625
+ // Tags
626
+ v.array(v.string().min(1)).unique().between(1, 10)
627
+
628
+ // User list
629
+ v.array(userSchema).minLength(1)
630
+
631
+ // Pre-sorted, deduped
632
+ v.array(v.string()).onlyUnique().sort("asc")
633
+
634
+ // Reverse-emit
635
+ v.array(v.string()).flip()
636
+
637
+ // Matrix
638
+ v.array(v.array(v.number())).minLength(1)
639
+
640
+ // Sorted ids
641
+ v.array(v.string().uuid()).sorted("asc").unique()
642
+
643
+ // Optional list with default
644
+ v.array(v.string()).default([]).optional()
645
+ ```
646
+
647
+
648
+ ### define-structural-shape/object-methods.md `@warlock.js/seal/define-structural-shape/object-methods.md`
649
+
650
+ # `v.object({...})` — method reference
651
+
652
+ Picking guide for structural validators is in [`@warlock.js/seal/define-structural-shape/SKILL.md`](@warlock.js/seal/define-structural-shape/SKILL.md). For field-level chaining (`.required` / `.optional` / `.attribute`), see [`@warlock.js/seal/compose-seal-modifiers/SKILL.md`](@warlock.js/seal/compose-seal-modifiers/SKILL.md).
653
+
654
+ ## Schema composition
655
+
656
+ These return a new `ObjectValidator` with a transformed schema. The TypeScript inference follows correctly — `Infer<>` reflects the post-composition shape.
657
+
658
+ ### `.extend(schemaOrValidator)` — add fields, keep config
659
+
660
+ ```ts
661
+ const baseUser = v.object({
662
+ name: v.string(),
663
+ email: v.string().email(),
664
+ }).allowUnknown();
665
+
666
+ const adminUser = baseUser.extend({
667
+ role: v.string().oneOf(["admin", "superadmin"]),
668
+ });
669
+ // adminUser type: { name; email; role } — keeps allowUnknown()
670
+ ```
671
+
672
+ Accepts a plain schema object **or** another `ObjectValidator` (only its schema is used — config is ignored). Use for reusable field collections (e.g. timestamp fields).
673
+
674
+ ### `.merge(otherValidator)` — combine, override config
675
+
676
+ ```ts
677
+ const base = v.object({ name: v.string() }).allowUnknown();
678
+ const audit = v.object({
679
+ createdAt: v.date(),
680
+ updatedAt: v.date(),
681
+ }).stripUnknown();
682
+
683
+ const merged = base.merge(audit);
684
+ // type: { name; createdAt; updatedAt }
685
+ // config: stripUnknown() from audit (overrides base's allowUnknown)
686
+ ```
687
+
688
+ `.merge` combines schemas **and** configurations — the other validator wins. Rules, mutators, transformers, and attribute display names from both validators are appended.
689
+
690
+ ### `.pick(...keys)` — keep only specified fields
691
+
692
+ ```ts
693
+ const fullUser = v.object({
694
+ id: v.int(),
695
+ name: v.string(),
696
+ email: v.string().email(),
697
+ password: v.string(),
698
+ });
699
+
700
+ const loginSchema = fullUser.pick("email", "password");
701
+ // type: { email; password }
702
+ ```
703
+
704
+ Returns `ObjectValidator<Pick<TSchema, K>>`. Keeps original config (`allowUnknown`, etc.).
705
+
706
+ ### `.without(...keys)` — drop specified fields
707
+
708
+ ```ts
709
+ const updateSchema = fullUser.without("id");
710
+ // type: { name; email; password }
711
+ ```
712
+
713
+ Returns `ObjectValidator<Omit<TSchema, K>>`. Inverse of `.pick`. Keeps original config.
714
+
715
+ ### `.partial(...keys?)` — mark fields optional
716
+
717
+ ```ts
718
+ fullUser.partial() // every field becomes optional
719
+ fullUser.partial("password") // only `password` becomes optional
720
+ ```
721
+
722
+ Walks the schema and applies `.optional()` to each named field (or all if no keys given). `Infer<>` makes those keys optional.
723
+
724
+ ### `.requiredFields(...keys?)` — mark fields required
725
+
726
+ ```ts
727
+ const partialUser = fullUser.partial(); // all optional
728
+ const updateUser = partialUser.requiredFields("id", "email");
729
+ // id and email are required again, others stay optional
730
+ ```
731
+
732
+ Inverse of `.partial`.
733
+
734
+ ## Unknown-keys policy
735
+
736
+ By default, extra keys in input are silently dropped from `data` (no error, no forward).
737
+
738
+ | Method | Effect |
739
+ |---|---|
740
+ | `.allowUnknown(allow = true)` | extra **direct-child** keys forward as-is |
741
+ | `.stripUnknown()` | explicit drop (mutator-based — affects `data` shape) |
742
+ | `.allow(...keys)` | whitelist specific extras to forward without validation |
743
+
744
+ `.allowUnknown()` only affects direct children — nested objects keep their own policies. For a fully permissive object including nested children, set `.allowUnknown()` on each level.
745
+
746
+ ## Object-level mutators
747
+
748
+ | Method | Args | Effect |
749
+ |---|---|---|
750
+ | `.trim(recursive?)` | default `true` | recursively trim string values across the object |
751
+
752
+ For per-field mutators, attach on the field validator instead.
753
+
754
+ ## Cross-field rules — context
755
+
756
+ The cross-field methods (`.sameAs`, `.requiredIf`, `.requiredWith`, etc.) are **field-level**, not object-level — you call them on the field validator inside `v.object`. The object validator's job is to hand them the parent context so sibling resolution works:
757
+
758
+ ```ts
759
+ v.object({
760
+ password: v.string(),
761
+ passwordConfirm: v.string().sameAs("password"),
762
+ })
763
+ ```
764
+
765
+ If you call cross-field rules outside a `v.object`, sibling resolution silently passes — there's nobody to compare against.
766
+
767
+ ## `Infer<>` semantics
768
+
769
+ ```ts
770
+ Infer<typeof userSchema>
771
+ // { reqField: T; optField?: T }
772
+ ```
773
+
774
+ - Required fields → required keys
775
+ - `.optional()` fields → optional keys (`?:`)
776
+ - `.omit()` / `.exclude()` fields → dropped from the inferred type
777
+ - `v.computed<T>()` / `v.managed<T>()` → present as `T` in inferred output (they produce values)
778
+
779
+ ## Common chains
780
+
781
+ ```ts
782
+ // User CRUD trio from one base
783
+ const baseUser = v.object({
784
+ id: v.int(),
785
+ name: v.string(),
786
+ email: v.string().email(),
787
+ password: v.string(),
788
+ });
789
+
790
+ const createUser = baseUser.without("id");
791
+ const updateUser = baseUser.partial().requiredFields("id");
792
+ const loginUser = baseUser.pick("email", "password");
793
+
794
+ // Reusable timestamps
795
+ const timestamps = v.object({
796
+ createdAt: v.date(),
797
+ updatedAt: v.date(),
798
+ });
799
+
800
+ const userWithAudit = baseUser.extend(timestamps);
801
+
802
+ // Permissive container that forwards extras
803
+ const eventEnvelope = v.object({
804
+ type: v.literal("user.created", "user.updated"),
805
+ payload: v.object({}).allowUnknown(),
806
+ }).allowUnknown();
807
+
808
+ // Confirmation pattern with omit
809
+ const signupSchema = v.object({
810
+ password: v.string().strongPassword(),
811
+ passwordConfirm: v.string().sameAs("password").omit(),
812
+ email: v.string().email(),
813
+ });
814
+ // Infer<> = { password; email } — passwordConfirm omitted from output
815
+ ```
816
+
817
+
818
+ ## extend-seal-with-plugins `@warlock.js/seal/extend-seal-with-plugins/SKILL.md`
819
+
820
+ ---
821
+ name: extend-seal-with-plugins
822
+ description: 'Author a custom seal plugin to add validator methods (`.slug`, `.postalCode`, etc) — `SealPlugin` shape, `registerPlugin` lifecycle, TS prototype augmentation. Triggers: `SealPlugin`, `registerPlugin`, `unregisterPlugin`, `hasPlugin`, `getInstalledPlugins`, `StringValidator`, `NumberValidator`, `DateValidator`, `BaseValidator`, `install`, `uninstall`; "how do I add a custom validator method", "write a seal plugin", "extend v.string with .slug", "module augmentation for seal"; typical import `import { StringValidator, registerPlugin, type SealPlugin } from "@warlock.js/seal"`. Skip: built-in primitives — `@warlock.js/seal/pick-seal-primitive/SKILL.md`; bridge typing — `@warlock.js/seal/bridge-standard-schema/SKILL.md`; competing `zod` `.refine`/`.transform`.'
823
+ ---
824
+
825
+ # Extend seal with plugins
826
+
827
+ Seal exposes a plugin system so you can add validator methods without forking the package. A plugin is an object with `name`, optional `version`/`description`, and an `install` function that runs once when the plugin is registered. The standard pattern is to `Object.assign(StringValidator.prototype, { ... })` to graft new methods onto a validator class.
828
+
829
+ ## When to reach for a plugin
830
+
831
+ - The validator method you want **does not exist** in built-in seal — check [`@warlock.js/seal/pick-seal-primitive/SKILL.md`](@warlock.js/seal/pick-seal-primitive/SKILL.md) and its method references first.
832
+ - The validation is **stable and reusable** across modules — domain-specific formats (IBAN, postal codes, tax IDs, license plates, internal ID schemes).
833
+ - You want the **chainable syntax** — `v.string().slug()` reads better than `v.string().pattern(/.../).addMutator(s => slugify(s))` at every call site.
834
+
835
+ **Don't** reach for a plugin when a one-off `.pattern()` would do. The boilerplate (declare module, register on boot) is justified only when you'll call the new method many times.
836
+
837
+ ## The plugin shape
838
+
839
+ ```ts
840
+ import type { SealPlugin } from "@warlock.js/seal";
841
+
842
+ type SealPlugin = {
843
+ name: string; // unique identifier — duplicates warn and skip install
844
+ version?: string;
845
+ description?: string;
846
+ install: (context: { name: string; version?: string }) => void | Promise<void>;
847
+ uninstall?: () => void | Promise<void>;
848
+ };
849
+ ```
850
+
851
+ The `install` function is where you add methods. Typically you patch a validator class prototype:
852
+
853
+ ```ts
854
+ import { StringValidator, type SealPlugin } from "@warlock.js/seal";
855
+
856
+ export const slugPlugin: SealPlugin = {
857
+ name: "slug",
858
+ version: "1.0.0",
859
+ description: "Adds .slug() — pattern-only slug validation",
860
+
861
+ install() {
862
+ Object.assign(StringValidator.prototype, {
863
+ slug(this: StringValidator, errorMessage?: string) {
864
+ return this.pattern(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, errorMessage);
865
+ },
866
+ });
867
+ },
868
+ };
869
+ ```
870
+
871
+ `uninstall` is optional. Provide it when your plugin needs to clean up — e.g. removing prototype methods for hot-reload scenarios. Most production plugins skip it; methods grafted at boot stay for the process lifetime.
872
+
873
+ ## Registering plugins
874
+
875
+ ```ts
876
+ import { registerPlugin, unregisterPlugin, hasPlugin, getInstalledPlugins } from "@warlock.js/seal";
877
+
878
+ await registerPlugin(slugPlugin);
879
+ // console.warn if "slug" is already installed; otherwise install() runs and the plugin is tracked.
880
+
881
+ hasPlugin("slug"); // → true
882
+ getInstalledPlugins(); // → [slugPlugin]
883
+
884
+ await unregisterPlugin("slug");
885
+ // runs slugPlugin.uninstall?.(); removes from registry.
886
+ ```
887
+
888
+ `registerPlugin` is async (the `install` function may be async). Await it during boot so the methods are available before the first request.
889
+
890
+ **Where to register:** the conventional place in a Warlock app is a side-effect file loaded by `warlock.config.ts` — e.g. `src/setup/seal-plugins.ts`:
891
+
892
+ ```ts title="src/setup/seal-plugins.ts"
893
+ import { registerPlugin } from "@warlock.js/seal";
894
+ import { slugPlugin } from "./plugins/slug-plugin";
895
+ import { postalCodePlugin } from "./plugins/postal-code-plugin";
896
+
897
+ export async function setupSealPlugins() {
898
+ await registerPlugin(slugPlugin);
899
+ await registerPlugin(postalCodePlugin);
900
+ }
901
+ ```
902
+
903
+ Then call `setupSealPlugins()` in a bootstrap connector. Registering at top-level module scope works too (it's idempotent — duplicates warn and skip), but explicit setup is clearer.
904
+
905
+ ## TypeScript — declare the new methods
906
+
907
+ `Object.assign` on a prototype is invisible to TypeScript. Declare the new methods with module augmentation so call sites compile:
908
+
909
+ ```ts title="src/setup/seal-plugins.types.ts"
910
+ import "@warlock.js/seal";
911
+
912
+ declare module "@warlock.js/seal" {
913
+ interface StringValidator {
914
+ /** Pattern-only slug — `"hello-world"`, not `"Hello World"`. */
915
+ slug(errorMessage?: string): StringValidator;
916
+ }
917
+ }
918
+ ```
919
+
920
+ After this file is included in the project's `tsconfig.json` (via `include` or a side-effect import), `v.string().slug()` autocompletes and type-checks everywhere.
921
+
922
+ **Important.** The augmentation has to declare on the **class** (`StringValidator`), not the factory return type. The factory return widens with `& StandardSchemaV1<...>` (see [`@warlock.js/seal/bridge-standard-schema/SKILL.md`](@warlock.js/seal/bridge-standard-schema/SKILL.md)) — augmentations on the intersection don't propagate. Patch the class, augment the class; the factory return picks up the new methods through structural inference.
923
+
924
+ ## Larger example — postal codes per country
925
+
926
+ ```ts
927
+ import { StringValidator, type SealPlugin } from "@warlock.js/seal";
928
+
929
+ const PATTERNS: Record<string, RegExp> = {
930
+ US: /^\d{5}(?:-\d{4})?$/,
931
+ DE: /^\d{5}$/,
932
+ UK: /^[A-Z]{1,2}\d[A-Z\d]? \d[A-Z]{2}$/i,
933
+ EG: /^\d{5}$/,
934
+ };
935
+
936
+ export const postalCodePlugin: SealPlugin = {
937
+ name: "postal-code",
938
+
939
+ install() {
940
+ Object.assign(StringValidator.prototype, {
941
+ postalCode(this: StringValidator, country: keyof typeof PATTERNS, errorMessage?: string) {
942
+ const pattern = PATTERNS[country];
943
+
944
+ if (!pattern) {
945
+ throw new Error(`postalCode: unknown country "${country}"`);
946
+ }
947
+
948
+ return this.pattern(pattern, errorMessage ?? `Invalid ${country} postal code`);
949
+ },
950
+ });
951
+ },
952
+ };
953
+ ```
954
+
955
+ ```ts
956
+ // Module augmentation
957
+ declare module "@warlock.js/seal" {
958
+ interface StringValidator {
959
+ postalCode(country: "US" | "DE" | "UK" | "EG", errorMessage?: string): StringValidator;
960
+ }
961
+ }
962
+
963
+ // Use site
964
+ const addressSchema = v.object({
965
+ country: v.literal("US", "DE", "UK", "EG"),
966
+ postal: v.string().postalCode("DE"),
967
+ });
968
+ ```
969
+
970
+ ## Patterns beyond `StringValidator`
971
+
972
+ The same approach works on any validator class. Pick the right prototype:
973
+
974
+ - `StringValidator` — string methods (`.slug`, `.postalCode`, `.licensePlate`).
975
+ - `NumberValidator` / `IntValidator` / `FloatValidator` — number methods.
976
+ - `DateValidator` — date methods (`.businessDayInCountry("US")`).
977
+ - `ArrayValidator` / `ObjectValidator` — structural methods (rarer).
978
+ - `BaseValidator` — universal methods (rare — usually a sign you want a separate `v.something()` factory instead).
979
+
980
+ For a method that creates a **new validator** (not chained from an existing one), expose it as a regular function alongside `v` rather than patching the factory. E.g. export `iban()` from your plugin module that returns a configured `v.string()`.
981
+
982
+ ## Introspection — checking what's loaded
983
+
984
+ ```ts
985
+ hasPlugin("slug"); // boolean
986
+ getInstalledPlugins(); // SealPlugin[]
987
+ ```
988
+
989
+ Use these in startup diagnostics or in tests that need to assert a plugin is registered before exercising a method that depends on it.
990
+
991
+ ## Things NOT to do
992
+
993
+ - Don't `Object.assign(BaseValidator.prototype, ...)` for type-specific methods. The method would exist on every validator (`v.boolean().slug()` typechecks but breaks at runtime). Patch the narrowest class that owns the method.
994
+ - Don't forget the module augmentation. Without it, the new methods exist at runtime but TS rejects every call site.
995
+ - Don't make the plugin's `install` function depend on shared state mutable from elsewhere. Plugins should be idempotent — installing twice (or registering across hot-reloads) should not break anything.
996
+ - Don't ship a plugin that overrides a built-in method without a clear reason. If you must, `uninstall` should restore the original — but the better path is a different method name.
997
+ - Don't author one plugin per method. Group related methods (e.g. "country-specific validators") into one plugin so the install/uninstall lifecycle is coherent.
998
+
999
+
1000
+ ## generate-json-schema `@warlock.js/seal/generate-json-schema/SKILL.md`
1001
+
1002
+ ---
1003
+ name: generate-json-schema
1004
+ description: 'Generate JSON Schema via `schema.toJsonSchema(target)` — `draft-2020-12` / `draft-07` / `openapi-3.0` / `openai-strict`. Triggers: `toJsonSchema`, `JsonSchemaTarget`, `draft-2020-12`, `draft-07`, `openapi-3.0`, `openai-strict`, `response_format`, `additionalProperties`, `nullable`; "how do I generate JSON Schema from seal", "OpenAI structured outputs from schema", "OpenAPI 3.0 nullable", "json_schema strict mode"; typical import `import { v } from "@warlock.js/seal"`. Skip: foundations — `@warlock.js/seal/seal-basics/SKILL.md`; bridge typing — `@warlock.js/seal/bridge-standard-schema/SKILL.md`; competing libs `zod-to-json-schema`, `ajv`, `@anatine/zod-openapi`.'
1005
+ ---
1006
+
1007
+ # JSON Schema generation
1008
+
1009
+ Every seal validator exposes `toJsonSchema(target)`. The result is a plain object — pass it straight to OpenAI's `response_format`, an OpenAPI spec, a UI form builder, or anywhere else JSON Schema is the contract.
1010
+
1011
+ ```ts
1012
+ const userSchema = v.object({
1013
+ email: v.string().email(),
1014
+ age: v.int().min(13).optional(),
1015
+ });
1016
+
1017
+ userSchema.toJsonSchema("draft-2020-12");
1018
+ // {
1019
+ // type: "object",
1020
+ // properties: {
1021
+ // email: { type: "string", format: "email" },
1022
+ // age: { type: "integer", minimum: 13 },
1023
+ // },
1024
+ // required: ["email"],
1025
+ // additionalProperties: false,
1026
+ // }
1027
+ ```
1028
+
1029
+ ## The four targets
1030
+
1031
+ ```ts
1032
+ type JsonSchemaTarget =
1033
+ | "draft-2020-12" // default — modern JSON Schema
1034
+ | "draft-07" // older tooling, Swagger 2.0
1035
+ | "openapi-3.0" // uses { nullable: true } instead of type unions
1036
+ | "openai-strict" // OpenAI Structured Outputs strict mode
1037
+ ```
1038
+
1039
+ Pick by consumer:
1040
+
1041
+ | Consumer | Target |
1042
+ | --- | --- |
1043
+ | Modern tooling, no specific reason otherwise | `"draft-2020-12"` |
1044
+ | Swagger 2.0 / older OpenAPI / older form builders | `"draft-07"` |
1045
+ | OpenAPI 3.0 spec (uses `nullable: true`) | `"openapi-3.0"` |
1046
+ | OpenAI `response_format: { type: "json_schema", strict: true }` | `"openai-strict"` |
1047
+
1048
+ ## OpenAI structured outputs (`openai-strict`)
1049
+
1050
+ This target encodes the quirks of OpenAI's strict mode:
1051
+
1052
+ - **Every field listed in `required`** — strict mode forbids leaving fields out.
1053
+ - **Optional fields encoded as `type: ["T", "null"]`** instead of being omitted from `required`.
1054
+ - **`additionalProperties: false` on every object.**
1055
+
1056
+ ```ts
1057
+ const schema = v.object({
1058
+ reply: v.string(),
1059
+ citations: v.array(v.string()).optional(),
1060
+ });
1061
+
1062
+ schema.toJsonSchema("openai-strict");
1063
+ // {
1064
+ // type: "object",
1065
+ // properties: {
1066
+ // reply: { type: "string" },
1067
+ // citations: { type: ["array", "null"], items: { type: "string" } },
1068
+ // },
1069
+ // required: ["reply", "citations"], // every field listed
1070
+ // additionalProperties: false,
1071
+ // }
1072
+ ```
1073
+
1074
+ Hand to OpenAI:
1075
+
1076
+ ```ts
1077
+ import OpenAI from "openai";
1078
+
1079
+ const completion = await openai.chat.completions.create({
1080
+ model: "gpt-4o",
1081
+ messages: [...],
1082
+ response_format: {
1083
+ type: "json_schema",
1084
+ json_schema: {
1085
+ name: "user_reply",
1086
+ strict: true,
1087
+ schema: schema.toJsonSchema("openai-strict"),
1088
+ },
1089
+ },
1090
+ });
1091
+ ```
1092
+
1093
+ In `@warlock.js/ai`, this happens automatically when you set `output: schema` on a supervisor / agent — the runtime picks `openai-strict` for OpenAI providers. You only call `toJsonSchema()` directly when integrating with a non-warlock OpenAI usage.
1094
+
1095
+ ## OpenAPI 3.0 nullable
1096
+
1097
+ ```ts
1098
+ v.string().nullable().toJsonSchema("openapi-3.0");
1099
+ // { type: "string", nullable: true }
1100
+
1101
+ v.string().nullable().toJsonSchema("draft-2020-12");
1102
+ // { type: ["string", "null"] }
1103
+ ```
1104
+
1105
+ OpenAPI 3.0 uses the boolean `nullable` keyword instead of a type union. Use this target when generating a `paths.openapi.yaml` consumed by Swagger UI or codegen tools.
1106
+
1107
+ ## What's representable
1108
+
1109
+ Cleanly mapped:
1110
+
1111
+ - `v.string()` — `{ type: "string" }` (with `format: email/url/uuid`, `pattern`, `minLength`, `maxLength`, `enum`)
1112
+ - `v.int()` / `v.float()` — `{ type: "integer" | "number" }` (with `minimum`, `maximum`, `multipleOf`)
1113
+ - `v.boolean()` — `{ type: "boolean" }`
1114
+ - `v.date()` — `{ type: "string", format: "date-time" | "date" | "time" }` (format derived from transformer if applicable)
1115
+ - `v.literal(values)` — `{ const: value }` (single) or `{ enum: [...] }` (multiple)
1116
+ - `v.array(item)` — `{ type: "array", items: ... }` (with `minItems`, `maxItems` from length rules; `.unique()`/`.sorted()` are runtime-only and not emitted)
1117
+ - `v.object({...})` — `{ type: "object", properties, required, additionalProperties }`
1118
+ - `v.union([...])` — `{ oneOf: [...] }`
1119
+ - `v.tuple([...])` — `{ type: "array", prefixItems: [...] }` (draft-2020-12) or `{ type: "array", items: [...] }` (draft-07)
1120
+ - `v.nullable()` — type union or `nullable: true` per target
1121
+
1122
+ ## What's silently dropped
1123
+
1124
+ Some seal constructs have no JSON Schema representation:
1125
+
1126
+ - **Cross-field rules** (`sameAs`, `requiredIf`, `requiredWith`, etc.) — runtime-only. The generated schema describes the *shape*, not the inter-field invariants.
1127
+ - **Transformers and mutators** — output reshaping doesn't appear in the schema; the schema reflects *post-mutator, pre-transformer* shape (since that's what rules see and what the LLM is asked to produce for `openai-strict`).
1128
+ - **`v.computed` / `v.managed`** — **skipped** entirely by the parent `v.object`; they never appear in `properties`. They aren't part of the data contract. (Calling `.toJsonSchema()` directly on one throws — the parent object is responsible for skipping them.)
1129
+ - **`v.instanceof(Ctor)`** — produces `{}`. Class identity isn't expressible. For `File`, attach `{ type: "string", format: "binary" }` manually after generation if needed for OpenAPI.
1130
+ - **`v.any()`** — produces `{}` deliberately (any value is valid).
1131
+
1132
+ Boolean rules `accepted` / `declined` and similar coercion-style rules are also dropped — JSON Schema doesn't have a notion of "yes/no/on/off" beyond `enum`.
1133
+
1134
+ ## When the generated schema rejects valid data
1135
+
1136
+ If the schema validator itself accepts data but the *generated* JSON Schema rejects the same data downstream, the cause is usually one of:
1137
+
1138
+ - **Cross-field rule.** The generated schema doesn't enforce it, but a separate consumer might. (Or the runtime check fired at a different stage.)
1139
+ - **Transformer running on the wrong side.** The schema describes the input shape (or strict-mode normalized form). If your transformer reshapes `Date` to ISO string for `data`, the *input* still needs to be a Date-parseable thing.
1140
+ - **`openai-strict` quirk.** Optional fields show as `["T", "null"]` rather than omitted — if the model omits them entirely (without sending `null`), strict mode fails. The fix is on the prompt side: tell the model to send `null` for unused fields.
1141
+
1142
+ ## Cost note
1143
+
1144
+ Generating JSON Schema is cheap (pure-function tree walk), so don't worry about caching the result for schemas that change at startup. For dynamic schemas built per-request, generate per-request — there's no shared mutable state.
1145
+
1146
+
1147
+ ## handle-seal-errors `@warlock.js/seal/handle-seal-errors/SKILL.md`
1148
+
1149
+ ---
1150
+ name: handle-seal-errors
1151
+ description: 'Read `ValidationResult` — `isValid`, `errors[]`, `data`. Branch on `error.type`, customize messages, hook translation. Triggers: `ValidationResult`, `ValidationError`, `validate`, `isValid`, `errors`, `data`, `error.type`, `error.input`, `error.error`, `translationParams`, `.attribute`, `SealConfig`; "how to read seal errors", "branch on a specific rule failure", "customize validation error message", "translate seal error", "surface validation errors as 422"; typical import `import { validate, v } from "@warlock.js/seal"`. Skip: modifiers — `@warlock.js/seal/compose-seal-modifiers/SKILL.md`; structural shapes — `@warlock.js/seal/define-structural-shape/SKILL.md`; competing libs `zod` `.safeParse`, `yup` `ValidationError`, `joi`.'
1152
+ ---
1153
+
1154
+ # `ValidationResult` — reading errors
1155
+
1156
+ `validate(schema, data)` never throws. It returns a `ValidationResult`:
1157
+
1158
+ ```ts
1159
+ type ValidationResult = {
1160
+ isValid: boolean;
1161
+ data: any; // shape after mutators + transformers (the validated value)
1162
+ errors: ValidationError[];
1163
+ };
1164
+
1165
+ type ValidationError = {
1166
+ type: string; // rule type that failed — "required", "email", "min", "string", ...
1167
+ error: string; // resolved message (translated, with attribute substitution)
1168
+ input: string; // input field name — "email" or "address.city"
1169
+ };
1170
+ ```
1171
+
1172
+ Branch on `isValid` first; reach for `errors[]` only when you need to act on a specific failure.
1173
+
1174
+ ## Basic flow
1175
+
1176
+ ```ts
1177
+ import { validate, v } from "@warlock.js/seal";
1178
+
1179
+ const schema = v.object({
1180
+ email: v.string().email(),
1181
+ age: v.int().min(13).optional(),
1182
+ });
1183
+
1184
+ const result = await validate(schema, input);
1185
+
1186
+ if (result.isValid) {
1187
+ return result.data; // typed as the inferred shape (post-transformer)
1188
+ }
1189
+
1190
+ return {
1191
+ status: 422,
1192
+ body: { errors: result.errors },
1193
+ };
1194
+ ```
1195
+
1196
+ ## Branching on a specific rule
1197
+
1198
+ ```ts
1199
+ const result = await validate(schema, input);
1200
+
1201
+ if (!result.isValid) {
1202
+ const emailMissing = result.errors.find(
1203
+ e => e.input === "email" && e.type === "required",
1204
+ );
1205
+ if (emailMissing) {
1206
+ return { redirect: "/signup", reason: "no email" };
1207
+ }
1208
+
1209
+ const ageInvalid = result.errors.find(
1210
+ e => e.input === "age" && (e.type === "int" || e.type === "min"),
1211
+ );
1212
+ if (ageInvalid) {
1213
+ return { error: "Age must be 13 or older" };
1214
+ }
1215
+ }
1216
+ ```
1217
+
1218
+ The `type` field is the **stable** identifier — the message is human-facing and may be localized. Branch on `type`, never on the message string.
1219
+
1220
+ ## Common rule type names
1221
+
1222
+ These are the strings you'll see in `error.type`:
1223
+
1224
+ The `type` is the rule's own `name` field — not the method you called. Several methods map to one shared rule name (e.g. `.min()` / `.minLength()` on a string both surface as `minLength`; `.sameAs()` surfaces as `equalsField`). The table below lists the actual `type` strings:
1225
+
1226
+ | Type | Produced by |
1227
+ | --- | --- |
1228
+ | `required`, `present` | `.required()`, `.present()` (note: `.optional()` has no error type — it clears the required rule) |
1229
+ | `requiredIf`, `requiredWith`, `requiredWithout`, `requiredUnless` | conditional required methods |
1230
+ | `string`, `number`, `int`, `float`, `boolean`, `scalar`, `object`, `array`, `date` | type guards from `matchesType` |
1231
+ | `minLength`, `maxLength`, `betweenLength`, `length` | string / array length rules (`.min`/`.max` on a string alias to `minLength`/`maxLength`) |
1232
+ | `min`, `max`, `betweenNumbers` | number range rules (`.min`/`.max`/`.between` on a number) |
1233
+ | `email`, `url`, `uuid`, `pattern`, `matches` | string format rules (`.pattern()` → `pattern`) |
1234
+ | `literal`, `enum`, `in`, `allowedValues`, `notAllowedValues` | value-membership rules (`.oneOf` aliases `in`; `.notIn`/`.forbids` → `notAllowedValues`; `.allowsOnly` → `allowedValues`) |
1235
+ | `instanceof` | `v.instanceof(Ctor)` |
1236
+ | `equalsField`, `notEqualsField` | cross-field equality (`.sameAs` → `equalsField`; `.differentFrom` → `notEqualsField`) |
1237
+ | `minDate`, `maxDate`, `beforeField`, `afterField`, `today`, `past`, `future`, `weekDay`, `weekend`, `businessDay`, `birthday` | date rules (`.min`/`.max` → `minDate`/`maxDate`; `.before`/`.after` → `beforeField`/`afterField`) |
1238
+
1239
+ If you write custom rules, the `type` name you set on the rule object is what shows up here. Pick stable, kebab-or-camel-case names — they become a public API.
1240
+
1241
+ ## Customizing error messages
1242
+
1243
+ Two layers:
1244
+
1245
+ ```ts
1246
+ v.string().email("Please enter a valid email address").required("Email is required");
1247
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
1248
+ // per-rule override per-rule override
1249
+ ```
1250
+
1251
+ Each chain method takes an optional `errorMessage` as its last argument. That overrides the rule's `defaultErrorMessage`. Use it when a single rule needs a tailored message in a specific schema.
1252
+
1253
+ For project-wide message overrides, hook into the translation layer (the framework calls `resolveTranslation` with the rule context — wire up your own `t()` function via `SealConfig`).
1254
+
1255
+ ## Translation params
1256
+
1257
+ Rules can stash dynamic substitution params on the context. The default messages reference them:
1258
+
1259
+ ```
1260
+ "The :input must be at least :min characters"
1261
+ ```
1262
+
1263
+ `:input` is the field name (or its translated display name); `:min` and others come from rule-specific metadata. If you need to render the message yourself in a custom UI, the params are available on the rule's context.
1264
+
1265
+ For attribute display names ("email" → "Email Address"), use `.attributes({ email: "Email Address" })` on the parent `v.object` or pass via the `validate()` options. The `:input` placeholder picks up the configured display name.
1266
+
1267
+ ## When to throw
1268
+
1269
+ Don't wrap `validate()` in try/catch for *validation* failures — those land in `result.errors`. The only thing that *throws* is a programming bug:
1270
+
1271
+ - A rule's callback threw (e.g. you wrote `async validate() { throw new Error(...) }`).
1272
+ - A transformer threw on output.
1273
+ - A mutator threw on input.
1274
+
1275
+ Those are bugs — fix them. Don't try/catch them in app code as a way to handle bad input.
1276
+
1277
+ ## At the framework boundary
1278
+
1279
+ If you're surfacing seal errors through HTTP / RPC, the typical shape is:
1280
+
1281
+ ```ts
1282
+ if (!result.isValid) {
1283
+ return reply.code(422).send({
1284
+ error: "validation_failed",
1285
+ fields: result.errors.map(e => ({
1286
+ field: e.input,
1287
+ type: e.type,
1288
+ message: e.error,
1289
+ })),
1290
+ });
1291
+ }
1292
+ ```
1293
+
1294
+ Avoid leaking `result.data` back to the client when rejecting — it might contain transformed sensitive fields.
1295
+
1296
+ For server-side logs, log `errors[]` with the field paths and rule types; redact values unless you're certain the field isn't sensitive. The `@warlock.js/logger` redaction layer is the right place to enforce that.
1297
+
1298
+
1299
+ ## overview `@warlock.js/seal/overview/SKILL.md`
1300
+
1301
+ ---
1302
+ name: overview
1303
+ description: 'Front-door orientation for `@warlock.js/seal` — framework-agnostic, type-safe validation. The `v` factory builds schemas, `validate(schema, data)` runs them, `Infer<typeof schema>` extracts the type. Primitives, structural shapes (object/array/record/tuple/union/discriminatedUnion/lazy), modifiers, mutators, a plugin system, JSON-Schema export, and a Standard Schema bridge. TRIGGER when: code imports `v`, `validate`, or `Infer` from `@warlock.js/seal`; user asks "what does @warlock.js/seal do", "validation library for Warlock", "compare seal with zod / yup / valibot", "infer a type from a schema", "JSON schema from a validator", "Standard Schema interop"; package.json adds `@warlock.js/seal`. Skip: specific task already known — load the matching task skill directly (`seal-basics`, `pick-seal-primitive`, `define-structural-shape`, `compose-seal-modifiers`, `handle-seal-errors`, `generate-json-schema`, `bridge-standard-schema`, `extend-seal-with-plugins`); framework-specific validators (FileValidator, database rules) live in `@warlock.js/core/v`, not here.'
1304
+ ---
1305
+
1306
+ # `@warlock.js/seal` — overview
1307
+
1308
+ A type-safe, framework-agnostic validation library. You build a schema with the `v` factory, run it with `validate(schema, data)`, and pull the static type out with `Infer<typeof schema>`. One schema is the runtime check *and* the TypeScript type *and* (optionally) a JSON Schema.
1309
+
1310
+ Standalone — no framework required. Ships built-in with `@warlock.js/core`, which adds framework-specific validators (file uploads, database existence/uniqueness rules) on top.
1311
+
1312
+ ## When to reach for it
1313
+
1314
+ - You want a single source of truth for a shape — runtime validation, the TS type, and JSON Schema all from one declaration.
1315
+ - You'd reach for **zod** / **yup** / **valibot** but want the library the rest of Warlock already speaks (request validation, AI tool inputs, Cascade model schemas).
1316
+ - You need **JSON Schema output** for OpenAI structured outputs or an OpenAPI spec.
1317
+
1318
+ Skip if you only need framework-bound validators (file uploads, DB rules) — those live in `@warlock.js/core/v`, which extends this package.
1319
+
1320
+ ## The mental model in one paragraph
1321
+
1322
+ `v` is a builder: `v.string()`, `v.int()`, `v.object({...})`, `v.array(...)`, and so on, chained with modifiers (`.optional()`, `.nullable()`, `.default(...)`, `.min(...)`). `validate(schema, data)` returns a `ValidationResult` with `isValid`, `data` (the validated value), and `errors[]`. `Infer<typeof schema>` gives you the static type (with `Infer.Input` / `Infer.Output` distinguishing pre- and post-transform shapes). Because every schema implements Standard Schema, it slots into any `StandardSchemaV1<T>` consumer — and `schema.toJsonSchema(target)` emits JSON Schema for external tools.
1323
+
1324
+ ## Skills index
1325
+
1326
+ Eight task skills. Most schemas only need `seal-basics` + `pick-seal-primitive` + `define-structural-shape`.
1327
+
1328
+ ### Foundations
1329
+
1330
+ #### [`seal-basics/`](../seal-basics/SKILL.md)
1331
+ Start here. The `v` factory, `validate(schema, data)`, and `Infer<typeof schema>`.
1332
+
1333
+ ### Building schemas
1334
+
1335
+ #### [`pick-seal-primitive/`](../pick-seal-primitive/SKILL.md)
1336
+ Choose the right primitive — `string` / `int` / `literal` / `date` / `enum` / `computed` / `managed` / `instanceof` / `any`. Covers the close calls (`string` vs `scalar`, `int` vs `number`, `literal` vs `enum`).
1337
+
1338
+ #### [`define-structural-shape/`](../define-structural-shape/SKILL.md)
1339
+ Compose `v.object` / `v.array` / `v.record` / `v.tuple` / `v.union` / `v.discriminatedUnion` / `v.lazy` — object schemas, dynamic-keyed records, tagged unions, recursive shapes.
1340
+
1341
+ #### [`compose-seal-modifiers/`](../compose-seal-modifiers/SKILL.md)
1342
+ Cross-cutting modifiers — `.optional` / `.nullable` / `.default` / `.catch` / `.omit` / membership rules — plus the mutator-vs-transformer pipeline and `Infer.Input` vs `Infer.Output`.
1343
+
1344
+ ### Output + interop
1345
+
1346
+ #### [`handle-seal-errors/`](../handle-seal-errors/SKILL.md)
1347
+ Read a `ValidationResult` — `isValid`, `errors[]`, `data`. Branch on `error.type`, customize messages, hook translation.
1348
+
1349
+ #### [`generate-json-schema/`](../generate-json-schema/SKILL.md)
1350
+ `schema.toJsonSchema(target)` — draft-2020-12 / draft-07 / openapi-3.0 / openai-strict. For OpenAI structured outputs, OpenAPI specs, any JSON-Schema consumer.
1351
+
1352
+ #### [`bridge-standard-schema/`](../bridge-standard-schema/SKILL.md)
1353
+ Standard Schema interop — why a `StandardSchemaV1<T>` slot might reject a schema, the phantom-intersection at the `v` factory return, Cascade `Model<TSchema>` variance. For migrating off `as unknown as` casts.
1354
+
1355
+ #### [`extend-seal-with-plugins/`](../extend-seal-with-plugins/SKILL.md)
1356
+ Author a plugin to add validator methods (`.slug`, `.postalCode`, …) — the `SealPlugin` shape, `registerPlugin` lifecycle, TS prototype augmentation.
1357
+
1358
+ ## Configuration
1359
+
1360
+ `configureSeal({ ... })` sets global behavior (translation hooks, first-error-only mode); `getSealConfig()` reads it; `resetSealConfig()` clears it. Most apps call `configureSeal` once at boot to wire i18n.
1361
+
1362
+ ## What this package deliberately doesn't do
1363
+
1364
+ - **Framework-bound validation.** File-upload and database (exists/unique) rules live in `@warlock.js/core/v`, which builds on this package.
1365
+ - **Coercion by default.** Seal validates the shape you declare; reshaping is explicit via mutators/transformers, not silent coercion.
1366
+ - **Async-everywhere.** `validate()` is async to support rules that need it, but the core primitives are synchronous checks.
1367
+
1368
+ ## See also
1369
+
1370
+ - [`@warlock.js/cascade`](../../cascade/skills/overview/SKILL.md) — uses seal schemas as `Model.schema`.
1371
+ - [`@warlock.js/core`](../../core/skills/overview/SKILL.md) — re-exports `v` (aliased) and adds framework validators in `core/v`.
1372
+ - [`mongez-agent-kit-authoring-skills`](../../../../domains/shared/skills/) (load via agent-kit sync) — how this becomes `.claude/skills/warlock-js-seal-overview/`.
1373
+
1374
+
1375
+ ## pick-seal-primitive `@warlock.js/seal/pick-seal-primitive/SKILL.md`
1376
+
1377
+ ---
1378
+ name: pick-seal-primitive
1379
+ description: 'Pick the right `v` factory primitive — string / int / literal / date / enum / computed / managed / instanceof / any. Triggers: `v.string`, `v.email`, `v.number`, `v.int`, `v.float`, `v.numeric`, `v.boolean`, `v.scalar`, `v.date`, `v.literal`, `v.enum`, `v.instanceof`, `v.computed`, `v.managed`, `v.any`; "v.string vs v.scalar", "v.literal vs v.enum", "v.date vs v.instanceof(Date)", "what is v.computed"; typical import `import { v } from "@warlock.js/seal"`. Skip: structural shapes — `@warlock.js/seal/define-structural-shape/SKILL.md`; modifiers — `@warlock.js/seal/compose-seal-modifiers/SKILL.md`; competing libs `zod`, `valibot`, `yup`.'
1380
+ ---
1381
+
1382
+ # Picking the right primitive
1383
+
1384
+ This is the orientation skill — *which* primitive for *which* job. For the chainable methods on each (`.email()`, `.min()`, `.between()`, etc.), load the matching `*-methods.md` reference file in this skill folder.
1385
+
1386
+ ## Strings
1387
+
1388
+ ```ts
1389
+ v.string() // type: string — full surface in string-methods.md
1390
+ v.email() // shorthand for v.string().email()
1391
+ v.enum(["a", "b"]) // type: "a" | "b" — runs as v.string().oneOf, but the factory overload preserves the literal union
1392
+ ```
1393
+
1394
+ Reach for `v.string()` for any text input. `v.email()` is just sugar — switch back to `v.string().email().min(...)` when you need extra rules.
1395
+
1396
+ ## Numbers — pick by what you accept
1397
+
1398
+ | Validator | Accepts | When |
1399
+ |---|---|---|
1400
+ | `v.number()` | any finite number | accepts both integers and floats |
1401
+ | `v.int()` | integers only | rejects `1.5` |
1402
+ | `v.float()` | finite, non-integer | rejects `1` |
1403
+ | `v.numeric()` | numeric strings + numbers | form/query inputs that arrive as `"42"` — coerces to number |
1404
+
1405
+ All four share the same chain surface (see [`number-methods.md`](./number-methods.md)). Picking is about input acceptance, not chain power.
1406
+
1407
+ ## Booleans & scalars
1408
+
1409
+ ```ts
1410
+ v.boolean() // type: boolean — adds .accepted() / .declined() for form-style inputs
1411
+ v.scalar() // type: string | number | boolean — usually a smell pointing at a missing discriminator
1412
+ ```
1413
+
1414
+ Use `v.scalar()` only when the field truly accepts any of the three primitives. If it's "one of N specific values across types", `v.literal(...)` is cleaner.
1415
+
1416
+ ## Dates
1417
+
1418
+ ```ts
1419
+ v.date() // type: Date — normalizes strings/timestamps to Date, rich rule surface
1420
+ v.instanceof(Date) // type: Date — raw instanceof, no normalization, no rules
1421
+ ```
1422
+
1423
+ `v.date()` is the right tool 99% of the time — it ships `.min/.max/.before/.after/.weekDay/.minAge/...` and a built-in mutator that parses strings. `v.instanceof(Date)` is the escape hatch when you specifically need strict instance identity with zero coercion.
1424
+
1425
+ ## Literals & instances
1426
+
1427
+ ```ts
1428
+ v.literal("items") // type: "items"
1429
+ v.literal("draft", "published", "archived") // type: "draft" | "published" | "archived"
1430
+ v.literal(1, 2, 3) // type: 1 | 2 | 3
1431
+ v.literal(true) // type: true
1432
+
1433
+ v.instanceof(File) // type: File
1434
+ v.instanceof(Buffer) // type: Buffer
1435
+ v.instanceof(MyClass) // type: MyClass
1436
+ ```
1437
+
1438
+ **`v.literal` vs `v.string().oneOf([...])` vs `v.enum([...])`:**
1439
+
1440
+ - `v.literal("a", "b")` infers as `"a" | "b"` (literal narrowing). **Use this for discriminator fields.**
1441
+ - `v.string().oneOf(["a", "b"])` infers as `string` (loses literal types). Use when broad type is fine.
1442
+ - `v.enum(["a", "b"])` runs the same `oneOf` rule at runtime (it builds a `StringValidator().oneOf(...)`), but the `v.enum` factory overload **preserves the literal union** — it infers `"a" | "b"`, not `string`. Pass a TS enum object (`v.enum(Direction)`) and it uses `Object.values`, inferring `Direction[keyof Direction]`.
1443
+
1444
+ `v.instanceof(Ctor)` for File/Buffer/Uint8Array/custom classes. Returns `{}` from `toJsonSchema()` (not representable). For OpenAPI `File`, attach `{ type: "string", format: "binary" }` manually after generation.
1445
+
1446
+ ## `v.any` — escape hatch
1447
+
1448
+ ```ts
1449
+ v.any() // type: any — skips validation entirely
1450
+ ```
1451
+
1452
+ Reach for it when you genuinely don't care about the shape. Usually a smell — search PRs for it and ask whether a real schema would catch a class of bugs.
1453
+
1454
+ ## Derived: `v.computed` and `v.managed`
1455
+
1456
+ These two **don't validate input** — they produce a value as part of validation.
1457
+
1458
+ ```ts
1459
+ v.object({
1460
+ firstName: v.string(),
1461
+ lastName: v.string(),
1462
+ fullName: v.computed<string>((data) => `${data.firstName} ${data.lastName}`),
1463
+ createdAt: v.managed<Date>(() => new Date()),
1464
+ createdBy: v.managed<string>((context) => context.context?.userId),
1465
+ });
1466
+ ```
1467
+
1468
+ - **`v.computed`** runs after sibling validation; callback signature is `(data, context)` — `data` is the validated sibling object. Use for derived values (full name, hash of fields, computed totals). An optional second arg validates the result: `v.computed<string>(cb, v.string().min(3))`.
1469
+ - **`v.managed`** runs from `SchemaContext` only — callback signature is `(context)`. Caller-supplied extras passed to `validate(schema, data, { context })` land on `context.context`. Use for framework-injected values — timestamps, current user, request id. The callback is optional (`v.managed()`) for values the framework injects without a generator.
1470
+
1471
+ Both are **skipped** when their parent `v.object` generates JSON Schema — they never appear in `properties`, since they're runtime-only and not part of the JSON contract an LLM or external API consumer reads. Calling `.toJsonSchema()` *directly* on a `v.computed` / `v.managed` validator **throws** (it's a programming error — let the parent object skip them).
1472
+
1473
+ ## Quick map — "I need to validate…"
1474
+
1475
+ | Need | Reach for |
1476
+ |---|---|
1477
+ | Email | `v.string().email()` or `v.email()` |
1478
+ | URL | `v.string().url()` |
1479
+ | UUID | `v.string().uuid()` (see [`string-methods.md`](./string-methods.md)) |
1480
+ | Number 0–100 | `v.number().between(0, 100)` |
1481
+ | Positive integer | `v.int().positive()` |
1482
+ | One of N constants | `v.literal(...values)` |
1483
+ | One of TS enum values | `v.enum(MyEnum)` |
1484
+ | Date in the past | `v.date().past()` |
1485
+ | File upload | `v.instanceof(File)` |
1486
+ | Class instance (not Date) | `v.instanceof(Ctor)` |
1487
+ | Discriminated union | see [`@warlock.js/seal/define-structural-shape/SKILL.md`](@warlock.js/seal/define-structural-shape/SKILL.md) |
1488
+ | Derived value (computed from siblings) | `v.computed<T>(callback)` |
1489
+ | Framework-injected value | `v.managed<T>(callback)` |
1490
+ | Free-form / pass-through | `v.any()` (only when you've thought about it) |
1491
+
1492
+ ## Method-surface reference
1493
+
1494
+ Each primitive's full method list lives in a sibling file:
1495
+
1496
+ - [`string-methods.md`](./string-methods.md) — `.email` / `.url` / `.uuid` / `.pattern` / `.startsWith` / `.alpha` / `.trim` / `.slug` / `.mask` / `.base64Encode` / …
1497
+ - [`number-methods.md`](./number-methods.md) — `.min` / `.max` / `.between` / `.greaterThan` / `.positive` / `.even` / `.multipleOf` / `.minSibling` / `.round` / …
1498
+ - [`date-methods.md`](./date-methods.md) — `.min` / `.before` / `.after` / `.today` / `.past` / `.future` / `.weekDay` / `.minAge` / `.year` / `.quarter` / `.toISOString` / …
1499
+ - [`boolean-methods.md`](./boolean-methods.md) — `.accepted` / `.declined` / `.mustBeTrue` / `.mustBeFalse` / `.acceptedIf` / `.declinedWithout` / …
1500
+
1501
+ For cross-cutting modifiers (`.optional`/`.nullable`/`.default`/`.catch`/`.in`/`.oneOf`), see [`@warlock.js/seal/compose-seal-modifiers/SKILL.md`](@warlock.js/seal/compose-seal-modifiers/SKILL.md). For containers (object/array/record/tuple/union), see [`@warlock.js/seal/define-structural-shape/SKILL.md`](@warlock.js/seal/define-structural-shape/SKILL.md).
1502
+
1503
+ ## Things NOT to do
1504
+
1505
+ - Don't `new ObjectValidator()` (or any class) directly — factory returns carry the StandardSchema bridge that bare instantiation loses.
1506
+ - Don't pick `v.scalar` because "it's flexible". Flexibility at this layer usually means a missing discriminator — try `v.literal` or `v.union` first.
1507
+ - Don't reach for `v.instanceof(Date)` when `v.date()` works. The latter is purpose-built.
1508
+ - Don't use `v.string().oneOf(["a", "b"])` for discriminator fields where you need the literal type — use `v.literal("a", "b")`.
1509
+ - Don't expect `v.computed` / `v.managed` to validate input — they ignore input shape entirely. Reach for them only when *producing* a value.
1510
+
1511
+
1512
+ ### pick-seal-primitive/boolean-methods.md `@warlock.js/seal/pick-seal-primitive/boolean-methods.md`
1513
+
1514
+ # `v.boolean()` — method reference
1515
+
1516
+ Picking guide is in [`@warlock.js/seal/pick-seal-primitive/SKILL.md`](@warlock.js/seal/pick-seal-primitive/SKILL.md). Membership rules (`.in`/`.oneOf`) inherited from PrimitiveValidator — see [`@warlock.js/seal/compose-seal-modifiers/SKILL.md`](@warlock.js/seal/compose-seal-modifiers/SKILL.md).
1517
+
1518
+ ## Strict equality
1519
+
1520
+ | Method | Effect |
1521
+ |---|---|
1522
+ | `.mustBeTrue(msg?)` | strictly `=== true` (rejects `"yes"`, `1`, `"on"`) |
1523
+ | `.mustBeFalse(msg?)` | strictly `=== false` |
1524
+
1525
+ Use these when the field is a real boolean checkbox value — e.g. "agree to terms" must be exactly `true`, not a truthy string.
1526
+
1527
+ ## Form-style coercion — `accepted` / `declined`
1528
+
1529
+ The "accepted" rules treat `true`, `"yes"`, `"on"`, `1`, `"1"`, `"true"` as accepted. "Declined" treats their counterparts (`false`, `"no"`, `"off"`, `0`, etc.) as declined. Designed for form inputs where a checkbox/radio arrives as a string.
1530
+
1531
+ | Method | Effect |
1532
+ |---|---|
1533
+ | `.accepted(msg?)` | value must be accepted |
1534
+ | `.declined(msg?)` | value must be declined |
1535
+
1536
+ ## Conditional variants — accepted
1537
+
1538
+ | Method | Args | Effect |
1539
+ |---|---|---|
1540
+ | `.acceptedIf(field, value, msg?)` | sibling field equals value | must be accepted in that case |
1541
+ | `.acceptedUnless(field, value, msg?)` | sibling field equals value | must be accepted unless that's true |
1542
+ | `.acceptedIfRequired(field, msg?)` | sibling field is required | — |
1543
+ | `.acceptedIfPresent(field, msg?)` | sibling field is present | — |
1544
+ | `.acceptedWithout(field, msg?)` | sibling field is absent | — |
1545
+
1546
+ ## Conditional variants — declined
1547
+
1548
+ | Method | Args | Effect |
1549
+ |---|---|---|
1550
+ | `.declinedIf(field, value, msg?)` | sibling field equals value | must be declined in that case |
1551
+ | `.declinedUnless(field, value, msg?)` | sibling field equals value | must be declined unless that's true |
1552
+ | `.declinedIfRequired(field, msg?)` | — | — |
1553
+ | `.declinedIfPresent(field, msg?)` | — | — |
1554
+ | `.declinedWithout(field, msg?)` | — | — |
1555
+
1556
+ All conditional variants only run inside `v.object` — sibling resolution silently passes otherwise.
1557
+
1558
+ ## JSON Schema mapping
1559
+
1560
+ - `v.boolean()` → `{ type: "boolean" }`
1561
+ - `.mustBeTrue()` / `.mustBeFalse()` — not currently emitted (could add `const: true/false` in the future)
1562
+ - `.accepted()` / `.declined()` and their conditional variants — runtime coercion concerns, not representable
1563
+
1564
+ ## Common chains
1565
+
1566
+ ```ts
1567
+ // Strict consent checkbox
1568
+ v.boolean().mustBeTrue("You must accept the terms")
1569
+
1570
+ // Form-style "remember me" — accepts "on" / true / 1
1571
+ v.boolean().accepted().optional()
1572
+
1573
+ // Cross-field — newsletter must be accepted if subscriptionType = "premium"
1574
+ v.object({
1575
+ subscriptionType: v.string().oneOf(["free", "premium"]),
1576
+ newsletter: v.boolean().acceptedIf("subscriptionType", "premium"),
1577
+ })
1578
+
1579
+ // Marketing opt-in — declined unless region is GDPR-exempt
1580
+ v.object({
1581
+ region: v.string(),
1582
+ marketingOptIn: v.boolean().declinedUnless("region", "US"),
1583
+ })
1584
+ ```
1585
+
1586
+
1587
+ ### pick-seal-primitive/date-methods.md `@warlock.js/seal/pick-seal-primitive/date-methods.md`
1588
+
1589
+ # `v.date()` — method reference
1590
+
1591
+ `v.date()` ships a built-in mutator that normalizes strings, timestamps, and `Date` objects to a `Date` before rules run. Picking guide (`v.date()` vs `v.instanceof(Date)`) is in [`@warlock.js/seal/pick-seal-primitive/SKILL.md`](@warlock.js/seal/pick-seal-primitive/SKILL.md).
1592
+
1593
+ ## Range — global value comparison
1594
+
1595
+ | Method | Args | Example |
1596
+ |---|---|---|
1597
+ | `.min(dateOrField, msg?)` | inclusive `>=` | `v.date().min("2024-01-01")` or `v.date().min(new Date())` |
1598
+ | `.max(dateOrField, msg?)` | inclusive `<=` | `v.date().max(new Date())` |
1599
+ | `.before(dateOrField, msg?)` | strict `<` | `v.date().before(new Date())` |
1600
+ | `.after(dateOrField, msg?)` | strict `>` | `v.date().after(new Date())` |
1601
+ | `.between(start, end, msg?)` | inclusive range | `v.date().between(start, end)` |
1602
+
1603
+ Smart detection: a string with `-` or `/` is a date string; a plain string is a sibling field name.
1604
+
1605
+ ## Range — explicit sibling scope
1606
+
1607
+ | Method | Effect |
1608
+ |---|---|
1609
+ | `.minSibling(field, msg?)` | `>=` sibling field |
1610
+ | `.maxSibling(field, msg?)` | `<=` sibling field |
1611
+ | `.beforeSibling(field, msg?)` | `<` sibling field |
1612
+ | `.afterSibling(field, msg?)` | `>` sibling field |
1613
+ | `.sameAsField(field, msg?)` | `===` sibling field |
1614
+ | `.sameAsFieldSibling(field, msg?)` | `===` sibling field (explicit scope) |
1615
+
1616
+ Only run inside `v.object`. Not representable in JSON Schema.
1617
+
1618
+ ## Today / past / future
1619
+
1620
+ | Method | Effect |
1621
+ |---|---|
1622
+ | `.today(msg?)` | exactly today |
1623
+ | `.fromToday(msg?)` | today or future |
1624
+ | `.beforeToday(msg?)` | strictly before today |
1625
+ | `.afterToday(msg?)` | strictly after today |
1626
+ | `.past(msg?)` | any past date |
1627
+ | `.future(msg?)` | any future date |
1628
+
1629
+ ## Relative window
1630
+
1631
+ | Method | Args | Effect |
1632
+ |---|---|---|
1633
+ | `.withinDays(n, msg?)` | within N days past or future | — |
1634
+ | `.withinPastDays(n, msg?)` | within N days in the past | — |
1635
+ | `.withinFutureDays(n, msg?)` | within N days in the future | — |
1636
+
1637
+ ## Age
1638
+
1639
+ | Method | Args | Effect |
1640
+ |---|---|---|
1641
+ | `.age(years, msg?)` | exactly N years old |
1642
+ | `.minAge(years, msg?)` | at least N years old |
1643
+ | `.maxAge(years, msg?)` | at most N years old |
1644
+ | `.betweenAge(min, max, msg?)` | between min/max years |
1645
+ | `.birthday(minAge?, maxAge?, msg?)` | not in future, optional age range |
1646
+
1647
+ ## Weekday / weekend / business day
1648
+
1649
+ | Method | Args | Effect |
1650
+ |---|---|---|
1651
+ | `.weekDay(day, msg?)` | day = `"monday"` … `"sunday"` |
1652
+ | `.weekdays(days, msg?)` | array of weekdays |
1653
+ | `.weekend(msg?)` | Saturday or Sunday |
1654
+ | `.businessDay(msg?)` | Monday – Friday |
1655
+
1656
+ ## Period — month / year / quarter
1657
+
1658
+ | Method | Args | Effect |
1659
+ |---|---|---|
1660
+ | `.month(m, msg?)` | `m` = 1–12 (or `Month` enum) |
1661
+ | `.year(y, msg?)` | exact year |
1662
+ | `.quarter(q, msg?)` | `q` = 1–4 |
1663
+ | `.leapYear(msg?)` | year is a leap year |
1664
+ | `.minYear(yearOrField, msg?)` | year `>=` |
1665
+ | `.maxYear(yearOrField, msg?)` | year `<=` |
1666
+ | `.minMonth(mOrField, msg?)` | month `>=` |
1667
+ | `.maxMonth(mOrField, msg?)` | month `<=` |
1668
+ | `.minDay(dOrField, msg?)` | day-of-month `>=` |
1669
+ | `.maxDay(dOrField, msg?)` | day-of-month `<=` |
1670
+ | `.betweenYears(start, end, msg?)` | inclusive year range |
1671
+ | `.betweenMonths(start, end, msg?)` | inclusive month range |
1672
+ | `.betweenDays(start, end, msg?)` | inclusive day-of-month range |
1673
+
1674
+ Each `min*` / `max*` / `between*` accepts a sibling field name. Sibling-explicit variants exist: `.minYearSibling`, `.maxYearSibling`, `.minMonthSibling`, `.maxMonthSibling`, `.minDaySibling`, `.maxDaySibling`, `.betweenYearsSibling`, `.betweenMonthsSibling`, `.betweenDaysSibling`.
1675
+
1676
+ ## Time — hour / minute
1677
+
1678
+ | Method | Args | Effect |
1679
+ |---|---|---|
1680
+ | `.fromHour(h, msg?)` | h = 0–23, time `>= h:00` |
1681
+ | `.beforeHour(h, msg?)` | time `< h:00` |
1682
+ | `.betweenHours(start, end, msg?)` | inclusive hour range |
1683
+ | `.fromMinute(m, msg?)` | m = 0–59 |
1684
+ | `.beforeMinute(m, msg?)` | — |
1685
+ | `.betweenMinutes(start, end, msg?)` | inclusive minute range |
1686
+ | `.betweenTimes(start, end, msg?)` | "HH:MM" strings |
1687
+
1688
+ ## Format
1689
+
1690
+ | Method | Args | Effect |
1691
+ |---|---|---|
1692
+ | `.format(fmt, msg?)` | dayjs format string | input must match the format |
1693
+
1694
+ ## Mutators (pre-validation reshape)
1695
+
1696
+ | Method | Effect |
1697
+ |---|---|
1698
+ | `.toStartOfDay()` | 00:00:00.000 |
1699
+ | `.toEndOfDay()` | 23:59:59.999 |
1700
+ | `.toStartOfMonth()` | first day of month |
1701
+ | `.toEndOfMonth()` | last day of month |
1702
+ | `.toStartOfYear()` | January 1st |
1703
+ | `.toEndOfYear()` | December 31st |
1704
+ | `.addDays(n)` | shift by N days (negative = back) |
1705
+ | `.addMonths(n)` | shift by N months |
1706
+ | `.addYears(n)` | shift by N years |
1707
+ | `.addHours(n)` | shift by N hours |
1708
+ | `.toUTC()` | normalize to UTC |
1709
+
1710
+ Mutators run *before* rules. `v.date().addDays(7).future()` checks whether the shifted date is in the future.
1711
+
1712
+ ## Transformers (post-validation, reshape `data`)
1713
+
1714
+ | Method | Args | Effect |
1715
+ |---|---|---|
1716
+ | `.toISOString()` | — | `Date` → `"2026-01-15T00:00:00.000Z"` |
1717
+ | `.toTimestamp()` | — | `Date` → number (ms since epoch) |
1718
+ | `.toFormat(fmt)` | dayjs format string | `Date` → formatted string |
1719
+ | `.toDateOnly()` | — | `"YYYY-MM-DD"` |
1720
+ | `.toTimeOnly()` | — | `"HH:mm:ss"` |
1721
+
1722
+ Transformers shape the *output*. `Infer<>` still resolves to `Date` even if a transformer changes the runtime shape — `Infer` reads the validator type, not the transformer pipeline.
1723
+
1724
+ ## Defaults
1725
+
1726
+ | Method | Effect |
1727
+ |---|---|
1728
+ | `.defaultNow()` | shorthand for `.default(() => new Date())` |
1729
+
1730
+ ## JSON Schema mapping
1731
+
1732
+ - `v.date()` → `{ type: "string", format: "date-time" }` by default
1733
+ - After `.toDateOnly()` or `.format("YYYY-MM-DD")` → `{ type: "string", format: "date" }`
1734
+ - After `.toTimeOnly()` or `.format("HH:mm:ss")` → `{ type: "string", format: "time" }`
1735
+ - Sibling-scoped rules and most relative checks are not representable — silently omitted
1736
+
1737
+ ## Common chains
1738
+
1739
+ ```ts
1740
+ // Birthday — must be 13+ and in the past
1741
+ v.date().past().minAge(13)
1742
+
1743
+ // Reservation — future, business day, between hours
1744
+ v.date().future().businessDay().betweenHours(9, 17)
1745
+
1746
+ // Effective date range (cross-field)
1747
+ v.object({
1748
+ startsAt: v.date(),
1749
+ endsAt: v.date().afterSibling("startsAt"),
1750
+ })
1751
+
1752
+ // API response — emit ISO string
1753
+ v.date().toISOString()
1754
+
1755
+ // Event window — within 30 future days, normalized to UTC
1756
+ v.date().toUTC().withinFutureDays(30)
1757
+
1758
+ // Quarterly report
1759
+ v.date().quarter(1).year(2026)
1760
+
1761
+ // Date-only, end-of-day for inclusive comparisons
1762
+ v.date().toEndOfDay().toDateOnly()
1763
+ ```
1764
+
1765
+
1766
+ ### pick-seal-primitive/number-methods.md `@warlock.js/seal/pick-seal-primitive/number-methods.md`
1767
+
1768
+ # `v.number()` / `v.int()` / `v.float()` / `v.numeric()` — method reference
1769
+
1770
+ All four share this surface. The picking guide (which factory to call) is in [`@warlock.js/seal/pick-seal-primitive/SKILL.md`](@warlock.js/seal/pick-seal-primitive/SKILL.md). For `.optional()` / `.in()` / `.oneOf()`, see [`@warlock.js/seal/compose-seal-modifiers/SKILL.md`](@warlock.js/seal/compose-seal-modifiers/SKILL.md).
1771
+
1772
+ ## Range — global value comparison
1773
+
1774
+ | Method | Args | JSON Schema | Example |
1775
+ |---|---|---|---|
1776
+ | `.min(n, msg?)` | inclusive lower bound | `minimum: n` | `v.int().min(0)` |
1777
+ | `.max(n, msg?)` | inclusive upper bound | `maximum: n` | `v.int().max(100)` |
1778
+ | `.between(a, b, msg?)` | inclusive range | `minimum: a, maximum: b` | `v.number().between(0, 1)` |
1779
+ | `.greaterThan(n, msg?)` | strict `>` | `exclusiveMinimum: n` | `v.int().greaterThan(0)` |
1780
+ | `.gt(n, msg?)` | alias for `.greaterThan` | `exclusiveMinimum: n` | — |
1781
+ | `.lessThan(n, msg?)` | strict `<` | `exclusiveMaximum: n` | `v.int().lessThan(100)` |
1782
+ | `.lt(n, msg?)` | alias for `.lessThan` | `exclusiveMaximum: n` | — |
1783
+
1784
+ `.min` / `.max` / `.between` / `.greaterThan` / `.lessThan` accept a **string** as the value — interpreted as a sibling field name (smart detection):
1785
+
1786
+ ```ts
1787
+ v.object({
1788
+ minPrice: v.int(),
1789
+ maxPrice: v.int().min("minPrice"), // maxPrice >= minPrice
1790
+ })
1791
+ ```
1792
+
1793
+ Sibling references are **not representable in JSON Schema** — silently omitted from generated output.
1794
+
1795
+ ## Range — explicit sibling scope
1796
+
1797
+ For when smart detection is ambiguous (e.g. a numeric string that happens to match a field name):
1798
+
1799
+ | Method | Effect |
1800
+ |---|---|
1801
+ | `.minSibling(field, msg?)` | value `>=` sibling field |
1802
+ | `.maxSibling(field, msg?)` | value `<=` sibling field |
1803
+ | `.greaterThanSibling(field, msg?)` | value `>` sibling field |
1804
+ | `.gtSibling(field, msg?)` | alias |
1805
+ | `.lessThanSibling(field, msg?)` | value `<` sibling field |
1806
+ | `.ltSibling(field, msg?)` | alias |
1807
+ | `.betweenSibling(minField, maxField, msg?)` | between two sibling fields |
1808
+
1809
+ These **only run inside `v.object`** — sibling resolution silently passes otherwise.
1810
+
1811
+ ## Sign & parity
1812
+
1813
+ | Method | Effect | Example |
1814
+ |---|---|---|
1815
+ | `.positive(msg?)` | value `> 0` | `v.int().positive()` |
1816
+ | `.negative(msg?)` | value `< 0` | `v.int().negative()` |
1817
+ | `.odd(msg?)` | value is odd | `v.int().odd()` |
1818
+ | `.even(msg?)` | value is even | `v.int().even()` |
1819
+
1820
+ ## Divisibility / modulo
1821
+
1822
+ | Method | Effect | JSON Schema |
1823
+ |---|---|---|
1824
+ | `.modulo(n, msg?)` | value `% n === 0` | `multipleOf: n` |
1825
+ | `.divisibleBy(n, msg?)` | alias | `multipleOf: n` |
1826
+ | `.multipleOf(n, msg?)` | alias | `multipleOf: n` |
1827
+ | `.modulusOf(n, msg?)` | alias | `multipleOf: n` |
1828
+
1829
+ ## String-form length (rare)
1830
+
1831
+ When the numeric value is a fixed-format code (PINs, IDs):
1832
+
1833
+ | Method | Effect |
1834
+ |---|---|
1835
+ | `.length(n, msg?)` | string-rep length must be exactly `n` |
1836
+ | `.minLength(n, msg?)` | string-rep length `>= n` |
1837
+ | `.maxLength(n, msg?)` | string-rep length `<= n` |
1838
+
1839
+ For most numeric-shaped IDs you'd use `v.string().length(n).numeric()` instead — let the value be a string.
1840
+
1841
+ ## Mutators (pre-validation reshape)
1842
+
1843
+ | Method | Args | Effect |
1844
+ |---|---|---|
1845
+ | `.abs()` | — | `Math.abs(value)` |
1846
+ | `.ceil()` | — | round up to integer |
1847
+ | `.floor()` | — | round down to integer |
1848
+ | `.round(decimals?)` | default 0 | round to N decimals |
1849
+ | `.toFixed(decimals?)` | default 2 | format as fixed-point |
1850
+
1851
+ These run *before* validation rules. If you mutate `1.6` with `.ceil()`, `v.int()` sees `2` and passes. Use mutators when the input arrives in a slightly wrong form and you want to coerce, not reject.
1852
+
1853
+ ## JSON Schema notes
1854
+
1855
+ - `v.number()` → `{ type: "number" }`
1856
+ - `v.int()` → `{ type: "integer" }`
1857
+ - `v.float()` → `{ type: "number" }` (no JSON Schema distinction from `number`)
1858
+ - `v.numeric()` → `{ type: "number" }` (input coercion is a runtime concern)
1859
+ - `exclusiveMinimum` / `exclusiveMaximum` are encoded as numbers in `draft-2020-12` and `openapi-3.0`, but as boolean flags + `minimum`/`maximum` in `draft-07`.
1860
+
1861
+ ## Common chains
1862
+
1863
+ ```ts
1864
+ // Age
1865
+ v.int().min(0).max(150)
1866
+
1867
+ // Price (cents)
1868
+ v.int().min(0)
1869
+
1870
+ // Probability
1871
+ v.number().between(0, 1)
1872
+
1873
+ // Even page index
1874
+ v.int().min(0).even()
1875
+
1876
+ // Quantity divisible by box size
1877
+ v.int().min(1).multipleOf(12)
1878
+
1879
+ // Coerced from form input
1880
+ v.numeric().min(0).max(100)
1881
+
1882
+ // Cross-field range
1883
+ v.object({
1884
+ startYear: v.int(),
1885
+ endYear: v.int().minSibling("startYear"),
1886
+ })
1887
+
1888
+ // Optional with default
1889
+ v.int().min(0).default(0).optional()
1890
+ ```
1891
+
1892
+
1893
+ ### pick-seal-primitive/string-methods.md `@warlock.js/seal/pick-seal-primitive/string-methods.md`
1894
+
1895
+ # `v.string()` — method reference
1896
+
1897
+ Reference for `v.string()` / `v.email()`. Covers length, format, content, color, mutators (case, trim, mask, slug, base64, …) and what each maps to in JSON Schema.
1898
+
1899
+ For the picking guide (`v.string` vs `v.scalar` vs `v.literal`), see [`@warlock.js/seal/pick-seal-primitive/SKILL.md`](@warlock.js/seal/pick-seal-primitive/SKILL.md). For `.optional()` / `.nullable()` / `.default()` / `.in()` / `.oneOf()`, see [`@warlock.js/seal/compose-seal-modifiers/SKILL.md`](@warlock.js/seal/compose-seal-modifiers/SKILL.md).
1900
+
1901
+ ## Length
1902
+
1903
+ | Method | Args | JSON Schema | Example |
1904
+ |---|---|---|---|
1905
+ | `.min(n, msg?)` | min length, inclusive | `minLength: n` | `v.string().min(3)` |
1906
+ | `.minLength(n, msg?)` | alias for `.min()` | `minLength: n` | `v.string().minLength(3)` |
1907
+ | `.max(n, msg?)` | max length, inclusive | `maxLength: n` | `v.string().max(120)` |
1908
+ | `.maxLength(n, msg?)` | alias for `.max()` | `maxLength: n` | `v.string().maxLength(120)` |
1909
+ | `.length(n, msg?)` | exact length | `minLength=maxLength=n` | `v.string().length(10)` |
1910
+ | `.lengthBetween(a, b, msg?)` | min and max length | `minLength: a, maxLength: b` | `v.string().lengthBetween(5, 30)` |
1911
+
1912
+ ## Format
1913
+
1914
+ | Method | Pattern | JSON Schema | Example |
1915
+ |---|---|---|---|
1916
+ | `.email(msg?)` | RFC-flavored regex | `format: "email"` | `v.string().email()` |
1917
+ | `.url(msg?)` | http/https URL | `format: "uri"` | `v.string().url()` |
1918
+ | `.pattern(re, msg?)` | custom regex | `pattern: re.source` | `v.string().pattern(/^[A-Z]/)` |
1919
+ | `.alpha(msg?)` | letters only | — | `v.string().alpha()` |
1920
+ | `.alphanumeric(msg?)` | letters + digits | — | `v.string().alphanumeric()` |
1921
+ | `.numeric(msg?)` | digits only (string) | — | `v.string().numeric()` |
1922
+ | `.withoutWhitespace(msg?)` | no spaces/tabs/newlines | — | `v.string().withoutWhitespace()` |
1923
+ | `.creditCard(msg?)` | credit-card-shaped | — | `v.string().creditCard()` |
1924
+ | `.ip(msg?)` | IPv4 or IPv6 | `format: "ipv4"` | `v.string().ip()` |
1925
+ | `.ip4(msg?)` | IPv4 only | `format: "ipv4"` | `v.string().ip4()` |
1926
+ | `.ip6(msg?)` | IPv6 only | `format: "ipv6"` | `v.string().ip6()` |
1927
+ | `.strongPassword(minLen?, msg?)` | 8+ chars, upper+lower+digit+symbol | — | `v.string().strongPassword(12)` |
1928
+
1929
+ ## ID formats
1930
+
1931
+ | Method | Args | JSON Schema | Example |
1932
+ |---|---|---|---|
1933
+ | `.uuid(version?, msg?)` | UUID, any version or restrict to 1/3/4/5/6/7 | `format: "uuid"` | `v.string().uuid(4)` |
1934
+ | `.cuid({ version?: 1\|2 }?)` | CUID2 default (24 chars, lowercase); v1 legacy | `pattern: …` | `v.string().cuid()` |
1935
+ | `.ulid(msg?)` | 26 chars, Crockford base32 (no I/L/O/U) | `pattern: …` | `v.string().ulid()` |
1936
+ | `.nanoid(length?, msg?)` | URL-safe alphabet, default length 21 | `pattern: …` | `v.string().nanoid(21)` |
1937
+
1938
+ UUID validation is RFC 4122 strict — the variant nibble (8/9/a/b at position 17) is checked, so "looks-like-UUID-but-not-valid" inputs are rejected. CUID defaults to **CUID2** since CUID1 is deprecated by its original author; pass `{ version: 1 }` only for legacy data. nanoid's alphabet is fixed (`A-Za-z0-9_-`) — for custom alphabets use `.pattern()` directly.
1939
+
1940
+ ## Word count
1941
+
1942
+ | Method | Args | Example |
1943
+ |---|---|---|
1944
+ | `.words(n, msg?)` | exact word count | `v.string().words(5)` |
1945
+ | `.minWords(n, msg?)` | min words | `v.string().minWords(3)` |
1946
+ | `.maxWords(n, msg?)` | max words | `v.string().maxWords(50)` |
1947
+
1948
+ ## Content
1949
+
1950
+ | Method | Args | Example |
1951
+ |---|---|---|
1952
+ | `.startsWith(s, msg?)` | prefix check | `v.string().startsWith("https://")` |
1953
+ | `.endsWith(s, msg?)` | suffix check | `v.string().endsWith(".pdf")` |
1954
+ | `.contains(s, msg?)` | substring check | `v.string().contains("@")` |
1955
+ | `.notContains(s, msg?)` | inverse substring | `v.string().notContains("javascript:")` |
1956
+
1957
+ ## Color
1958
+
1959
+ | Method | Accepts | Example |
1960
+ |---|---|---|
1961
+ | `.color(msg?)` | any valid CSS color | `v.string().color()` |
1962
+ | `.hexColor(msg?)` | `#rgb`, `#rrggbb` | `v.string().hexColor()` |
1963
+ | `.rgbColor(msg?)` | `rgb(r,g,b)` | — |
1964
+ | `.rgbaColor(msg?)` | `rgba(r,g,b,a)` | — |
1965
+ | `.hslColor(msg?)` | `hsl(h,s,l)` | — |
1966
+ | `.lightColor(msg?)` | luminance-based | — |
1967
+ | `.darkColor(msg?)` | luminance-based | — |
1968
+
1969
+ JSON Schema: `format: "color"` for `.hexColor()`; the others map to `format: "color"` only via `.hexColor()` — for OpenAPI consumers expecting strict format, prefer `.hexColor()`.
1970
+
1971
+ ## Case mutators (pre-validation)
1972
+
1973
+ | Method | Effect | Example |
1974
+ |---|---|---|
1975
+ | `.uppercase()` | "Hello" → "HELLO" | `v.string().uppercase()` |
1976
+ | `.lowercase()` | "Hello" → "hello" | — |
1977
+ | `.capitalize()` | "hello world" → "Hello world" | — |
1978
+ | `.titleCase()` | "hello world" → "Hello World" | — |
1979
+ | `.camelCase()` | "hello world" → "helloWorld" | — |
1980
+ | `.pascalCase()` | "hello world" → "HelloWorld" | — |
1981
+ | `.snakeCase()` | "hello world" → "hello_world" | — |
1982
+ | `.kebabCase()` | "hello world" → "hello-world" | — |
1983
+
1984
+ ## Trim & whitespace mutators
1985
+
1986
+ | Method | Args | Effect |
1987
+ |---|---|---|
1988
+ | `.trim(needle?)` | default = space | trim both ends |
1989
+ | `.ltrim(needle?)` | — | trim left only |
1990
+ | `.rtrim(needle?)` | — | trim right only |
1991
+ | `.trimMultipleWhitespace()` | — | "a b" → "a b" |
1992
+ | `.padStart(len, char?)` | char default = " " | left-pad to length |
1993
+ | `.padEnd(len, char?)` | char default = " " | right-pad to length |
1994
+
1995
+ ## Replace, append, modify mutators
1996
+
1997
+ | Method | Args | Example |
1998
+ |---|---|---|
1999
+ | `.replace(search, replace)` | string or RegExp + string | — |
2000
+ | `.replaceAll(search, replace)` | string or RegExp + string | — |
2001
+ | `.append(suffix)` | string | "foo" → "foobar" via `.append("bar")` |
2002
+ | `.prepend(prefix)` | string | "foo" → "barfoo" via `.prepend("bar")` |
2003
+ | `.reverse()` | — | "abc" → "cba" |
2004
+ | `.repeat(count)` | number | "ab" → "ababab" via `.repeat(3)` |
2005
+ | `.truncate(maxLen, suffix?)` | suffix default = "…" | "long text" → "long…" |
2006
+ | `.mask(start, end?, char?)` | char default = "*" | "1234567890" → "12******90" |
2007
+
2008
+ ## Filter mutators
2009
+
2010
+ | Method | Effect |
2011
+ |---|---|
2012
+ | `.toAlpha()` | strip non-letters |
2013
+ | `.toAlphanumeric()` | strip non-alphanumerics |
2014
+ | `.removeSpecialCharacters()` | keep alphanumerics + whitespace |
2015
+ | `.removeNumbers()` | strip digits |
2016
+ | `.safeHtml()` | strip HTML tags |
2017
+ | `.htmlEscape()` | `<` → `&lt;` etc |
2018
+ | `.unescapeHtml()` | reverse `htmlEscape()` |
2019
+
2020
+ ## Encoding mutators
2021
+
2022
+ | Method | Effect |
2023
+ |---|---|
2024
+ | `.base64Encode()` | utf8 → base64 |
2025
+ | `.base64Decode()` | base64 → utf8 |
2026
+ | `.urlEncode()` | percent-encode |
2027
+ | `.urlDecode()` | percent-decode |
2028
+ | `.slug()` | "Hello World!" → "hello-world" |
2029
+ | `.toString()` | coerce non-string input to string |
2030
+
2031
+ ## Mutator vs transformer
2032
+
2033
+ The methods above are **all mutators** — they reshape the value *before* validation rules run. If you want post-validation reshaping, attach via `.addTransformer(fn)` (see [`@warlock.js/seal/compose-seal-modifiers/SKILL.md`](@warlock.js/seal/compose-seal-modifiers/SKILL.md)).
2034
+
2035
+ Practical implication: `v.string().min(3).trim()` runs `min(3)` against the *un-trimmed* input. To check trimmed length, mutate first: `v.string().trim().min(3)`.
2036
+
2037
+ ## Common chains
2038
+
2039
+ ```ts
2040
+ // Email field
2041
+ v.string().email()
2042
+
2043
+ // Username
2044
+ v.string().min(3).max(30).alphanumeric().lowercase()
2045
+
2046
+ // Slug from title
2047
+ v.string().slug()
2048
+
2049
+ // Strong password
2050
+ v.string().strongPassword(12)
2051
+
2052
+ // URL with strict format
2053
+ v.string().url().startsWith("https://")
2054
+
2055
+ // Sanitized HTML body
2056
+ v.string().safeHtml().min(1)
2057
+
2058
+ // Masked phone for response
2059
+ v.string().pattern(/^\+\d{8,}$/).mask(3, -2)
2060
+
2061
+ // Optional with default
2062
+ v.string().email().default("guest@example.com").optional()
2063
+ ```
2064
+
2065
+
2066
+ ## seal-basics `@warlock.js/seal/seal-basics/SKILL.md`
2067
+
2068
+ ---
2069
+ name: seal-basics
2070
+ description: 'Start with @warlock.js/seal — the `v` factory, `validate(schema, data)`, and `Infer<typeof schema>`. Triggers: `v`, `validate`, `Infer`, `Infer.Input`, `Infer.Output`, `v.object`, `v.lazy`, `v.discriminatedUnion`, `v.computed`, `v.managed`, `ValidationResult`; "how do I start with seal", "what is the v factory", "validate a schema in warlock", "Infer.Input vs Infer.Output"; typical import `import { v, validate, type Infer } from "@warlock.js/seal"`. Skip: primitive picking — `@warlock.js/seal/pick-seal-primitive/SKILL.md`; modifiers — `@warlock.js/seal/compose-seal-modifiers/SKILL.md`; competing libs `zod`, `valibot`, `yup`, `joi`, `ajv`.'
2071
+ ---
2072
+
2073
+ # Validate with seal
2074
+
2075
+ Schema-first validation. Single entry point: the `v` factory. Every validator chains, composes, and infers. Schemas double as runtime validators *and* type-level shapes via `Infer<typeof schema>`, and ship `~standard` so any Standard-Schema-aware consumer accepts them directly.
2076
+
2077
+ > This skill is the seal **map** — read it first, then load the specific skill for the task.
2078
+
2079
+ ## Install
2080
+
2081
+ ```bash
2082
+ yarn add @warlock.js/seal
2083
+ ```
2084
+
2085
+ Most warlock projects already have `@warlock.js/seal` transitively via `@warlock.js/core` (which re-exports the `v` factory and `Infer` types). Import direct from the package you control: `@warlock.js/seal` if you build a leaf package, `@warlock.js/core` if you write app code.
2086
+
2087
+ ## Minimal example
2088
+
2089
+ ```ts
2090
+ import { v, validate, type Infer } from "@warlock.js/seal";
2091
+
2092
+ const userSchema = v.object({
2093
+ email: v.string().email(),
2094
+ age: v.int().min(13).optional(),
2095
+ role: v.literal("admin", "user", "guest"),
2096
+ });
2097
+
2098
+ type User = Infer<typeof userSchema>;
2099
+ // { email: string; age?: number; role: "admin" | "user" | "guest" }
2100
+
2101
+ const result = await validate(userSchema, input);
2102
+ if (result.isValid) {
2103
+ result.data; // typed, post-transformer
2104
+ } else {
2105
+ result.errors; // [{ type, error, input }, ...]
2106
+ }
2107
+ ```
2108
+
2109
+ ## Foundations
2110
+
2111
+ The 12 things that are true in every seal use:
2112
+
2113
+ 1. **Public API is the `v` factory.** Never `new ObjectValidator(...)` from app code — bare classes lose the StandardSchema bridge typing. See [`@warlock.js/seal/bridge-standard-schema/SKILL.md`](@warlock.js/seal/bridge-standard-schema/SKILL.md).
2114
+ 2. **Every factory return is a `StandardSchemaV1<Infer.Output<T>>`.** Pass seal schemas straight into `StandardSchemaV1<T>`-typed slots — no casts.
2115
+ 3. **Two inference helpers — `Infer.Input<T>` and `Infer.Output<T>`.** Bare `Infer<T>` is an alias for `Infer.Input<T>` (the dominant usage: HTTP bodies, DTOs, form payloads). Use `Infer.Output<T>` for validated state (Cascade `Model<>` params, post-`validate()` data). See [the rules below](#inferinput-vs-inferoutput).
2116
+ 4. **Fields are required by default.** Mark optional explicitly: `.optional()`. Skip `.required()` — canonical seal style omits the redundant call; inferred types already show what's required.
2117
+ 5. **`validate(schema, data)` never throws.** Returns `Promise<ValidationResult>` with `{ isValid, data, errors }` — the validated value is `result.data`. See [`@warlock.js/seal/handle-seal-errors/SKILL.md`](@warlock.js/seal/handle-seal-errors/SKILL.md).
2118
+ 6. **Validators are immutable by default.** Every chain method (`.min(3)`, `.email()`, `.optional()`, …) returns a clone. Toggle with the `.mutable` getter.
2119
+ 7. **Two pipelines: mutators (pre-validation), transformers (post-validation).** Order: `default → mutators → required check → required-condition rule → other rules → transformers → data`. `.catch(fallback)` rescues any failure on leaf validators.
2120
+ 8. **Cross-field rules need a `v.object` parent.** Standalone scalar validators have no siblings to resolve against.
2121
+ 9. **JSON Schema generation is built-in.** `schema.toJsonSchema(target)` for `"draft-2020-12"` (default), `"draft-07"`, `"openapi-3.0"`, `"openai-strict"`. See [`@warlock.js/seal/generate-json-schema/SKILL.md`](@warlock.js/seal/generate-json-schema/SKILL.md).
2122
+ 10. **`v.computed` / `v.managed` derive — they don't validate inputs.** They produce values from siblings or context, and are **skipped** when the parent `v.object` emits JSON Schema (runtime-only constructs — calling `.toJsonSchema()` on one directly throws).
2123
+ 11. **`v.lazy(() => schema)` for recursive shapes.** Defers resolution until validate-time so self-referencing types work.
2124
+ 12. **`v.discriminatedUnion(field, branches)` for tagged unions.** Routes by a literal discriminator field instead of `matchesType()` trial — precise errors, exact inference.
2125
+
2126
+ ## `Infer.Input` vs `Infer.Output`
2127
+
2128
+ The two inference shapes describe the two halves of the pipeline:
2129
+
2130
+ - **`Infer.Input<T>`** — what the caller sends. `.optional()`, `.default()`, `.catch()` all make a key optional (any of them means "you don't have to supply this").
2131
+ - **`Infer.Output<T>`** — what `data` contains after validation. `.default()` and `.catch()` guarantee a value, so keys with those brands are required even when chained with `.optional()`.
2132
+
2133
+ ```ts
2134
+ const schema = v.object({
2135
+ email: v.string().email().optional(),
2136
+ status: v.enum(Status).optional().default(Status.ACTIVE),
2137
+ });
2138
+
2139
+ type In = Infer.Input<typeof schema>;
2140
+ // { email?: string; status?: Status } ← caller may omit both
2141
+
2142
+ type Out = Infer.Output<typeof schema>;
2143
+ // { email?: string; status: Status } ← default fired for status
2144
+
2145
+ type Default = Infer<typeof schema>; // alias for Infer.Input
2146
+ ```
2147
+
2148
+ Both flavours widen with `| null` when `.nullable()` is set.
2149
+
2150
+ **When to reach for which:**
2151
+
2152
+ - `Infer.Input<T>` (or bare `Infer<T>`) — for HTTP request bodies, form payloads, DTOs, anything pre-validation. **The common case in HTTP-shaped code.**
2153
+ - `Infer.Output<T>` — for Cascade `Model<>` params, validated state, anywhere downstream of `validate()`.
2154
+
2155
+ ## Pick a skill
2156
+
2157
+ | If the task is about… | Load |
2158
+ | --- | --- |
2159
+ | Picking the right primitive (`v.string` vs `v.scalar`, `v.literal` vs `v.enum`, `v.date` vs `v.instanceof(Date)`) | [`@warlock.js/seal/pick-seal-primitive/SKILL.md`](@warlock.js/seal/pick-seal-primitive/SKILL.md) |
2160
+ | Building object / array / record / tuple / union schemas, discriminated unions, recursive schemas | [`@warlock.js/seal/define-structural-shape/SKILL.md`](@warlock.js/seal/define-structural-shape/SKILL.md) |
2161
+ | Modifiers — `.required` / `.optional` / `.nullable` / `.default` / `.catch` / `.omit`, transformer vs mutator pipelines, membership rules | [`@warlock.js/seal/compose-seal-modifiers/SKILL.md`](@warlock.js/seal/compose-seal-modifiers/SKILL.md) |
2162
+ | Reading `ValidationResult`, branching on `error.type`, error message customization, translation | [`@warlock.js/seal/handle-seal-errors/SKILL.md`](@warlock.js/seal/handle-seal-errors/SKILL.md) |
2163
+ | Generating JSON Schema for OpenAI strict / OpenAPI / draft-07 | [`@warlock.js/seal/generate-json-schema/SKILL.md`](@warlock.js/seal/generate-json-schema/SKILL.md) |
2164
+ | Why a `StandardSchemaV1<T>` slot accepts/rejects a schema, the phantom-intersection design, `Result<unknown>` errors | [`@warlock.js/seal/bridge-standard-schema/SKILL.md`](@warlock.js/seal/bridge-standard-schema/SKILL.md) |
2165
+ | Authoring custom seal plugins to add validator methods | [`@warlock.js/seal/extend-seal-with-plugins/SKILL.md`](@warlock.js/seal/extend-seal-with-plugins/SKILL.md) |
2166
+
2167
+ ## Things NOT to do
2168
+
2169
+ - Don't `new ObjectValidator(...)` from app code — use `v.object(...)` so the StandardSchema bridge attaches.
2170
+ - Don't annotate a schema with the bare class type — strips the bridge intersection. Let inference run.
2171
+ - Don't expect `validate()` to throw on bad input — bad input lands in `result.errors`. The only things that throw are bugs (a rule's callback threw, a transformer threw).
2172
+ - Don't expect `.requiredIf()` / `.sameAs()` to work on a standalone validator outside `v.object` — sibling resolution silently passes.
2173
+ - Don't put `.trim()` before `.min(3)` and expect it to trim first — `.trim()` is a transformer (post-validation). For pre-validation trim, attach with `.addMutator(s => s.trim())`.
2174
+
2175
+