@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,7 +1,7 @@
1
- import { Boundary } from '../schema/axis/boundary/Boundary.js';
2
- import { Lifecycle } from '../schema/axis/lifecycle/Lifecycle.js';
3
- import { Role } from '../schema/axis/role/Role.js';
4
- import type { Fields } from '../schema/fields/Field.js';
1
+ import { Boundary } from '../axis/boundary/Boundary.js';
2
+ import { Lifecycle } from '../axis/lifecycle/Lifecycle.js';
3
+ import { Role } from '../axis/role/Role.js';
4
+ import type { Fields } from '../field/Field.js';
5
5
 
6
6
  export class Visibility {
7
7
  private constructor(private readonly fields: Fields) {}
@@ -10,6 +10,7 @@ export class Visibility {
10
10
  return new Visibility(fields);
11
11
  }
12
12
 
13
+ /** A write-only secret is absent from the type, not just from the value. */
13
14
  get input(): Fields {
14
15
  const result: Fields = {};
15
16
  for (const [name, field] of Object.entries(this.fields)) {
@@ -1,7 +1,7 @@
1
- import type { Resolver } from '../../schema/axis/Axis.js';
2
- import type { EntityConstructor } from '../../schema/axis/role/Relation.js';
3
- import { lowerFirst } from '../../utils.js';
4
- import type { SchemaView } from '../../schema/SchemaView.js';
1
+ import type { Resolver } from '../../axis/Axis.js';
2
+ import type { EntityConstructor } from '../../axis/role/Relation.js';
3
+ import { lowerFirst } from '../../lib/utils.js';
4
+ import type { SchemaView } from '../../SchemaView.js';
5
5
  import { Card } from './Card.js';
6
6
  import type { SchemaBundle, SchemaDescriptor } from './Descriptor.js';
7
7
  import type { Diff, SetDiff, SetDiffOptions } from './diff.js';
@@ -47,12 +47,12 @@ export class Bundle {
47
47
  }
48
48
 
49
49
  toSchemas(): Record<string, SchemaView> {
50
- const map: Record<string, EntityConstructor> = {};
51
- const resolve: Resolver = (name) => map[name.toLowerCase()];
50
+ const byName: Record<string, EntityConstructor> = {};
51
+ const resolve: Resolver = (name) => byName[name.toLowerCase()];
52
52
  const schemas: Record<string, SchemaView> = {};
53
53
  for (const [name, descriptor] of Object.entries(this.descriptor.$defs)) {
54
54
  const schema = Card.fromDescriptor(descriptor).toSchema(resolve, name);
55
- map[name.toLowerCase()] = schema as unknown as EntityConstructor;
55
+ byName[name.toLowerCase()] = schema as unknown as EntityConstructor;
56
56
  schemas[name] = schema;
57
57
  }
58
58
  return schemas;
@@ -65,11 +65,11 @@ export class Bundle {
65
65
  for (const [name, descriptor] of Object.entries(before)) {
66
66
  const target = after[name];
67
67
  if (target === undefined) continue;
68
- const answer = Card.fromDescriptor(descriptor).diff(
68
+ const diff = Card.fromDescriptor(descriptor).diff(
69
69
  Card.fromDescriptor(target),
70
70
  { renamed: options.renamed?.[name] ?? {} },
71
71
  );
72
- if (answer.changes.length > 0 || answer.ambiguous.length > 0) entities[name] = answer;
72
+ if (diff.changes.length > 0 || diff.ambiguous.length > 0) entities[name] = diff;
73
73
  }
74
74
  return {
75
75
  entitiesAdded: Object.keys(after).filter((name) => !(name in before)),
@@ -1,10 +1,11 @@
1
- import { EXTENSION_AXES, EXTENSION_SLOTS, type Resolver } from '../../schema/axis/Axis.js';
1
+ import { EXTENSION_AXES, EXTENSION_SLOTS, type Resolver } from '../../axis/Axis.js';
2
2
  import { dequal } from 'dequal';
3
- import { clean, isObject } from '../../utils.js';
4
- import { Field, type Fields } from '../../schema/fields/Field.js';
5
- import { RowJudge } from '../../judge/RowJudge.js';
6
- import { Schema, type SchemaConstructor } from '../../schema/Schema.js';
7
- import type { Row, SchemaView } from '../../schema/SchemaView.js';
3
+ import { clean, isObject } from '../../lib/utils.js';
4
+ import { Field, type Fields } from '../../field/Field.js';
5
+ import { deduplicated } from '../../field/FieldSet.js';
6
+ import { InputValidator } from '../../validator/InputValidator.js';
7
+ import { Schema, type SchemaConstructor } from '../../Schema.js';
8
+ import type { Values, SchemaView } from '../../SchemaView.js';
8
9
  import { refuse } from './admission.js';
9
10
  import type {
10
11
  DerivedFrom,
@@ -17,21 +18,23 @@ import type { Change, Diff, DiffOptions, RenameCandidate, TypeSet } from './diff
17
18
  type FieldsOf<T> = { [K in keyof T]-?: Field<T[K]> };
18
19
 
19
20
  /** One portable schema description and every decision made about that description. */
20
- export class Card<T = Row<Fields>> {
21
+ export class Card<T = Values<Fields>> {
21
22
  private constructor(readonly descriptor: SchemaDescriptor) {}
22
23
 
23
24
  static fromSchema<TFields extends Fields>(
24
25
  schema: SchemaView<TFields>,
25
26
  name?: string,
26
- ): Card<Row<TFields>> {
27
+ ): Card<Values<TFields>> {
27
28
  const fields = schema.getFields();
28
- const judge = RowJudge.of(fields);
29
+ const validator = InputValidator.of(fields);
29
30
  const properties: Record<string, FieldDescriptor> = {};
30
31
  const required: string[] = [];
31
32
  for (const [key, field] of Object.entries(fields)) {
32
33
  properties[key] = describeField(field, key);
33
- if (judge.onAbsent(field) === null) required.push(key);
34
+ if (validator.onAbsent(field) === null) required.push(key);
34
35
  }
36
+ for (const group of schema.getUnique() ?? [])
37
+ for (const member of group) carryGroup(properties[member], group);
35
38
 
36
39
  const descriptor: SchemaDescriptor = {
37
40
  type: 'object',
@@ -45,53 +48,50 @@ export class Card<T = Row<Fields>> {
45
48
 
46
49
  const origin = originOf(schema);
47
50
  if (origin) descriptor['x-fougere-derived'] = origin;
48
- return new Card<Row<TFields>>(descriptor);
51
+ return new Card<Values<TFields>>(descriptor);
49
52
  }
50
53
 
51
- static fromDescriptor<T = Row<Fields>>(descriptor: SchemaDescriptor): Card<T> {
54
+ static fromDescriptor<T = Values<Fields>>(descriptor: SchemaDescriptor): Card<T> {
52
55
  return new Card<T>(descriptor);
53
56
  }
54
57
 
55
- /** The root derivation recorded by this card, when its schema was cut from another. */
56
58
  get origin(): DerivedFrom | undefined {
57
59
  return this.descriptor['x-fougere-derived'];
58
60
  }
59
61
 
60
- /**
61
- * Rebuild the live schema. A bundle supplies `resolve` so relation thunks can find the
62
- * other reconstructed cards; a lone card deliberately falls back to a name stand-in.
63
- */
64
62
  toSchema(resolve?: Resolver, name?: string): SchemaConstructor<FieldsOf<T>> {
65
63
  const descriptor = this.descriptor;
66
- const where = name ? `schema '${name}'` : 'this schema';
64
+ const subject = name ? `schema '${name}'` : 'this schema';
67
65
  if (!isObject(descriptor))
68
- refuse(`${where} is not an object`, 'A card carries one JSON Schema per door.');
66
+ refuse(`${subject} is not an object`, 'A card carries one JSON Schema per door.');
69
67
  const version = descriptor['x-fougere-version'];
70
68
  if (version !== 1) {
71
69
  refuse(
72
- `${where} states \`x-fougere-version: ${JSON.stringify(version)}\` and this reader speaks 1`,
70
+ `${subject} states \`x-fougere-version: ${JSON.stringify(version)}\` and this reader speaks 1`,
73
71
  'A producer and its readers move together: re-sync the consumer, or serve the version it speaks.',
74
72
  );
75
73
  }
76
74
  if (!isObject(descriptor.properties)) {
77
75
  refuse(
78
- `${where} carries no \`properties\` object`,
76
+ `${subject} carries no \`properties\` object`,
79
77
  'A schema is its fields; there is nothing to rebuild.',
80
78
  );
81
79
  }
82
80
 
83
81
  const fields: Fields = {};
82
+ const groups: string[][] = [];
84
83
  for (const [key, property] of Object.entries(descriptor.properties)) {
85
84
  fields[key] = reconstructField(property, key, resolve);
85
+ for (const group of property['x-fougere']?.role?.unique ?? [])
86
+ if (group.length > 1) groups.push([...group]);
86
87
  }
87
- const schema = Schema.of({ fields });
88
+ const schema = Schema.of({ fields, constraints: { unique: deduplicated(groups) } });
88
89
  const title = name ?? descriptor.title;
89
90
  if (title)
90
91
  Object.defineProperty(schema, 'name', { value: title, configurable: true });
91
92
  return schema as unknown as SchemaConstructor<FieldsOf<T>>;
92
93
  }
93
94
 
94
- /** What must change to turn this card into `other`. */
95
95
  diff(other: Card, options: DiffOptions = {}): Diff {
96
96
  const changes: Change[] = [];
97
97
  const renamed = options.renamed ?? {};
@@ -155,6 +155,11 @@ export class Card<T = Row<Fields>> {
155
155
  }
156
156
  }
157
157
 
158
+ /**
159
+ * So the three axes write themselves under `x-fougere`, each by its own hand.
160
+ * FR : pour que les trois axes s'écrivent sous `x-fougere`, chacun de sa main.
161
+ * `ref(User)` → `{ role: { relation: { to: 'user', kind: 'one' } } }`
162
+ */
158
163
  function describeExtension(field: Field, key: string): FieldExtension | undefined {
159
164
  const extension: Record<string, unknown> = {};
160
165
  for (const axis of EXTENSION_AXES) {
@@ -167,72 +172,57 @@ function describeExtension(field: Field, key: string): FieldExtension | undefine
167
172
  return Object.keys(extension).length ? (extension as FieldExtension) : undefined;
168
173
  }
169
174
 
175
+ /**
176
+ * So the shape stays plain JSON Schema, and what is ours sits under one key.
177
+ * FR : pour que la forme reste du JSON Schema, ce qui est à nous tenant sous une clé.
178
+ * `text({ max: 200 })` → `{ type: 'string', maxLength: 200 }`
179
+ */
170
180
  function describeField(field: Field, key: string): FieldDescriptor {
171
- const descriptor: FieldDescriptor = {};
172
- for (const [shapeKey, value] of Object.entries(field.shape)) {
173
- if (value !== undefined) (descriptor as Record<string, unknown>)[shapeKey] = value;
174
- }
181
+ // The shape IS JSON Schema, so it lands whole rather than key by key — which is what let
182
+ // it be copied under a computed key into a type that names its own.
183
+ const descriptor: FieldDescriptor = clean({ ...field.shape }) as FieldDescriptor;
175
184
  if (field.meta?.description) descriptor.description = field.meta.description;
176
185
  const extension = describeExtension(field, key);
177
186
  if (extension) descriptor['x-fougere'] = extension;
178
187
  return descriptor;
179
188
  }
180
189
 
190
+ /**
191
+ * So a derived card names its root and what became of each field.
192
+ * FR : pour qu'une carte dérivée nomme sa racine et le sort de chaque champ.
193
+ * `Post.pick('title')` → `{ from: 'Post', nameOf: { title: 'title' } }`
194
+ */
181
195
  function originOf(schema: SchemaView): DerivedFrom | undefined {
182
196
  const { derivation } = schema;
183
197
  if (!derivation) return undefined;
184
- const survived = Object.fromEntries(
185
- Object.entries(derivation.survived).map(([key, value]) => [key, value ?? null]),
198
+ const nameOf = Object.fromEntries(
199
+ Object.entries(derivation.nameOf).map(([key, value]) => [key, value ?? null]),
186
200
  );
187
- return { from: derivation.sourceName, survived };
201
+ return { from: derivation.sourceName, nameOf };
188
202
  }
189
203
 
204
+ /**
205
+ * So a shape read back is the shape that was written, and an unknown type is refused.
206
+ * FR : pour qu'une forme relue soit celle qui a été écrite, un type inconnu étant refusé.
207
+ * `{ type: 'string', maxLength: 200 }` → the same shape a `text({ max: 200 })` states
208
+ */
190
209
  function reconstructShape(property: FieldDescriptor): Field['shape'] | undefined {
191
- const types = Array.isArray(property.type)
192
- ? property.type
193
- : property.type
194
- ? [property.type]
195
- : [];
196
- const base = types.find((type) => type !== 'null');
197
- if (base === undefined) return undefined;
198
- const type = property.type as Field['shape']['type'];
199
- if (base === 'array') {
200
- const items = property.items ? reconstructShape(property.items) : undefined;
201
- return clean({
202
- type,
203
- items,
204
- minItems: property.minItems,
205
- maxItems: property.maxItems,
206
- }) as Field['shape'];
207
- }
208
- switch (base) {
209
- case 'string':
210
- return clean({
211
- type,
212
- minLength: property.minLength,
213
- maxLength: property.maxLength,
214
- pattern: property.pattern,
215
- enum: property.enum,
216
- format: property.format,
217
- }) as Field['shape'];
218
- case 'number':
219
- case 'integer':
220
- return clean({
221
- type,
222
- minimum: property.minimum,
223
- maximum: property.maximum,
224
- }) as Field['shape'];
225
- case 'boolean':
226
- return { type } as Field['shape'];
227
- default:
228
- return clean({
229
- type,
230
- properties: property.properties,
231
- required: property.required,
232
- }) as Field['shape'];
233
- }
210
+ const types = Array.isArray(property.type) ? property.type : property.type ? [property.type] : [];
211
+ if (!types.some((type) => type !== 'null')) return undefined;
212
+
213
+ // `describeField` writes the shape whole, so it is read whole: a list of keywords here
214
+ // would be a second inventory, and the one that forgets a keyword loses it in silence.
215
+ const { 'x-fougere': _extension, description: _description, ...shape } = property;
216
+ if (shape.items) shape.items = reconstructShape(shape.items) as FieldDescriptor;
217
+
218
+ return clean(shape) as Field['shape'];
234
219
  }
235
220
 
221
+ /**
222
+ * So a field read back carries its axes, rebuilt by the axes themselves.
223
+ * FR : pour qu'un champ relu porte ses axes, reconstruits par les axes eux-mêmes.
224
+ * `{ 'x-fougere': { lifecycle: { create: 'now' } } }` → a field stamped at create
225
+ */
236
226
  function reconstructField(
237
227
  property: FieldDescriptor,
238
228
  key: string,
@@ -261,6 +251,11 @@ function reconstructField(
261
251
  } as never);
262
252
  }
263
253
 
254
+ /**
255
+ * So an axis that changed is one named difference, not a whole field marked dirty.
256
+ * FR : pour qu'un axe modifié soit une différence nommée, pas un champ entier marqué.
257
+ * `{ kind: 'restated', field: 'body', axis: 'boundary', … }`
258
+ */
264
259
  function restated(
265
260
  field: string,
266
261
  before: FieldExtension | undefined,
@@ -278,22 +273,42 @@ function restated(
278
273
  );
279
274
  }
280
275
 
276
+ /**
277
+ * So two shapes are compared without what is not shape getting in the way.
278
+ * FR : pour que deux formes se comparent sans que le reste s'en mêle.
279
+ * `{ type: 'string', description: 'x' }` → `{ type: 'string' }`
280
+ */
281
281
  function shapeOf(descriptor: FieldDescriptor): Record<string, unknown> {
282
- const { 'x-fougere': _extension, ...shape } = descriptor;
282
+ const { 'x-fougere': _extension, description: _description, ...shape } = descriptor;
283
283
  return shape as Record<string, unknown>;
284
284
  }
285
285
 
286
+ /**
287
+ * So `['string','null']` and `['null','string']` are the same type, not a change.
288
+ * FR : pour que `['string','null']` et `['null','string']` soient un même type.
289
+ * `typesOf({ type: ['null', 'string'] })` → `['null', 'string']`
290
+ */
286
291
  function typesOf(descriptor: FieldDescriptor): TypeSet {
287
292
  const type = descriptor.type;
288
293
  if (type === undefined) return [];
289
294
  return (Array.isArray(type) ? [...type] : [type]).sort();
290
295
  }
291
296
 
297
+ /**
298
+ * So a bound that moved is a `reshaped`, told apart from a type that changed.
299
+ * FR : pour qu'une borne déplacée soit un `reshaped`, distinct d'un type changé.
300
+ * `maxLength: 200` → `maxLength: 100` → one `reshaped`, never a `retyped`
301
+ */
292
302
  function boundsOf(descriptor: FieldDescriptor): Record<string, unknown> {
293
303
  const { type: _type, ...rest } = shapeOf(descriptor);
294
304
  return rest;
295
305
  }
296
306
 
307
+ /**
308
+ * So a removal plus an addition of the same shape is a question, never a guess.
309
+ * FR : pour qu'une suppression plus un ajout de même forme soit une question, pas un pari.
310
+ * `body` gone, `content` appeared → `ambiguous: [{ removed: 'body', added: 'content' }]`
311
+ */
297
312
  function candidates(
298
313
  removed: string[],
299
314
  added: string[],
@@ -313,3 +328,15 @@ function candidates(
313
328
  Math.abs(now.indexOf(appeared) - was.indexOf(gone));
314
329
  return found.sort((a, b) => apart(a) - apart(b));
315
330
  }
331
+
332
+ /**
333
+ * So a group spanning several fields reaches a reader that only ever sees one field.
334
+ * FR : pour qu'un groupe couvrant plusieurs champs atteigne un lecteur qui n'en voit qu'un.
335
+ * `carryGroup(properties.listId, ['listId', 'docId'])` → the pair lands under its `role`
336
+ */
337
+ function carryGroup(property: FieldDescriptor | undefined, group: readonly string[]): void {
338
+ if (!property) return;
339
+ const extension = (property['x-fougere'] ??= {}) as { role?: { unique?: string[][] } };
340
+ const role = (extension.role ??= {});
341
+ (role.unique ??= []).push([...group]);
342
+ }
@@ -1,8 +1,8 @@
1
- import type { BoundaryRef } from '../../schema/axis/boundary/Boundary.js';
2
- import type { LifecycleRules } from '../../schema/axis/lifecycle/Lifecycle.js';
3
- import type { Relation } from '../../schema/axis/role/Relation.js';
4
- import type { RoleRules } from '../../schema/axis/role/Role.js';
5
- import type { Shape } from '../../schema/axis/shape/Shape.js';
1
+ import type { BoundaryRef } from '../../axis/boundary/Boundary.js';
2
+ import type { LifecycleRules } from '../../axis/lifecycle/Lifecycle.js';
3
+ import type { Relation } from '../../axis/role/Relation.js';
4
+ import type { RoleRules } from '../../axis/role/Role.js';
5
+ import type { Shape } from '../../axis/shape/Shape.js';
6
6
 
7
7
  type JsonSchemaType =
8
8
  | 'string'
@@ -40,7 +40,7 @@ export type RoleDescriptor = Pick<RoleRules, 'primary' | 'index'> & {
40
40
  export type RelationDescriptor = Pick<Relation, 'kind' | 'onDelete'> & { to: string };
41
41
 
42
42
  /**
43
- * What a derivation was cut from, and what the cut left — `survived` keyed by the
43
+ * What a derivation was cut from, and what the cut left — `nameOf` keyed by the
44
44
  * ORIGIN's field names. Absent on a declaration that derives from nothing.
45
45
  *
46
46
  * A dropped field is `null` and never `undefined`: JSON.stringify erases the second,
@@ -48,7 +48,7 @@ export type RelationDescriptor = Pick<Relation, 'kind' | 'onDelete'> & { to: str
48
48
  */
49
49
  export interface DerivedFrom {
50
50
  from: string;
51
- survived: Record<string, string | null>;
51
+ nameOf: Record<string, string | null>;
52
52
  }
53
53
 
54
54
  export interface SchemaDescriptor {
@@ -1,21 +1,26 @@
1
- import type { ValidationError } from '../../judge/result.js';
1
+ import type { ValidationError } from '../../validation.js';
2
2
 
3
- /** A card is refused by naming what is wrong AND the remedy — never by a bare throw. */
3
+ /**
4
+ * So a card that cannot be read says what is wrong and what to write instead.
5
+ * FR : pour qu'une carte illisible dise ce qui cloche et quoi écrire.
6
+ * `refuse('role.relation.kind is "maybe"', 'Expected one of one, many.')`
7
+ */
4
8
  export function refuse(what: string, fix: string): never {
5
9
  throw new Error(`This card cannot be read: ${what}.\n ${fix}`);
6
10
  }
7
11
 
8
12
  /**
9
- * A wire value admitted by the axis's OWN judge — legal only where its declared and wire
10
- * forms are the same value, which `describe: v => v` states.
13
+ * So a card's axis passes the same validator as a hand-written one, and no second validator exists.
14
+ * FR : pour qu'un axe d'une carte passe le juge des autres, sans second juge.
15
+ * `{ update: 'maybe' }` on a card → `lifecycle is malformed — lifecycle.update: Expected 'now' or 'forbidden'`
11
16
  */
12
17
  export function admitWire(
13
- judge: (value: unknown, errors: ValidationError[]) => void,
18
+ validator: (value: unknown, errors: ValidationError[]) => void,
14
19
  value: unknown,
15
20
  slot: string,
16
21
  ): void {
17
22
  const errors: ValidationError[] = [];
18
- judge(value, errors);
23
+ validator(value, errors);
19
24
  if (errors.length) {
20
25
  refuse(
21
26
  `${slot} is malformed — ${errors.map((e) => `${e.path}: ${e.message}`).join('; ')}`,
@@ -24,6 +29,11 @@ export function admitWire(
24
29
  }
25
30
  }
26
31
 
32
+ /**
33
+ * So a closed set is checked against the list that declares it, never against a copy.
34
+ * FR : pour qu'un ensemble fermé soit vérifié contre la liste qui le déclare.
35
+ * `oneOfTokens('many', RELATION_KINDS)` → `true`
36
+ */
27
37
  export const oneOfTokens = <T extends readonly string[]>(
28
38
  value: unknown,
29
39
  tokens: T,
@@ -1,5 +1,5 @@
1
- import type { BoundaryRef } from '../../schema/axis/boundary/Boundary.js';
2
- import type { LifecycleRules } from '../../schema/axis/lifecycle/Lifecycle.js';
1
+ import type { BoundaryRef } from '../../axis/boundary/Boundary.js';
2
+ import type { LifecycleRules } from '../../axis/lifecycle/Lifecycle.js';
3
3
  import type { FieldDescriptor, RoleDescriptor } from './Descriptor.js';
4
4
 
5
5
  /** One named difference, at one place. Each kind exists because a reader asks for it. */
@@ -0,0 +1,40 @@
1
+ import { Validator } from '@cfworker/json-schema';
2
+ import type { Shape } from '../axis/shape/Shape.js';
3
+ import { isObject } from '../lib/utils.js';
4
+
5
+ /**
6
+ * The format is DATA, not a TypeScript interface: an interface is erased before a JS
7
+ * caller, a config or a card from another language could be measured against it.
8
+ */
9
+ export class AdapterFieldValidator {
10
+ private constructor(private readonly validator: Validator) {}
11
+
12
+ /** Compiled once, at the adapter's own module load. */
13
+ static of(format: Shape): AdapterFieldValidator {
14
+ return new AdapterFieldValidator(new Validator(format as object, '2020-12', true));
15
+ }
16
+
17
+ /** `Post.adapters.sql.body.columnType: Property "postgre" does not match …` */
18
+ assert(entries: unknown, path: string): void {
19
+ if (entries === undefined) return;
20
+
21
+ if (!isObject(entries)) {
22
+ throw new Error(
23
+ `${path}: expected an object keyed by field name, got ${typeof entries}.`,
24
+ );
25
+ }
26
+
27
+ for (const [field, entry] of Object.entries(entries)) {
28
+ const verdict = this.validator.validate(entry);
29
+ if (verdict.valid) continue;
30
+
31
+ // The engine reports outermost first and ends on `False boolean schema`, which names
32
+ // nothing. The last unit above that one is the one carrying the offending key.
33
+ const units = verdict.errors.filter((unit) => unit.keyword !== 'false');
34
+ const failure = units[units.length - 1] ?? verdict.errors[0];
35
+ const nested = (failure?.instanceLocation ?? '#').slice(1).replaceAll('/', '.');
36
+
37
+ throw new Error(`${path}.${field}${nested}: ${failure?.error ?? 'does not match the format'}`);
38
+ }
39
+ }
40
+ }
@@ -1,14 +1,14 @@
1
- import { EXTENSION_AXES } from '../schema/axis/Axis.js';
2
- import { Anatomy } from '../schema/axis/shape/Shape.js';
3
- import type { Field } from '../schema/fields/Field.js';
4
- import { isObject } from '../utils.js';
5
- import type { ValidationError, ValidationResult } from './result.js';
1
+ import { EXTENSION_AXES } from '../axis/Axis.js';
2
+ import { Shapes } from '../axis/shape/Shape.js';
3
+ import type { Field } from '../field/Field.js';
4
+ import { isObject } from '../lib/utils.js';
5
+ import type { ValidationError, ValidationResult } from '../validation.js';
6
6
 
7
- export class FieldJudge {
7
+ export class FieldDeclarationValidator {
8
8
  private constructor(private readonly declaration: unknown) {}
9
9
 
10
- static of(declaration: unknown): FieldJudge {
11
- return new FieldJudge(declaration);
10
+ static of(declaration: unknown): FieldDeclarationValidator {
11
+ return new FieldDeclarationValidator(declaration);
12
12
  }
13
13
 
14
14
  get verdict(): ValidationResult<Field> {
@@ -28,7 +28,7 @@ export class FieldJudge {
28
28
 
29
29
  const errors: ValidationError[] = [];
30
30
 
31
- if (!Anatomy.is(declaration.shape)) {
31
+ if (!Shapes.is(declaration.shape)) {
32
32
  errors.push({
33
33
  path: 'shape',
34
34
  message: `Every field states a shape — got ${JSON.stringify(declaration.shape)}`,
@@ -37,7 +37,7 @@ export class FieldJudge {
37
37
 
38
38
  for (const axis of EXTENSION_AXES) {
39
39
  const declared = declaration[axis.slot];
40
- if (declared !== undefined) axis.judge(declared, errors);
40
+ if (declared !== undefined) axis.validator(declared, errors);
41
41
  }
42
42
 
43
43
  if (declaration.meta !== undefined) {
@@ -1,8 +1,8 @@
1
1
  import { Validator, format as engineFormats } from '@cfworker/json-schema';
2
- import { Formats, type FormatPredicate } from '../schema/axis/shape/Formats.js';
3
- import { Anatomy, type Shape } from '../schema/axis/shape/Shape.js';
4
- import type { Field } from '../schema/fields/Field.js';
5
- import type { Checked } from './result.js';
2
+ import { Formats, type FormatPredicate } from '../axis/shape/Formats.js';
3
+ import { Shapes, type Shape } from '../axis/shape/Shape.js';
4
+ import type { Field } from '../field/Field.js';
5
+ import type { Checked } from '../validation.js';
6
6
 
7
7
  interface ShapePlan {
8
8
  validator: Validator;
@@ -10,18 +10,19 @@ interface ShapePlan {
10
10
  formatName?: string;
11
11
  }
12
12
 
13
- export class ValueJudge {
13
+ export class FieldValueValidator {
14
14
  private static readonly plans = new WeakMap<object, ShapePlan>();
15
15
 
16
16
  private constructor(private readonly field: Field) {}
17
17
 
18
- static of(field: Field): ValueJudge {
19
- return new ValueJudge(field);
18
+ /** The shape is compiled once and reused, not rebuilt per value. */
19
+ static of(field: Field): FieldValueValidator {
20
+ return new FieldValueValidator(field);
20
21
  }
21
22
 
22
- check(value: unknown): Checked {
23
+ validate(value: unknown): Checked {
23
24
  const shape = this.field.shape;
24
- const base = Anatomy.of(shape).base;
25
+ const base = Shapes.of(shape).base;
25
26
  if (value !== null) {
26
27
  if (base?.type === 'object' && !base.properties) return { value };
27
28
  if (
@@ -39,7 +40,7 @@ export class ValueJudge {
39
40
  return { error: 'Expected a number' };
40
41
  }
41
42
  }
42
- const plan = ValueJudge.planFor(shape);
43
+ const plan = FieldValueValidator.planFor(shape);
43
44
  const result = plan.validator.validate(value);
44
45
  if (!result.valid) return { error: result.errors[0]?.error ?? 'Invalid value' };
45
46
  if (plan.custom && typeof value === 'string' && !plan.custom(value)) {
@@ -51,7 +52,7 @@ export class ValueJudge {
51
52
  private static planFor(shape: Shape): ShapePlan {
52
53
  let plan = this.plans.get(shape);
53
54
  if (!plan) {
54
- const base = Anatomy.of(shape).base;
55
+ const base = Shapes.of(shape).base;
55
56
  const formatName = base?.type === 'string' ? base.format : undefined;
56
57
  plan = {
57
58
  validator: new Validator(shape as object, '2020-12', true),
@@ -64,11 +65,11 @@ export class ValueJudge {
64
65
  }
65
66
 
66
67
  private static customFormatOf(name: string): FormatPredicate | undefined {
67
- const custom = Formats.resolve(name);
68
+ const custom = Formats.find(name);
68
69
  if (!custom && !(name in engineFormats)) {
69
70
  throw new Error(
70
71
  `Unknown format: '${name}'. Register it with Formats.register('${name}', …) — ` +
71
- `the engine judges ${Object.keys(engineFormats).length} formats natively and this is not one of them.`,
72
+ `the engine validates ${Object.keys(engineFormats).length} formats natively and this is not one of them.`,
72
73
  );
73
74
  }
74
75
  return custom;
@@ -3,15 +3,13 @@
3
3
  *
4
4
  * A value refused by its own shape carries the engine's message and a decoder refused by
5
5
  * user code carries that code's; neither is structural and neither belongs here. These
6
- * five are `RowJudge`'s own, and a table of cases enumerates them instead of reading the
6
+ * five are `InputValidator`'s own, and a table of cases enumerates them instead of reading the
7
7
  * text of a function — which a minifier rewrites without a word.
8
8
  */
9
- export const RowRefusal = {
9
+ export const InputRefusal = {
10
10
  notAnObject: 'Expected an object',
11
11
  unknownField: 'Unknown field',
12
12
  required: 'Required',
13
13
  readOnly: 'Read-only',
14
14
  immutable: 'Immutable',
15
15
  } as const;
16
-
17
- export type RowRefusal = (typeof RowRefusal)[keyof typeof RowRefusal];