@beechcms/core 0.8.0 → 0.9.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 (389) hide show
  1. package/dist/auth/account-email.d.ts +3 -0
  2. package/dist/auth/account-email.d.ts.map +1 -0
  3. package/dist/auth/account-email.js +9 -0
  4. package/dist/auth/password-reset-token.repository.d.ts +13 -2
  5. package/dist/auth/password-reset-token.repository.d.ts.map +1 -1
  6. package/dist/auth/user.repository.d.ts +69 -4
  7. package/dist/auth/user.repository.d.ts.map +1 -1
  8. package/dist/automations-grammar-words.d.ts +2 -0
  9. package/dist/automations-grammar-words.d.ts.map +1 -0
  10. package/dist/automations-grammar-words.js +8 -0
  11. package/dist/automations.repository.interface.d.ts +19 -0
  12. package/dist/automations.repository.interface.d.ts.map +1 -0
  13. package/dist/automations.repository.interface.js +3 -0
  14. package/dist/automations.runner.interface.d.ts +10 -0
  15. package/dist/automations.runner.interface.d.ts.map +1 -0
  16. package/dist/automations.runner.interface.js +3 -0
  17. package/dist/automations.runner.stub.d.ts +5 -0
  18. package/dist/automations.runner.stub.d.ts.map +1 -0
  19. package/dist/automations.runner.stub.js +7 -0
  20. package/dist/automations.types.d.ts +75 -0
  21. package/dist/automations.types.d.ts.map +1 -0
  22. package/dist/automations.types.js +3 -0
  23. package/dist/clock.d.ts +25 -0
  24. package/dist/clock.d.ts.map +1 -0
  25. package/dist/clock.js +11 -0
  26. package/dist/common/canonical-json.d.ts +31 -0
  27. package/dist/common/canonical-json.d.ts.map +1 -0
  28. package/dist/common/canonical-json.js +91 -0
  29. package/dist/content/content-scan.repository.d.ts +1 -1
  30. package/dist/content/content.repository.d.ts +154 -3
  31. package/dist/content/content.repository.d.ts.map +1 -1
  32. package/dist/content/content.repository.js +62 -0
  33. package/dist/content/deletion-ledger.d.ts +39 -0
  34. package/dist/content/deletion-ledger.d.ts.map +1 -0
  35. package/dist/content/deletion-ledger.js +3 -0
  36. package/dist/content/seed-media-purge.repository.d.ts +34 -0
  37. package/dist/content/seed-media-purge.repository.d.ts.map +1 -0
  38. package/dist/content/seed-media-purge.repository.js +3 -0
  39. package/dist/content/seed.repository.d.ts +14 -0
  40. package/dist/content/seed.repository.d.ts.map +1 -1
  41. package/dist/content-scan.repository.d.ts +9 -0
  42. package/dist/content-scan.repository.d.ts.map +1 -0
  43. package/dist/content-scan.repository.js +3 -0
  44. package/dist/content.repository.d.ts +247 -0
  45. package/dist/content.repository.d.ts.map +1 -0
  46. package/dist/content.repository.js +59 -0
  47. package/dist/dashboard-layout/content-view.d.ts +757 -0
  48. package/dist/dashboard-layout/content-view.d.ts.map +1 -0
  49. package/dist/dashboard-layout/content-view.js +285 -0
  50. package/dist/dashboard-layout/content-view.repository.d.ts +39 -0
  51. package/dist/dashboard-layout/content-view.repository.d.ts.map +1 -0
  52. package/dist/dashboard-layout/content-view.repository.js +3 -0
  53. package/dist/dashboard-layout/dashboard-layout.d.ts +5 -0
  54. package/dist/dashboard-layout/dashboard-layout.d.ts.map +1 -1
  55. package/dist/dashboard-layout/dashboard-layout.js +17 -9
  56. package/dist/dashboard-layout/kanban/kanban.d.ts +32 -18
  57. package/dist/dashboard-layout/kanban/kanban.d.ts.map +1 -1
  58. package/dist/dashboard-layout/kanban/kanban.js +45 -21
  59. package/dist/dashboard-layout/seed-layout.d.ts +22 -31
  60. package/dist/dashboard-layout/seed-layout.d.ts.map +1 -1
  61. package/dist/dashboard-layout/seed-layout.js +93 -18
  62. package/dist/dashboard-layout/seed-layout.repository.d.ts +1 -5
  63. package/dist/dashboard-layout/seed-layout.repository.d.ts.map +1 -1
  64. package/dist/dashboard-layout.d.ts +154 -0
  65. package/dist/dashboard-layout.d.ts.map +1 -0
  66. package/dist/dashboard-layout.js +186 -0
  67. package/dist/dashboard-layout.repository.d.ts +18 -0
  68. package/dist/dashboard-layout.repository.d.ts.map +1 -0
  69. package/dist/dashboard-layout.repository.js +3 -0
  70. package/dist/dashboard-permissions.d.ts +3 -0
  71. package/dist/dashboard-permissions.d.ts.map +1 -0
  72. package/dist/dashboard-permissions.js +11 -0
  73. package/dist/dashboard-scopes.d.ts +12 -0
  74. package/dist/dashboard-scopes.d.ts.map +1 -0
  75. package/dist/dashboard-scopes.js +30 -0
  76. package/dist/define-seed.d.ts +3 -0
  77. package/dist/define-seed.d.ts.map +1 -0
  78. package/dist/define-seed.js +5 -0
  79. package/dist/demo-data.repository.d.ts +5 -0
  80. package/dist/demo-data.repository.d.ts.map +1 -0
  81. package/dist/demo-data.repository.js +3 -0
  82. package/dist/email.provider.d.ts +32 -0
  83. package/dist/email.provider.d.ts.map +1 -0
  84. package/dist/email.provider.js +4 -0
  85. package/dist/engine/ddl/ddl.d.ts +247 -0
  86. package/dist/engine/ddl/ddl.d.ts.map +1 -0
  87. package/dist/engine/ddl/ddl.js +653 -0
  88. package/dist/engine/ddl/schema-mutator.d.ts +29 -0
  89. package/dist/engine/ddl/schema-mutator.d.ts.map +1 -0
  90. package/dist/engine/ddl/schema-mutator.js +3 -0
  91. package/dist/engine/ddl/seed-ddl-destructive.d.ts +40 -0
  92. package/dist/engine/ddl/seed-ddl-destructive.d.ts.map +1 -0
  93. package/dist/engine/ddl/seed-ddl-destructive.js +149 -0
  94. package/dist/engine/ddl/seed-ddl.d.ts +43 -0
  95. package/dist/engine/ddl/seed-ddl.d.ts.map +1 -0
  96. package/dist/engine/ddl/seed-ddl.js +115 -0
  97. package/dist/engine/ddl/seed-purge-guards.d.ts +7 -0
  98. package/dist/engine/ddl/seed-purge-guards.d.ts.map +1 -0
  99. package/dist/engine/ddl/seed-purge-guards.js +19 -0
  100. package/dist/engine/engine.d.ts +4 -3
  101. package/dist/engine/engine.d.ts.map +1 -1
  102. package/dist/engine/engine.js +4 -3
  103. package/dist/engine/introspection/introspection.d.ts +101 -0
  104. package/dist/engine/introspection/introspection.d.ts.map +1 -0
  105. package/dist/engine/introspection/introspection.js +127 -0
  106. package/dist/engine/introspection/relation-audit.d.ts +46 -0
  107. package/dist/engine/introspection/relation-audit.d.ts.map +1 -0
  108. package/dist/engine/introspection/relation-audit.js +103 -0
  109. package/dist/engine/introspection/schema-fingerprint.d.ts +74 -0
  110. package/dist/engine/introspection/schema-fingerprint.d.ts.map +1 -0
  111. package/dist/engine/introspection/schema-fingerprint.js +102 -0
  112. package/dist/engine/introspection.d.ts +101 -0
  113. package/dist/engine/introspection.d.ts.map +1 -0
  114. package/dist/engine/introspection.js +127 -0
  115. package/dist/engine/localization/localization.d.ts +127 -0
  116. package/dist/engine/localization/localization.d.ts.map +1 -0
  117. package/dist/engine/localization/localization.js +212 -0
  118. package/dist/engine/localization.d.ts +127 -0
  119. package/dist/engine/localization.d.ts.map +1 -0
  120. package/dist/engine/localization.js +212 -0
  121. package/dist/engine/privacy/policies.d.ts +58 -0
  122. package/dist/engine/privacy/policies.d.ts.map +1 -0
  123. package/dist/engine/privacy/policies.js +191 -0
  124. package/dist/engine/privacy/privacy.service.d.ts +78 -0
  125. package/dist/engine/privacy/privacy.service.d.ts.map +1 -0
  126. package/dist/engine/privacy/privacy.service.js +138 -0
  127. package/dist/engine/privacy.service.d.ts.map +1 -1
  128. package/dist/engine/query/active-clause.d.ts +19 -0
  129. package/dist/engine/query/active-clause.d.ts.map +1 -0
  130. package/dist/engine/query/active-clause.js +27 -0
  131. package/dist/engine/query/query.d.ts +36 -0
  132. package/dist/engine/query/query.d.ts.map +1 -0
  133. package/dist/engine/query/query.js +393 -0
  134. package/dist/engine/query/relations.d.ts +28 -0
  135. package/dist/engine/query/relations.d.ts.map +1 -0
  136. package/dist/engine/query/relations.js +25 -0
  137. package/dist/engine/query/serialize.d.ts +22 -0
  138. package/dist/engine/query/serialize.d.ts.map +1 -0
  139. package/dist/engine/query/serialize.js +175 -0
  140. package/dist/engine/schema-fingerprint.d.ts +73 -0
  141. package/dist/engine/schema-fingerprint.d.ts.map +1 -0
  142. package/dist/engine/schema-fingerprint.js +97 -0
  143. package/dist/engine/seed-registry.d.ts.map +1 -1
  144. package/dist/engine/seeds/candidate-ids.d.ts +14 -0
  145. package/dist/engine/seeds/candidate-ids.d.ts.map +1 -0
  146. package/dist/engine/seeds/candidate-ids.js +40 -0
  147. package/dist/engine/seeds/define-seed.d.ts +3 -0
  148. package/dist/engine/seeds/define-seed.d.ts.map +1 -0
  149. package/dist/engine/seeds/define-seed.js +5 -0
  150. package/dist/engine/seeds/seed-definition-diff.d.ts +38 -0
  151. package/dist/engine/seeds/seed-definition-diff.d.ts.map +1 -0
  152. package/dist/engine/seeds/seed-definition-diff.js +51 -0
  153. package/dist/engine/seeds/seed-registry.d.ts +88 -0
  154. package/dist/engine/seeds/seed-registry.d.ts.map +1 -0
  155. package/dist/engine/seeds/seed-registry.js +194 -0
  156. package/dist/engine/seeds/seed-types-generator.d.ts +25 -0
  157. package/dist/engine/seeds/seed-types-generator.d.ts.map +1 -0
  158. package/dist/engine/seeds/seed-types-generator.js +116 -0
  159. package/dist/engine/seeds/seed-validation.d.ts +35 -0
  160. package/dist/engine/seeds/seed-validation.d.ts.map +1 -0
  161. package/dist/engine/seeds/seed-validation.js +384 -0
  162. package/dist/engine/seeds/seeds.d.ts +20 -0
  163. package/dist/engine/seeds/seeds.d.ts.map +1 -0
  164. package/dist/engine/seeds/seeds.js +21 -0
  165. package/dist/engine/seeds/tag-migration.d.ts +73 -0
  166. package/dist/engine/seeds/tag-migration.d.ts.map +1 -0
  167. package/dist/engine/seeds/tag-migration.js +212 -0
  168. package/dist/engine/seeds/tag-options.d.ts +15 -0
  169. package/dist/engine/seeds/tag-options.d.ts.map +1 -0
  170. package/dist/engine/seeds/tag-options.js +111 -0
  171. package/dist/engine/seeds/tag-value.d.ts +31 -0
  172. package/dist/engine/seeds/tag-value.d.ts.map +1 -0
  173. package/dist/engine/seeds/tag-value.js +51 -0
  174. package/dist/engine/types.d.ts +59 -7
  175. package/dist/engine/types.d.ts.map +1 -1
  176. package/dist/engine/validation/cache.d.ts.map +1 -1
  177. package/dist/engine/validation/cache.js +20 -4
  178. package/dist/engine/validation/emptiness.d.ts +12 -0
  179. package/dist/engine/validation/emptiness.d.ts.map +1 -0
  180. package/dist/engine/validation/emptiness.js +33 -0
  181. package/dist/engine/validation/index.d.ts +11 -0
  182. package/dist/engine/validation/index.d.ts.map +1 -1
  183. package/dist/engine/validation/index.js +29 -33
  184. package/dist/engine/validation/primitives.d.ts +12 -0
  185. package/dist/engine/validation/primitives.d.ts.map +1 -1
  186. package/dist/engine/validation/primitives.js +22 -0
  187. package/dist/engine/validation/richtext-sanitizer.d.ts +9 -1
  188. package/dist/engine/validation/richtext-sanitizer.d.ts.map +1 -1
  189. package/dist/engine/validation/richtext-sanitizer.js +36 -7
  190. package/dist/engine/validation/schema-builders.d.ts +16 -0
  191. package/dist/engine/validation/schema-builders.d.ts.map +1 -1
  192. package/dist/engine/validation/schema-builders.js +125 -18
  193. package/dist/engine.d.ts +144 -0
  194. package/dist/engine.d.ts.map +1 -0
  195. package/dist/engine.js +741 -0
  196. package/dist/file-types.d.ts +13 -0
  197. package/dist/file-types.d.ts.map +1 -0
  198. package/dist/file-types.js +85 -0
  199. package/dist/hooks.d.ts +29 -0
  200. package/dist/hooks.d.ts.map +1 -0
  201. package/dist/hooks.js +3 -0
  202. package/dist/id-generator.d.ts +26 -0
  203. package/dist/id-generator.d.ts.map +1 -0
  204. package/dist/id-generator.js +12 -0
  205. package/dist/idempotency.repository.d.ts +13 -0
  206. package/dist/idempotency.repository.d.ts.map +1 -0
  207. package/dist/idempotency.repository.js +3 -0
  208. package/dist/index.d.ts +34 -11
  209. package/dist/index.d.ts.map +1 -1
  210. package/dist/index.js +34 -11
  211. package/dist/kanban-position.repository.d.ts +19 -0
  212. package/dist/kanban-position.repository.d.ts.map +1 -0
  213. package/dist/kanban-position.repository.js +3 -0
  214. package/dist/kanban.d.ts +75 -0
  215. package/dist/kanban.d.ts.map +1 -0
  216. package/dist/kanban.js +82 -0
  217. package/dist/layout-permissions.d.ts +3 -0
  218. package/dist/layout-permissions.d.ts.map +1 -0
  219. package/dist/layout-permissions.js +11 -0
  220. package/dist/media/file-types.d.ts +12 -0
  221. package/dist/media/file-types.d.ts.map +1 -1
  222. package/dist/media/file-types.js +24 -4
  223. package/dist/media/image-transformer.d.ts +34 -0
  224. package/dist/media/image-transformer.d.ts.map +1 -0
  225. package/dist/media/image-transformer.js +3 -0
  226. package/dist/media/magic-bytes.d.ts.map +1 -1
  227. package/dist/media/magic-bytes.js +19 -9
  228. package/dist/media/media-transform.d.ts +92 -0
  229. package/dist/media/media-transform.d.ts.map +1 -0
  230. package/dist/media/media-transform.js +197 -0
  231. package/dist/media/media.repository.d.ts +5 -0
  232. package/dist/media/media.repository.d.ts.map +1 -1
  233. package/dist/media.repository.d.ts +61 -0
  234. package/dist/media.repository.d.ts.map +1 -0
  235. package/dist/media.repository.js +3 -0
  236. package/dist/notifications/notification.repository.d.ts +11 -2
  237. package/dist/notifications/notification.repository.d.ts.map +1 -1
  238. package/dist/oauth/authorization-code.repository.d.ts +10 -5
  239. package/dist/oauth/authorization-code.repository.d.ts.map +1 -1
  240. package/dist/oauth/role-guard.d.ts +30 -11
  241. package/dist/oauth/role-guard.d.ts.map +1 -1
  242. package/dist/oauth/role-guard.js +27 -5
  243. package/dist/oauth/token.repository.d.ts +2 -0
  244. package/dist/oauth/token.repository.d.ts.map +1 -1
  245. package/dist/policies.d.ts +10 -0
  246. package/dist/policies.d.ts.map +1 -0
  247. package/dist/policies.js +33 -0
  248. package/dist/queue/queue.interface.d.ts +9 -1
  249. package/dist/queue/queue.interface.d.ts.map +1 -1
  250. package/dist/queue/queue.stub.d.ts +1 -1
  251. package/dist/queue/queue.stub.d.ts.map +1 -1
  252. package/dist/queue/queue.stub.js +2 -3
  253. package/dist/queue.interface.d.ts +39 -0
  254. package/dist/queue.interface.d.ts.map +1 -0
  255. package/dist/queue.interface.js +3 -0
  256. package/dist/queue.stub.d.ts +6 -0
  257. package/dist/queue.stub.d.ts.map +1 -0
  258. package/dist/queue.stub.js +8 -0
  259. package/dist/rate-limit/token-bucket-rate-limiter.d.ts +7 -0
  260. package/dist/rate-limit/token-bucket-rate-limiter.d.ts.map +1 -1
  261. package/dist/rate-limit/token-bucket-rate-limiter.js +66 -0
  262. package/dist/rbac/evaluate.d.ts +57 -0
  263. package/dist/rbac/evaluate.d.ts.map +1 -0
  264. package/dist/rbac/evaluate.js +113 -0
  265. package/dist/rbac/invitation.repository.d.ts +84 -0
  266. package/dist/rbac/invitation.repository.d.ts.map +1 -0
  267. package/dist/rbac/invitation.repository.js +3 -0
  268. package/dist/rbac/permissions.d.ts +39 -0
  269. package/dist/rbac/permissions.d.ts.map +1 -0
  270. package/dist/rbac/permissions.js +43 -0
  271. package/dist/rbac/types.d.ts +130 -0
  272. package/dist/rbac/types.d.ts.map +1 -0
  273. package/dist/rbac/types.js +4 -0
  274. package/dist/relations.d.ts +28 -0
  275. package/dist/relations.d.ts.map +1 -0
  276. package/dist/relations.js +25 -0
  277. package/dist/richtext-render.d.ts +11 -0
  278. package/dist/richtext-render.d.ts.map +1 -0
  279. package/dist/richtext-render.js +87 -0
  280. package/dist/richtext.d.ts +11 -0
  281. package/dist/richtext.d.ts.map +1 -0
  282. package/dist/richtext.js +13 -0
  283. package/dist/scheduler.interface.d.ts +4 -0
  284. package/dist/scheduler.interface.d.ts.map +1 -0
  285. package/dist/scheduler.interface.js +3 -0
  286. package/dist/scheduler.stub.d.ts +5 -0
  287. package/dist/scheduler.stub.d.ts.map +1 -0
  288. package/dist/scheduler.stub.js +7 -0
  289. package/dist/schema/canonical.d.ts +15 -0
  290. package/dist/schema/canonical.d.ts.map +1 -0
  291. package/dist/schema/canonical.js +37 -0
  292. package/dist/schema/define.d.ts +42 -0
  293. package/dist/schema/define.d.ts.map +1 -0
  294. package/dist/schema/define.js +56 -0
  295. package/dist/schema/emit.d.ts +14 -0
  296. package/dist/schema/emit.d.ts.map +1 -0
  297. package/dist/schema/emit.js +43 -0
  298. package/dist/schema/index.d.ts +12 -0
  299. package/dist/schema/index.d.ts.map +1 -0
  300. package/dist/schema/index.js +13 -0
  301. package/dist/schema/manifest-seeds.d.ts +12 -0
  302. package/dist/schema/manifest-seeds.d.ts.map +1 -0
  303. package/dist/schema/manifest-seeds.js +48 -0
  304. package/dist/schema/manifest-validation.d.ts +13 -0
  305. package/dist/schema/manifest-validation.d.ts.map +1 -0
  306. package/dist/schema/manifest-validation.js +41 -0
  307. package/dist/schema/manifest.types.d.ts +54 -0
  308. package/dist/schema/manifest.types.d.ts.map +1 -0
  309. package/dist/schema/manifest.types.js +7 -0
  310. package/dist/schema-mutator.d.ts +26 -0
  311. package/dist/schema-mutator.d.ts.map +1 -0
  312. package/dist/schema-mutator.js +3 -0
  313. package/dist/search/search.repository.d.ts +5 -4
  314. package/dist/search/search.repository.d.ts.map +1 -1
  315. package/dist/search/vector-extractor.d.ts.map +1 -1
  316. package/dist/search/vector-extractor.js +23 -2
  317. package/dist/search/vector.repository.d.ts +2 -1
  318. package/dist/search/vector.repository.d.ts.map +1 -1
  319. package/dist/security/time-trap-token.repository.d.ts +5 -3
  320. package/dist/security/time-trap-token.repository.d.ts.map +1 -1
  321. package/dist/seed-ddl-destructive.d.ts +40 -0
  322. package/dist/seed-ddl-destructive.d.ts.map +1 -0
  323. package/dist/seed-ddl-destructive.js +149 -0
  324. package/dist/seed-ddl.d.ts +40 -0
  325. package/dist/seed-ddl.d.ts.map +1 -0
  326. package/dist/seed-ddl.js +100 -0
  327. package/dist/seed-layout.d.ts +145 -0
  328. package/dist/seed-layout.d.ts.map +1 -0
  329. package/dist/seed-layout.js +192 -0
  330. package/dist/seed-layout.repository.d.ts +22 -0
  331. package/dist/seed-layout.repository.d.ts.map +1 -0
  332. package/dist/seed-layout.repository.js +3 -0
  333. package/dist/seed-registry.d.ts +71 -0
  334. package/dist/seed-registry.d.ts.map +1 -0
  335. package/dist/seed-registry.js +143 -0
  336. package/dist/seed-types-generator.d.ts +1 -1
  337. package/dist/seed-types-generator.d.ts.map +1 -1
  338. package/dist/seed-validation.d.ts +23 -0
  339. package/dist/seed-validation.d.ts.map +1 -0
  340. package/dist/seed-validation.js +224 -0
  341. package/dist/seed.repository.d.ts +37 -0
  342. package/dist/seed.repository.d.ts.map +1 -0
  343. package/dist/seed.repository.js +3 -0
  344. package/dist/seeds.d.ts +20 -0
  345. package/dist/seeds.d.ts.map +1 -0
  346. package/dist/seeds.js +21 -0
  347. package/dist/settings/site-settings.repository.d.ts +8 -0
  348. package/dist/settings/site-settings.repository.d.ts.map +1 -1
  349. package/dist/site-settings.repository.d.ts +16 -0
  350. package/dist/site-settings.repository.d.ts.map +1 -0
  351. package/dist/site-settings.repository.js +3 -0
  352. package/dist/slug-utils.d.ts +18 -0
  353. package/dist/slug-utils.d.ts.map +1 -0
  354. package/dist/slug-utils.js +32 -0
  355. package/dist/storage.d.ts +46 -0
  356. package/dist/storage.d.ts.map +1 -0
  357. package/dist/storage.js +3 -0
  358. package/dist/transfer/csv.d.ts +34 -0
  359. package/dist/transfer/csv.d.ts.map +1 -0
  360. package/dist/transfer/csv.js +135 -0
  361. package/dist/transfer/flat-seed.d.ts +13 -0
  362. package/dist/transfer/flat-seed.d.ts.map +1 -0
  363. package/dist/transfer/flat-seed.js +50 -0
  364. package/dist/transfer/index.d.ts +7 -0
  365. package/dist/transfer/index.d.ts.map +1 -0
  366. package/dist/transfer/index.js +8 -0
  367. package/dist/transfer/ndjson.d.ts +25 -0
  368. package/dist/transfer/ndjson.d.ts.map +1 -0
  369. package/dist/transfer/ndjson.js +62 -0
  370. package/dist/transfer/row-mapping.d.ts +36 -0
  371. package/dist/transfer/row-mapping.d.ts.map +1 -0
  372. package/dist/transfer/row-mapping.js +97 -0
  373. package/dist/transfer/transfer.constants.d.ts +20 -0
  374. package/dist/transfer/transfer.constants.d.ts.map +1 -0
  375. package/dist/transfer/transfer.constants.js +21 -0
  376. package/dist/transfer/transfer.types.d.ts +46 -0
  377. package/dist/transfer/transfer.types.d.ts.map +1 -0
  378. package/dist/transfer/transfer.types.js +6 -0
  379. package/dist/types.d.ts +243 -0
  380. package/dist/types.d.ts.map +1 -0
  381. package/dist/types.js +3 -0
  382. package/dist/validation.d.ts +50 -0
  383. package/dist/validation.d.ts.map +1 -0
  384. package/dist/validation.js +660 -0
  385. package/dist/webhook-validation.d.ts +3 -0
  386. package/dist/webhook-validation.d.ts.map +1 -0
  387. package/dist/webhook-validation.js +6 -0
  388. package/package.json +11 -6
  389. package/dist/.tsbuildinfo +0 -1
@@ -0,0 +1,13 @@
1
+ export type FileAccept = 'image' | 'document' | 'any';
2
+ export declare const IMAGE_EXTENSIONS: Set<string>;
3
+ export declare const BLOCKED_IMAGE_EXTENSIONS: Set<string>;
4
+ export declare const DOCUMENT_EXTENSIONS: Set<string>;
5
+ export declare const ARCHIVE_EXTENSIONS: Set<string>;
6
+ export declare const IMAGE_MIME_TYPES: readonly ["image/jpeg", "image/png", "image/gif", "image/webp", "image/avif", "image/bmp", "image/x-icon", "image/vnd.microsoft.icon"];
7
+ export declare const BLOCKED_IMAGE_MIME_TYPES: readonly ["image/svg+xml", "image/svg"];
8
+ export declare const DOCUMENT_MIME_TYPES: readonly ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/vnd.ms-powerpoint", "application/vnd.openxmlformats-officedocument.presentationml.presentation", "text/plain", "text/csv", "text/markdown"];
9
+ export declare const ARCHIVE_MIME_TYPES: readonly ["application/zip", "application/x-zip-compressed", "application/x-7z-compressed", "application/x-tar", "application/gzip", "application/json"];
10
+ export declare function extensionFromUrl(url: string): string | null;
11
+ export declare function isExtensionAccepted(ext: string | null, accept: FileAccept): boolean;
12
+ export declare function isMimeAccepted(mime: string, accept: FileAccept): boolean;
13
+ //# sourceMappingURL=file-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-types.d.ts","sourceRoot":"","sources":["../src/file-types.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,KAAK,CAAA;AAKrD,eAAO,MAAM,gBAAgB,aAAuE,CAAA;AACpG,eAAO,MAAM,wBAAwB,aAA2B,CAAA;AAChE,eAAO,MAAM,mBAAmB,aAAoF,CAAA;AACpH,eAAO,MAAM,kBAAkB,aAA8C,CAAA;AAI7E,eAAO,MAAM,gBAAgB,wIASnB,CAAA;AAGV,eAAO,MAAM,wBAAwB,yCAA0C,CAAA;AAC/E,eAAO,MAAM,mBAAmB,yXAWtB,CAAA;AACV,eAAO,MAAM,kBAAkB,0JAOrB,CAAA;AAEV,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS3D;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAMnF;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAcxE"}
@@ -0,0 +1,85 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2024–2026 Flavio De Musso
3
+ // SVG is intentionally excluded: SVG can embed <script> tags and is rendered
4
+ // inline by browsers when served as image/svg+xml on a same-origin route,
5
+ // creating a stored XSS vector (see security audit finding #4).
6
+ export const IMAGE_EXTENSIONS = new Set(['jpg', 'jpeg', 'png', 'gif', 'webp', 'avif', 'bmp', 'ico']);
7
+ export const BLOCKED_IMAGE_EXTENSIONS = new Set(['svg', 'svgz']);
8
+ export const DOCUMENT_EXTENSIONS = new Set(['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'csv', 'md']);
9
+ export const ARCHIVE_EXTENSIONS = new Set(['zip', '7z', 'tar', 'gz', 'json']);
10
+ // Explicitly enumerate safe image MIME types instead of using the wildcard
11
+ // `image/*` prefix, which would permit `image/svg+xml` and other XSS vectors.
12
+ export const IMAGE_MIME_TYPES = [
13
+ 'image/jpeg',
14
+ 'image/png',
15
+ 'image/gif',
16
+ 'image/webp',
17
+ 'image/avif',
18
+ 'image/bmp',
19
+ 'image/x-icon',
20
+ 'image/vnd.microsoft.icon',
21
+ ];
22
+ // Blocked image MIME types — listed explicitly so upload code can reject them
23
+ // with a clear error rather than a generic "file type not allowed".
24
+ export const BLOCKED_IMAGE_MIME_TYPES = ['image/svg+xml', 'image/svg'];
25
+ export const DOCUMENT_MIME_TYPES = [
26
+ 'application/pdf',
27
+ 'application/msword',
28
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
29
+ 'application/vnd.ms-excel',
30
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
31
+ 'application/vnd.ms-powerpoint',
32
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
33
+ 'text/plain',
34
+ 'text/csv',
35
+ 'text/markdown',
36
+ ];
37
+ export const ARCHIVE_MIME_TYPES = [
38
+ 'application/zip',
39
+ 'application/x-zip-compressed',
40
+ 'application/x-7z-compressed',
41
+ 'application/x-tar',
42
+ 'application/gzip',
43
+ 'application/json',
44
+ ];
45
+ export function extensionFromUrl(url) {
46
+ try {
47
+ const path = new URL(url).pathname;
48
+ const dot = path.lastIndexOf('.');
49
+ if (dot < 0 || dot === path.length - 1)
50
+ return null;
51
+ return path.slice(dot + 1).toLowerCase();
52
+ }
53
+ catch {
54
+ return null;
55
+ }
56
+ }
57
+ export function isExtensionAccepted(ext, accept) {
58
+ if (accept === 'any')
59
+ return true;
60
+ if (ext == null)
61
+ return false;
62
+ if (accept === 'image')
63
+ return IMAGE_EXTENSIONS.has(ext);
64
+ if (accept === 'document')
65
+ return DOCUMENT_EXTENSIONS.has(ext);
66
+ return false;
67
+ }
68
+ export function isMimeAccepted(mime, accept) {
69
+ // Normalise: strip parameters (e.g. "image/jpeg; charset=utf-8" → "image/jpeg")
70
+ const normalised = mime.split(';')[0].trim().toLowerCase();
71
+ // Unconditionally reject SVG regardless of accept mode — SVG can carry
72
+ // embedded scripts and is rendered by browsers when served inline.
73
+ if (BLOCKED_IMAGE_MIME_TYPES.includes(normalised))
74
+ return false;
75
+ if (accept === 'any') {
76
+ return IMAGE_MIME_TYPES.includes(normalised)
77
+ || DOCUMENT_MIME_TYPES.includes(normalised)
78
+ || ARCHIVE_MIME_TYPES.includes(normalised);
79
+ }
80
+ if (accept === 'image')
81
+ return IMAGE_MIME_TYPES.includes(normalised);
82
+ if (accept === 'document')
83
+ return DOCUMENT_MIME_TYPES.includes(normalised);
84
+ return false;
85
+ }
@@ -0,0 +1,29 @@
1
+ import type { ContentRepository } from './content.repository.js';
2
+ import type { Seed } from './types.js';
3
+ export interface HookActor {
4
+ id: string;
5
+ role?: string;
6
+ email?: string;
7
+ }
8
+ export interface HookContext {
9
+ seed: Seed;
10
+ /** Canale lecito per side-effect sui contenuti dagli hook (rispetta la Botanical Engine). */
11
+ repository: ContentRepository;
12
+ /** Utente che esegue l'operazione, estratto dal JWT. Assente per operazioni di sistema/cron. */
13
+ actor?: HookActor;
14
+ /**
15
+ * Escape hatch per la connessione nativa (D1Database in prod, better-sqlite3 nei test).
16
+ * Tipizzato `unknown` per non accoppiare @beechcms/core a Cloudflare. Usare con cautela:
17
+ * scrivere qui bypassa la Botanical Engine.
18
+ */
19
+ db: unknown;
20
+ }
21
+ export interface BeechHooks {
22
+ beforeCreate?: (data: Record<string, any>, ctx: HookContext) => Promise<Record<string, any> | void> | Record<string, any> | void;
23
+ beforeUpdate?: (id: string, patches: Record<string, any>, ctx: HookContext) => Promise<Record<string, any> | void> | Record<string, any> | void;
24
+ beforeDelete?: (id: string, ctx: HookContext) => Promise<void> | void;
25
+ afterCreate?: (entry: Record<string, any>, ctx: HookContext) => Promise<void> | void;
26
+ afterUpdate?: (entry: Record<string, any>, ctx: HookContext) => Promise<void> | void;
27
+ afterDelete?: (id: string, ctx: HookContext) => Promise<void> | void;
28
+ }
29
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAChE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAEtC,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,IAAI,CAAA;IACV,6FAA6F;IAC7F,UAAU,EAAE,iBAAiB,CAAA;IAC7B,gGAAgG;IAChG,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB;;;;OAIG;IACH,EAAE,EAAE,OAAO,CAAA;CACZ;AAED,MAAM,WAAW,UAAU;IAGzB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAA;IAChI,YAAY,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAA;IAC/I,YAAY,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAGrE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACpF,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACpF,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;CACrE"}
package/dist/hooks.js ADDED
@@ -0,0 +1,3 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2024–2026 Flavio De Musso
3
+ export {};
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Identifier abstraction. Hides direct calls to {@link crypto.randomUUID}
3
+ * so callers can swap in deterministic generators during tests for stable
4
+ * snapshot assertions and predictable insert ordering.
5
+ */
6
+ export interface IIdGenerator {
7
+ /**
8
+ * Generates a new universally unique identifier.
9
+ * Production implementation delegates to crypto.randomUUID().
10
+ * Test implementations return deterministic values for snapshot assertions.
11
+ */
12
+ uuid(): string;
13
+ /**
14
+ * Returns true when `value` has the exact shape produced by `uuid()`.
15
+ * The ONLY place in the codebase that knows the id format. Never inline
16
+ * a regex; always go through this method when validating a relation id,
17
+ * a route param, or any user-supplied id.
18
+ */
19
+ isValid(value: unknown): value is string;
20
+ }
21
+ /**
22
+ * Production singleton. Delegates to the host runtime CSPRNG-backed UUID
23
+ * generator. Stateless and therefore safe to share across requests.
24
+ */
25
+ export declare const SystemIdGenerator: IIdGenerator;
26
+ //# sourceMappingURL=id-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id-generator.d.ts","sourceRoot":"","sources":["../src/id-generator.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,IAAI,IAAI,MAAM,CAAA;IAEd;;;;;OAKG;IACH,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAA;CACzC;AAMD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,YAI/B,CAAA"}
@@ -0,0 +1,12 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2024–2026 Flavio De Musso
3
+ // Internal — never exported. Callers depend on the interface, not the shape.
4
+ const SYSTEM_ID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
5
+ /**
6
+ * Production singleton. Delegates to the host runtime CSPRNG-backed UUID
7
+ * generator. Stateless and therefore safe to share across requests.
8
+ */
9
+ export const SystemIdGenerator = {
10
+ uuid: () => crypto.randomUUID(),
11
+ isValid: (value) => typeof value === 'string' && SYSTEM_ID_REGEX.test(value),
12
+ };
@@ -0,0 +1,13 @@
1
+ export interface IdempotencyRecord {
2
+ key: string;
3
+ fingerprint: string;
4
+ responseStatus: number;
5
+ responseBody: string;
6
+ expiresAt: number;
7
+ }
8
+ export interface IdempotencyRepository {
9
+ lookup(key: string): Promise<IdempotencyRecord | null>;
10
+ store(record: IdempotencyRecord): Promise<void>;
11
+ cleanup(now: number): Promise<void>;
12
+ }
13
+ //# sourceMappingURL=idempotency.repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idempotency.repository.d.ts","sourceRoot":"","sources":["../src/idempotency.repository.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAA;IACtD,KAAK,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/C,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACpC"}
@@ -0,0 +1,3 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2024–2026 Flavio De Musso
3
+ export {};
package/dist/index.d.ts CHANGED
@@ -9,19 +9,23 @@
9
9
  */
10
10
  export * from './engine/types.js';
11
11
  export * from './media/file-types.js';
12
- export * from './engine/define-seed.js';
13
- export * from './engine/seeds.js';
12
+ export * from './engine/seeds/define-seed.js';
13
+ export * from './engine/seeds/seeds.js';
14
14
  export * from './engine/engine.js';
15
15
  export * from './engine/validation/index.js';
16
+ export * from './engine/localization/localization.js';
16
17
  export * from './content/richtext/richtext.js';
17
18
  export * from './content/slug-utils.js';
18
19
  export * from './content/content.repository.js';
20
+ export * from './content/deletion-ledger.js';
19
21
  export * from './common/hooks.js';
22
+ export { canonicalStringify } from './common/canonical-json.js';
20
23
  export * from './content/idempotency.repository.js';
21
24
  export * from './media/media.repository.js';
22
25
  export * from './common/storage.js';
23
- export * from './engine/policies.js';
24
- export * from './engine/privacy.service.js';
26
+ export * from './engine/privacy/policies.js';
27
+ export * from './engine/privacy/privacy.service.js';
28
+ export * from './auth/account-email.js';
25
29
  export * from './auth/hash-provider.js';
26
30
  export * from './auth/token-service.js';
27
31
  export * from './auth/user.repository.js';
@@ -34,6 +38,10 @@ export * from './oauth/client.repository.js';
34
38
  export * from './oauth/authorization-code.repository.js';
35
39
  export * from './oauth/token.repository.js';
36
40
  export * from './oauth/consent.repository.js';
41
+ export * from './rbac/permissions.js';
42
+ export * from './rbac/types.js';
43
+ export * from './rbac/evaluate.js';
44
+ export * from './rbac/invitation.repository.js';
37
45
  export * from './rate-limit/rate-limiter.js';
38
46
  export * from './observability/activity-logger.js';
39
47
  export * from './observability/activity-log.repository.js';
@@ -47,7 +55,11 @@ export * from './search/vector.repository.js';
47
55
  export * from './content/content-scan.repository.js';
48
56
  export * from './common/clock.js';
49
57
  export * from './common/id-generator.js';
50
- export * from './engine/seed-registry.js';
58
+ export * from './engine/seeds/seed-registry.js';
59
+ export * from './engine/seeds/candidate-ids.js';
60
+ export * from './engine/introspection/introspection.js';
61
+ export * from './engine/introspection/relation-audit.js';
62
+ export * from './engine/introspection/schema-fingerprint.js';
51
63
  export * from './automations/automations.types.js';
52
64
  export * from './automations/automations-grammar-words.js';
53
65
  export * from './automations/automations.runner.interface.js';
@@ -56,8 +68,9 @@ export * from './queue/scheduler.interface.js';
56
68
  export * from './queue/scheduler.stub.js';
57
69
  export * from './queue/queue.interface.js';
58
70
  export * from './queue/queue.stub.js';
71
+ export * from './transfer/index.js';
59
72
  export * from './webhooks/webhook-validation.js';
60
- export * from './engine/relations.js';
73
+ export * from './engine/query/relations.js';
61
74
  export * from './settings/site-settings.repository.js';
62
75
  export * from './content/demo-data.repository.js';
63
76
  export * from './dashboard-layout/seed-layout.js';
@@ -68,16 +81,26 @@ export * from './dashboard-layout/dashboard-scopes.js';
68
81
  export * from './dashboard-layout/dashboard-permissions.js';
69
82
  export * from './dashboard-layout/dashboard-layout.repository.js';
70
83
  export * from './content/seed.repository.js';
71
- export * from './engine/seed-validation.js';
72
- export * from './engine/seed-ddl.js';
73
- export * from './engine/schema-mutator.js';
74
- export * from './engine/seed-types-generator.js';
84
+ export * from './content/seed-media-purge.repository.js';
85
+ export * from './engine/seeds/seed-validation.js';
86
+ export * from './engine/seeds/tag-options.js';
87
+ export * from './engine/seeds/tag-migration.js';
88
+ export * from './engine/seeds/tag-value.js';
89
+ export * from './engine/seeds/seed-definition-diff.js';
90
+ export { SQL_RESERVED_WORDS } from './engine/sql-reserved-words.js';
91
+ export * from './engine/ddl/seed-ddl.js';
92
+ export * from './engine/ddl/schema-mutator.js';
93
+ export * from './engine/ddl/seed-purge-guards.js';
94
+ export * from './engine/seeds/seed-types-generator.js';
75
95
  export * from './webhooks/webhook-crypto.js';
76
96
  export * from './dashboard-layout/kanban/kanban.js';
77
97
  export * from './dashboard-layout/view-authorization.js';
78
- export * from './dashboard-layout/kanban/kanban-position.repository.js';
98
+ export * from './dashboard-layout/content-view.js';
99
+ export * from './dashboard-layout/content-view.repository.js';
79
100
  export * from './common/email.provider.js';
80
101
  export * from './media/magic-bytes.js';
102
+ export * from './media/image-transformer.js';
103
+ export * from './media/media-transform.js';
81
104
  export * from './security/time-trap.js';
82
105
  export * from './antivirus/antivirus.interface.js';
83
106
  export * from './antivirus/virustotal-antivirus.provider.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AAEH,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,gCAAgC,CAAA;AAE9C,cAAc,yBAAyB,CAAA;AACvC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,mBAAmB,CAAA;AACjC,cAAc,qCAAqC,CAAA;AACnD,cAAc,6BAA6B,CAAA;AAC3C,cAAc,qBAAqB,CAAA;AACnC,cAAc,sBAAsB,CAAA;AACpC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,yBAAyB,CAAA;AACvC,cAAc,yBAAyB,CAAA;AACvC,cAAc,2BAA2B,CAAA;AACzC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,2CAA2C,CAAA;AACzD,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,0CAA0C,CAAA;AACxD,cAAc,6BAA6B,CAAA;AAC3C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,oCAAoC,CAAA;AAClD,cAAc,4CAA4C,CAAA;AAC1D,cAAc,yCAAyC,CAAA;AACvD,cAAc,4CAA4C,CAAA;AAC1D,cAAc,yCAAyC,CAAA;AACvD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,sCAAsC,CAAA;AACpD,cAAc,mBAAmB,CAAA;AACjC,cAAc,0BAA0B,CAAA;AACxC,cAAc,2BAA2B,CAAA;AACzC,cAAc,oCAAoC,CAAA;AAClD,cAAc,4CAA4C,CAAA;AAC1D,cAAc,+CAA+C,CAAA;AAC7D,cAAc,mDAAmD,CAAA;AACjE,cAAc,gCAAgC,CAAA;AAC9C,cAAc,2BAA2B,CAAA;AACzC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,uBAAuB,CAAA;AACrC,cAAc,kCAAkC,CAAA;AAChD,cAAc,uBAAuB,CAAA;AACrC,cAAc,wCAAwC,CAAA;AACtD,cAAc,mCAAmC,CAAA;AACjD,cAAc,mCAAmC,CAAA;AACjD,cAAc,8CAA8C,CAAA;AAC5D,cAAc,0CAA0C,CAAA;AACxD,cAAc,wCAAwC,CAAA;AACtD,cAAc,wCAAwC,CAAA;AACtD,cAAc,6CAA6C,CAAA;AAC3D,cAAc,mDAAmD,CAAA;AACjE,cAAc,8BAA8B,CAAA;AAC5C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,sBAAsB,CAAA;AACpC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,kCAAkC,CAAA;AAChD,cAAc,8BAA8B,CAAA;AAC5C,cAAc,qCAAqC,CAAA;AACnD,cAAc,0CAA0C,CAAA;AACxD,cAAc,yDAAyD,CAAA;AACvE,cAAc,4BAA4B,CAAA;AAC1C,cAAc,wBAAwB,CAAA;AACtC,cAAc,yBAAyB,CAAA;AACvC,cAAc,oCAAoC,CAAA;AAClD,cAAc,8CAA8C,CAAA;AAC5D,cAAc,wCAAwC,CAAA;AACtD,cAAc,2CAA2C,CAAA;AACzD,cAAc,0CAA0C,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AAEH,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,yBAAyB,CAAA;AACvC,cAAc,oBAAoB,CAAA;AAClC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,uCAAuC,CAAA;AACrD,cAAc,gCAAgC,CAAA;AAE9C,cAAc,yBAAyB,CAAA;AACvC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,mBAAmB,CAAA;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAC/D,cAAc,qCAAqC,CAAA;AACnD,cAAc,6BAA6B,CAAA;AAC3C,cAAc,qBAAqB,CAAA;AACnC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,qCAAqC,CAAA;AACnD,cAAc,yBAAyB,CAAA;AACvC,cAAc,yBAAyB,CAAA;AACvC,cAAc,yBAAyB,CAAA;AACvC,cAAc,2BAA2B,CAAA;AACzC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,2CAA2C,CAAA;AACzD,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,0CAA0C,CAAA;AACxD,cAAc,6BAA6B,CAAA;AAC3C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,uBAAuB,CAAA;AACrC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,oCAAoC,CAAA;AAClD,cAAc,4CAA4C,CAAA;AAC1D,cAAc,yCAAyC,CAAA;AACvD,cAAc,4CAA4C,CAAA;AAC1D,cAAc,yCAAyC,CAAA;AACvD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,sCAAsC,CAAA;AACpD,cAAc,mBAAmB,CAAA;AACjC,cAAc,0BAA0B,CAAA;AACxC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,yCAAyC,CAAA;AACvD,cAAc,0CAA0C,CAAA;AACxD,cAAc,8CAA8C,CAAA;AAC5D,cAAc,oCAAoC,CAAA;AAClD,cAAc,4CAA4C,CAAA;AAC1D,cAAc,+CAA+C,CAAA;AAC7D,cAAc,mDAAmD,CAAA;AACjE,cAAc,gCAAgC,CAAA;AAC9C,cAAc,2BAA2B,CAAA;AACzC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,kCAAkC,CAAA;AAChD,cAAc,6BAA6B,CAAA;AAC3C,cAAc,wCAAwC,CAAA;AACtD,cAAc,mCAAmC,CAAA;AACjD,cAAc,mCAAmC,CAAA;AACjD,cAAc,8CAA8C,CAAA;AAC5D,cAAc,0CAA0C,CAAA;AACxD,cAAc,wCAAwC,CAAA;AACtD,cAAc,wCAAwC,CAAA;AACtD,cAAc,6CAA6C,CAAA;AAC3D,cAAc,mDAAmD,CAAA;AACjE,cAAc,8BAA8B,CAAA;AAC5C,cAAc,0CAA0C,CAAA;AACxD,cAAc,mCAAmC,CAAA;AACjD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,wCAAwC,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AACnE,cAAc,0BAA0B,CAAA;AACxC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,mCAAmC,CAAA;AACjD,cAAc,wCAAwC,CAAA;AACtD,cAAc,8BAA8B,CAAA;AAC5C,cAAc,qCAAqC,CAAA;AACnD,cAAc,0CAA0C,CAAA;AACxD,cAAc,oCAAoC,CAAA;AAClD,cAAc,+CAA+C,CAAA;AAC7D,cAAc,4BAA4B,CAAA;AAC1C,cAAc,wBAAwB,CAAA;AACtC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,yBAAyB,CAAA;AACvC,cAAc,oCAAoC,CAAA;AAClD,cAAc,8CAA8C,CAAA;AAC5D,cAAc,wCAAwC,CAAA;AACtD,cAAc,2CAA2C,CAAA;AACzD,cAAc,0CAA0C,CAAA"}
package/dist/index.js CHANGED
@@ -11,19 +11,23 @@
11
11
  */
12
12
  export * from './engine/types.js';
13
13
  export * from './media/file-types.js';
14
- export * from './engine/define-seed.js';
15
- export * from './engine/seeds.js';
14
+ export * from './engine/seeds/define-seed.js';
15
+ export * from './engine/seeds/seeds.js';
16
16
  export * from './engine/engine.js';
17
17
  export * from './engine/validation/index.js';
18
+ export * from './engine/localization/localization.js';
18
19
  export * from './content/richtext/richtext.js';
19
20
  export * from './content/slug-utils.js';
20
21
  export * from './content/content.repository.js';
22
+ export * from './content/deletion-ledger.js';
21
23
  export * from './common/hooks.js';
24
+ export { canonicalStringify } from './common/canonical-json.js';
22
25
  export * from './content/idempotency.repository.js';
23
26
  export * from './media/media.repository.js';
24
27
  export * from './common/storage.js';
25
- export * from './engine/policies.js';
26
- export * from './engine/privacy.service.js';
28
+ export * from './engine/privacy/policies.js';
29
+ export * from './engine/privacy/privacy.service.js';
30
+ export * from './auth/account-email.js';
27
31
  export * from './auth/hash-provider.js';
28
32
  export * from './auth/token-service.js';
29
33
  export * from './auth/user.repository.js';
@@ -36,6 +40,10 @@ export * from './oauth/client.repository.js';
36
40
  export * from './oauth/authorization-code.repository.js';
37
41
  export * from './oauth/token.repository.js';
38
42
  export * from './oauth/consent.repository.js';
43
+ export * from './rbac/permissions.js';
44
+ export * from './rbac/types.js';
45
+ export * from './rbac/evaluate.js';
46
+ export * from './rbac/invitation.repository.js';
39
47
  export * from './rate-limit/rate-limiter.js';
40
48
  export * from './observability/activity-logger.js';
41
49
  export * from './observability/activity-log.repository.js';
@@ -49,7 +57,11 @@ export * from './search/vector.repository.js';
49
57
  export * from './content/content-scan.repository.js';
50
58
  export * from './common/clock.js';
51
59
  export * from './common/id-generator.js';
52
- export * from './engine/seed-registry.js';
60
+ export * from './engine/seeds/seed-registry.js';
61
+ export * from './engine/seeds/candidate-ids.js';
62
+ export * from './engine/introspection/introspection.js';
63
+ export * from './engine/introspection/relation-audit.js';
64
+ export * from './engine/introspection/schema-fingerprint.js';
53
65
  export * from './automations/automations.types.js';
54
66
  export * from './automations/automations-grammar-words.js';
55
67
  export * from './automations/automations.runner.interface.js';
@@ -58,8 +70,9 @@ export * from './queue/scheduler.interface.js';
58
70
  export * from './queue/scheduler.stub.js';
59
71
  export * from './queue/queue.interface.js';
60
72
  export * from './queue/queue.stub.js';
73
+ export * from './transfer/index.js';
61
74
  export * from './webhooks/webhook-validation.js';
62
- export * from './engine/relations.js';
75
+ export * from './engine/query/relations.js';
63
76
  export * from './settings/site-settings.repository.js';
64
77
  export * from './content/demo-data.repository.js';
65
78
  export * from './dashboard-layout/seed-layout.js';
@@ -70,16 +83,26 @@ export * from './dashboard-layout/dashboard-scopes.js';
70
83
  export * from './dashboard-layout/dashboard-permissions.js';
71
84
  export * from './dashboard-layout/dashboard-layout.repository.js';
72
85
  export * from './content/seed.repository.js';
73
- export * from './engine/seed-validation.js';
74
- export * from './engine/seed-ddl.js';
75
- export * from './engine/schema-mutator.js';
76
- export * from './engine/seed-types-generator.js';
86
+ export * from './content/seed-media-purge.repository.js';
87
+ export * from './engine/seeds/seed-validation.js';
88
+ export * from './engine/seeds/tag-options.js';
89
+ export * from './engine/seeds/tag-migration.js';
90
+ export * from './engine/seeds/tag-value.js';
91
+ export * from './engine/seeds/seed-definition-diff.js';
92
+ export { SQL_RESERVED_WORDS } from './engine/sql-reserved-words.js';
93
+ export * from './engine/ddl/seed-ddl.js';
94
+ export * from './engine/ddl/schema-mutator.js';
95
+ export * from './engine/ddl/seed-purge-guards.js';
96
+ export * from './engine/seeds/seed-types-generator.js';
77
97
  export * from './webhooks/webhook-crypto.js';
78
98
  export * from './dashboard-layout/kanban/kanban.js';
79
99
  export * from './dashboard-layout/view-authorization.js';
80
- export * from './dashboard-layout/kanban/kanban-position.repository.js';
100
+ export * from './dashboard-layout/content-view.js';
101
+ export * from './dashboard-layout/content-view.repository.js';
81
102
  export * from './common/email.provider.js';
82
103
  export * from './media/magic-bytes.js';
104
+ export * from './media/image-transformer.js';
105
+ export * from './media/media-transform.js';
83
106
  export * from './security/time-trap.js';
84
107
  export * from './antivirus/antivirus.interface.js';
85
108
  export * from './antivirus/virustotal-antivirus.provider.js';
@@ -0,0 +1,19 @@
1
+ export interface KanbanPositionRecord {
2
+ entryId: string;
3
+ position: string;
4
+ }
5
+ /**
6
+ * Persistence contract for card ordering. The ONLY gateway to `kanban_positions`.
7
+ * Handlers and the dashboard never touch the table directly (Botanical invariant).
8
+ */
9
+ export interface IKanbanPositionRepository {
10
+ /** entryId → position for one column axis (entries without a row are omitted). */
11
+ getColumn(seedSlug: string, axisBranchId: string): Promise<Map<string, string>>;
12
+ /** Single-row upsert — exactly one write per drag (KB-S04b). */
13
+ setPosition(seedSlug: string, entryId: string, axisBranchId: string, position: string): Promise<void>;
14
+ /** Remove an entry's position row (e.g. entry deleted). */
15
+ remove(seedSlug: string, entryId: string, axisBranchId: string): Promise<void>;
16
+ /** Async rebalance (KB-S04f): rewrite a whole column's positions in one batch. */
17
+ rebalance(seedSlug: string, axisBranchId: string, ordered: KanbanPositionRecord[]): Promise<void>;
18
+ }
19
+ //# sourceMappingURL=kanban-position.repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kanban-position.repository.d.ts","sourceRoot":"","sources":["../src/kanban-position.repository.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC,kFAAkF;IAClF,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAC/E,gEAAgE;IAChE,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACrG,2DAA2D;IAC3D,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9E,kFAAkF;IAClF,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAClG"}
@@ -0,0 +1,3 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2024–2026 Flavio De Musso
3
+ export {};
@@ -0,0 +1,75 @@
1
+ import type { Seed, Branch, FilterGroup } from './types.js';
2
+ /** Branch types that can form a discrete, finite set of columns (KB §2). */
3
+ export type KanbanAxisBranchType = 'text' | 'tags' | 'boolean';
4
+ /** A branch eligible to be the kanban axis. */
5
+ export interface KanbanAxisCandidate {
6
+ /** Stable branch id (br_XX) — persisted as the axis key. Never the alias. */
7
+ branchId: string;
8
+ alias: string;
9
+ label: string;
10
+ type: KanbanAxisBranchType;
11
+ }
12
+ /** A single column on the board, in deterministic display order (Q2). */
13
+ export interface KanbanColumnDescriptor {
14
+ /** The discrete axis value. `null` ⇒ the always-last "Senza valore" column. */
15
+ value: string | null;
16
+ label: string;
17
+ }
18
+ /** Per-seed, dashboard-side kanban view preferences. Persisted in
19
+ * seed_layouts.view_config (KB-S02). NOT part of FormLayout. */
20
+ export interface KanbanConfig {
21
+ /** Chosen axis branch id, or null when the user has not configured one (KB-U02). */
22
+ axisBranchId: string | null;
23
+ /** Card sort inside columns. null ⇒ manual order via kanban_positions (KB-U22b). */
24
+ sort: {
25
+ branchId: string;
26
+ dir: 'ASC' | 'DESC';
27
+ } | null;
28
+ /** Axis values the user chose to hide when columns exceed the cap (KB-U06c). */
29
+ hiddenColumnValues?: string[];
30
+ }
31
+ export type KanbanIncompatibleReason = 'drafts-enabled' | 'no-candidate-branch';
32
+ export interface KanbanCompatibility {
33
+ compatible: boolean;
34
+ reason?: KanbanIncompatibleReason;
35
+ candidates: KanbanAxisCandidate[];
36
+ }
37
+ /**
38
+ * Determines whether a seed can be displayed as a Kanban board, and which
39
+ * branches may serve as the column axis. Pure — no I/O. (KB-S01)
40
+ *
41
+ * Q3: seeds with `allowDrafts: true` are NOT kanban-compatible.
42
+ */
43
+ export declare function resolveKanbanConfig(seed: Seed): KanbanCompatibility;
44
+ /**
45
+ * Deterministic, stable column order for a chosen axis (Q2). The "Senza valore"
46
+ * (value: null) column is always appended last. Values out of `options` are NOT
47
+ * given their own column (KB-U25) — the board folds them into "Senza valore".
48
+ *
49
+ * @param distinctTagValues unique tag values observed in data (tags axis without options).
50
+ */
51
+ export declare function resolveKanbanColumns(branch: Branch, distinctTagValues?: string[]): KanbanColumnDescriptor[];
52
+ /**
53
+ * Pure: the FilterGroup selecting one kanban column's entries for a given axis branch.
54
+ * `value: null` ⇒ "Senza valore" — entries where the axis field is NULL or empty (KB-U25).
55
+ * Boolean descriptor values 'true'/'false' are coerced to actual booleans for the engine.
56
+ */
57
+ /** Body of PATCH /:slug/:id/kanban-move. The server applies the axis change (if any)
58
+ * AND the position upsert atomically (KB-S04e). */
59
+ export interface KanbanMoveBody {
60
+ /** Axis branch id (br_XX). Identifies which kanban_positions row + which branch to patch. */
61
+ axisBranchId: string;
62
+ /** New fractional-index key for this entry in the destination column (KB-S04b/d). */
63
+ position: string;
64
+ /** Present only on a cross-column move (axis value changed). Omit for same-column reorder. */
65
+ axis?: {
66
+ kind: 'scalar';
67
+ value: string | null;
68
+ } | {
69
+ kind: 'tags';
70
+ oldValue: string | null;
71
+ newValue: string | null;
72
+ };
73
+ }
74
+ export declare function kanbanColumnFilter(branch: Branch, value: string | null): FilterGroup;
75
+ //# sourceMappingURL=kanban.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kanban.d.ts","sourceRoot":"","sources":["../src/kanban.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE3D,4EAA4E;AAC5E,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;AAE9D,+CAA+C;AAC/C,MAAM,WAAW,mBAAmB;IAClC,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,oBAAoB,CAAA;CAC3B;AAED,yEAAyE;AACzE,MAAM,WAAW,sBAAsB;IACrC,+EAA+E;IAC/E,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;CACd;AAED;iEACiE;AACjE,MAAM,WAAW,YAAY;IAC3B,oFAAoF;IACpF,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,oFAAoF;IACpF,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,KAAK,GAAG,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IACtD,gFAAgF;IAChF,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC9B;AAED,MAAM,MAAM,wBAAwB,GAAG,gBAAgB,GAAG,qBAAqB,CAAA;AAE/E,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,OAAO,CAAA;IACnB,MAAM,CAAC,EAAE,wBAAwB,CAAA;IACjC,UAAU,EAAE,mBAAmB,EAAE,CAAA;CAClC;AAgBD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,GAAG,mBAAmB,CAanE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,iBAAiB,GAAE,MAAM,EAAO,GAC/B,sBAAsB,EAAE,CAiB1B;AAED;;;;GAIG;AACH;oDACoD;AACpD,MAAM,WAAW,cAAc;IAC7B,6FAA6F;IAC7F,YAAY,EAAE,MAAM,CAAA;IACpB,qFAAqF;IACrF,QAAQ,EAAE,MAAM,CAAA;IAChB,8FAA8F;IAC9F,IAAI,CAAC,EACD;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GACxC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CACvE;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,WAAW,CAYpF"}
package/dist/kanban.js ADDED
@@ -0,0 +1,82 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2024–2026 Flavio De Musso
3
+ /** Branch types that are explicitly never an axis (KB §2). */
4
+ const NON_AXIS_TYPES = new Set([
5
+ 'richtext', 'file', 'number', 'date', 'json', 'relation', 'repeater',
6
+ ]);
7
+ function isAxisCandidate(b) {
8
+ if (b.alias === 'status')
9
+ return null; // system status excluded (KB §2)
10
+ if (NON_AXIS_TYPES.has(b.type))
11
+ return null;
12
+ if (b.type === 'text')
13
+ return (b.options && b.options.length > 0) ? 'text' : null;
14
+ if (b.type === 'tags')
15
+ return 'tags';
16
+ if (b.type === 'boolean')
17
+ return 'boolean';
18
+ return null;
19
+ }
20
+ /**
21
+ * Determines whether a seed can be displayed as a Kanban board, and which
22
+ * branches may serve as the column axis. Pure — no I/O. (KB-S01)
23
+ *
24
+ * Q3: seeds with `allowDrafts: true` are NOT kanban-compatible.
25
+ */
26
+ export function resolveKanbanConfig(seed) {
27
+ if (seed.allowDrafts) {
28
+ return { compatible: false, reason: 'drafts-enabled', candidates: [] };
29
+ }
30
+ const candidates = [];
31
+ for (const b of seed.branches) {
32
+ const type = isAxisCandidate(b);
33
+ if (type)
34
+ candidates.push({ branchId: b.id, alias: b.alias, label: b.label, type });
35
+ }
36
+ if (candidates.length === 0) {
37
+ return { compatible: false, reason: 'no-candidate-branch', candidates: [] };
38
+ }
39
+ return { compatible: true, candidates };
40
+ }
41
+ /**
42
+ * Deterministic, stable column order for a chosen axis (Q2). The "Senza valore"
43
+ * (value: null) column is always appended last. Values out of `options` are NOT
44
+ * given their own column (KB-U25) — the board folds them into "Senza valore".
45
+ *
46
+ * @param distinctTagValues unique tag values observed in data (tags axis without options).
47
+ */
48
+ export function resolveKanbanColumns(branch, distinctTagValues = []) {
49
+ const cols = [];
50
+ if (branch.type === 'boolean') {
51
+ cols.push({ value: 'false', label: 'No' }, { value: 'true', label: 'Sì' }); // [false, true]
52
+ }
53
+ else if (branch.type === 'text' && branch.options?.length) {
54
+ for (const o of branch.options)
55
+ cols.push({ value: o, label: o }); // options order
56
+ }
57
+ else if (branch.type === 'tags') {
58
+ const ordered = branch.options?.length
59
+ ? branch.options
60
+ : [...distinctTagValues].sort((a, b) => a.localeCompare(b)); // alphabetical
61
+ for (const o of ordered)
62
+ cols.push({ value: o, label: o });
63
+ }
64
+ const isRequired = Boolean(branch.requiredOnCreate || branch.requiredOnUpdate);
65
+ if (!isRequired) {
66
+ cols.push({ value: null, label: `Senza ${branch.label}` }); // always last if not required
67
+ }
68
+ return cols;
69
+ }
70
+ export function kanbanColumnFilter(branch, value) {
71
+ if (value === null) {
72
+ const type = branch.type === 'boolean' ? 'boolean' : branch.type === 'tags' ? 'tags' : 'text';
73
+ return { column: branch.alias, type, conditions: [{ op: 'is_empty', value: null }] };
74
+ }
75
+ if (branch.type === 'boolean') {
76
+ return { column: branch.alias, type: 'boolean', conditions: [{ op: 'eq', value: value === 'true' }] };
77
+ }
78
+ if (branch.type === 'tags') {
79
+ return { column: branch.alias, type: 'tags', conditions: [{ op: 'has_tag', value }] };
80
+ }
81
+ return { column: branch.alias, type: 'select', conditions: [{ op: 'eq', value }] };
82
+ }
@@ -0,0 +1,3 @@
1
+ export declare const ROLES_ALLOWED_TO_EDIT_LAYOUT: ReadonlyArray<string>;
2
+ export declare function canEditLayout(role: string | undefined | null): boolean;
3
+ //# sourceMappingURL=layout-permissions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout-permissions.d.ts","sourceRoot":"","sources":["../src/layout-permissions.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,4BAA4B,EAAE,aAAa,CAAC,MAAM,CAAa,CAAA;AAE5E,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAGtE"}
@@ -0,0 +1,11 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2024–2026 Flavio De Musso
3
+ // NOTE: change this list to extend write-access to other roles
4
+ // (e.g. add 'editor', or introduce a fine-grained 'layout:edit' permission).
5
+ // Single source of truth — used by both API guards and dashboard buttons.
6
+ export const ROLES_ALLOWED_TO_EDIT_LAYOUT = ['admin'];
7
+ export function canEditLayout(role) {
8
+ if (!role)
9
+ return false;
10
+ return ROLES_ALLOWED_TO_EDIT_LAYOUT.includes(role);
11
+ }