@agentshouse/mdmodel 0.1.0-alpha.9 → 0.1.0-c04c0d681d2d4

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 (404) hide show
  1. package/API.md +368 -0
  2. package/README.md +36 -194
  3. package/dist/blocks.d.ts +11 -0
  4. package/dist/blocks.d.ts.map +1 -0
  5. package/dist/blocks.js +69 -0
  6. package/dist/condition.d.ts +162 -0
  7. package/dist/condition.d.ts.map +1 -0
  8. package/dist/condition.js +616 -0
  9. package/dist/definition.d.ts +70 -27
  10. package/dist/definition.d.ts.map +1 -1
  11. package/dist/definition.js +728 -146
  12. package/dist/divide.d.ts +3 -0
  13. package/dist/divide.d.ts.map +1 -0
  14. package/dist/divide.js +320 -0
  15. package/dist/document.d.ts +12 -2
  16. package/dist/document.d.ts.map +1 -1
  17. package/dist/document.js +400 -177
  18. package/dist/fields.d.ts +6 -0
  19. package/dist/fields.d.ts.map +1 -0
  20. package/dist/fields.js +10 -0
  21. package/dist/index.d.ts +16 -3
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +10 -4
  24. package/dist/links.d.ts +4 -0
  25. package/dist/links.d.ts.map +1 -1
  26. package/dist/links.js +633 -225
  27. package/dist/paths.d.ts +15 -4
  28. package/dist/paths.d.ts.map +1 -1
  29. package/dist/paths.js +149 -36
  30. package/dist/profile.js +1 -3
  31. package/dist/project.d.ts +20 -1
  32. package/dist/project.d.ts.map +1 -1
  33. package/dist/project.js +101 -95
  34. package/dist/references.d.ts +4 -0
  35. package/dist/references.d.ts.map +1 -0
  36. package/dist/references.js +30 -0
  37. package/dist/refuse.d.ts.map +1 -1
  38. package/dist/refuse.js +2 -10
  39. package/dist/schema.d.ts +7 -5
  40. package/dist/schema.d.ts.map +1 -1
  41. package/dist/schema.js +156 -41
  42. package/dist/sections.d.ts +2 -1
  43. package/dist/sections.d.ts.map +1 -1
  44. package/dist/sections.js +44 -66
  45. package/dist/types.d.ts +95 -3
  46. package/dist/types.d.ts.map +1 -1
  47. package/dist/types.js +1 -3
  48. package/dist/validate.d.ts +10 -2
  49. package/dist/validate.d.ts.map +1 -1
  50. package/dist/validate.js +283 -159
  51. package/dist/version.d.ts +1 -1
  52. package/dist/version.d.ts.map +1 -1
  53. package/dist/version.js +1 -3
  54. package/dist/yaml.d.ts +9 -3
  55. package/dist/yaml.d.ts.map +1 -1
  56. package/dist/yaml.js +300 -201
  57. package/fixtures/README.md +91 -56
  58. package/fixtures/cases/absent-link-dangles/library/item.md +8 -0
  59. package/fixtures/cases/absent-link-dangles/schema.yaml +6 -0
  60. package/fixtures/cases/absent-optional-field/context.json +1 -0
  61. package/fixtures/cases/absent-optional-field/expected.json +1 -0
  62. package/fixtures/cases/absent-optional-field/library/companies/acme.md +4 -0
  63. package/fixtures/cases/absent-optional-field/library/deals/lead.md +6 -0
  64. package/fixtures/cases/absent-optional-field/schema.yaml +56 -0
  65. package/fixtures/cases/absolute-link/context.json +1 -0
  66. package/fixtures/cases/absolute-link/expected.json +5 -0
  67. package/fixtures/cases/absolute-link/library/item.md +8 -0
  68. package/fixtures/cases/absolute-link/schema.yaml +6 -0
  69. package/fixtures/cases/attachment-reference-any-file/context.json +1 -0
  70. package/fixtures/cases/attachment-reference-any-file/expected.json +1 -0
  71. package/fixtures/cases/attachment-reference-any-file/library/companies/acme.md +4 -0
  72. package/fixtures/cases/attachment-reference-any-file/library/deals/renewal.md +15 -0
  73. package/fixtures/cases/attachment-reference-any-file/library/places/depot.md +4 -0
  74. package/fixtures/cases/attachment-reference-any-file/library/products/seats.md +4 -0
  75. package/fixtures/cases/attachment-reference-any-file/library/products/support.md +4 -0
  76. package/fixtures/cases/attachment-reference-any-file/schema.yaml +32 -0
  77. package/fixtures/cases/attachment-reference-dangles/context.json +1 -0
  78. package/fixtures/cases/attachment-reference-dangles/expected.json +1 -0
  79. package/fixtures/cases/attachment-reference-dangles/library/companies/acme.md +4 -0
  80. package/fixtures/cases/attachment-reference-dangles/library/deals/renewal.md +15 -0
  81. package/fixtures/cases/attachment-reference-dangles/library/places/depot.md +4 -0
  82. package/fixtures/cases/attachment-reference-dangles/library/products/seats.md +4 -0
  83. package/fixtures/cases/attachment-reference-dangles/library/products/support.md +4 -0
  84. package/fixtures/cases/attachment-reference-dangles/schema.yaml +32 -0
  85. package/fixtures/cases/attachment-reference-outside/context.json +1 -0
  86. package/fixtures/cases/attachment-reference-outside/expected.json +6 -0
  87. package/fixtures/cases/attachment-reference-outside/library/companies/acme.md +4 -0
  88. package/fixtures/cases/attachment-reference-outside/library/deals/renewal.md +15 -0
  89. package/fixtures/cases/attachment-reference-outside/library/places/depot.md +4 -0
  90. package/fixtures/cases/attachment-reference-outside/library/products/seats.md +4 -0
  91. package/fixtures/cases/attachment-reference-outside/library/products/support.md +4 -0
  92. package/fixtures/cases/attachment-reference-outside/schema.yaml +32 -0
  93. package/fixtures/cases/binary-any-reference/expected.json +1 -2
  94. package/fixtures/cases/binary-any-reference/schema.yaml +4 -0
  95. package/fixtures/cases/binary-document-collision/expected.json +1 -2
  96. package/fixtures/cases/binary-document-collision/schema.yaml +1 -0
  97. package/fixtures/cases/binary-image-dangles/expected.json +1 -0
  98. package/fixtures/cases/binary-image-dangles/schema.yaml +1 -0
  99. package/fixtures/cases/binary-link-dangles/expected.json +1 -0
  100. package/fixtures/cases/binary-link-dangles/schema.yaml +1 -0
  101. package/fixtures/cases/binary-link-outside-collection/expected.json +1 -2
  102. package/fixtures/cases/binary-link-outside-collection/schema.yaml +1 -0
  103. package/fixtures/cases/binary-prototype-reference/expected.json +1 -2
  104. package/fixtures/cases/binary-prototype-reference/schema.yaml +4 -0
  105. package/fixtures/cases/binary-typed-reference/expected.json +1 -2
  106. package/fixtures/cases/binary-typed-reference/schema.yaml +5 -0
  107. package/fixtures/cases/boolean-field/context.json +1 -0
  108. package/fixtures/cases/boolean-field/expected.json +6 -0
  109. package/fixtures/cases/boolean-field/library/companies/acme.md +4 -0
  110. package/fixtures/cases/boolean-field/library/deals/renewal.md +31 -0
  111. package/fixtures/cases/boolean-field/schema.yaml +56 -0
  112. package/fixtures/cases/bracketed-link-definition/schema.yaml +6 -0
  113. package/fixtures/cases/closed-nested-object/context.json +1 -0
  114. package/fixtures/cases/closed-nested-object/expected.json +6 -0
  115. package/fixtures/cases/closed-nested-object/library/companies/acme.md +4 -0
  116. package/fixtures/cases/closed-nested-object/library/deals/renewal.md +32 -0
  117. package/fixtures/cases/closed-nested-object/schema.yaml +56 -0
  118. package/fixtures/cases/composed-root-reference/context.json +1 -0
  119. package/fixtures/cases/composed-root-reference/expected.json +6 -0
  120. package/fixtures/cases/composed-root-reference/library/a.md +5 -0
  121. package/fixtures/cases/composed-root-reference/schema.yaml +13 -0
  122. package/fixtures/cases/cross-room-link/context.json +1 -0
  123. package/fixtures/cases/cross-room-link/expected.json +1 -0
  124. package/fixtures/cases/cross-room-link/library/clients/acme.md +6 -0
  125. package/fixtures/cases/cross-room-link/schema.yaml +3 -0
  126. package/fixtures/cases/cross-room-reference/context.json +1 -0
  127. package/fixtures/cases/cross-room-reference/expected.json +1 -0
  128. package/fixtures/cases/cross-room-reference/library/clients/acme.md +9 -0
  129. package/fixtures/cases/cross-room-reference/schema.yaml +9 -0
  130. package/fixtures/cases/date-time-format/context.json +1 -0
  131. package/fixtures/cases/date-time-format/expected.json +6 -0
  132. package/fixtures/cases/date-time-format/library/companies/acme.md +4 -0
  133. package/fixtures/cases/date-time-format/library/deals/renewal.md +31 -0
  134. package/fixtures/cases/date-time-format/schema.yaml +56 -0
  135. package/fixtures/cases/declared-binary-links/schema.yaml +1 -0
  136. package/fixtures/cases/default-unfilled/context.json +1 -0
  137. package/fixtures/cases/default-unfilled/expected.json +6 -0
  138. package/fixtures/cases/default-unfilled/library/companies/acme.md +4 -0
  139. package/fixtures/cases/default-unfilled/library/deals/renewal.md +29 -0
  140. package/fixtures/cases/default-unfilled/schema.yaml +56 -0
  141. package/fixtures/cases/defs-pattern/context.json +1 -0
  142. package/fixtures/cases/defs-pattern/expected.json +6 -0
  143. package/fixtures/cases/defs-pattern/library/companies/acme.md +4 -0
  144. package/fixtures/cases/defs-pattern/library/deals/renewal.md +31 -0
  145. package/fixtures/cases/defs-pattern/schema.yaml +56 -0
  146. package/fixtures/cases/dependent-rule/context.json +1 -0
  147. package/fixtures/cases/dependent-rule/expected.json +6 -0
  148. package/fixtures/cases/dependent-rule/library/companies/acme.md +4 -0
  149. package/fixtures/cases/dependent-rule/library/deals/renewal.md +30 -0
  150. package/fixtures/cases/dependent-rule/schema.yaml +56 -0
  151. package/fixtures/cases/duplicate-link-definition/schema.yaml +6 -0
  152. package/fixtures/cases/email-format/context.json +1 -0
  153. package/fixtures/cases/email-format/expected.json +6 -0
  154. package/fixtures/cases/email-format/library/companies/acme.md +4 -0
  155. package/fixtures/cases/email-format/library/deals/renewal.md +31 -0
  156. package/fixtures/cases/email-format/schema.yaml +56 -0
  157. package/fixtures/cases/fenced-link-definition/schema.yaml +6 -0
  158. package/fixtures/cases/field-enum/expected.json +2 -3
  159. package/fixtures/cases/field-enum/schema.yaml +7 -0
  160. package/fixtures/cases/frontmatter-schema/context.json +1 -0
  161. package/fixtures/cases/frontmatter-schema/expected.json +5 -0
  162. package/fixtures/cases/frontmatter-schema/schema.yaml +5 -0
  163. package/fixtures/cases/integer-field/context.json +1 -0
  164. package/fixtures/cases/integer-field/expected.json +6 -0
  165. package/fixtures/cases/integer-field/library/companies/acme.md +4 -0
  166. package/fixtures/cases/integer-field/library/deals/renewal.md +31 -0
  167. package/fixtures/cases/integer-field/schema.yaml +56 -0
  168. package/fixtures/cases/interrupted-link-definition/schema.yaml +1 -0
  169. package/fixtures/cases/json-schema-constructs/context.json +1 -0
  170. package/fixtures/cases/json-schema-constructs/expected.json +1 -0
  171. package/fixtures/cases/json-schema-constructs/library/companies/acme.md +4 -0
  172. package/fixtures/cases/json-schema-constructs/library/deals/renewal.md +31 -0
  173. package/fixtures/cases/json-schema-constructs/schema.yaml +56 -0
  174. package/fixtures/cases/list-of-objects-closed/context.json +1 -0
  175. package/fixtures/cases/list-of-objects-closed/expected.json +6 -0
  176. package/fixtures/cases/list-of-objects-closed/library/companies/acme.md +4 -0
  177. package/fixtures/cases/list-of-objects-closed/library/deals/renewal.md +32 -0
  178. package/fixtures/cases/list-of-objects-closed/schema.yaml +56 -0
  179. package/fixtures/cases/list-of-objects-item/context.json +1 -0
  180. package/fixtures/cases/list-of-objects-item/expected.json +6 -0
  181. package/fixtures/cases/list-of-objects-item/library/companies/acme.md +4 -0
  182. package/fixtures/cases/list-of-objects-item/library/deals/renewal.md +31 -0
  183. package/fixtures/cases/list-of-objects-item/schema.yaml +56 -0
  184. package/fixtures/cases/list-of-objects-reference/context.json +1 -0
  185. package/fixtures/cases/list-of-objects-reference/expected.json +6 -0
  186. package/fixtures/cases/list-of-objects-reference/library/companies/acme.md +4 -0
  187. package/fixtures/cases/list-of-objects-reference/library/deals/renewal.md +14 -0
  188. package/fixtures/cases/list-of-objects-reference/library/places/depot.md +4 -0
  189. package/fixtures/cases/list-of-objects-reference/library/products/seats.md +4 -0
  190. package/fixtures/cases/list-of-objects-reference/library/products/support.md +4 -0
  191. package/fixtures/cases/list-of-objects-reference/schema.yaml +32 -0
  192. package/fixtures/cases/list-size/context.json +1 -0
  193. package/fixtures/cases/list-size/expected.json +6 -0
  194. package/fixtures/cases/list-size/library/companies/acme.md +4 -0
  195. package/fixtures/cases/list-size/library/deals/renewal.md +31 -0
  196. package/fixtures/cases/list-size/schema.yaml +56 -0
  197. package/fixtures/cases/long-fence-link-definition/schema.yaml +1 -0
  198. package/fixtures/cases/malformed-definition/expected.json +2 -4
  199. package/fixtures/cases/malformed-definition/schema.yaml +3 -0
  200. package/fixtures/cases/member-document/context.json +1 -0
  201. package/fixtures/cases/member-document/expected.json +1 -0
  202. package/fixtures/cases/member-document/library/people/ana.md +5 -0
  203. package/fixtures/cases/member-document/schema.yaml +5 -0
  204. package/fixtures/cases/missing-required-field/expected.json +2 -3
  205. package/fixtures/cases/missing-required-field/schema.yaml +7 -0
  206. package/fixtures/cases/missing-section-item-kind/expected.json +2 -4
  207. package/fixtures/cases/missing-section-item-kind/schema.yaml +6 -0
  208. package/fixtures/cases/misspelled-key/context.json +1 -0
  209. package/fixtures/cases/misspelled-key/expected.json +6 -0
  210. package/fixtures/cases/misspelled-key/library/companies/acme.md +4 -0
  211. package/fixtures/cases/misspelled-key/library/deals/renewal.md +32 -0
  212. package/fixtures/cases/misspelled-key/schema.yaml +56 -0
  213. package/fixtures/cases/nested-defs/context.json +1 -0
  214. package/fixtures/cases/nested-defs/expected.json +6 -0
  215. package/fixtures/cases/nested-defs/library/deal.md +6 -0
  216. package/fixtures/cases/nested-defs/schema.yaml +11 -0
  217. package/fixtures/cases/nested-object-reference/context.json +1 -0
  218. package/fixtures/cases/nested-object-reference/expected.json +6 -0
  219. package/fixtures/cases/nested-object-reference/library/companies/acme.md +4 -0
  220. package/fixtures/cases/nested-object-reference/library/deals/renewal.md +14 -0
  221. package/fixtures/cases/nested-object-reference/library/places/depot.md +4 -0
  222. package/fixtures/cases/nested-object-reference/library/products/seats.md +4 -0
  223. package/fixtures/cases/nested-object-reference/library/products/support.md +4 -0
  224. package/fixtures/cases/nested-object-reference/schema.yaml +32 -0
  225. package/fixtures/cases/nested-reference/context.json +1 -0
  226. package/fixtures/cases/nested-reference/expected.json +1 -0
  227. package/fixtures/cases/nested-reference/library/companies/acme.md +4 -0
  228. package/fixtures/cases/nested-reference/library/deals/renewal.md +15 -0
  229. package/fixtures/cases/nested-reference/library/places/depot.md +4 -0
  230. package/fixtures/cases/nested-reference/library/products/seats.md +4 -0
  231. package/fixtures/cases/nested-reference/library/products/support.md +4 -0
  232. package/fixtures/cases/nested-reference/schema.yaml +32 -0
  233. package/fixtures/cases/nested-required-field/context.json +1 -0
  234. package/fixtures/cases/nested-required-field/expected.json +6 -0
  235. package/fixtures/cases/nested-required-field/library/companies/acme.md +4 -0
  236. package/fixtures/cases/nested-required-field/library/deals/renewal.md +30 -0
  237. package/fixtures/cases/nested-required-field/schema.yaml +56 -0
  238. package/fixtures/cases/null-refused/context.json +1 -0
  239. package/fixtures/cases/null-refused/expected.json +6 -0
  240. package/fixtures/cases/null-refused/library/companies/acme.md +4 -0
  241. package/fixtures/cases/null-refused/library/deals/renewal.md +31 -0
  242. package/fixtures/cases/null-refused/schema.yaml +56 -0
  243. package/fixtures/cases/numeric-range/context.json +1 -0
  244. package/fixtures/cases/numeric-range/expected.json +6 -0
  245. package/fixtures/cases/numeric-range/library/companies/acme.md +4 -0
  246. package/fixtures/cases/numeric-range/library/deals/renewal.md +31 -0
  247. package/fixtures/cases/numeric-range/schema.yaml +56 -0
  248. package/fixtures/cases/one-of-variant/context.json +1 -0
  249. package/fixtures/cases/one-of-variant/expected.json +6 -0
  250. package/fixtures/cases/one-of-variant/library/companies/acme.md +4 -0
  251. package/fixtures/cases/one-of-variant/library/deals/renewal.md +31 -0
  252. package/fixtures/cases/one-of-variant/schema.yaml +56 -0
  253. package/fixtures/cases/open-map-value/context.json +1 -0
  254. package/fixtures/cases/open-map-value/expected.json +6 -0
  255. package/fixtures/cases/open-map-value/library/companies/acme.md +4 -0
  256. package/fixtures/cases/open-map-value/library/deals/renewal.md +31 -0
  257. package/fixtures/cases/open-map-value/schema.yaml +56 -0
  258. package/fixtures/cases/other-room-reference/context.json +1 -0
  259. package/fixtures/cases/other-room-reference/expected.json +6 -0
  260. package/fixtures/cases/other-room-reference/library/companies/acme.md +4 -0
  261. package/fixtures/cases/other-room-reference/library/deals/renewal.md +14 -0
  262. package/fixtures/cases/other-room-reference/library/places/depot.md +4 -0
  263. package/fixtures/cases/other-room-reference/library/products/seats.md +4 -0
  264. package/fixtures/cases/other-room-reference/library/products/support.md +4 -0
  265. package/fixtures/cases/other-room-reference/schema.yaml +32 -0
  266. package/fixtures/cases/paragraph-link-definition/schema.yaml +1 -0
  267. package/fixtures/cases/prototype-field/expected.json +2 -3
  268. package/fixtures/cases/prototype-field/schema.yaml +6 -0
  269. package/fixtures/cases/quoted-link-definition/expected.json +1 -2
  270. package/fixtures/cases/quoted-link-definition/library/notes/draft.md +1 -1
  271. package/fixtures/cases/quoted-link-definition/schema.yaml +1 -0
  272. package/fixtures/cases/referenced-missing-file/expected.json +0 -1
  273. package/fixtures/cases/referenced-missing-file/schema.yaml +11 -0
  274. package/fixtures/cases/remote-ref/context.json +1 -0
  275. package/fixtures/cases/remote-ref/expected.json +5 -0
  276. package/fixtures/cases/remote-ref/schema.yaml +3 -0
  277. package/fixtures/cases/second-member-document/context.json +1 -0
  278. package/fixtures/cases/second-member-document/expected.json +5 -0
  279. package/fixtures/cases/second-member-document/schema.yaml +4 -0
  280. package/fixtures/cases/section-item-enum/context.json +1 -0
  281. package/fixtures/cases/section-item-enum/expected.json +6 -0
  282. package/fixtures/cases/section-item-enum/library/task.md +8 -0
  283. package/fixtures/cases/section-item-enum/schema.yaml +3 -0
  284. package/fixtures/cases/section-item-kind/context.json +1 -0
  285. package/fixtures/cases/section-item-kind/expected.json +6 -0
  286. package/fixtures/cases/section-item-kind/library/task.md +8 -0
  287. package/fixtures/cases/section-item-kind/schema.yaml +3 -0
  288. package/fixtures/cases/section-items/context.json +1 -0
  289. package/fixtures/cases/section-items/expected.json +1 -0
  290. package/fixtures/cases/section-items/library/other.md +3 -0
  291. package/fixtures/cases/section-items/library/page.md +42 -0
  292. package/fixtures/cases/section-items/schema.yaml +10 -0
  293. package/fixtures/cases/section-reference-path/context.json +1 -0
  294. package/fixtures/cases/section-reference-path/expected.json +6 -0
  295. package/fixtures/cases/section-reference-path/library/other.md +3 -0
  296. package/fixtures/cases/section-reference-path/library/page.md +7 -0
  297. package/fixtures/cases/section-reference-path/schema.yaml +3 -0
  298. package/fixtures/cases/section-reference-type/context.json +1 -0
  299. package/fixtures/cases/section-reference-type/expected.json +6 -0
  300. package/fixtures/cases/section-reference-type/library/note.md +1 -0
  301. package/fixtures/cases/section-reference-type/library/page.md +7 -0
  302. package/fixtures/cases/section-reference-type/schema.yaml +3 -0
  303. package/fixtures/cases/shortcut-reference-link/context.json +1 -0
  304. package/fixtures/cases/shortcut-reference-link/expected.json +5 -0
  305. package/fixtures/cases/shortcut-reference-link/library/item.md +10 -0
  306. package/fixtures/cases/shortcut-reference-link/schema.yaml +6 -0
  307. package/fixtures/cases/string-length/context.json +1 -0
  308. package/fixtures/cases/string-length/expected.json +6 -0
  309. package/fixtures/cases/string-length/library/companies/acme.md +4 -0
  310. package/fixtures/cases/string-length/library/deals/renewal.md +31 -0
  311. package/fixtures/cases/string-length/schema.yaml +56 -0
  312. package/fixtures/cases/structured-section/expected.json +1 -2
  313. package/fixtures/cases/structured-section/schema.yaml +7 -0
  314. package/fixtures/cases/submission-keys/context.json +1 -0
  315. package/fixtures/cases/submission-keys/expected.json +1 -0
  316. package/fixtures/cases/submission-keys/library/notes/visitor.md +8 -0
  317. package/fixtures/cases/submission-keys/schema.yaml +4 -0
  318. package/fixtures/cases/text-field-kind/context.json +1 -0
  319. package/fixtures/cases/text-field-kind/expected.json +6 -0
  320. package/fixtures/cases/text-field-kind/library/page.md +4 -0
  321. package/fixtures/cases/text-field-kind/schema.yaml +4 -0
  322. package/fixtures/cases/truncated-link-definition/expected.json +1 -2
  323. package/fixtures/cases/truncated-link-definition/library/notes/draft.md +1 -1
  324. package/fixtures/cases/truncated-link-definition/schema.yaml +1 -0
  325. package/fixtures/cases/types-folder-content/context.json +1 -0
  326. package/fixtures/cases/types-folder-content/expected.json +1 -0
  327. package/fixtures/cases/types-folder-content/library/types/task.md +4 -0
  328. package/fixtures/cases/types-folder-content/schema.yaml +4 -0
  329. package/fixtures/cases/unclosed-frontmatter/expected.json +1 -2
  330. package/fixtures/cases/undeclared-field/expected.json +2 -3
  331. package/fixtures/cases/undeclared-field/schema.yaml +6 -0
  332. package/fixtures/cases/unevaluated-items-closed/context.json +1 -0
  333. package/fixtures/cases/unevaluated-items-closed/expected.json +6 -0
  334. package/fixtures/cases/unevaluated-items-closed/library/trip.md +6 -0
  335. package/fixtures/cases/unevaluated-items-closed/schema.yaml +10 -0
  336. package/fixtures/cases/unknown-type/context.json +1 -0
  337. package/fixtures/cases/unknown-type/expected.json +6 -0
  338. package/fixtures/cases/unknown-type/library/item.md +3 -0
  339. package/fixtures/cases/unknown-type/schema.yaml +3 -0
  340. package/fixtures/cases/unlisted-reference-type/context.json +1 -0
  341. package/fixtures/cases/unlisted-reference-type/expected.json +5 -0
  342. package/fixtures/cases/unlisted-reference-type/schema.yaml +3 -0
  343. package/fixtures/cases/unresolved-link/expected.json +1 -2
  344. package/fixtures/cases/unresolved-link/library/item.md +1 -1
  345. package/fixtures/cases/unresolved-link/schema.yaml +6 -0
  346. package/fixtures/cases/valid-typed-document/schema.yaml +16 -0
  347. package/fixtures/cases/wide-item-fence-link/schema.yaml +1 -0
  348. package/fixtures/division.json +409 -0
  349. package/fixtures/projection.json +90 -21
  350. package/package.json +6 -13
  351. package/dist/definition.js.map +0 -1
  352. package/dist/document.js.map +0 -1
  353. package/dist/index.js.map +0 -1
  354. package/dist/links.js.map +0 -1
  355. package/dist/paths.js.map +0 -1
  356. package/dist/profile.js.map +0 -1
  357. package/dist/project.js.map +0 -1
  358. package/dist/refuse.js.map +0 -1
  359. package/dist/schema.js.map +0 -1
  360. package/dist/sections.js.map +0 -1
  361. package/dist/types.js.map +0 -1
  362. package/dist/validate.js.map +0 -1
  363. package/dist/version.js.map +0 -1
  364. package/dist/yaml.js.map +0 -1
  365. package/fixtures/cases/binary-any-reference/library/types/note.md +0 -5
  366. package/fixtures/cases/binary-document-collision/library/types/note.md +0 -3
  367. package/fixtures/cases/binary-link-outside-collection/library/types/note.md +0 -3
  368. package/fixtures/cases/binary-prototype-reference/library/types/note.md +0 -5
  369. package/fixtures/cases/binary-typed-reference/library/types/note.md +0 -5
  370. package/fixtures/cases/binary-typed-reference/library/types/person.md +0 -3
  371. package/fixtures/cases/bracketed-link-definition/library/types/task.md +0 -7
  372. package/fixtures/cases/declared-binary-links/library/types/note.md +0 -3
  373. package/fixtures/cases/duplicate-link-definition/library/types/task.md +0 -7
  374. package/fixtures/cases/fenced-link-definition/library/types/task.md +0 -7
  375. package/fixtures/cases/field-enum/library/types/task.md +0 -8
  376. package/fixtures/cases/interrupted-link-definition/library/types/note.md +0 -3
  377. package/fixtures/cases/long-fence-link-definition/library/types/note.md +0 -3
  378. package/fixtures/cases/malformed-definition/library/types/task.md +0 -5
  379. package/fixtures/cases/missing-binary-image/expected.json +0 -6
  380. package/fixtures/cases/missing-binary-image/library/types/note.md +0 -3
  381. package/fixtures/cases/missing-binary-link/expected.json +0 -6
  382. package/fixtures/cases/missing-binary-link/library/types/note.md +0 -3
  383. package/fixtures/cases/missing-required-field/library/types/task.md +0 -8
  384. package/fixtures/cases/missing-section-item-kind/library/types/task.md +0 -7
  385. package/fixtures/cases/paragraph-link-definition/library/types/note.md +0 -3
  386. package/fixtures/cases/prd-definition/library/types/task.md +0 -16
  387. package/fixtures/cases/prototype-field/library/types/task.md +0 -7
  388. package/fixtures/cases/quoted-link-definition/library/types/note.md +0 -3
  389. package/fixtures/cases/referenced-missing-file/library/types/person.md +0 -5
  390. package/fixtures/cases/referenced-missing-file/library/types/task.md +0 -8
  391. package/fixtures/cases/structured-section/library/types/task.md +0 -8
  392. package/fixtures/cases/truncated-link-definition/library/types/note.md +0 -3
  393. package/fixtures/cases/undeclared-field/library/types/task.md +0 -7
  394. package/fixtures/cases/unresolved-link/library/types/task.md +0 -7
  395. package/fixtures/cases/valid-typed-document/library/types/person.md +0 -5
  396. package/fixtures/cases/valid-typed-document/library/types/task.md +0 -13
  397. package/fixtures/cases/wide-item-fence-link/library/types/note.md +0 -3
  398. package/markdown-syntax-profile.md +0 -9
  399. /package/fixtures/cases/{prd-definition → absent-link-dangles}/context.json +0 -0
  400. /package/fixtures/cases/{prd-definition → absent-link-dangles}/expected.json +0 -0
  401. /package/fixtures/cases/{missing-binary-image → binary-image-dangles}/context.json +0 -0
  402. /package/fixtures/cases/{missing-binary-image → binary-image-dangles}/library/notes/draft.md +0 -0
  403. /package/fixtures/cases/{missing-binary-link → binary-link-dangles}/context.json +0 -0
  404. /package/fixtures/cases/{missing-binary-link → binary-link-dangles}/library/notes/draft.md +0 -0
@@ -0,0 +1,616 @@
1
+ import { ARRAY_INDEX, escapePointer, fieldFacts, itemFacts, memberFacts, pointerFacts, pointerSegments, } from './definition.js';
2
+ import { roomPath, target } from './paths.js';
3
+ import { plain } from './yaml.js';
4
+ export const CONDITION_OPERATORS = [
5
+ 'eq',
6
+ 'in',
7
+ 'exists',
8
+ 'contains',
9
+ 'gt',
10
+ 'gte',
11
+ 'lt',
12
+ 'lte',
13
+ 'prefix',
14
+ ];
15
+ export const WRITE_DOORS = ['browser', 'agent', 'client'];
16
+ const PROSE = { kind: 'prose' };
17
+ const NULL = { kind: 'null' };
18
+ const UNREADABLE = { kind: 'unreadable' };
19
+ const UNREAD = { present: undefined, values: [undefined], items: [undefined] };
20
+ const NO_ITEM = { present: false, values: [], items: [] };
21
+ const DATE = /^\d{4}-\d{2}-\d{2}$/u;
22
+ const HEADER = /^\/headers\/[!#$%&'*+.^_`|~0-9a-z-]+$/u;
23
+ const DATE_TIME = /^(\d{4})-(\d{2})-(\d{2})[Tt](\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?(?:[Zz]|([+-])(\d{2}):(\d{2}))$/u;
24
+ export function factKind(facts) {
25
+ if (facts.reference !== undefined)
26
+ return 'reference';
27
+ if (facts.values !== undefined)
28
+ return 'enum';
29
+ if (facts.type === 'number' || facts.type === 'integer')
30
+ return 'number';
31
+ if (facts.type === 'boolean')
32
+ return 'boolean';
33
+ if (facts.type !== 'string')
34
+ return null;
35
+ if (facts.format === 'date')
36
+ return 'date';
37
+ if (facts.format === 'date-time')
38
+ return 'time';
39
+ return 'string';
40
+ }
41
+ function fits(kind, facts, value) {
42
+ if (!scalar(value))
43
+ return false;
44
+ if (kind === 'enum')
45
+ return (facts.values ?? []).includes(value);
46
+ if (kind === 'number')
47
+ return typeof value === 'number';
48
+ if (kind === 'boolean')
49
+ return typeof value === 'boolean';
50
+ if (typeof value !== 'string')
51
+ return false;
52
+ if (kind === 'date')
53
+ return dated(value);
54
+ if (kind === 'time')
55
+ return instant(value) !== undefined;
56
+ return true;
57
+ }
58
+ function factOf(value, declared, place) {
59
+ if (value === null)
60
+ return NULL;
61
+ if (Array.isArray(value)) {
62
+ if (declared?.type !== undefined && declared.type !== 'array')
63
+ return UNREADABLE;
64
+ return {
65
+ kind: 'list',
66
+ items: value.map((item, index) => factOf(item, declared === undefined ? undefined : itemFacts(declared, index), place)),
67
+ };
68
+ }
69
+ if (plain(value)) {
70
+ if (declared?.type !== undefined && declared.type !== 'object')
71
+ return UNREADABLE;
72
+ const fields = Object.create(null);
73
+ for (const [key, held] of Object.entries(value))
74
+ fields[key] = factOf(held, declared === undefined ? undefined : memberFacts(declared, key), place);
75
+ return { kind: 'object', fields };
76
+ }
77
+ if (declared?.type === 'array' || declared?.type === 'object')
78
+ return UNREADABLE;
79
+ const kind = declared === undefined || declared.prose ? null : factKind(declared);
80
+ if (kind === null)
81
+ return PROSE;
82
+ if (!fits(kind, declared, value))
83
+ return UNREADABLE;
84
+ if (kind !== 'reference')
85
+ return { kind, value };
86
+ const reached = target(place.path, value) ?? roomPath(value);
87
+ const resolved = reached === null ? undefined : place.resolve(reached);
88
+ if (resolved === undefined)
89
+ return UNREADABLE;
90
+ return resolved.member === undefined
91
+ ? { kind, value: resolved.id }
92
+ : { kind, value: resolved.id, member: resolved.member };
93
+ }
94
+ export function facts(document, at, model, resolve) {
95
+ const type = document.type ?? null;
96
+ const definition = type !== null && Object.hasOwn(model.types, type) ? model.types[type] : null;
97
+ const fields = Object.create(null);
98
+ const place = { path: at.path, resolve };
99
+ for (const [name, value] of Object.entries(document.fields)) {
100
+ const declared = definition === null ? undefined : fieldFacts(definition, name);
101
+ if (declared !== undefined)
102
+ fields[name] = factOf(value, declared, place);
103
+ }
104
+ return {
105
+ id: at.id,
106
+ path: `/${at.path}`,
107
+ type,
108
+ fields,
109
+ sections: Object.keys(document.sections).sort(),
110
+ };
111
+ }
112
+ function rootOf(facts, prefix) {
113
+ return { pointer: prefix, fact: { kind: 'object', fields: facts.fields } };
114
+ }
115
+ export function prosePaths(facts) {
116
+ const paths = facts.sections.map((heading) => `/sections/${heading}`);
117
+ const visit = ({ pointer, fact }) => {
118
+ if (fact.kind === 'prose')
119
+ paths.push(pointer);
120
+ if (fact.kind === 'list')
121
+ fact.items.forEach((item, index) => visit({ pointer: `${pointer}/${index}`, fact: item }));
122
+ if (fact.kind === 'object')
123
+ for (const [key, held] of Object.entries(fact.fields))
124
+ visit({ pointer: `${pointer}/${escapePointer(key)}`, fact: held });
125
+ };
126
+ visit(rootOf(facts, '/fields'));
127
+ return paths.sort();
128
+ }
129
+ function walked(start, pointer) {
130
+ let reached = [start];
131
+ let several = false;
132
+ let missing = false;
133
+ const each = (from, next) => from.flatMap((one) => {
134
+ const found = next(one);
135
+ if (found === null)
136
+ missing = true;
137
+ return found ?? [];
138
+ });
139
+ for (const token of pointerSegments(pointer)) {
140
+ const step = ({ pointer: at, fact }) => {
141
+ if (fact.kind === 'unreadable')
142
+ return [{ pointer: at, fact }];
143
+ if (fact.kind === 'object')
144
+ return Object.hasOwn(fact.fields, token)
145
+ ? [{ pointer: `${at}/${escapePointer(token)}`, fact: fact.fields[token] }]
146
+ : null;
147
+ if (fact.kind !== 'list')
148
+ return null;
149
+ if (ARRAY_INDEX.test(token)) {
150
+ const item = fact.items[Number(token)];
151
+ return item === undefined ? null : [{ pointer: `${at}/${token}`, fact: item }];
152
+ }
153
+ several = true;
154
+ return each(fact.items.map((item, index) => ({ pointer: `${at}/${index}`, fact: item })), step);
155
+ };
156
+ reached = each(reached, step);
157
+ }
158
+ return { reached, several, missing };
159
+ }
160
+ function expand(fact) {
161
+ return fact.kind === 'list' ? fact.items.flatMap(expand) : [fact];
162
+ }
163
+ function fieldHeld(fact) {
164
+ if (fact.kind === 'unreadable')
165
+ return undefined;
166
+ if (fact.kind === 'null')
167
+ return { kind: 'null' };
168
+ return 'value' in fact ? { kind: fact.kind, value: fact.value } : { kind: 'prose' };
169
+ }
170
+ function memberHeld(fact) {
171
+ if (fact.kind === 'unreadable')
172
+ return undefined;
173
+ return fact.kind === 'reference' && fact.member !== undefined
174
+ ? { kind: 'member', value: fact.member }
175
+ : null;
176
+ }
177
+ function single(held) {
178
+ return { present: true, values: [held], items: null };
179
+ }
180
+ function documentRead({ reached, several, missing }, held) {
181
+ if (reached.length === 0)
182
+ return missing ? undefined : NO_ITEM;
183
+ const facts = reached.map(({ fact }) => fact);
184
+ const kept = (all) => all.map(held).filter((value) => value !== null);
185
+ const unknown = missing ? [undefined] : [];
186
+ const values = kept(facts.filter((fact) => fact.kind !== 'list'));
187
+ const listed = several || facts.some((fact) => fact.kind === 'list');
188
+ const present = facts.some((fact) => fact.kind === 'list') || values.some(Boolean);
189
+ return {
190
+ present: present ? true : values.length > 0 ? undefined : false,
191
+ values: [...values, ...unknown],
192
+ items: listed ? [...kept(facts.flatMap(expand)), ...unknown] : null,
193
+ };
194
+ }
195
+ function readDocument(facts, path) {
196
+ const own = tested(DOCUMENT_TESTS, path);
197
+ if (own !== undefined)
198
+ return own.read(facts, path);
199
+ if (path.startsWith('/sections/'))
200
+ return facts.sections.includes(path.slice('/sections/'.length))
201
+ ? single({ kind: 'prose' })
202
+ : undefined;
203
+ if (path.startsWith('/fields/'))
204
+ return documentRead(walked(rootOf(facts, '/fields'), path.slice('/fields'.length)), fieldHeld);
205
+ if (path.startsWith('/members/'))
206
+ return documentRead(walked(rootOf(facts, '/members'), path.slice('/members'.length)), memberHeld);
207
+ return undefined;
208
+ }
209
+ export function datePointers(fields) {
210
+ return Object.entries(fields)
211
+ .filter(([, facts]) => facts.type === 'string' && facts.format === 'date')
212
+ .map(([name]) => `/fields/${escapePointer(name)}`)
213
+ .sort();
214
+ }
215
+ export function valuedChange(definition, field) {
216
+ if (!field.startsWith('/fields/'))
217
+ return false;
218
+ const reached = pointerFacts(definition, field.slice('/fields'.length));
219
+ return (reached !== undefined &&
220
+ !reached.through &&
221
+ reached.facts.type !== 'array' &&
222
+ !reached.facts.prose &&
223
+ factKind(reached.facts) !== null);
224
+ }
225
+ export function changeFields(definition) {
226
+ return [
227
+ ...Object.keys(definition.fields).map((name) => `/fields/${escapePointer(name)}`),
228
+ ...Object.keys(definition.sections).map((heading) => `/sections/${heading}`),
229
+ ];
230
+ }
231
+ export function memberPointers(definition, memberType) {
232
+ return Object.entries(definition.fields)
233
+ .filter(([, facts]) => (facts.type === 'array' ? facts.items : facts)?.reference?.includes(memberType) === true)
234
+ .map(([name]) => `/members/${escapePointer(name)}`);
235
+ }
236
+ function kindOperators(kind) {
237
+ switch (kind) {
238
+ case 'string':
239
+ return ['eq', 'in', 'prefix', 'exists'];
240
+ case 'boolean':
241
+ return ['eq', 'exists'];
242
+ case 'number':
243
+ case 'date':
244
+ case 'time':
245
+ return ['eq', 'in', 'gt', 'gte', 'lt', 'lte', 'exists'];
246
+ default:
247
+ return ['eq', 'in', 'exists'];
248
+ }
249
+ }
250
+ function pointerOperators({ facts, through }) {
251
+ const scalar = facts.type === 'array' ? facts.items : facts;
252
+ const kind = scalar === undefined || scalar.prose ? null : factKind(scalar);
253
+ if (kind === null)
254
+ return ['exists'];
255
+ if (facts.type === 'array')
256
+ return ['contains', 'exists'];
257
+ const own = kindOperators(kind);
258
+ return through ? [...own.filter((operator) => operator !== 'exists'), 'contains', 'exists'] : own;
259
+ }
260
+ function typeOperators(definition, path, memberType) {
261
+ if (path.startsWith('/sections/'))
262
+ return Object.hasOwn(definition.sections, path.slice('/sections/'.length)) ? ['exists'] : [];
263
+ const pointer = path.startsWith('/fields/')
264
+ ? path.slice('/fields'.length)
265
+ : memberType !== null && memberPointers(definition, memberType).includes(path)
266
+ ? path.slice('/members'.length)
267
+ : undefined;
268
+ const reached = pointer === undefined ? undefined : pointerFacts(definition, pointer);
269
+ return reached === undefined ? [] : pointerOperators(reached);
270
+ }
271
+ function envelope(path, kind, value) {
272
+ return {
273
+ path,
274
+ names: (named) => named === path,
275
+ kind,
276
+ operators: kindOperators(kind),
277
+ read: (facts) => {
278
+ const held = value(facts);
279
+ return held === null || held === undefined ? undefined : single({ kind, value: held });
280
+ },
281
+ };
282
+ }
283
+ function tested(tests, path) {
284
+ return tests.find(({ names }) => names(path));
285
+ }
286
+ function reader(tests, facts) {
287
+ return (path) => tested(tests, path)?.read(facts, path);
288
+ }
289
+ const DOCUMENT_TESTS = [
290
+ {
291
+ path: '/path',
292
+ names: (named) => named === '/path',
293
+ kind: 'string',
294
+ operators: ['eq', 'in', 'prefix'],
295
+ read: (facts) => single({ kind: 'string', value: facts.path }),
296
+ },
297
+ envelope('/type', 'enum', (facts) => facts.type),
298
+ ];
299
+ const ACTOR_TESTS = [
300
+ envelope('/user', 'enum', (actor) => actor.user),
301
+ envelope('/site', 'enum', (actor) => actor.site),
302
+ envelope('/door', 'enum', (actor) => actor.door),
303
+ ];
304
+ const ITEM_TESTS = [
305
+ envelope('/delivery', 'enum', (item) => item.delivery),
306
+ envelope('/source', 'enum', (item) => item.source),
307
+ envelope('/has_attachment', 'boolean', (item) => item.has_attachment),
308
+ envelope('/container', 'string', (item) => item.container),
309
+ envelope('/author', 'string', (item) => item.author),
310
+ {
311
+ path: '/headers/<lowercase name>',
312
+ names: (named) => HEADER.test(named),
313
+ kind: 'string',
314
+ operators: kindOperators('string'),
315
+ read: (item, path) => {
316
+ const name = path.slice('/headers/'.length);
317
+ return Object.hasOwn(item.headers, name)
318
+ ? single({ kind: 'string', value: item.headers[name] })
319
+ : undefined;
320
+ },
321
+ },
322
+ {
323
+ path: '/json/<JSON Pointer>',
324
+ names: (named) => named.startsWith('/json/'),
325
+ kind: null,
326
+ operators: CONDITION_OPERATORS,
327
+ read: (item, path) => item.json === null ? UNREAD : jsonRead(pointed(item.json.value, path.slice('/json'.length))),
328
+ },
329
+ ];
330
+ export const DOCUMENT_PATHS = DOCUMENT_TESTS.map(({ path }) => path);
331
+ export const ACTOR_PATHS = ACTOR_TESTS.map(({ path }) => path);
332
+ export const ITEM_PATHS = ITEM_TESTS.map(({ path }) => path);
333
+ export function testOperators(definitions, path, memberType) {
334
+ const own = tested(DOCUMENT_TESTS, path);
335
+ if (own !== undefined)
336
+ return own.operators;
337
+ return [
338
+ ...new Set(definitions.flatMap((definition) => typeOperators(definition, path, memberType))),
339
+ ];
340
+ }
341
+ export function actorOperators(path) {
342
+ return tested(ACTOR_TESTS, path)?.operators ?? [];
343
+ }
344
+ export function itemOperators(path) {
345
+ return tested(ITEM_TESTS, path)?.operators ?? [];
346
+ }
347
+ export function itemKind(path) {
348
+ return tested(ITEM_TESTS, path)?.kind ?? null;
349
+ }
350
+ export function dated(value) {
351
+ return (typeof value === 'string' && DATE.test(value) && instant(`${value}T00:00:00Z`) !== undefined);
352
+ }
353
+ export function instant(value) {
354
+ if (typeof value !== 'string')
355
+ return undefined;
356
+ const parts = DATE_TIME.exec(value);
357
+ if (parts === null)
358
+ return undefined;
359
+ const [year, month, day, hour, minute, second, offsetHours, offsetMinutes] = [
360
+ 1, 2, 3, 4, 5, 6, 9, 10,
361
+ ].map((at) => Number(parts[at] ?? 0));
362
+ const at = new Date(0);
363
+ at.setUTCFullYear(year, month - 1, day);
364
+ at.setUTCHours(hour, minute, second);
365
+ if (at.getUTCFullYear() !== year ||
366
+ at.getUTCMonth() !== month - 1 ||
367
+ at.getUTCDate() !== day ||
368
+ at.getUTCHours() !== hour ||
369
+ at.getUTCMinutes() !== minute ||
370
+ offsetHours > 23 ||
371
+ offsetMinutes > 59)
372
+ return undefined;
373
+ const offset = (parts[8] === '-' ? -1 : 1) * (offsetHours * 60 + offsetMinutes);
374
+ const fraction = (parts[7] ?? '').padEnd(9, '0').slice(0, 9);
375
+ return (BigInt(at.getTime()) - BigInt(offset) * 60000n) * 1000000n + BigInt(fraction);
376
+ }
377
+ export function pointed(value, pointer) {
378
+ let reached = value;
379
+ for (const token of pointerSegments(pointer)) {
380
+ if (Array.isArray(reached)) {
381
+ if (!ARRAY_INDEX.test(token))
382
+ return undefined;
383
+ reached = reached[Number(token)];
384
+ }
385
+ else if (plain(reached) && Object.hasOwn(reached, token)) {
386
+ reached = reached[token];
387
+ }
388
+ else {
389
+ return undefined;
390
+ }
391
+ }
392
+ return reached;
393
+ }
394
+ function scalar(value) {
395
+ return (typeof value === 'string' ||
396
+ typeof value === 'boolean' ||
397
+ (typeof value === 'number' && Number.isFinite(value)));
398
+ }
399
+ function jsonHeld(value) {
400
+ if (typeof value === 'string')
401
+ return {
402
+ kind: dated(value) ? 'date' : instant(value) === undefined ? 'string' : 'time',
403
+ value,
404
+ };
405
+ if (typeof value === 'boolean')
406
+ return { kind: 'boolean', value };
407
+ return { kind: 'number', value };
408
+ }
409
+ function jsonRead(value) {
410
+ if (value === undefined)
411
+ return undefined;
412
+ if (scalar(value))
413
+ return single(jsonHeld(value));
414
+ if (!Array.isArray(value))
415
+ return single({ kind: 'prose' });
416
+ return { present: true, values: [], items: value.filter(scalar).map(jsonHeld), loose: true };
417
+ }
418
+ function equal(held, value) {
419
+ if (!('value' in held))
420
+ return undefined;
421
+ if (typeof value !== typeof held.value)
422
+ return undefined;
423
+ if (held.kind !== 'time')
424
+ return value === held.value;
425
+ const left = instant(held.value);
426
+ const right = instant(value);
427
+ return left === undefined || right === undefined ? undefined : left === right;
428
+ }
429
+ function sign(left, right) {
430
+ return left < right ? -1 : left > right ? 1 : 0;
431
+ }
432
+ function ordered(held, value, compare) {
433
+ if (!('value' in held))
434
+ return undefined;
435
+ if (held.kind === 'number') {
436
+ if (typeof value !== 'number' || typeof held.value !== 'number')
437
+ return undefined;
438
+ return compare(Math.sign(held.value - value));
439
+ }
440
+ if (held.kind === 'date') {
441
+ if (!dated(value) || !dated(held.value))
442
+ return undefined;
443
+ return compare(sign(held.value, value));
444
+ }
445
+ if (held.kind !== 'time')
446
+ return undefined;
447
+ const at = instant(held.value);
448
+ const wanted = instant(value);
449
+ if (at === undefined || wanted === undefined)
450
+ return undefined;
451
+ return compare(sign(at, wanted));
452
+ }
453
+ function anyOf(truths) {
454
+ if (truths.some((truth) => truth === true))
455
+ return true;
456
+ return truths.some((truth) => truth === undefined) ? undefined : false;
457
+ }
458
+ function allOf(truths) {
459
+ if (truths.some((truth) => truth === false))
460
+ return false;
461
+ return truths.some((truth) => truth === undefined) ? undefined : true;
462
+ }
463
+ function compared(test, held) {
464
+ if ('eq' in test)
465
+ return equal(held, test.eq);
466
+ if ('in' in test)
467
+ return anyOf(test.in.map((value) => equal(held, value)));
468
+ if ('prefix' in test) {
469
+ if (!('value' in held) || typeof held.value !== 'string')
470
+ return undefined;
471
+ if (held.kind === 'number' || held.kind === 'reference' || held.kind === 'member')
472
+ return undefined;
473
+ return held.value.startsWith(test.prefix);
474
+ }
475
+ if ('gt' in test)
476
+ return ordered(held, test.gt, (sign) => sign > 0);
477
+ if ('gte' in test)
478
+ return ordered(held, test.gte, (sign) => sign >= 0);
479
+ if ('lt' in test)
480
+ return ordered(held, test.lt, (sign) => sign < 0);
481
+ return ordered(held, test.lte, (sign) => sign <= 0);
482
+ }
483
+ function leaf(test, read) {
484
+ if ('exists' in test) {
485
+ const present = read === undefined ? false : read.present;
486
+ return present === undefined ? undefined : present === test.exists;
487
+ }
488
+ if (read === undefined)
489
+ return undefined;
490
+ if ('contains' in test) {
491
+ if (read.items === null)
492
+ return undefined;
493
+ const truths = read.items.map((item) => item === undefined ? undefined : equal(item, test.contains));
494
+ return read.loose === true && !truths.includes(true) ? false : anyOf(truths);
495
+ }
496
+ if (read.values.length === 0)
497
+ return read === NO_ITEM ? false : undefined;
498
+ return anyOf(read.values.map((value) => (value === undefined ? undefined : compared(test, value))));
499
+ }
500
+ function evaluated(test, read) {
501
+ if ('all' in test)
502
+ return allOf(test.all.map((part) => evaluated(part, read)));
503
+ if ('any' in test)
504
+ return anyOf(test.any.map((part) => evaluated(part, read)));
505
+ if ('not' in test) {
506
+ const truth = evaluated(test.not, read);
507
+ return truth === undefined ? undefined : !truth;
508
+ }
509
+ return leaf(test, read(test.path));
510
+ }
511
+ export function members(document, path) {
512
+ if (!path.startsWith('/members/'))
513
+ return [];
514
+ const read = readDocument(document, path);
515
+ const values = read === undefined ? [] : [...read.values, ...(read.items ?? [])];
516
+ return [
517
+ ...new Set(values.flatMap((value) => value !== undefined && value.kind === 'member' && 'value' in value
518
+ ? [String(value.value)]
519
+ : [])),
520
+ ].sort();
521
+ }
522
+ export function holds(test, document) {
523
+ return evaluated(test, (path) => readDocument(document, path));
524
+ }
525
+ function inScope(scope, document) {
526
+ if (document === null)
527
+ return false;
528
+ if ('type' in scope)
529
+ return document.type === scope.type;
530
+ if ('document' in scope)
531
+ return document.id === scope.document;
532
+ return scope.folder === '/' || document.path.startsWith(`${scope.folder}/`);
533
+ }
534
+ function matched(condition, test, document) {
535
+ if (!inScope(condition.scope, document))
536
+ return false;
537
+ return test === undefined || holds(test, document) === true;
538
+ }
539
+ function reachedAt(document, field) {
540
+ if (document === null)
541
+ return [];
542
+ if (field.startsWith('/sections/'))
543
+ return document.sections.includes(field.slice('/sections/'.length))
544
+ ? [{ pointer: field, fact: PROSE }]
545
+ : [];
546
+ if (!field.startsWith('/fields/'))
547
+ return [];
548
+ return walked(rootOf(document, '/fields'), field.slice('/fields'.length)).reached;
549
+ }
550
+ function valueOf(fact) {
551
+ if (fact.kind === 'list')
552
+ return { kind: fact.kind, items: fact.items.map(valueOf) };
553
+ if (fact.kind === 'object')
554
+ return {
555
+ kind: fact.kind,
556
+ fields: Object.keys(fact.fields)
557
+ .sort()
558
+ .map((key) => [key, valueOf(fact.fields[key])]),
559
+ };
560
+ if (fact.kind === 'time') {
561
+ const at = instant(fact.value);
562
+ if (at !== undefined)
563
+ return { kind: fact.kind, at: String(at) };
564
+ }
565
+ return 'value' in fact ? { kind: fact.kind, value: fact.value } : fact;
566
+ }
567
+ function signature(reached) {
568
+ return JSON.stringify(reached.map(({ fact }) => valueOf(fact)));
569
+ }
570
+ function among(values, document, field) {
571
+ return holds({ path: field, in: values }, document) === true;
572
+ }
573
+ function fieldChanged(condition, event) {
574
+ const { field, from, to } = condition;
575
+ const before = reachedAt(event.before, field);
576
+ const after = reachedAt(event.after, field);
577
+ const pointers = [field, ...[...before, ...after].map(({ pointer }) => pointer)];
578
+ const prose = event.changed.some((changed) => pointers.some((pointer) => changed === pointer || changed.startsWith(`${pointer}/`)));
579
+ if (from === undefined && to === undefined && prose)
580
+ return true;
581
+ if (before.length === 0 && after.length === 0)
582
+ return false;
583
+ if (event.before !== null && event.after !== null && signature(before) === signature(after))
584
+ return false;
585
+ if (from === 'new'
586
+ ? event.before !== null
587
+ : from !== undefined && (event.before === null || !among(from, event.before, field)))
588
+ return false;
589
+ if (to === 'deleted'
590
+ ? event.after !== null
591
+ : to !== undefined && (event.after === null || !among(to, event.after, field)))
592
+ return false;
593
+ return true;
594
+ }
595
+ export function fires(condition, event) {
596
+ if (condition.moved_between_rooms !== undefined &&
597
+ condition.moved_between_rooms !== event.moved_between_rooms)
598
+ return false;
599
+ if (condition.by !== undefined && evaluated(condition.by, reader(ACTOR_TESTS, event.by)) !== true)
600
+ return false;
601
+ if (condition.mode === 'starts_matching') {
602
+ if (event.before === null && !condition.new_documents)
603
+ return false;
604
+ return (matched(condition, condition.match, event.after) &&
605
+ !matched(condition, condition.match, event.before));
606
+ }
607
+ const side = event.after ?? event.before;
608
+ return matched(condition, condition.match, side) && fieldChanged(condition, event);
609
+ }
610
+ export function itemFires(condition, item) {
611
+ if (condition.source !== undefined && item.source !== condition.source)
612
+ return false;
613
+ if (condition.address !== undefined && item.address !== condition.address)
614
+ return false;
615
+ return (condition.match === undefined || evaluated(condition.match, reader(ITEM_TESTS, item)) === true);
616
+ }