@fougere/schema 0.2.0-alpha.2 → 0.3.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 (343) hide show
  1. package/dist/EntityDeclarations.d.ts +22 -0
  2. package/dist/EntityDeclarations.d.ts.map +1 -0
  3. package/dist/{hints.js → EntityDeclarations.js} +1 -5
  4. package/dist/EntityDeclarations.js.map +1 -0
  5. package/dist/Field.d.ts +21 -0
  6. package/dist/Field.d.ts.map +1 -0
  7. package/dist/Field.js +50 -0
  8. package/dist/Field.js.map +1 -0
  9. package/dist/{schema/schema.d.ts → Schema.d.ts} +27 -34
  10. package/dist/Schema.d.ts.map +1 -0
  11. package/dist/{schema/schema.js → Schema.js} +49 -59
  12. package/dist/Schema.js.map +1 -0
  13. package/dist/SchemaView.d.ts +18 -0
  14. package/dist/SchemaView.d.ts.map +1 -0
  15. package/dist/SchemaView.js +2 -0
  16. package/dist/SchemaView.js.map +1 -0
  17. package/dist/axis/Axis.d.ts +10 -0
  18. package/dist/axis/Axis.d.ts.map +1 -0
  19. package/dist/axis/Axis.js +9 -0
  20. package/dist/axis/Axis.js.map +1 -0
  21. package/dist/axis/Meta.d.ts +4 -0
  22. package/dist/axis/Meta.d.ts.map +1 -0
  23. package/dist/axis/Meta.js +2 -0
  24. package/dist/axis/Meta.js.map +1 -0
  25. package/dist/axis/boundary/Boundaries.d.ts +20 -0
  26. package/dist/axis/boundary/Boundaries.d.ts.map +1 -0
  27. package/dist/axis/boundary/Boundaries.js +31 -0
  28. package/dist/axis/boundary/Boundaries.js.map +1 -0
  29. package/dist/axis/boundary/Boundary.d.ts +26 -0
  30. package/dist/axis/boundary/Boundary.d.ts.map +1 -0
  31. package/dist/axis/boundary/Boundary.js +53 -0
  32. package/dist/axis/boundary/Boundary.js.map +1 -0
  33. package/dist/axis/boundary/axis.d.ts +4 -0
  34. package/dist/axis/boundary/axis.d.ts.map +1 -0
  35. package/dist/axis/boundary/axis.js +29 -0
  36. package/dist/axis/boundary/axis.js.map +1 -0
  37. package/dist/axis/lifecycle/Generators.d.ts +4 -0
  38. package/dist/axis/lifecycle/Generators.d.ts.map +1 -0
  39. package/dist/axis/lifecycle/Generators.js +8 -0
  40. package/dist/axis/lifecycle/Generators.js.map +1 -0
  41. package/dist/axis/lifecycle/Lifecycle.d.ts +28 -0
  42. package/dist/axis/lifecycle/Lifecycle.d.ts.map +1 -0
  43. package/dist/axis/lifecycle/Lifecycle.js +38 -0
  44. package/dist/axis/lifecycle/Lifecycle.js.map +1 -0
  45. package/dist/axis/lifecycle/apply.d.ts +8 -0
  46. package/dist/axis/lifecycle/apply.d.ts.map +1 -0
  47. package/dist/axis/lifecycle/apply.js +72 -0
  48. package/dist/axis/lifecycle/apply.js.map +1 -0
  49. package/dist/axis/lifecycle/axis.d.ts +4 -0
  50. package/dist/axis/lifecycle/axis.d.ts.map +1 -0
  51. package/dist/axis/lifecycle/axis.js +46 -0
  52. package/dist/axis/lifecycle/axis.js.map +1 -0
  53. package/dist/axis/role/Relation.d.ts +10 -0
  54. package/dist/axis/role/Relation.d.ts.map +1 -0
  55. package/dist/axis/role/Relation.js +6 -0
  56. package/dist/axis/role/Relation.js.map +1 -0
  57. package/dist/axis/role/Role.d.ts +38 -0
  58. package/dist/axis/role/Role.d.ts.map +1 -0
  59. package/dist/axis/role/Role.js +50 -0
  60. package/dist/axis/role/Role.js.map +1 -0
  61. package/dist/axis/role/axis.d.ts +5 -0
  62. package/dist/axis/role/axis.d.ts.map +1 -0
  63. package/dist/axis/role/axis.js +101 -0
  64. package/dist/axis/role/axis.js.map +1 -0
  65. package/dist/axis/shape/Formats.d.ts +8 -0
  66. package/dist/axis/shape/Formats.d.ts.map +1 -0
  67. package/dist/axis/shape/Formats.js +10 -0
  68. package/dist/axis/shape/Formats.js.map +1 -0
  69. package/dist/axis/shape/Shape.d.ts +58 -0
  70. package/dist/axis/shape/Shape.d.ts.map +1 -0
  71. package/dist/{field/shape.js → axis/shape/Shape.js} +10 -25
  72. package/dist/axis/shape/Shape.js.map +1 -0
  73. package/dist/card/Descriptor.d.ts +55 -0
  74. package/dist/card/Descriptor.d.ts.map +1 -0
  75. package/dist/card/Descriptor.js +2 -0
  76. package/dist/card/Descriptor.js.map +1 -0
  77. package/dist/card/describe.d.ts +12 -0
  78. package/dist/card/describe.d.ts.map +1 -0
  79. package/dist/card/describe.js +83 -0
  80. package/dist/card/describe.js.map +1 -0
  81. package/dist/card/diff.d.ts +140 -0
  82. package/dist/card/diff.d.ts.map +1 -0
  83. package/dist/card/diff.js +123 -0
  84. package/dist/card/diff.js.map +1 -0
  85. package/dist/card/reconstruct.d.ts +11 -0
  86. package/dist/card/reconstruct.d.ts.map +1 -0
  87. package/dist/card/reconstruct.js +83 -0
  88. package/dist/card/reconstruct.js.map +1 -0
  89. package/dist/card/typescript.d.ts +17 -0
  90. package/dist/card/typescript.d.ts.map +1 -0
  91. package/dist/card/typescript.js +93 -0
  92. package/dist/card/typescript.js.map +1 -0
  93. package/dist/clean.d.ts +2 -0
  94. package/dist/clean.d.ts.map +1 -0
  95. package/dist/{projections/card.js → clean.js} +1 -2
  96. package/dist/clean.js.map +1 -0
  97. package/dist/constraint/FieldGroup.d.ts +21 -0
  98. package/dist/constraint/FieldGroup.d.ts.map +1 -0
  99. package/dist/constraint/FieldGroup.js +65 -0
  100. package/dist/constraint/FieldGroup.js.map +1 -0
  101. package/dist/constraint/Unique.d.ts +4 -0
  102. package/dist/constraint/Unique.d.ts.map +1 -0
  103. package/dist/constraint/Unique.js +4 -0
  104. package/dist/constraint/Unique.js.map +1 -0
  105. package/dist/entity.d.ts +4 -19
  106. package/dist/entity.d.ts.map +1 -1
  107. package/dist/entity.js +13 -39
  108. package/dist/entity.js.map +1 -1
  109. package/dist/index.d.ts +54 -37
  110. package/dist/index.d.ts.map +1 -1
  111. package/dist/index.js +46 -48
  112. package/dist/index.js.map +1 -1
  113. package/dist/judge/Judge.d.ts +14 -0
  114. package/dist/judge/Judge.d.ts.map +1 -0
  115. package/dist/judge/Judge.js +161 -0
  116. package/dist/judge/Judge.js.map +1 -0
  117. package/dist/judge/cases.d.ts +50 -0
  118. package/dist/judge/cases.d.ts.map +1 -0
  119. package/dist/judge/cases.js +100 -0
  120. package/dist/judge/cases.js.map +1 -0
  121. package/dist/judge/form.d.ts +11 -0
  122. package/dist/judge/form.d.ts.map +1 -0
  123. package/dist/judge/form.js +18 -0
  124. package/dist/judge/form.js.map +1 -0
  125. package/dist/judge/options.d.ts +4 -0
  126. package/dist/judge/options.d.ts.map +1 -0
  127. package/dist/judge/options.js +2 -0
  128. package/dist/judge/options.js.map +1 -0
  129. package/dist/judge/result.d.ts +17 -0
  130. package/dist/judge/result.d.ts.map +1 -0
  131. package/dist/judge/result.js +2 -0
  132. package/dist/judge/result.js.map +1 -0
  133. package/dist/name.d.ts +1 -6
  134. package/dist/name.d.ts.map +1 -1
  135. package/dist/name.js +3 -6
  136. package/dist/name.js.map +1 -1
  137. package/dist/projection/encode.d.ts +3 -0
  138. package/dist/projection/encode.d.ts.map +1 -0
  139. package/dist/projection/encode.js +19 -0
  140. package/dist/projection/encode.js.map +1 -0
  141. package/dist/projection/io.d.ts +4 -0
  142. package/dist/projection/io.d.ts.map +1 -0
  143. package/dist/projection/io.js +29 -0
  144. package/dist/projection/io.js.map +1 -0
  145. package/dist/projection/source.d.ts +7 -0
  146. package/dist/projection/source.d.ts.map +1 -0
  147. package/dist/projection/source.js +11 -0
  148. package/dist/projection/source.js.map +1 -0
  149. package/dist/{projections → projection}/standard.d.ts +0 -8
  150. package/dist/projection/standard.d.ts.map +1 -0
  151. package/dist/projection/standard.js +2 -0
  152. package/dist/projection/standard.js.map +1 -0
  153. package/dist/same.d.ts +6 -0
  154. package/dist/same.d.ts.map +1 -0
  155. package/dist/same.js +35 -0
  156. package/dist/same.js.map +1 -0
  157. package/dist/vocabulary/bool.d.ts +1 -1
  158. package/dist/vocabulary/bool.d.ts.map +1 -1
  159. package/dist/vocabulary/bool.js +1 -1
  160. package/dist/vocabulary/bool.js.map +1 -1
  161. package/dist/vocabulary/created.d.ts +1 -5
  162. package/dist/vocabulary/created.d.ts.map +1 -1
  163. package/dist/vocabulary/created.js +1 -5
  164. package/dist/vocabulary/created.js.map +1 -1
  165. package/dist/vocabulary/date.d.ts +1 -1
  166. package/dist/vocabulary/date.d.ts.map +1 -1
  167. package/dist/vocabulary/date.js +1 -1
  168. package/dist/vocabulary/date.js.map +1 -1
  169. package/dist/vocabulary/email.d.ts +1 -2
  170. package/dist/vocabulary/email.d.ts.map +1 -1
  171. package/dist/vocabulary/email.js +0 -1
  172. package/dist/vocabulary/email.js.map +1 -1
  173. package/dist/vocabulary/immutable.d.ts +2 -6
  174. package/dist/vocabulary/immutable.d.ts.map +1 -1
  175. package/dist/vocabulary/immutable.js +4 -7
  176. package/dist/vocabulary/immutable.js.map +1 -1
  177. package/dist/vocabulary/indexed.d.ts +2 -7
  178. package/dist/vocabulary/indexed.d.ts.map +1 -1
  179. package/dist/vocabulary/indexed.js +2 -8
  180. package/dist/vocabulary/indexed.js.map +1 -1
  181. package/dist/vocabulary/json.d.ts +2 -10
  182. package/dist/vocabulary/json.d.ts.map +1 -1
  183. package/dist/vocabulary/json.js +10 -7
  184. package/dist/vocabulary/json.js.map +1 -1
  185. package/dist/vocabulary/list.d.ts +1 -12
  186. package/dist/vocabulary/list.d.ts.map +1 -1
  187. package/dist/vocabulary/list.js +1 -14
  188. package/dist/vocabulary/list.js.map +1 -1
  189. package/dist/vocabulary/many.d.ts +2 -5
  190. package/dist/vocabulary/many.d.ts.map +1 -1
  191. package/dist/vocabulary/many.js +2 -5
  192. package/dist/vocabulary/many.js.map +1 -1
  193. package/dist/vocabulary/nullable.d.ts +2 -6
  194. package/dist/vocabulary/nullable.d.ts.map +1 -1
  195. package/dist/vocabulary/nullable.js +5 -8
  196. package/dist/vocabulary/nullable.js.map +1 -1
  197. package/dist/vocabulary/number.d.ts +1 -1
  198. package/dist/vocabulary/number.d.ts.map +1 -1
  199. package/dist/vocabulary/number.js +1 -1
  200. package/dist/vocabulary/number.js.map +1 -1
  201. package/dist/vocabulary/oneOf.d.ts +1 -8
  202. package/dist/vocabulary/oneOf.d.ts.map +1 -1
  203. package/dist/vocabulary/oneOf.js +1 -1
  204. package/dist/vocabulary/oneOf.js.map +1 -1
  205. package/dist/vocabulary/optional.d.ts +2 -9
  206. package/dist/vocabulary/optional.d.ts.map +1 -1
  207. package/dist/vocabulary/optional.js +6 -14
  208. package/dist/vocabulary/optional.js.map +1 -1
  209. package/dist/vocabulary/primary.d.ts +2 -15
  210. package/dist/vocabulary/primary.d.ts.map +1 -1
  211. package/dist/vocabulary/primary.js +3 -9
  212. package/dist/vocabulary/primary.js.map +1 -1
  213. package/dist/vocabulary/readOnly.d.ts +2 -6
  214. package/dist/vocabulary/readOnly.d.ts.map +1 -1
  215. package/dist/vocabulary/readOnly.js +5 -8
  216. package/dist/vocabulary/readOnly.js.map +1 -1
  217. package/dist/vocabulary/ref.d.ts +2 -7
  218. package/dist/vocabulary/ref.d.ts.map +1 -1
  219. package/dist/vocabulary/ref.js +2 -7
  220. package/dist/vocabulary/ref.js.map +1 -1
  221. package/dist/vocabulary/text.d.ts +2 -2
  222. package/dist/vocabulary/text.d.ts.map +1 -1
  223. package/dist/vocabulary/text.js +1 -1
  224. package/dist/vocabulary/text.js.map +1 -1
  225. package/dist/vocabulary/unique.d.ts +2 -12
  226. package/dist/vocabulary/unique.d.ts.map +1 -1
  227. package/dist/vocabulary/unique.js +5 -13
  228. package/dist/vocabulary/unique.js.map +1 -1
  229. package/dist/vocabulary/updated.d.ts +1 -6
  230. package/dist/vocabulary/updated.d.ts.map +1 -1
  231. package/dist/vocabulary/updated.js +0 -5
  232. package/dist/vocabulary/updated.js.map +1 -1
  233. package/dist/vocabulary/url.d.ts +1 -2
  234. package/dist/vocabulary/url.d.ts.map +1 -1
  235. package/dist/vocabulary/url.js +0 -1
  236. package/dist/vocabulary/url.js.map +1 -1
  237. package/dist/vocabulary/vocabulary.d.ts +5 -0
  238. package/dist/vocabulary/vocabulary.d.ts.map +1 -0
  239. package/dist/vocabulary/vocabulary.js +31 -0
  240. package/dist/vocabulary/vocabulary.js.map +1 -0
  241. package/dist/vocabulary/writeOnly.d.ts +2 -6
  242. package/dist/vocabulary/writeOnly.d.ts.map +1 -1
  243. package/dist/vocabulary/writeOnly.js +5 -8
  244. package/dist/vocabulary/writeOnly.js.map +1 -1
  245. package/package.json +1 -1
  246. package/dist/field/boundary.d.ts +0 -69
  247. package/dist/field/boundary.d.ts.map +0 -1
  248. package/dist/field/boundary.js +0 -82
  249. package/dist/field/boundary.js.map +0 -1
  250. package/dist/field/field.d.ts +0 -21
  251. package/dist/field/field.d.ts.map +0 -1
  252. package/dist/field/field.js +0 -24
  253. package/dist/field/field.js.map +0 -1
  254. package/dist/field/format.d.ts +0 -29
  255. package/dist/field/format.d.ts.map +0 -1
  256. package/dist/field/format.js +0 -24
  257. package/dist/field/format.js.map +0 -1
  258. package/dist/field/index.d.ts +0 -8
  259. package/dist/field/index.d.ts.map +0 -1
  260. package/dist/field/index.js +0 -10
  261. package/dist/field/index.js.map +0 -1
  262. package/dist/field/lifecycle.d.ts +0 -31
  263. package/dist/field/lifecycle.d.ts.map +0 -1
  264. package/dist/field/lifecycle.js +0 -20
  265. package/dist/field/lifecycle.js.map +0 -1
  266. package/dist/field/meta.d.ts +0 -5
  267. package/dist/field/meta.d.ts.map +0 -1
  268. package/dist/field/meta.js +0 -5
  269. package/dist/field/meta.js.map +0 -1
  270. package/dist/field/role.d.ts +0 -47
  271. package/dist/field/role.d.ts.map +0 -1
  272. package/dist/field/role.js +0 -35
  273. package/dist/field/role.js.map +0 -1
  274. package/dist/field/shape.d.ts +0 -89
  275. package/dist/field/shape.d.ts.map +0 -1
  276. package/dist/field/shape.js.map +0 -1
  277. package/dist/hints.d.ts +0 -28
  278. package/dist/hints.d.ts.map +0 -1
  279. package/dist/hints.js.map +0 -1
  280. package/dist/projections/card.d.ts +0 -98
  281. package/dist/projections/card.d.ts.map +0 -1
  282. package/dist/projections/card.js.map +0 -1
  283. package/dist/projections/describe.d.ts +0 -25
  284. package/dist/projections/describe.d.ts.map +0 -1
  285. package/dist/projections/describe.js +0 -131
  286. package/dist/projections/describe.js.map +0 -1
  287. package/dist/projections/encode.d.ts +0 -11
  288. package/dist/projections/encode.d.ts.map +0 -1
  289. package/dist/projections/encode.js +0 -26
  290. package/dist/projections/encode.js.map +0 -1
  291. package/dist/projections/io.d.ts +0 -24
  292. package/dist/projections/io.d.ts.map +0 -1
  293. package/dist/projections/io.js +0 -46
  294. package/dist/projections/io.js.map +0 -1
  295. package/dist/projections/lifecycle.d.ts +0 -29
  296. package/dist/projections/lifecycle.d.ts.map +0 -1
  297. package/dist/projections/lifecycle.js +0 -93
  298. package/dist/projections/lifecycle.js.map +0 -1
  299. package/dist/projections/reconstruct.d.ts +0 -31
  300. package/dist/projections/reconstruct.d.ts.map +0 -1
  301. package/dist/projections/reconstruct.js +0 -146
  302. package/dist/projections/reconstruct.js.map +0 -1
  303. package/dist/projections/source.d.ts +0 -18
  304. package/dist/projections/source.d.ts.map +0 -1
  305. package/dist/projections/source.js +0 -18
  306. package/dist/projections/source.js.map +0 -1
  307. package/dist/projections/standard.d.ts.map +0 -1
  308. package/dist/projections/standard.js +0 -10
  309. package/dist/projections/standard.js.map +0 -1
  310. package/dist/projections/typescript.d.ts +0 -37
  311. package/dist/projections/typescript.d.ts.map +0 -1
  312. package/dist/projections/typescript.js +0 -157
  313. package/dist/projections/typescript.js.map +0 -1
  314. package/dist/schema/index.d.ts +0 -3
  315. package/dist/schema/index.d.ts.map +0 -1
  316. package/dist/schema/index.js +0 -2
  317. package/dist/schema/index.js.map +0 -1
  318. package/dist/schema/schema.d.ts.map +0 -1
  319. package/dist/schema/schema.js.map +0 -1
  320. package/dist/schema/view.d.ts +0 -26
  321. package/dist/schema/view.d.ts.map +0 -1
  322. package/dist/schema/view.js +0 -2
  323. package/dist/schema/view.js.map +0 -1
  324. package/dist/unique.d.ts +0 -40
  325. package/dist/unique.d.ts.map +0 -1
  326. package/dist/unique.js +0 -57
  327. package/dist/unique.js.map +0 -1
  328. package/dist/validation/index.d.ts +0 -4
  329. package/dist/validation/index.d.ts.map +0 -1
  330. package/dist/validation/index.js +0 -2
  331. package/dist/validation/index.js.map +0 -1
  332. package/dist/validation/judge.d.ts +0 -55
  333. package/dist/validation/judge.d.ts.map +0 -1
  334. package/dist/validation/judge.js +0 -351
  335. package/dist/validation/judge.js.map +0 -1
  336. package/dist/validation/options.d.ts +0 -6
  337. package/dist/validation/options.d.ts.map +0 -1
  338. package/dist/validation/options.js +0 -3
  339. package/dist/validation/options.js.map +0 -1
  340. package/dist/validation/result.d.ts +0 -20
  341. package/dist/validation/result.d.ts.map +0 -1
  342. package/dist/validation/result.js +0 -3
  343. package/dist/validation/result.js.map +0 -1
@@ -0,0 +1,10 @@
1
+ export class Formats {
2
+ static registry = new Map();
3
+ static register(name, predicate) {
4
+ this.registry.set(name, predicate);
5
+ }
6
+ static resolve(name) {
7
+ return this.registry.get(name);
8
+ }
9
+ }
10
+ //# sourceMappingURL=Formats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Formats.js","sourceRoot":"","sources":["../../../src/axis/shape/Formats.ts"],"names":[],"mappings":"AAWA,MAAM,OAAO,OAAO;IACV,MAAM,CAAU,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;IAEtE,MAAM,CAAC,QAAQ,CAAC,IAAY,EAAE,SAA0B;QACtD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,CAAC,OAAO,CAAC,IAAY;QACzB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;CACF"}
@@ -0,0 +1,58 @@
1
+ import type { StringFormat } from './Formats.js';
2
+ type Nullably<T extends string> = T | readonly [T, 'null'];
3
+ interface StringConstraints {
4
+ minLength?: number;
5
+ maxLength?: number;
6
+ pattern?: string;
7
+ enum?: readonly (string | null)[];
8
+ format?: StringFormat;
9
+ }
10
+ interface NumericConstraints {
11
+ minimum?: number;
12
+ maximum?: number;
13
+ }
14
+ interface ArrayConstraints {
15
+ items?: Shape;
16
+ minItems?: number;
17
+ maxItems?: number;
18
+ }
19
+ interface ObjectConstraints {
20
+ properties?: Record<string, unknown>;
21
+ required?: readonly string[];
22
+ }
23
+ export type Shape = ({
24
+ type: Nullably<'string'>;
25
+ } & StringConstraints) | ({
26
+ type: Nullably<'number'> | Nullably<'integer'>;
27
+ } & NumericConstraints) | {
28
+ type: Nullably<'boolean'>;
29
+ } | ({
30
+ type: Nullably<'array'>;
31
+ } & ArrayConstraints) | ({
32
+ type: Nullably<'object'>;
33
+ } & ObjectConstraints);
34
+ type BaseShape = ({
35
+ type: 'string';
36
+ } & StringConstraints) | ({
37
+ type: 'number' | 'integer';
38
+ } & NumericConstraints) | {
39
+ type: 'boolean';
40
+ } | ({
41
+ type: 'array';
42
+ } & ArrayConstraints) | ({
43
+ type: 'object';
44
+ } & ObjectConstraints);
45
+ interface ShapeAnatomy {
46
+ base?: BaseShape;
47
+ nullable: boolean;
48
+ }
49
+ export declare class Anatomy {
50
+ static is(value: unknown): value is Shape;
51
+ static nullable(shape: Shape): Shape;
52
+ private static readonly cache;
53
+ private static readonly none;
54
+ static of(shape?: Shape): ShapeAnatomy;
55
+ static isNullable(shape?: Shape): boolean;
56
+ }
57
+ export {};
58
+ //# sourceMappingURL=Shape.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Shape.d.ts","sourceRoot":"","sources":["../../../src/axis/shape/Shape.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,KAAK,QAAQ,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAE3D,UAAU,iBAAiB;IAAG,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,YAAY,CAAA;CAAE;AAClJ,UAAU,kBAAkB;IAAG,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE;AACnE,UAAU,gBAAgB;IAAG,KAAK,CAAC,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE;AAClF,UAAU,iBAAiB;IAAG,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE;AAElG,MAAM,MAAM,KAAK,GACb,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAA;CAAE,GAAG,iBAAiB,CAAC,GAClD,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAA;CAAE,GAAG,kBAAkB,CAAC,GACzE;IAAE,IAAI,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAA;CAAE,GAC7B,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;CAAE,GAAG,gBAAgB,CAAC,GAChD,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAA;CAAE,GAAG,iBAAiB,CAAC,CAAC;AAcvD,KAAK,SAAS,GACV,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAAG,iBAAiB,CAAC,GACxC,CAAC;IAAE,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAA;CAAE,GAAG,kBAAkB,CAAC,GACrD;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB,CAAC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,gBAAgB,CAAC,GACtC,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAAG,iBAAiB,CAAC,CAAC;AAW7C,UAAU,YAAY;IACpB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,qBAAa,OAAO;IAClB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,KAAK,CAExC;IAED,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAEnC;IAED,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAuC;IACpE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAsD;IAElF,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,YAAY,CAiBrC;IAED,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,OAAO,CAExC;CACF"}
@@ -1,13 +1,5 @@
1
- /**
2
- * The BASE type names — what `Anatomy.of(shape).base?.type` narrows to for a dispatch.
3
- *
4
- * The runtime list is the source and the type derives from it, not the reverse: a type
5
- * union cannot be enumerated at runtime, so writing both by hand means two lists that
6
- * drift. {@link isShape} needs the values, so it is the values that are declared.
7
- */
8
- export const SHAPE_TYPES = ['string', 'number', 'integer', 'boolean', 'array', 'object'];
9
- /** Is this a shape? Asked of its `type`, against {@link SHAPE_TYPES}. */
10
- export function isShape(value) {
1
+ const SHAPE_TYPES = ['string', 'number', 'integer', 'boolean', 'array', 'object'];
2
+ function isShapeImpl(value) {
11
3
  if (typeof value !== 'object' || value === null)
12
4
  return false;
13
5
  const declared = value.type;
@@ -15,13 +7,7 @@ export function isShape(value) {
15
7
  return (names.some((name) => SHAPE_TYPES.includes(name)) &&
16
8
  names.every((name) => name === 'null' || SHAPE_TYPES.includes(name)));
17
9
  }
18
- // ─── nullableShape / anatomy — the two gates of the union ──────────
19
- /**
20
- * Write side: make a shape's grammar accept `null` — the type becomes the union
21
- * `[T, 'null']`, and `null` joins `enum` when present (an enum is a closed value
22
- * set; null must be IN it to be legal). Idempotent.
23
- */
24
- export function nullableShape(shape) {
10
+ function nullableShapeImpl(shape) {
25
11
  if (Array.isArray(shape.type))
26
12
  return shape;
27
13
  const out = { ...shape, type: [shape.type, 'null'] };
@@ -30,13 +16,13 @@ export function nullableShape(shape) {
30
16
  }
31
17
  return out;
32
18
  }
33
- /**
34
- * The read side — the single customs post at the standard's border. Every consumer that
35
- * dispatches on a shape's type comes through here: `shape.type` may be the union
36
- * `[T,'null']`, and a direct comparison fails silently on it.
37
- */
38
19
  export class Anatomy {
39
- /** Cached per shape reference — derivations copy field refs, they never rebuild shapes. */
20
+ static is(value) {
21
+ return isShapeImpl(value);
22
+ }
23
+ static nullable(shape) {
24
+ return nullableShapeImpl(shape);
25
+ }
40
26
  static cache = new WeakMap();
41
27
  static none = { base: undefined, nullable: false };
42
28
  static of(shape) {
@@ -59,9 +45,8 @@ export class Anatomy {
59
45
  }
60
46
  return a;
61
47
  }
62
- /** Sugar for the most common read: does this shape's grammar accept `null`? */
63
48
  static isNullable(shape) {
64
49
  return this.of(shape).nullable;
65
50
  }
66
51
  }
67
- //# sourceMappingURL=shape.js.map
52
+ //# sourceMappingURL=Shape.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Shape.js","sourceRoot":"","sources":["../../../src/axis/shape/Shape.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
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
+ type JsonSchemaType = 'string' | 'number' | 'integer' | 'boolean' | 'object' | 'array' | 'null';
7
+ type ShapeKeywords = UnionToIntersection<KeywordsOf<Shape>>;
8
+ type KeywordsOf<S> = S extends unknown ? Partial<Omit<S, 'type' | 'items' | 'properties'>> : never;
9
+ type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
10
+ export type FieldDescriptor = ShapeKeywords & {
11
+ type?: JsonSchemaType | JsonSchemaType[];
12
+ items?: FieldDescriptor;
13
+ properties?: Record<string, FieldDescriptor>;
14
+ description?: string;
15
+ 'x-fougere'?: FieldExtension;
16
+ };
17
+ export interface FieldExtension {
18
+ role?: RoleDescriptor;
19
+ lifecycle?: LifecycleRules;
20
+ boundary?: BoundaryRef;
21
+ }
22
+ export type RoleDescriptor = Pick<RoleRules, 'primary' | 'index'> & {
23
+ unique?: string[][];
24
+ relation?: RelationDescriptor;
25
+ };
26
+ export type RelationDescriptor = Pick<Relation, 'kind' | 'onDelete'> & {
27
+ to: string;
28
+ };
29
+ /**
30
+ * What a derivation was cut from, and what the cut left — `survived` keyed by the
31
+ * ORIGIN's field names. Absent on a declaration that derives from nothing.
32
+ *
33
+ * A dropped field is `null` and never `undefined`: JSON.stringify erases the second,
34
+ * which would leave the card saying only what remains — what `properties` already says.
35
+ */
36
+ export interface DerivedFrom {
37
+ from: string;
38
+ survived: Record<string, string | null>;
39
+ }
40
+ export interface SchemaDescriptor {
41
+ title?: string;
42
+ type: 'object';
43
+ properties: Record<string, FieldDescriptor>;
44
+ required?: string[];
45
+ 'x-fougere-derived'?: DerivedFrom;
46
+ 'x-fougere-version': 1;
47
+ 'x-fougere-vendor': 'fougere';
48
+ }
49
+ export interface SchemaBundle {
50
+ $defs: Record<string, SchemaDescriptor>;
51
+ 'x-fougere-version': 1;
52
+ 'x-fougere-vendor': 'fougere';
53
+ }
54
+ export {};
55
+ //# sourceMappingURL=Descriptor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Descriptor.d.ts","sourceRoot":"","sources":["../../src/card/Descriptor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAEpD,KAAK,cAAc,GACf,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,SAAS,GACT,QAAQ,GACR,OAAO,GACP,MAAM,CAAC;AAEX,KAAK,aAAa,GAAG,mBAAmB,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;AAE5D,KAAK,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,YAAY,CAAC,CAAC,GAAG,KAAK,CAAC;AACnG,KAAK,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC;AAEpH,MAAM,MAAM,eAAe,GAAG,aAAa,GAAG;IAC5C,IAAI,CAAC,EAAE,cAAc,GAAG,cAAc,EAAE,CAAC;IACzC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,cAAc,CAAC;CAC9B,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,QAAQ,CAAC,EAAE,WAAW,CAAC;CACxB;AAED,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,GAAG;IAClE,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC;IACpB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAAC,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtF;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC5C,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,mBAAmB,CAAC,EAAE,WAAW,CAAC;IAClC,mBAAmB,EAAE,CAAC,CAAC;IACvB,kBAAkB,EAAE,SAAS,CAAC;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACxC,mBAAmB,EAAE,CAAC,CAAC;IACvB,kBAAkB,EAAE,SAAS,CAAC;CAC/B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=Descriptor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Descriptor.js","sourceRoot":"","sources":["../../src/card/Descriptor.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ import type { SchemaView } from '../SchemaView.js';
2
+ import { type DerivedFrom, type SchemaBundle, type SchemaDescriptor } from './Descriptor.js';
3
+ export declare function describe(schema: SchemaView, name?: string): SchemaDescriptor;
4
+ /**
5
+ * A view says what it is a view OF. `title` already carries the origin's name, and
6
+ * carried it alone: two derivations of one entity described identically while serving
7
+ * different fields, and nothing in the card said which was which.
8
+ */
9
+ export declare function derivedOf(schema: SchemaView): DerivedFrom | undefined;
10
+ export declare function sourceNameOf(schema: SchemaView): string | undefined;
11
+ export declare function describeSet(schemas: Record<string, SchemaView> | SchemaView[]): SchemaBundle;
12
+ //# sourceMappingURL=describe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describe.d.ts","sourceRoot":"","sources":["../../src/card/describe.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,KAAK,WAAW,EAA6C,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AA0BxI,wBAAgB,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAmB5E;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,SAAS,CAKrE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAGnE;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,UAAU,EAAE,GAAG,YAAY,CAU5F"}
@@ -0,0 +1,83 @@
1
+ import { clean } from '../clean.js';
2
+ import { Judge } from '../judge/Judge.js';
3
+ import { EXTENSION_AXES } from '../axis/Axis.js';
4
+ import { registrationKeyOf } from '../name.js';
5
+ function describeExtension(field, key) {
6
+ const ext = {};
7
+ for (const axis of EXTENSION_AXES) {
8
+ const declared = field[axis.slot];
9
+ if (declared === undefined)
10
+ continue;
11
+ const wire = axis.describe(declared, key);
12
+ if (wire !== undefined)
13
+ ext[axis.slot] = wire;
14
+ }
15
+ clean(ext);
16
+ return Object.keys(ext).length ? ext : undefined;
17
+ }
18
+ function describeField(field, key) {
19
+ const out = {};
20
+ for (const [key, value] of Object.entries(field.shape)) {
21
+ if (value === undefined)
22
+ continue;
23
+ out[key] = value;
24
+ }
25
+ if (field.meta?.description)
26
+ out.description = field.meta.description;
27
+ const ext = describeExtension(field, key);
28
+ if (ext)
29
+ out['x-fougere'] = ext;
30
+ return out;
31
+ }
32
+ export function describe(schema, name) {
33
+ const properties = {};
34
+ const required = [];
35
+ for (const [key, field] of Object.entries(schema.getFields())) {
36
+ properties[key] = describeField(field, key);
37
+ if (Judge.onAbsent(field) === null)
38
+ required.push(key);
39
+ }
40
+ const descriptor = {
41
+ type: 'object',
42
+ properties,
43
+ 'x-fougere-version': 1,
44
+ 'x-fougere-vendor': 'fougere',
45
+ };
46
+ const title = name ?? sourceNameOf(schema);
47
+ if (title)
48
+ descriptor.title = title;
49
+ if (required.length)
50
+ descriptor.required = required;
51
+ const derived = derivedOf(schema);
52
+ if (derived)
53
+ descriptor['x-fougere-derived'] = derived;
54
+ return descriptor;
55
+ }
56
+ /**
57
+ * A view says what it is a view OF. `title` already carries the origin's name, and
58
+ * carried it alone: two derivations of one entity described identically while serving
59
+ * different fields, and nothing in the card said which was which.
60
+ */
61
+ export function derivedOf(schema) {
62
+ const s = schema;
63
+ if (!s.source?.name || !s.survived)
64
+ return undefined;
65
+ const survived = Object.fromEntries(Object.entries(s.survived).map(([k, v]) => [k, v ?? null]));
66
+ return { from: s.source.name, survived };
67
+ }
68
+ export function sourceNameOf(schema) {
69
+ const s = schema;
70
+ return s.source?.name ?? s.name;
71
+ }
72
+ export function describeSet(schemas) {
73
+ const entries = Array.isArray(schemas)
74
+ ? schemas.map((s) => [sourceNameOf(s) ?? '', s])
75
+ : Object.entries(schemas);
76
+ const $defs = {};
77
+ for (const [name, schema] of entries) {
78
+ const key = registrationKeyOf(name);
79
+ $defs[key] = describe(schema, key);
80
+ }
81
+ return { $defs, 'x-fougere-version': 1, 'x-fougere-vendor': 'fougere' };
82
+ }
83
+ //# sourceMappingURL=describe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describe.js","sourceRoot":"","sources":["../../src/card/describe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * What changed between two shapes — the one calculation three readers share.
3
+ *
4
+ * A DDL applies it ONCE to the rows (a migration), a codec applies it at EVERY call
5
+ * (an old API version still being served), and a boot reads it to refuse a version that
6
+ * can no longer produce a valid row. Writing it three times would let the three disagree
7
+ * about the same two shapes.
8
+ *
9
+ * It knows no engine and no protocol: a `Change` is a fact about descriptors, and the
10
+ * dialect stays where the dialect belongs.
11
+ *
12
+ * **It never guesses a rename.** A field gone plus a field appeared is either a rename or
13
+ * a drop-and-add, and the two produce opposite DDL — one keeps the data, the other throws
14
+ * it away. The intent lives in the transition and no pair of snapshots holds it, so it is
15
+ * an input here (`renamed`) and what is left over is REPORTED rather than resolved.
16
+ */
17
+ import type { BoundaryRef } from '../axis/boundary/Boundary.js';
18
+ import type { LifecycleRules } from '../axis/lifecycle/Lifecycle.js';
19
+ import type { FieldDescriptor, RoleDescriptor, SchemaBundle, SchemaDescriptor } from './Descriptor.js';
20
+ /** One named difference, at one place. Each kind exists because a reader asks for it. */
21
+ export type Change =
22
+ /** DDL: add the column. Codec: the old caller never sends it. Boot: refuse when required. */
23
+ {
24
+ kind: 'added';
25
+ field: string;
26
+ to: FieldDescriptor;
27
+ required: boolean;
28
+ }
29
+ /** DDL: drop the column. Codec: the old caller still sends it, and it goes nowhere. */
30
+ | {
31
+ kind: 'removed';
32
+ field: string;
33
+ from: FieldDescriptor;
34
+ required: boolean;
35
+ }
36
+ /** DDL: rename the column. Codec and ORM: one more entry in the field→column map. */
37
+ | {
38
+ kind: 'renamed';
39
+ from: string;
40
+ to: string;
41
+ field: FieldDescriptor;
42
+ }
43
+ /** DDL: alter the type. Codec: convert the value, when it can. */
44
+ | {
45
+ kind: 'retyped';
46
+ field: string;
47
+ from: TypeSet;
48
+ to: TypeSet;
49
+ }
50
+ /** Same type, different bounds — a CHECK moves, and a value legal yesterday may not be. */
51
+ | {
52
+ kind: 'reshaped';
53
+ field: string;
54
+ from: FieldDescriptor;
55
+ to: FieldDescriptor;
56
+ }
57
+ /** NOT NULL in either direction. Boot: an old writer cannot fill what it never knew. */
58
+ | {
59
+ kind: 'required';
60
+ field: string;
61
+ from: boolean;
62
+ to: boolean;
63
+ }
64
+ /**
65
+ * An axis other than shape was restated — `axis` names which, so a reader switches on
66
+ * it rather than re-comparing the descriptor it was handed.
67
+ *
68
+ * One kind for three axes and three kinds for shape is not lopsided: shape is the half
69
+ * a JSON Schema reader honours, and its differences mean different things to a table.
70
+ * A field is FOUR axes, and a comparison that reads one of them answers a quarter of
71
+ * the question — measured, and every reader of `diff` was blind the same way.
72
+ */
73
+ | {
74
+ kind: 'restated';
75
+ field: string;
76
+ axis: 'role';
77
+ from?: RoleDescriptor;
78
+ to?: RoleDescriptor;
79
+ } | {
80
+ kind: 'restated';
81
+ field: string;
82
+ axis: 'lifecycle';
83
+ from?: LifecycleRules;
84
+ to?: LifecycleRules;
85
+ } | {
86
+ kind: 'restated';
87
+ field: string;
88
+ axis: 'boundary';
89
+ from?: BoundaryRef;
90
+ to?: BoundaryRef;
91
+ };
92
+ /** A field's declared type(s) — `describe` folds nullable into a union, so it is a set. */
93
+ export type TypeSet = string[];
94
+ /** A removal and an addition that could be one rename — same shape, different name. */
95
+ export interface RenameCandidate {
96
+ removed: string;
97
+ added: string;
98
+ }
99
+ export interface Diff {
100
+ changes: Change[];
101
+ /**
102
+ * What the calculation refuses to decide. Empty means the answer is complete; anything
103
+ * here has to be settled by whoever made the change, while they still remember.
104
+ */
105
+ ambiguous: RenameCandidate[];
106
+ }
107
+ export interface DiffOptions {
108
+ /** Renames as declared at the time — old name → new name. */
109
+ renamed?: Record<string, string>;
110
+ }
111
+ /**
112
+ * What separates two shapes.
113
+ *
114
+ * `from` is the older one — a frozen version, or the state a migration starts at. The
115
+ * changes read as instructions to get from it to `to`.
116
+ */
117
+ export declare function diff(from: SchemaDescriptor, to: SchemaDescriptor, options?: DiffOptions): Diff;
118
+ /**
119
+ * What separates two BUNDLES — the dual of `describeSet`, and the shape a freeze
120
+ * actually compares: a version is a set of entities, not one.
121
+ *
122
+ * An entity that appeared or left is reported by name and nothing more. Renaming an
123
+ * ENTITY is deliberately not modelled here: the field-level ambiguity has a declaration
124
+ * to resolve it (`renamed`), and inventing a second one before anything asks would be
125
+ * two mechanisms for one question.
126
+ */
127
+ export interface SetDiff {
128
+ /** Entities `to` has and `from` had not — a `createTable` for a migration. */
129
+ entitiesAdded: string[];
130
+ /** Entities `from` had and `to` has not. */
131
+ entitiesRemoved: string[];
132
+ /** Per entity present in both, when anything differs. An unchanged entity is absent. */
133
+ entities: Record<string, Diff>;
134
+ }
135
+ export interface SetDiffOptions {
136
+ /** Declared renames, per entity: `{ post: { body: 'content' } }`. */
137
+ renamed?: Record<string, Record<string, string>>;
138
+ }
139
+ export declare function diffSet(from: SchemaBundle, to: SchemaBundle, options?: SetDiffOptions): SetDiff;
140
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/card/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ import { same } from '../same.js';
2
+ /** The three axes `shapeOf` sets aside, compared one by one. */
3
+ const AXES = ['role', 'lifecycle', 'boundary'];
4
+ /**
5
+ * What moved on the axes a JSON Schema reader cannot see.
6
+ *
7
+ * Compared as VALUES: every axis is normal-form data by construction — that is what makes
8
+ * a descriptor travel — so equality is the whole test and no axis needs its own reader.
9
+ */
10
+ function restated(field, before, after) {
11
+ return AXES.filter((axis) => !same(before?.[axis], after?.[axis])).map((axis) => ({ kind: 'restated', field, axis, from: before?.[axis], to: after?.[axis] }));
12
+ }
13
+ /** The shape half of a descriptor: everything a JSON Schema reader would honour. */
14
+ function shapeOf(descriptor) {
15
+ const { 'x-fougere': _extension, ...shape } = descriptor;
16
+ return shape;
17
+ }
18
+ /** Its type, always as a set — `'string'` and `['string', 'null']` compare as sets. */
19
+ function typesOf(descriptor) {
20
+ const type = descriptor.type;
21
+ if (type === undefined)
22
+ return [];
23
+ return (Array.isArray(type) ? [...type] : [type]).sort();
24
+ }
25
+ /** Everything but the type — the bounds, the format, the value list. */
26
+ function boundsOf(descriptor) {
27
+ const { type: _type, ...rest } = shapeOf(descriptor);
28
+ return rest;
29
+ }
30
+ /**
31
+ * What separates two shapes.
32
+ *
33
+ * `from` is the older one — a frozen version, or the state a migration starts at. The
34
+ * changes read as instructions to get from it to `to`.
35
+ */
36
+ export function diff(from, to, options = {}) {
37
+ const changes = [];
38
+ const renamed = options.renamed ?? {};
39
+ const before = from.properties ?? {};
40
+ const after = to.properties ?? {};
41
+ const requiredBefore = new Set(from.required ?? []);
42
+ const requiredAfter = new Set(to.required ?? []);
43
+ // A declared rename is applied FIRST: past this point the field is compared under its
44
+ // new name, so a rename plus a type change reads as two changes and not as a
45
+ // drop-and-add that happens to look alike.
46
+ const nameAfter = (field) => renamed[field] ?? field;
47
+ const removed = [];
48
+ for (const [field, descriptor] of Object.entries(before)) {
49
+ const now = nameAfter(field);
50
+ const target = after[now];
51
+ if (target === undefined) {
52
+ removed.push(field);
53
+ continue;
54
+ }
55
+ if (now !== field)
56
+ changes.push({ kind: 'renamed', from: field, to: now, field: target });
57
+ const wasType = typesOf(descriptor);
58
+ const isType = typesOf(target);
59
+ if (!same(wasType, isType))
60
+ changes.push({ kind: 'retyped', field: now, from: wasType, to: isType });
61
+ else if (!same(boundsOf(descriptor), boundsOf(target))) {
62
+ changes.push({ kind: 'reshaped', field: now, from: descriptor, to: target });
63
+ }
64
+ const wasRequired = requiredBefore.has(field);
65
+ const isRequired = requiredAfter.has(now);
66
+ if (wasRequired !== isRequired) {
67
+ changes.push({ kind: 'required', field: now, from: wasRequired, to: isRequired });
68
+ }
69
+ changes.push(...restated(now, descriptor['x-fougere'], target['x-fougere']));
70
+ }
71
+ const claimed = new Set(Object.values(renamed));
72
+ const added = Object.keys(after).filter((field) => !(field in before) && !claimed.has(field));
73
+ for (const field of removed) {
74
+ changes.push({ kind: 'removed', field, from: before[field], required: requiredBefore.has(field) });
75
+ }
76
+ for (const field of added) {
77
+ changes.push({ kind: 'added', field, to: after[field], required: requiredAfter.has(field) });
78
+ }
79
+ return { changes, ambiguous: candidates(removed, added, before, after) };
80
+ }
81
+ /**
82
+ * Which removal could be which addition. Paired on an identical shape, because that is
83
+ * the whole of what a snapshot knows: two fields carrying the same declaration under two
84
+ * names is exactly what a rename leaves behind.
85
+ *
86
+ * Reported, never applied — including when there is only one pair. A confident guess is
87
+ * still a guess, and being wrong here drops a column of live data.
88
+ */
89
+ function candidates(removed, added, before, after) {
90
+ const found = [];
91
+ for (const gone of removed) {
92
+ for (const appeared of added) {
93
+ if (same(shapeOf(before[gone]), shapeOf(after[appeared])))
94
+ found.push({ removed: gone, added: appeared });
95
+ }
96
+ }
97
+ // Nearest first: a rename usually leaves the field where it was, so the declaration's
98
+ // own order ranks the pairs. It ORDERS them and decides nothing — the list is whole.
99
+ const was = Object.keys(before);
100
+ const now = Object.keys(after);
101
+ const apart = ({ removed: gone, added: appeared }) => Math.abs(now.indexOf(appeared) - was.indexOf(gone));
102
+ return found.sort((a, b) => apart(a) - apart(b));
103
+ }
104
+ export function diffSet(from, to, options = {}) {
105
+ const before = from.$defs ?? {};
106
+ const after = to.$defs ?? {};
107
+ const entities = {};
108
+ for (const [name, descriptor] of Object.entries(before)) {
109
+ const target = after[name];
110
+ if (target === undefined)
111
+ continue;
112
+ const answer = diff(descriptor, target, { renamed: options.renamed?.[name] ?? {} });
113
+ // An entity that did not move says nothing — a freeze records differences, not a census.
114
+ if (answer.changes.length > 0 || answer.ambiguous.length > 0)
115
+ entities[name] = answer;
116
+ }
117
+ return {
118
+ entitiesAdded: Object.keys(after).filter((name) => !(name in before)),
119
+ entitiesRemoved: Object.keys(before).filter((name) => !(name in after)),
120
+ entities,
121
+ };
122
+ }
123
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/card/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { Field, type Fields } from '../Field.js';
2
+ import { type SchemaConstructor } from '../Schema.js';
3
+ import { type SchemaView, type Row } from '../SchemaView.js';
4
+ import { type SchemaBundle, type SchemaDescriptor } from './Descriptor.js';
5
+ type FieldsOf<T> = {
6
+ [K in keyof T]-?: Field<T[K]>;
7
+ };
8
+ export declare function reconstruct<T = Row<Fields>>(descriptor: SchemaDescriptor): SchemaConstructor<FieldsOf<T>>;
9
+ export declare function reconstructSet(bundle: SchemaBundle): Record<string, SchemaView>;
10
+ export {};
11
+ //# sourceMappingURL=reconstruct.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconstruct.d.ts","sourceRoot":"","sources":["../../src/card/reconstruct.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAGjD,OAAO,EAAU,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAwB,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAwEjG,KAAK,QAAQ,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC;AAErD,wBAAgB,WAAW,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,EACzC,UAAU,EAAE,gBAAgB,GAC3B,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAEhC;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAU/E"}