@fougere/schema 0.6.0-alpha.0 → 0.7.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (421) hide show
  1. package/README.md +5 -4
  2. package/dist/{schema/Schema.d.ts → Schema.d.ts} +17 -27
  3. package/dist/Schema.d.ts.map +1 -0
  4. package/dist/{schema/Schema.js → Schema.js} +21 -61
  5. package/dist/Schema.js.map +1 -0
  6. package/dist/SchemaDefinition.d.ts +73 -0
  7. package/dist/SchemaDefinition.d.ts.map +1 -0
  8. package/dist/SchemaDefinition.js +184 -0
  9. package/dist/SchemaDefinition.js.map +1 -0
  10. package/dist/SchemaDerivation.d.ts +16 -0
  11. package/dist/SchemaDerivation.d.ts.map +1 -0
  12. package/dist/SchemaDerivation.js +31 -0
  13. package/dist/SchemaDerivation.js.map +1 -0
  14. package/dist/{schema/SchemaView.d.ts → SchemaView.d.ts} +9 -9
  15. package/dist/SchemaView.d.ts.map +1 -0
  16. package/dist/{schema/SchemaView.js.map → SchemaView.js.map} +1 -1
  17. package/dist/{schema/axis → axis}/Axis.d.ts +2 -2
  18. package/dist/axis/Axis.d.ts.map +1 -0
  19. package/dist/axis/Axis.js.map +1 -0
  20. package/dist/axis/Meta.d.ts.map +1 -0
  21. package/dist/{schema/axis → axis}/Meta.js.map +1 -1
  22. package/dist/axis/boundary/Boundaries.d.ts +21 -0
  23. package/dist/axis/boundary/Boundaries.d.ts.map +1 -0
  24. package/dist/axis/boundary/Boundaries.js +25 -0
  25. package/dist/axis/boundary/Boundaries.js.map +1 -0
  26. package/dist/{schema/axis → axis}/boundary/Boundary.d.ts +3 -1
  27. package/dist/axis/boundary/Boundary.d.ts.map +1 -0
  28. package/dist/{schema/axis → axis}/boundary/Boundary.js +8 -6
  29. package/dist/axis/boundary/Boundary.js.map +1 -0
  30. package/dist/axis/boundary/BoundaryAxis.d.ts.map +1 -0
  31. package/dist/{schema/axis → axis}/boundary/BoundaryAxis.js +4 -4
  32. package/dist/axis/boundary/BoundaryAxis.js.map +1 -0
  33. package/dist/{schema/axis → axis}/lifecycle/Clock.d.ts +1 -1
  34. package/dist/axis/lifecycle/Clock.d.ts.map +1 -0
  35. package/dist/{schema/axis → axis}/lifecycle/Clock.js +1 -1
  36. package/dist/axis/lifecycle/Clock.js.map +1 -0
  37. package/dist/axis/lifecycle/Generators.d.ts +10 -0
  38. package/dist/axis/lifecycle/Generators.d.ts.map +1 -0
  39. package/dist/axis/lifecycle/Generators.js +20 -0
  40. package/dist/axis/lifecycle/Generators.js.map +1 -0
  41. package/dist/axis/lifecycle/Lifecycle.d.ts.map +1 -0
  42. package/dist/axis/lifecycle/Lifecycle.js.map +1 -0
  43. package/dist/axis/lifecycle/LifecycleAxis.d.ts.map +1 -0
  44. package/dist/{schema/axis → axis}/lifecycle/LifecycleAxis.js +11 -6
  45. package/dist/axis/lifecycle/LifecycleAxis.js.map +1 -0
  46. package/dist/axis/lifecycle/apply.d.ts +15 -0
  47. package/dist/axis/lifecycle/apply.d.ts.map +1 -0
  48. package/dist/axis/lifecycle/apply.js +50 -0
  49. package/dist/axis/lifecycle/apply.js.map +1 -0
  50. package/dist/{schema/axis → axis}/role/Relation.d.ts +3 -2
  51. package/dist/axis/role/Relation.d.ts.map +1 -0
  52. package/dist/{schema/axis → axis}/role/Relation.js +6 -5
  53. package/dist/axis/role/Relation.js.map +1 -0
  54. package/dist/{schema/axis → axis}/role/Role.d.ts +6 -6
  55. package/dist/axis/role/Role.d.ts.map +1 -0
  56. package/dist/axis/role/Role.js +36 -0
  57. package/dist/axis/role/Role.js.map +1 -0
  58. package/dist/{schema/axis → axis}/role/RoleAxis.d.ts +1 -1
  59. package/dist/axis/role/RoleAxis.d.ts.map +1 -0
  60. package/dist/{schema/axis → axis}/role/RoleAxis.js +28 -36
  61. package/dist/axis/role/RoleAxis.js.map +1 -0
  62. package/dist/axis/shape/Formats.d.ts +11 -0
  63. package/dist/axis/shape/Formats.d.ts.map +1 -0
  64. package/dist/axis/shape/Formats.js +9 -0
  65. package/dist/axis/shape/Formats.js.map +1 -0
  66. package/dist/{schema/axis → axis}/shape/Shape.d.ts +5 -3
  67. package/dist/axis/shape/Shape.d.ts.map +1 -0
  68. package/dist/{schema/axis → axis}/shape/Shape.js +13 -13
  69. package/dist/axis/shape/Shape.js.map +1 -0
  70. package/dist/entity/EntityAdapterSet.d.ts +22 -0
  71. package/dist/entity/EntityAdapterSet.d.ts.map +1 -0
  72. package/dist/entity/EntityAdapterSet.js +63 -0
  73. package/dist/entity/EntityAdapterSet.js.map +1 -0
  74. package/dist/entity/EntityAdapters.d.ts +1 -24
  75. package/dist/entity/EntityAdapters.d.ts.map +1 -1
  76. package/dist/entity/EntityAdapters.js +1 -74
  77. package/dist/entity/EntityAdapters.js.map +1 -1
  78. package/dist/entity/EntityDeclarations.d.ts +1 -1
  79. package/dist/entity/EntityDeclarations.d.ts.map +1 -1
  80. package/dist/entity.d.ts +7 -2
  81. package/dist/entity.d.ts.map +1 -1
  82. package/dist/entity.js +6 -1
  83. package/dist/entity.js.map +1 -1
  84. package/dist/{schema/fields → field}/Field.d.ts +2 -3
  85. package/dist/field/Field.d.ts.map +1 -0
  86. package/dist/field/Field.js +35 -0
  87. package/dist/field/Field.js.map +1 -0
  88. package/dist/field/FieldSet.d.ts +22 -0
  89. package/dist/field/FieldSet.d.ts.map +1 -0
  90. package/dist/field/FieldSet.js +58 -0
  91. package/dist/field/FieldSet.js.map +1 -0
  92. package/dist/index.d.ts +27 -30
  93. package/dist/index.d.ts.map +1 -1
  94. package/dist/index.js +20 -23
  95. package/dist/index.js.map +1 -1
  96. package/dist/lib/Registry.d.ts +12 -0
  97. package/dist/lib/Registry.d.ts.map +1 -0
  98. package/dist/lib/Registry.js +29 -0
  99. package/dist/lib/Registry.js.map +1 -0
  100. package/dist/lib/utils.d.ts.map +1 -0
  101. package/dist/lib/utils.js.map +1 -0
  102. package/dist/projection/Cases.d.ts +9 -20
  103. package/dist/projection/Cases.d.ts.map +1 -1
  104. package/dist/projection/Cases.js +44 -39
  105. package/dist/projection/Cases.js.map +1 -1
  106. package/dist/projection/Visibility.d.ts +2 -1
  107. package/dist/projection/Visibility.d.ts.map +1 -1
  108. package/dist/projection/Visibility.js +4 -3
  109. package/dist/projection/Visibility.js.map +1 -1
  110. package/dist/projection/card/Bundle.d.ts +1 -1
  111. package/dist/projection/card/Bundle.d.ts.map +1 -1
  112. package/dist/projection/card/Bundle.js +7 -7
  113. package/dist/projection/card/Bundle.js.map +1 -1
  114. package/dist/projection/card/Card.d.ts +7 -13
  115. package/dist/projection/card/Card.d.ts.map +1 -1
  116. package/dist/projection/card/Card.js +96 -69
  117. package/dist/projection/card/Card.js.map +1 -1
  118. package/dist/projection/card/Descriptor.d.ts +7 -7
  119. package/dist/projection/card/Descriptor.d.ts.map +1 -1
  120. package/dist/projection/card/admission.d.ts +15 -5
  121. package/dist/projection/card/admission.d.ts.map +1 -1
  122. package/dist/projection/card/admission.js +15 -5
  123. package/dist/projection/card/admission.js.map +1 -1
  124. package/dist/projection/card/diff.d.ts +2 -2
  125. package/dist/projection/card/diff.d.ts.map +1 -1
  126. package/dist/{judge/result.d.ts → validation.d.ts} +1 -1
  127. package/dist/validation.d.ts.map +1 -0
  128. package/dist/validation.js +2 -0
  129. package/dist/validation.js.map +1 -0
  130. package/dist/validator/AdapterFieldValidator.d.ts +14 -0
  131. package/dist/validator/AdapterFieldValidator.d.ts.map +1 -0
  132. package/dist/validator/AdapterFieldValidator.js +36 -0
  133. package/dist/validator/AdapterFieldValidator.js.map +1 -0
  134. package/dist/validator/FieldDeclarationValidator.d.ts +9 -0
  135. package/dist/validator/FieldDeclarationValidator.d.ts.map +1 -0
  136. package/dist/{judge/FieldJudge.js → validator/FieldDeclarationValidator.js} +8 -8
  137. package/dist/validator/FieldDeclarationValidator.js.map +1 -0
  138. package/dist/validator/FieldValueValidator.d.ts +13 -0
  139. package/dist/validator/FieldValueValidator.d.ts.map +1 -0
  140. package/dist/{judge/ValueJudge.js → validator/FieldValueValidator.js} +12 -11
  141. package/dist/validator/FieldValueValidator.js.map +1 -0
  142. package/dist/{judge/RowRefusal.d.ts → validator/InputRefusal.d.ts} +3 -4
  143. package/dist/validator/InputRefusal.d.ts.map +1 -0
  144. package/dist/{judge/RowRefusal.js → validator/InputRefusal.js} +3 -3
  145. package/dist/validator/InputRefusal.js.map +1 -0
  146. package/dist/validator/InputValidator.d.ts +15 -0
  147. package/dist/validator/InputValidator.d.ts.map +1 -0
  148. package/dist/{judge/RowJudge.js → validator/InputValidator.js} +24 -20
  149. package/dist/validator/InputValidator.js.map +1 -0
  150. package/dist/vocabulary/bool.d.ts +6 -1
  151. package/dist/vocabulary/bool.d.ts.map +1 -1
  152. package/dist/vocabulary/bool.js +6 -1
  153. package/dist/vocabulary/bool.js.map +1 -1
  154. package/dist/vocabulary/created.d.ts +6 -1
  155. package/dist/vocabulary/created.d.ts.map +1 -1
  156. package/dist/vocabulary/created.js +5 -0
  157. package/dist/vocabulary/created.js.map +1 -1
  158. package/dist/vocabulary/date.d.ts +6 -1
  159. package/dist/vocabulary/date.d.ts.map +1 -1
  160. package/dist/vocabulary/date.js +6 -1
  161. package/dist/vocabulary/date.js.map +1 -1
  162. package/dist/vocabulary/email.d.ts +6 -1
  163. package/dist/vocabulary/email.d.ts.map +1 -1
  164. package/dist/vocabulary/email.js +5 -0
  165. package/dist/vocabulary/email.js.map +1 -1
  166. package/dist/vocabulary/immutable.d.ts +6 -1
  167. package/dist/vocabulary/immutable.d.ts.map +1 -1
  168. package/dist/vocabulary/immutable.js +5 -0
  169. package/dist/vocabulary/immutable.js.map +1 -1
  170. package/dist/vocabulary/indexed.d.ts +6 -1
  171. package/dist/vocabulary/indexed.d.ts.map +1 -1
  172. package/dist/vocabulary/indexed.js +5 -0
  173. package/dist/vocabulary/indexed.js.map +1 -1
  174. package/dist/vocabulary/json.d.ts +2 -2
  175. package/dist/vocabulary/json.d.ts.map +1 -1
  176. package/dist/vocabulary/json.js +9 -4
  177. package/dist/vocabulary/json.js.map +1 -1
  178. package/dist/vocabulary/list.d.ts +6 -1
  179. package/dist/vocabulary/list.d.ts.map +1 -1
  180. package/dist/vocabulary/list.js +6 -1
  181. package/dist/vocabulary/list.js.map +1 -1
  182. package/dist/vocabulary/many.d.ts +7 -2
  183. package/dist/vocabulary/many.d.ts.map +1 -1
  184. package/dist/vocabulary/many.js +7 -2
  185. package/dist/vocabulary/many.js.map +1 -1
  186. package/dist/vocabulary/nullable.d.ts +6 -1
  187. package/dist/vocabulary/nullable.d.ts.map +1 -1
  188. package/dist/vocabulary/nullable.js +7 -2
  189. package/dist/vocabulary/nullable.js.map +1 -1
  190. package/dist/vocabulary/number.d.ts +6 -1
  191. package/dist/vocabulary/number.d.ts.map +1 -1
  192. package/dist/vocabulary/number.js +6 -1
  193. package/dist/vocabulary/number.js.map +1 -1
  194. package/dist/vocabulary/oneOf.d.ts +1 -1
  195. package/dist/vocabulary/oneOf.d.ts.map +1 -1
  196. package/dist/vocabulary/oneOf.js +6 -1
  197. package/dist/vocabulary/oneOf.js.map +1 -1
  198. package/dist/vocabulary/optional.d.ts +6 -1
  199. package/dist/vocabulary/optional.d.ts.map +1 -1
  200. package/dist/vocabulary/optional.js +7 -2
  201. package/dist/vocabulary/optional.js.map +1 -1
  202. package/dist/vocabulary/primary.d.ts +2 -2
  203. package/dist/vocabulary/primary.d.ts.map +1 -1
  204. package/dist/vocabulary/primary.js +7 -2
  205. package/dist/vocabulary/primary.js.map +1 -1
  206. package/dist/vocabulary/readOnly.d.ts +6 -1
  207. package/dist/vocabulary/readOnly.d.ts.map +1 -1
  208. package/dist/vocabulary/readOnly.js +6 -1
  209. package/dist/vocabulary/readOnly.js.map +1 -1
  210. package/dist/vocabulary/ref.d.ts +7 -2
  211. package/dist/vocabulary/ref.d.ts.map +1 -1
  212. package/dist/vocabulary/ref.js +7 -2
  213. package/dist/vocabulary/ref.js.map +1 -1
  214. package/dist/vocabulary/text.d.ts +7 -2
  215. package/dist/vocabulary/text.d.ts.map +1 -1
  216. package/dist/vocabulary/text.js +6 -1
  217. package/dist/vocabulary/text.js.map +1 -1
  218. package/dist/vocabulary/unique.d.ts +6 -1
  219. package/dist/vocabulary/unique.d.ts.map +1 -1
  220. package/dist/vocabulary/unique.js +7 -3
  221. package/dist/vocabulary/unique.js.map +1 -1
  222. package/dist/vocabulary/updated.d.ts +6 -1
  223. package/dist/vocabulary/updated.d.ts.map +1 -1
  224. package/dist/vocabulary/updated.js +5 -0
  225. package/dist/vocabulary/updated.js.map +1 -1
  226. package/dist/vocabulary/url.d.ts +6 -1
  227. package/dist/vocabulary/url.d.ts.map +1 -1
  228. package/dist/vocabulary/url.js +5 -0
  229. package/dist/vocabulary/url.js.map +1 -1
  230. package/dist/vocabulary/vocabulary.d.ts +6 -1
  231. package/dist/vocabulary/vocabulary.d.ts.map +1 -1
  232. package/dist/vocabulary/vocabulary.js +22 -12
  233. package/dist/vocabulary/vocabulary.js.map +1 -1
  234. package/dist/vocabulary/writeOnly.d.ts +6 -1
  235. package/dist/vocabulary/writeOnly.d.ts.map +1 -1
  236. package/dist/vocabulary/writeOnly.js +6 -1
  237. package/dist/vocabulary/writeOnly.js.map +1 -1
  238. package/package.json +1 -1
  239. package/src/{schema/Schema.ts → Schema.ts} +31 -74
  240. package/src/SchemaDefinition.ts +257 -0
  241. package/src/SchemaDerivation.ts +44 -0
  242. package/src/{schema/SchemaView.ts → SchemaView.ts} +9 -9
  243. package/src/{schema/axis → axis}/Axis.ts +2 -2
  244. package/src/axis/boundary/Boundaries.ts +37 -0
  245. package/src/{schema/axis → axis}/boundary/Boundary.ts +9 -7
  246. package/src/{schema/axis → axis}/boundary/BoundaryAxis.ts +4 -4
  247. package/src/{schema/axis → axis}/lifecycle/Clock.ts +1 -1
  248. package/src/axis/lifecycle/Generators.ts +29 -0
  249. package/src/{schema/axis → axis}/lifecycle/LifecycleAxis.ts +12 -7
  250. package/src/axis/lifecycle/apply.ts +53 -0
  251. package/src/{schema/axis → axis}/role/Relation.ts +6 -5
  252. package/src/axis/role/Role.ts +52 -0
  253. package/src/{schema/axis → axis}/role/RoleAxis.ts +28 -40
  254. package/src/axis/shape/Formats.ts +20 -0
  255. package/src/{schema/axis → axis}/shape/Shape.ts +18 -18
  256. package/src/entity/EntityAdapterSet.ts +81 -0
  257. package/src/entity/EntityAdapters.ts +4 -96
  258. package/src/entity/EntityDeclarations.ts +1 -1
  259. package/src/entity.ts +7 -2
  260. package/src/{schema/fields → field}/Field.ts +8 -26
  261. package/src/field/FieldSet.ts +75 -0
  262. package/src/index.ts +29 -44
  263. package/src/lib/Registry.ts +37 -0
  264. package/src/projection/Cases.ts +56 -55
  265. package/src/projection/Visibility.ts +5 -4
  266. package/src/projection/card/Bundle.ts +9 -9
  267. package/src/projection/card/Card.ts +101 -74
  268. package/src/projection/card/Descriptor.ts +7 -7
  269. package/src/projection/card/admission.ts +16 -6
  270. package/src/projection/card/diff.ts +2 -2
  271. package/src/validator/AdapterFieldValidator.ts +40 -0
  272. package/src/{judge/FieldJudge.ts → validator/FieldDeclarationValidator.ts} +10 -10
  273. package/src/{judge/ValueJudge.ts → validator/FieldValueValidator.ts} +14 -13
  274. package/src/{judge/RowRefusal.ts → validator/InputRefusal.ts} +2 -4
  275. package/src/{judge/RowJudge.ts → validator/InputValidator.ts} +30 -23
  276. package/src/vocabulary/bool.ts +6 -1
  277. package/src/vocabulary/created.ts +6 -1
  278. package/src/vocabulary/date.ts +6 -1
  279. package/src/vocabulary/email.ts +6 -1
  280. package/src/vocabulary/immutable.ts +6 -1
  281. package/src/vocabulary/indexed.ts +6 -1
  282. package/src/vocabulary/json.ts +10 -5
  283. package/src/vocabulary/list.ts +6 -1
  284. package/src/vocabulary/many.ts +7 -2
  285. package/src/vocabulary/nullable.ts +8 -3
  286. package/src/vocabulary/number.ts +6 -1
  287. package/src/vocabulary/oneOf.ts +6 -1
  288. package/src/vocabulary/optional.ts +8 -3
  289. package/src/vocabulary/primary.ts +7 -2
  290. package/src/vocabulary/readOnly.ts +7 -2
  291. package/src/vocabulary/ref.ts +7 -2
  292. package/src/vocabulary/text.ts +7 -2
  293. package/src/vocabulary/unique.ts +8 -4
  294. package/src/vocabulary/updated.ts +6 -1
  295. package/src/vocabulary/url.ts +6 -1
  296. package/src/vocabulary/vocabulary.ts +22 -12
  297. package/src/vocabulary/writeOnly.ts +7 -2
  298. package/dist/judge/FieldJudge.d.ts +0 -9
  299. package/dist/judge/FieldJudge.d.ts.map +0 -1
  300. package/dist/judge/FieldJudge.js.map +0 -1
  301. package/dist/judge/RowJudge.d.ts +0 -12
  302. package/dist/judge/RowJudge.d.ts.map +0 -1
  303. package/dist/judge/RowJudge.js.map +0 -1
  304. package/dist/judge/RowRefusal.d.ts.map +0 -1
  305. package/dist/judge/RowRefusal.js.map +0 -1
  306. package/dist/judge/ValueJudge.d.ts +0 -12
  307. package/dist/judge/ValueJudge.d.ts.map +0 -1
  308. package/dist/judge/ValueJudge.js.map +0 -1
  309. package/dist/judge/options.d.ts +0 -4
  310. package/dist/judge/options.d.ts.map +0 -1
  311. package/dist/judge/options.js +0 -2
  312. package/dist/judge/options.js.map +0 -1
  313. package/dist/judge/result.d.ts.map +0 -1
  314. package/dist/judge/result.js +0 -2
  315. package/dist/judge/result.js.map +0 -1
  316. package/dist/projection/SchemaOrCard.d.ts +0 -7
  317. package/dist/projection/SchemaOrCard.d.ts.map +0 -1
  318. package/dist/projection/SchemaOrCard.js +0 -11
  319. package/dist/projection/SchemaOrCard.js.map +0 -1
  320. package/dist/projection/card/EntityTypeSource.d.ts +0 -12
  321. package/dist/projection/card/EntityTypeSource.d.ts.map +0 -1
  322. package/dist/projection/card/EntityTypeSource.js +0 -78
  323. package/dist/projection/card/EntityTypeSource.js.map +0 -1
  324. package/dist/projection/card/FacadeTypeSource.d.ts +0 -19
  325. package/dist/projection/card/FacadeTypeSource.d.ts.map +0 -1
  326. package/dist/projection/card/FacadeTypeSource.js +0 -40
  327. package/dist/projection/card/FacadeTypeSource.js.map +0 -1
  328. package/dist/schema/Schema.d.ts.map +0 -1
  329. package/dist/schema/Schema.js.map +0 -1
  330. package/dist/schema/SchemaDefinition.d.ts +0 -60
  331. package/dist/schema/SchemaDefinition.d.ts.map +0 -1
  332. package/dist/schema/SchemaDefinition.js +0 -85
  333. package/dist/schema/SchemaDefinition.js.map +0 -1
  334. package/dist/schema/SchemaDerivation.d.ts +0 -34
  335. package/dist/schema/SchemaDerivation.d.ts.map +0 -1
  336. package/dist/schema/SchemaDerivation.js +0 -51
  337. package/dist/schema/SchemaDerivation.js.map +0 -1
  338. package/dist/schema/SchemaView.d.ts.map +0 -1
  339. package/dist/schema/axis/Axis.d.ts.map +0 -1
  340. package/dist/schema/axis/Axis.js.map +0 -1
  341. package/dist/schema/axis/Meta.d.ts.map +0 -1
  342. package/dist/schema/axis/boundary/Boundaries.d.ts +0 -20
  343. package/dist/schema/axis/boundary/Boundaries.d.ts.map +0 -1
  344. package/dist/schema/axis/boundary/Boundaries.js +0 -31
  345. package/dist/schema/axis/boundary/Boundaries.js.map +0 -1
  346. package/dist/schema/axis/boundary/Boundary.d.ts.map +0 -1
  347. package/dist/schema/axis/boundary/Boundary.js.map +0 -1
  348. package/dist/schema/axis/boundary/BoundaryAxis.d.ts.map +0 -1
  349. package/dist/schema/axis/boundary/BoundaryAxis.js.map +0 -1
  350. package/dist/schema/axis/lifecycle/Clock.d.ts.map +0 -1
  351. package/dist/schema/axis/lifecycle/Clock.js.map +0 -1
  352. package/dist/schema/axis/lifecycle/Generators.d.ts +0 -18
  353. package/dist/schema/axis/lifecycle/Generators.d.ts.map +0 -1
  354. package/dist/schema/axis/lifecycle/Generators.js +0 -38
  355. package/dist/schema/axis/lifecycle/Generators.js.map +0 -1
  356. package/dist/schema/axis/lifecycle/Lifecycle.d.ts.map +0 -1
  357. package/dist/schema/axis/lifecycle/Lifecycle.js.map +0 -1
  358. package/dist/schema/axis/lifecycle/LifecycleAxis.d.ts.map +0 -1
  359. package/dist/schema/axis/lifecycle/LifecycleAxis.js.map +0 -1
  360. package/dist/schema/axis/lifecycle/apply.d.ts +0 -6
  361. package/dist/schema/axis/lifecycle/apply.d.ts.map +0 -1
  362. package/dist/schema/axis/lifecycle/apply.js +0 -34
  363. package/dist/schema/axis/lifecycle/apply.js.map +0 -1
  364. package/dist/schema/axis/role/Relation.d.ts.map +0 -1
  365. package/dist/schema/axis/role/Relation.js.map +0 -1
  366. package/dist/schema/axis/role/Role.d.ts.map +0 -1
  367. package/dist/schema/axis/role/Role.js +0 -40
  368. package/dist/schema/axis/role/Role.js.map +0 -1
  369. package/dist/schema/axis/role/RoleAxis.d.ts.map +0 -1
  370. package/dist/schema/axis/role/RoleAxis.js.map +0 -1
  371. package/dist/schema/axis/shape/Formats.d.ts +0 -8
  372. package/dist/schema/axis/shape/Formats.d.ts.map +0 -1
  373. package/dist/schema/axis/shape/Formats.js +0 -10
  374. package/dist/schema/axis/shape/Formats.js.map +0 -1
  375. package/dist/schema/axis/shape/Shape.d.ts.map +0 -1
  376. package/dist/schema/axis/shape/Shape.js.map +0 -1
  377. package/dist/schema/fields/Field.d.ts.map +0 -1
  378. package/dist/schema/fields/Field.js +0 -52
  379. package/dist/schema/fields/Field.js.map +0 -1
  380. package/dist/schema/fields/FieldSet.d.ts +0 -28
  381. package/dist/schema/fields/FieldSet.d.ts.map +0 -1
  382. package/dist/schema/fields/FieldSet.js +0 -55
  383. package/dist/schema/fields/FieldSet.js.map +0 -1
  384. package/dist/schema/fields/constraint/FieldGroup.d.ts +0 -21
  385. package/dist/schema/fields/constraint/FieldGroup.d.ts.map +0 -1
  386. package/dist/schema/fields/constraint/FieldGroup.js +0 -65
  387. package/dist/schema/fields/constraint/FieldGroup.js.map +0 -1
  388. package/dist/schema/fields/constraint/Unique.d.ts +0 -4
  389. package/dist/schema/fields/constraint/Unique.d.ts.map +0 -1
  390. package/dist/schema/fields/constraint/Unique.js +0 -4
  391. package/dist/schema/fields/constraint/Unique.js.map +0 -1
  392. package/dist/utils.d.ts.map +0 -1
  393. package/dist/utils.js.map +0 -1
  394. package/src/judge/options.ts +0 -3
  395. package/src/projection/SchemaOrCard.ts +0 -18
  396. package/src/projection/card/EntityTypeSource.ts +0 -90
  397. package/src/projection/card/FacadeTypeSource.ts +0 -55
  398. package/src/schema/SchemaDefinition.ts +0 -150
  399. package/src/schema/SchemaDerivation.ts +0 -65
  400. package/src/schema/axis/boundary/Boundaries.ts +0 -44
  401. package/src/schema/axis/lifecycle/Generators.ts +0 -46
  402. package/src/schema/axis/lifecycle/apply.ts +0 -39
  403. package/src/schema/axis/role/Role.ts +0 -56
  404. package/src/schema/axis/shape/Formats.ts +0 -22
  405. package/src/schema/fields/FieldSet.ts +0 -63
  406. package/src/schema/fields/constraint/FieldGroup.ts +0 -84
  407. package/src/schema/fields/constraint/Unique.ts +0 -3
  408. /package/dist/{schema/SchemaView.js → SchemaView.js} +0 -0
  409. /package/dist/{schema/axis → axis}/Axis.js +0 -0
  410. /package/dist/{schema/axis → axis}/Meta.d.ts +0 -0
  411. /package/dist/{schema/axis → axis}/Meta.js +0 -0
  412. /package/dist/{schema/axis → axis}/boundary/BoundaryAxis.d.ts +0 -0
  413. /package/dist/{schema/axis → axis}/lifecycle/Lifecycle.d.ts +0 -0
  414. /package/dist/{schema/axis → axis}/lifecycle/Lifecycle.js +0 -0
  415. /package/dist/{schema/axis → axis}/lifecycle/LifecycleAxis.d.ts +0 -0
  416. /package/dist/{utils.d.ts → lib/utils.d.ts} +0 -0
  417. /package/dist/{utils.js → lib/utils.js} +0 -0
  418. /package/src/{schema/axis → axis}/Meta.ts +0 -0
  419. /package/src/{schema/axis → axis}/lifecycle/Lifecycle.ts +0 -0
  420. /package/src/{utils.ts → lib/utils.ts} +0 -0
  421. /package/src/{judge/result.ts → validation.ts} +0 -0
@@ -1,100 +1,8 @@
1
- import type { FieldName, Fields } from '../schema/fields/Field.js';
2
- import { isObject } from '../utils.js';
1
+ import type { FieldName, Fields } from '../field/Field.js';
3
2
 
4
3
  // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-object-type
5
4
  export interface FougereEntityAdapters<K extends string> {}
6
5
 
7
- export type EntityAdapters<TFields extends Fields> = Readonly<Partial<FougereEntityAdapters<FieldName<TFields>>>>;
8
-
9
- /** What `cut` REQUIRES of an augmentation, and the open registry cannot state: addressed by field. */
10
- type FieldEntries = Record<FieldName<Fields>, unknown>;
11
-
12
- type AdapterEntries = Record<string, FieldEntries>;
13
-
14
- /**
15
- * What one schema states per adapter: an adapter name, a field name, then that adapter's own value.
16
- */
17
- export class EntityAdapterSet {
18
- private constructor(private readonly byAdapter: AdapterEntries) {}
19
-
20
- static of(declared: EntityAdapters<Fields> | undefined): EntityAdapterSet | undefined {
21
- if (declared === undefined) return undefined;
22
-
23
- if (!isObject(declared)) {
24
- throw new Error(
25
- `adapters: expected an object keyed by adapter name, got ${typeof declared}.`,
26
- );
27
- }
28
-
29
- const byAdapter: AdapterEntries = {};
30
-
31
- for (const [adapter, perField] of Object.entries(declared as AdapterEntries)) {
32
- if (perField === undefined) continue;
33
-
34
- if (!isObject(perField)) {
35
- throw new Error(
36
- `adapters.${adapter}: expected an object keyed by field name, got ${typeof perField}. ` +
37
- `What an adapter is handed is addressed by the field it applies to.`,
38
- );
39
- }
40
-
41
- if (Object.keys(perField).length) byAdapter[adapter] = perField;
42
- }
43
-
44
- return EntityAdapterSet.made(byAdapter);
45
- }
46
-
47
- /** Several schemas folded into one set; a later source wins, per adapter and per field. */
48
- static merged(sources: readonly (EntityAdapters<Fields> | undefined)[]): EntityAdapterSet | undefined {
49
- const out: AdapterEntries = {};
50
-
51
- for (const source of sources) {
52
- const set = EntityAdapterSet.of(source);
53
- if (!set) continue;
54
-
55
- for (const [adapter, perField] of Object.entries(set.byAdapter)) {
56
- out[adapter] = { ...out[adapter], ...perField };
57
- }
58
- }
59
-
60
- return EntityAdapterSet.made(out);
61
- }
62
-
63
- /** Every field name these entries address — what a caller checks against its own shape. */
64
- get fieldNames(): string[] {
65
- return [...new Set(Object.values(this.byAdapter).flatMap((perField) => Object.keys(perField)))];
66
- }
67
-
68
- /** The plain object, which is what a reader outside this package receives. */
69
- get stated(): EntityAdapters<Fields> {
70
- return this.byAdapter as EntityAdapters<Fields>;
71
- }
72
-
73
- /**
74
- * The entries whose field survives a cut, re-addressed by that field's new name.
75
- *
76
- * The adapter name is not a field and does not move; only the level below it does. An
77
- * entry left on the old name is not an error anywhere downstream — `adapter/sql` looks
78
- * it up by the field it is iterating and simply finds nothing.
79
- */
80
- cut(survives: (key: string) => string | undefined): EntityAdapterSet | undefined {
81
- const out: AdapterEntries = {};
82
-
83
- for (const [adapter, perField] of Object.entries(this.byAdapter)) {
84
- const mapped: FieldEntries = {};
85
-
86
- for (const [key, entry] of Object.entries(perField)) {
87
- const next = survives(key);
88
- if (next !== undefined) mapped[next] = entry;
89
- }
90
-
91
- if (Object.keys(mapped).length) out[adapter] = mapped;
92
- }
93
-
94
- return EntityAdapterSet.made(out);
95
- }
96
-
97
- private static made(byAdapter: AdapterEntries): EntityAdapterSet | undefined {
98
- return Object.keys(byAdapter).length ? new EntityAdapterSet(byAdapter) : undefined;
99
- }
100
- }
6
+ export type EntityAdapters<TFields extends Fields> = Readonly<
7
+ Partial<FougereEntityAdapters<FieldName<TFields>>>
8
+ >;
@@ -1,4 +1,4 @@
1
- import type { FieldName, Fields } from '../schema/fields/Field.js';
1
+ import type { FieldName, Fields } from '../field/Field.js';
2
2
  import type { EntityAdapters } from './EntityAdapters.js';
3
3
 
4
4
  // Ex: [['title', 'name'], ['id']]
package/src/entity.ts CHANGED
@@ -1,7 +1,12 @@
1
- import { type Fields } from './schema/fields/Field.js';
1
+ import { type Fields } from './field/Field.js';
2
2
  import { type EntityDeclarations } from './entity/EntityDeclarations.js';
3
- import { Schema, type SchemaConstructor } from './schema/Schema.js';
3
+ import { Schema, type SchemaConstructor } from './Schema.js';
4
4
 
5
+ /**
6
+ * So the whole framework starts from one call: fields, and what they say about themselves.
7
+ * FR : pour que tout parte d'un appel : les champs, et ce qu'ils disent d'eux-mêmes.
8
+ * `class Post extends entity({ id: primary(), title: text() }, { unique: [['title']] }) {}`
9
+ */
5
10
  export function entity<TFields extends Fields>(
6
11
  fields: TFields,
7
12
  declarations: EntityDeclarations<TFields> = {},
@@ -1,18 +1,18 @@
1
1
  import type { Shape } from '../axis/shape/Shape.js';
2
- import { Role, type RoleRules } from '../axis/role/Role.js';
2
+ import type { RoleRules } from '../axis/role/Role.js';
3
3
  import type { LifecycleRules } from '../axis/lifecycle/Lifecycle.js';
4
4
  import type { BoundaryRef } from '../axis/boundary/Boundary.js';
5
5
  import type { Meta } from '../axis/Meta.js';
6
6
  import type { Axis } from '../axis/Axis.js';
7
- import { FieldJudge } from '../../judge/FieldJudge.js';
8
- import { ValueJudge } from '../../judge/ValueJudge.js';
7
+ import { FieldDeclarationValidator } from '../validator/FieldDeclarationValidator.js';
8
+ import { FieldValueValidator } from '../validator/FieldValueValidator.js';
9
9
 
10
10
  export type Fields = Record<string, Field>;
11
11
 
12
12
  /** A key of a field set — the name a declaration addresses a field by. */
13
13
  export type FieldName<TFields extends Fields> = Extract<keyof TFields, string>;
14
14
 
15
- /** The carrier, the three extension axes, the annotation — the five the judge reads. */
15
+ /** The carrier, the three extension axes, the annotation — the five the validator reads. */
16
16
  export type FieldDeclaration = Pick<Field, 'shape' | Axis['slot'] | 'meta'>;
17
17
 
18
18
  export class Field<T = unknown> {
@@ -25,7 +25,7 @@ export class Field<T = unknown> {
25
25
  declare readonly _type?: T;
26
26
 
27
27
  constructor(init: FieldDeclaration, key?: string) {
28
- const verdict = FieldJudge.of(init).verdict;
28
+ const verdict = FieldDeclarationValidator.of(init).verdict;
29
29
 
30
30
  if (!verdict.success) {
31
31
  throw new Error(
@@ -35,14 +35,14 @@ export class Field<T = unknown> {
35
35
  }
36
36
 
37
37
  this.shape = init.shape;
38
- this.role = Role.resolvedOn(init.role, key);
38
+ this.role = init.role;
39
39
  this.lifecycle = init.lifecycle;
40
40
  this.boundary = init.boundary;
41
41
  this.meta = init.meta;
42
42
 
43
43
  const create = this.lifecycle?.create;
44
44
  if (typeof create === 'object' && create !== null && 'value' in create) {
45
- const checked = ValueJudge.of(this).check(create.value);
45
+ const checked = FieldValueValidator.of(this).validate(create.value);
46
46
  if ('error' in checked)
47
47
  throw new Error(
48
48
  `${key ? `Field '${key}': ` : ''}the declared default ${JSON.stringify(create.value)} ` +
@@ -52,28 +52,10 @@ export class Field<T = unknown> {
52
52
  }
53
53
 
54
54
  static is(value: unknown): value is Field {
55
- return FieldJudge.of(value).verdict.success;
55
+ return FieldDeclarationValidator.of(value).verdict.success;
56
56
  }
57
57
 
58
58
  with<U = T>(overrides: Partial<FieldDeclaration>): Field<U> {
59
59
  return new Field<U>({ ...this, ...overrides });
60
60
  }
61
-
62
- rename(map: (key: string) => string | undefined): Field<T> {
63
- const rules = this.role?.rules;
64
- if (!rules?.length) return this;
65
-
66
- const carried = rules
67
- .map((group) => group.rename(map))
68
- .filter((group) => group !== null);
69
- const unchanged =
70
- carried.length === rules.length &&
71
- carried.every((group, i) => group.equals(rules[i]!));
72
- if (unchanged) return this;
73
-
74
- const { rules: _dropped, ...rest } = this.role!;
75
- return this.with({
76
- role: carried.length ? { ...rest, rules: carried } : rest,
77
- });
78
- }
79
61
  }
@@ -0,0 +1,75 @@
1
+ import { Role } from '../axis/role/Role.js';
2
+ import type { CompositeUnique } from '../entity/EntityDeclarations.js';
3
+ import { Field, type FieldName, type Fields } from './Field.js';
4
+
5
+ export class FieldSet<TFields extends Fields = Fields> {
6
+ private constructor(private readonly fields: TFields) {}
7
+
8
+ static of<TFields extends Fields>(fields: TFields): FieldSet<TFields> {
9
+ return new FieldSet(fields);
10
+ }
11
+
12
+ /**
13
+ * So a declared unique lands where it belongs: on the field, or on the schema.
14
+ * FR : pour qu'une unicité déclarée atterrisse sur le champ ou sur le schéma.
15
+ * `declaring(fields, [['email'], ['listId', 'docId']])`
16
+ * → `email` carries `role.unique`, the pair becomes a schema constraint
17
+ */
18
+ static declaring<TFields extends Fields>(
19
+ declared: TFields,
20
+ unique?: CompositeUnique<TFields>,
21
+ ): { fields: TFields; unique: CompositeUnique<TFields> | undefined } {
22
+ const fields: Fields = {};
23
+ for (const [key, field] of Object.entries(declared))
24
+ fields[key] = new Field(field, key);
25
+
26
+ const composite: string[][] = [];
27
+ for (const group of unique ?? []) {
28
+ const missing = group.filter((key) => !(key in fields));
29
+ if (missing.length)
30
+ throw new Error(
31
+ `unique: [${group.join(', ')}] names ` +
32
+ `${missing.map((key) => `'${key}'`).join(', ')}, which the entity does not declare.`,
33
+ );
34
+
35
+ if (group.length === 1) {
36
+ const key = group[0]!;
37
+ fields[key] = fields[key]!.with({ role: { ...fields[key]!.role, unique: true } });
38
+ continue;
39
+ }
40
+ composite.push([...group]);
41
+ }
42
+
43
+ return {
44
+ fields: fields as TFields,
45
+ unique: deduplicated(composite) as CompositeUnique<TFields> | undefined,
46
+ };
47
+ }
48
+
49
+ /** A second `primary` is refused, naming both, rather than the first winning silently. */
50
+ get primary(): FieldName<TFields> | undefined {
51
+ const primaries = Object.entries(this.fields)
52
+ .filter(([, field]) => Role.of(field).isPrimary)
53
+ .map(([name]) => name);
54
+
55
+ if (primaries.length > 1) {
56
+ throw new Error(
57
+ `FieldSet.primary: ${primaries.map((name) => JSON.stringify(name)).join(', ')} all declare ` +
58
+ '`primary`; a field set can have only one primary field.',
59
+ );
60
+ }
61
+
62
+ return primaries[0] as FieldName<TFields> | undefined;
63
+ }
64
+
65
+ }
66
+
67
+ /** The order is part of a group: `['a','b']` and `['b','a']` are two constraints. */
68
+ export function deduplicated(
69
+ groups: readonly (readonly string[])[],
70
+ ): readonly (readonly string[])[] | undefined {
71
+ const seen = new Map<string, readonly string[]>();
72
+ for (const group of groups) seen.set(JSON.stringify(group), group);
73
+
74
+ return seen.size ? [...seen.values()] : undefined;
75
+ }
package/src/index.ts CHANGED
@@ -1,42 +1,39 @@
1
- export { Field, type Fields } from './schema/fields/Field.js';
2
- export { FieldSet } from './schema/fields/FieldSet.js';
3
- export { type Shape, Anatomy } from './schema/axis/shape/Shape.js';
1
+ export { Field, type Fields } from './field/Field.js';
2
+ export { FieldSet } from './field/FieldSet.js';
3
+ export { type Shape, Shapes } from './axis/shape/Shape.js';
4
4
  export {
5
5
  type StringFormat,
6
6
  type FormatPredicate,
7
7
  Formats,
8
- } from './schema/axis/shape/Formats.js';
9
- export { Role, type RoleRules } from './schema/axis/role/Role.js';
10
- export { type Relation, type EntityConstructor } from './schema/axis/role/Relation.js';
11
- export { Lifecycle, type LifecycleRules } from './schema/axis/lifecycle/Lifecycle.js';
12
- export { type GeneratorRef, Generators } from './schema/axis/lifecycle/Generators.js';
13
- export { Clock } from './schema/axis/lifecycle/Clock.js';
8
+ } from './axis/shape/Formats.js';
9
+ export { Role, type RoleRules } from './axis/role/Role.js';
10
+ export { type Relation, type EntityConstructor } from './axis/role/Relation.js';
11
+ export { Lifecycle, type LifecycleRules } from './axis/lifecycle/Lifecycle.js';
12
+ export { type GeneratorRef, Generators } from './axis/lifecycle/Generators.js';
13
+ export { Clock } from './axis/lifecycle/Clock.js';
14
14
  export {
15
15
  Boundary,
16
16
  type BoundaryRules,
17
17
  type BoundaryRef,
18
- } from './schema/axis/boundary/Boundary.js';
19
- export { type Decoder, type Encoder, Boundaries } from './schema/axis/boundary/Boundaries.js';
20
- export { type Meta } from './schema/axis/Meta.js';
21
- export { FieldGroup } from './schema/fields/constraint/FieldGroup.js';
22
- export { Unique } from './schema/fields/constraint/Unique.js';
18
+ } from './axis/boundary/Boundary.js';
19
+ export { type Decoder, type Encoder, Boundaries } from './axis/boundary/Boundaries.js';
20
+ export { type Meta } from './axis/Meta.js';
23
21
 
22
+ export { Schema, ANONYMOUS_SCHEMA_NAME, type SchemaConstructor } from './Schema.js';
23
+ export { SchemaDerivation } from './SchemaDerivation.js';
24
+ export { Cases, type ValidationCase } from './projection/Cases.js';
25
+ export { InputRefusal } from './validator/InputRefusal.js';
26
+ export { type SchemaView, type Values, type PartialValues } from './SchemaView.js';
24
27
  export {
25
- Schema,
26
- ANONYMOUS_SCHEMA_NAME,
27
- type SchemaConstructor,
28
- } from './schema/Schema.js';
29
- export { SchemaDerivation } from './schema/SchemaDerivation.js';
30
- export { Cases, type Case } from './projection/Cases.js';
31
- export { RowRefusal } from './judge/RowRefusal.js';
32
- export { type SchemaView, type Row, type PartialRow } from './schema/SchemaView.js';
33
- export { type FougereEntityAdapters, type EntityAdapters } from './entity/EntityAdapters.js';
28
+ type FougereEntityAdapters,
29
+ type EntityAdapters,
30
+ } from './entity/EntityAdapters.js';
34
31
  export {
35
32
  type EntityDeclarations,
36
33
  type CompositeUnique,
37
34
  type PreviousNames,
38
35
  } from './entity/EntityDeclarations.js';
39
- export { lowerFirst, upperFirst, isObject } from './utils.js';
36
+ export { lowerFirst, upperFirst, isObject } from './lib/utils.js';
40
37
 
41
38
  export { primary } from './vocabulary/primary.js';
42
39
  export { text } from './vocabulary/text.js';
@@ -60,7 +57,7 @@ export { readOnly } from './vocabulary/readOnly.js';
60
57
  export { writeOnly } from './vocabulary/writeOnly.js';
61
58
  export { json } from './vocabulary/json.js';
62
59
 
63
- export { applyCreate, applyUpdate } from './schema/axis/lifecycle/apply.js';
60
+ export { applyCreate, applyUpdate } from './axis/lifecycle/apply.js';
64
61
  export { Visibility } from './projection/Visibility.js';
65
62
  export { Card } from './projection/card/Card.js';
66
63
  export { Bundle } from './projection/card/Bundle.js';
@@ -73,15 +70,6 @@ export type {
73
70
  RenameCandidate,
74
71
  TypeSet,
75
72
  } from './projection/card/diff.js';
76
- export {
77
- EntityTypeSource,
78
- type EntityTypeSourceOptions,
79
- } from './projection/card/EntityTypeSource.js';
80
- export {
81
- FacadeTypeSource,
82
- type FacadeTypeSourceOptions,
83
- type OpDescriptor,
84
- } from './projection/card/FacadeTypeSource.js';
85
73
  export {
86
74
  type SchemaBundle,
87
75
  type SchemaDescriptor,
@@ -90,17 +78,14 @@ export {
90
78
  type RoleDescriptor,
91
79
  type RelationDescriptor,
92
80
  } from './projection/card/Descriptor.js';
93
- export { type SchemaOrCard, schemaOf, fieldsOf } from './projection/SchemaOrCard.js';
94
81
  export type { StandardSchemaV1 } from './projection/standard.js';
95
82
 
96
83
  export { entity } from './entity.js';
97
84
 
98
- export { FieldJudge } from './judge/FieldJudge.js';
99
- export { ValueJudge } from './judge/ValueJudge.js';
100
- export { RowJudge } from './judge/RowJudge.js';
101
- export { type ValidateOptions } from './judge/options.js';
102
- export {
103
- type ValidationError,
104
- type ValidationResult,
105
- type Checked,
106
- } from './judge/result.js';
85
+ export { FieldDeclarationValidator } from './validator/FieldDeclarationValidator.js';
86
+ export { FieldValueValidator } from './validator/FieldValueValidator.js';
87
+ export { InputValidator } from './validator/InputValidator.js';
88
+ export { AdapterFieldValidator } from './validator/AdapterFieldValidator.js';
89
+ export { Registry } from './lib/Registry.js';
90
+ export { type ValidateOptions } from './validator/InputValidator.js';
91
+ export { type ValidationError, type ValidationResult, type Checked } from './validation.js';
@@ -0,0 +1,37 @@
1
+ export class Registry<T> {
2
+ private readonly entries: Map<string, T>;
3
+
4
+ /** `Unknown boundary decoder 'celsius' — call Boundaries.decoders.register(name, fn).` */
5
+ constructor(
6
+ private readonly label: string,
7
+ private readonly hint?: string,
8
+ builtins?: Iterable<readonly [string, T]>,
9
+ ) {
10
+ this.entries = new Map(builtins);
11
+ }
12
+
13
+ register(name: string, value: T): T {
14
+ this.entries.set(name, value);
15
+
16
+ return value;
17
+ }
18
+
19
+ find(name: string): T | undefined {
20
+ return this.entries.get(name);
21
+ }
22
+
23
+ resolve(name: string, path?: string): T {
24
+ const found = this.find(name);
25
+
26
+ if (found !== undefined) return found;
27
+
28
+ throw new Error(
29
+ `${path ? `${path}: ` : ''}Unknown ${this.label} '${name}'${this.hint ? ` — ${this.hint}` : ''}. ` +
30
+ `This process answers ${this.names.join(', ') || 'nothing yet'}.`,
31
+ );
32
+ }
33
+
34
+ private get names(): string[] {
35
+ return [...this.entries.keys()];
36
+ }
37
+ }
@@ -1,70 +1,74 @@
1
- import { Anatomy } from '../schema/axis/shape/Shape.js';
2
- import { Boundary } from '../schema/axis/boundary/Boundary.js';
3
- import { Lifecycle } from '../schema/axis/lifecycle/Lifecycle.js';
4
- import { Role } from '../schema/axis/role/Role.js';
5
- import type { Field } from '../schema/fields/Field.js';
6
- import type { SchemaView } from '../schema/SchemaView.js';
7
- import { RowJudge } from '../judge/RowJudge.js';
8
- import { RowRefusal } from '../judge/RowRefusal.js';
1
+ import { Shapes } from '../axis/shape/Shape.js';
2
+ import { Boundary } from '../axis/boundary/Boundary.js';
3
+ import { Lifecycle } from '../axis/lifecycle/Lifecycle.js';
4
+ import { Role } from '../axis/role/Role.js';
5
+ import type { Field } from '../field/Field.js';
6
+ import type { SchemaView } from '../SchemaView.js';
7
+ import { InputValidator } from '../validator/InputValidator.js';
8
+ import { InputRefusal } from '../validator/InputRefusal.js';
9
9
 
10
10
  /**
11
- * One input, and what the judge must answer.
11
+ * One input, and what the validator must answer.
12
12
  *
13
13
  * `expect` carries the PATH of the field at fault and never the message. We know which
14
14
  * field must be refused because we are the ones who broke it; naming the message would
15
- * make this list a second judge, and the two would then have to be kept in step by hand —
15
+ * make this list a second validator, and the two would then have to be kept in step by hand —
16
16
  * which is the duplication the whole thing exists to remove.
17
17
  */
18
- export interface Case {
18
+ export interface ValidationCase {
19
19
  /** What this input does, in one clause — carried into the assertion so a failure reads. */
20
20
  why: string;
21
- body: unknown;
22
- /**
23
- * Judged as an update rather than a creation. The two modes refuse different things:
24
- * an absence is `Required` on create and legal on patch, an immutable field is legal
25
- * on create and refused on patch.
26
- */
21
+ input: unknown;
22
+ /** Judged as an update rather than a creation. */
27
23
  patch: boolean;
28
24
  expect: 'accept' | { reject: string };
29
25
  }
30
26
 
31
- /** A value of the wrong type for the declared shape — the one violation every field has. */
27
+ /**
28
+ * So every field has at least one case, whatever else it declares.
29
+ * FR : pour que chaque champ ait un cas, quoi qu'il déclare par ailleurs.
30
+ * `text()` → `42`; `number()` → `'not-a-value-of-this-shape'`
31
+ */
32
32
  function wrongTypeFor(field: Field): unknown {
33
33
  const declared = (field.shape as { type?: string | readonly string[] }).type;
34
34
  const names = Array.isArray(declared) ? declared : [declared];
35
35
  return names.includes('string') ? 42 : 'not-a-value-of-this-shape';
36
36
  }
37
37
 
38
- /** Values that break a stated bound. Empty when the field states none. */
38
+ /**
39
+ * So a bound stated in a shape produces the case that breaks it, and none is invented.
40
+ * FR : pour qu'une borne énoncée produise le cas qui la casse, et aucun autre.
41
+ * `text({ maxLength: 3 })` → one case with `'xxxx'`; `text()` → no case
42
+ */
39
43
  function outOfBoundsFor(field: Field): { why: string; value: unknown }[] {
40
- // Through `Anatomy`, not a cast: the cast admitted any keyword, and it declared
44
+ // Through `Shapes`, not a cast: the cast admitted any keyword, and it declared
41
45
  // `maxItems` — which no branch below ever produced. In the one function whose job is
42
46
  // to be exhaustive, a bound the type does not carry is a case nobody notices missing.
43
- const shape = Anatomy.of(field.shape).base;
44
- const out: { why: string; value: unknown }[] = [];
47
+ const shape = Shapes.of(field.shape).base;
48
+ const cases: { why: string; value: unknown }[] = [];
45
49
  if (shape?.type === 'string') {
46
50
  if (typeof shape.minLength === 'number' && shape.minLength > 0)
47
- out.push({ why: 'shorter than min', value: 'x'.repeat(shape.minLength - 1) });
51
+ cases.push({ why: 'shorter than min', value: 'x'.repeat(shape.minLength - 1) });
48
52
  if (typeof shape.maxLength === 'number')
49
- out.push({ why: 'longer than max', value: 'x'.repeat(shape.maxLength + 1) });
50
- if (shape.enum) out.push({ why: 'outside the stated set', value: '__not-in-enum__' });
53
+ cases.push({ why: 'longer than max', value: 'x'.repeat(shape.maxLength + 1) });
54
+ if (shape.enum) cases.push({ why: 'outside the stated set', value: '__not-in-enum__' });
51
55
  }
52
56
  if (shape?.type === 'number' || shape?.type === 'integer') {
53
57
  if (typeof shape.minimum === 'number')
54
- out.push({ why: 'below minimum', value: shape.minimum - 1 });
58
+ cases.push({ why: 'below minimum', value: shape.minimum - 1 });
55
59
  if (typeof shape.maximum === 'number')
56
- out.push({ why: 'above maximum', value: shape.maximum + 1 });
60
+ cases.push({ why: 'above maximum', value: shape.maximum + 1 });
57
61
  }
58
62
  if (shape?.type === 'array') {
59
63
  if (typeof shape.minItems === 'number' && shape.minItems > 0)
60
- out.push({ why: 'fewer items than min', value: [] });
64
+ cases.push({ why: 'fewer items than min', value: [] });
61
65
  if (typeof shape.maxItems === 'number')
62
- out.push({
66
+ cases.push({
63
67
  why: 'more items than max',
64
68
  value: Array.from({ length: shape.maxItems + 1 }, () => null),
65
69
  });
66
70
  }
67
- return out;
71
+ return cases;
68
72
  }
69
73
 
70
74
  /**
@@ -74,20 +78,14 @@ function outOfBoundsFor(field: Field): { why: string; value: unknown }[] {
74
78
  * supplies a valid row; generating data belongs to the testing package.
75
79
  */
76
80
  export class Cases {
77
- private constructor(readonly all: readonly Case[]) {}
81
+ private constructor(readonly all: readonly ValidationCase[]) {}
78
82
 
79
83
  static of(entity: SchemaView, valid: Record<string, unknown>): Cases {
80
84
  return new Cases(enumerate(entity, valid));
81
85
  }
82
86
 
83
- /**
84
- * Whether a verdict is the one a case expected.
85
- *
86
- * Takes the RESULT rather than the input so the same reader serves the local judge, the
87
- * façade and a door — the three that have to agree.
88
- */
89
87
  static holds(
90
- expected: Case['expect'],
88
+ expected: ValidationCase['expect'],
91
89
  result: { success: boolean; errors?: { path: string }[] },
92
90
  ): boolean {
93
91
  if (expected === 'accept') return result.success;
@@ -95,32 +93,35 @@ export class Cases {
95
93
  return (result.errors ?? []).some((error) => error.path === expected.reject);
96
94
  }
97
95
 
98
- /** Every way a row is refused for its structure — the closed set this table must cover. */
99
96
  static get refusals(): string[] {
100
- return Object.values(RowRefusal);
97
+ return Object.values(InputRefusal);
101
98
  }
102
99
 
103
- [Symbol.iterator](): Iterator<Case> {
100
+ [Symbol.iterator](): Iterator<ValidationCase> {
104
101
  return this.all[Symbol.iterator]();
105
102
  }
106
103
  }
107
104
 
108
- function enumerate(entity: SchemaView, valid: Record<string, unknown>): Case[] {
105
+ /**
106
+ * So the four axes decide which cases exist, and no list of them is maintained by hand.
107
+ * FR : pour que les axes décident des cas, sans liste tenue à la main.
108
+ */
109
+ function enumerate(entity: SchemaView, valid: Record<string, unknown>): ValidationCase[] {
109
110
  const fields = entity.getFields();
110
- const judge = RowJudge.of(fields);
111
- const cases: Case[] = [];
111
+ const validator = InputValidator.of(fields);
112
+ const cases: ValidationCase[] = [];
112
113
  const withField = (name: string, value: unknown) => ({ ...valid, [name]: value });
113
114
 
114
- cases.push({ why: 'a valid body', body: valid, patch: false, expect: 'accept' });
115
+ cases.push({ why: 'a valid input', input: valid, patch: false, expect: 'accept' });
115
116
  cases.push({
116
117
  why: 'a key outside the contract',
117
- body: { ...valid, __unknown__: 'x' },
118
+ input: { ...valid, __unknown__: 'x' },
118
119
  patch: false,
119
120
  expect: { reject: '__unknown__' },
120
121
  });
121
122
  cases.push({
122
123
  why: 'not an object at all',
123
- body: 'a string',
124
+ input: 'a string',
124
125
  patch: false,
125
126
  expect: { reject: '.' },
126
127
  });
@@ -130,16 +131,16 @@ function enumerate(entity: SchemaView, valid: Record<string, unknown>): Case[] {
130
131
  // get to invent a second one, so the only case we can state about it is the bound one.
131
132
  const isRef = Role.of(field).isReference;
132
133
 
133
- if (judge.onAbsent(field) === null && name in valid) {
134
- const body = { ...valid };
135
- delete body[name];
136
- cases.push({ why: `${name} absent`, body, patch: false, expect: { reject: name } });
134
+ if (validator.onAbsent(field) === null && name in valid) {
135
+ const input = { ...valid };
136
+ delete input[name];
137
+ cases.push({ why: `${name} absent`, input, patch: false, expect: { reject: name } });
137
138
  }
138
139
 
139
140
  if (Boundary.of(field).readOnly) {
140
141
  cases.push({
141
142
  why: `${name} supplied although read-only`,
142
- body: withField(name, wrongTypeFor(field)),
143
+ input: withField(name, wrongTypeFor(field)),
143
144
  patch: false,
144
145
  expect: { reject: name },
145
146
  });
@@ -148,7 +149,7 @@ function enumerate(entity: SchemaView, valid: Record<string, unknown>): Case[] {
148
149
  if (Lifecycle.of(field).immutable && !Role.of(field).isPrimary) {
149
150
  cases.push({
150
151
  why: `${name} supplied on an update`,
151
- body: { [name]: valid[name] ?? wrongTypeFor(field) },
152
+ input: { [name]: valid[name] ?? wrongTypeFor(field) },
152
153
  patch: true,
153
154
  expect: { reject: name },
154
155
  });
@@ -157,14 +158,14 @@ function enumerate(entity: SchemaView, valid: Record<string, unknown>): Case[] {
157
158
  if (name in valid && !isRef) {
158
159
  cases.push({
159
160
  why: `${name} of the wrong type`,
160
- body: withField(name, wrongTypeFor(field)),
161
+ input: withField(name, wrongTypeFor(field)),
161
162
  patch: false,
162
163
  expect: { reject: name },
163
164
  });
164
165
  for (const { why, value } of outOfBoundsFor(field))
165
166
  cases.push({
166
167
  why: `${name} ${why}`,
167
- body: withField(name, value),
168
+ input: withField(name, value),
168
169
  patch: false,
169
170
  expect: { reject: name },
170
171
  });