@beechcms/api 0.6.0-preview.2 → 0.6.0-preview.4

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 (388) hide show
  1. package/README.md +4 -4
  2. package/assets/dashboard/BeechLogo.svg +18 -18
  3. package/assets/dashboard/BeechLogoLIght.svg +48 -48
  4. package/assets/dashboard/assets/chart-BwlCt-IA.js +39 -0
  5. package/assets/dashboard/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  6. package/assets/dashboard/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  7. package/assets/dashboard/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  8. package/assets/dashboard/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  9. package/assets/dashboard/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  10. package/assets/dashboard/assets/index-BcVN-DNy.js +642 -0
  11. package/assets/dashboard/assets/index-Cf1yRCqG.css +1 -0
  12. package/assets/dashboard/assets/lora-cyrillic-ext-wght-normal-YcVxMP-u.woff2 +0 -0
  13. package/assets/dashboard/assets/lora-cyrillic-wght-normal-UWPuZLjM.woff2 +0 -0
  14. package/assets/dashboard/assets/lora-latin-ext-wght-normal-C2Wlntb9.woff2 +0 -0
  15. package/assets/dashboard/assets/lora-latin-wght-normal-BiLcIKcI.woff2 +0 -0
  16. package/assets/dashboard/assets/lora-math-wght-normal-sOy7rEfW.woff2 +0 -0
  17. package/assets/dashboard/assets/lora-symbols-wght-normal-DQ5VrUkH.woff2 +0 -0
  18. package/assets/dashboard/assets/lora-vietnamese-wght-normal-CfJ7gtf3.woff2 +0 -0
  19. package/assets/dashboard/assets/pie-chart-recharts-BMWpjFzf.js +1 -0
  20. package/assets/dashboard/assets/timeseries-chart-recharts-8_GwAFR0.js +1 -0
  21. package/assets/dashboard/beechLogoDark.svg +48 -48
  22. package/assets/dashboard/index.html +18 -18
  23. package/assets/dashboard/noResult.svg +42 -42
  24. package/assets/dashboard/sol.svg +3 -3
  25. package/assets/dashboard/undraw_enter_nwx3.svg +36 -36
  26. package/dist/auth/__fixtures__/in-memory-hash-provider.d.ts +5 -0
  27. package/dist/auth/__fixtures__/static-token-service.d.ts +6 -0
  28. package/dist/auth/bcrypt-hash-provider.d.ts +8 -0
  29. package/dist/auth/constants.d.ts +10 -0
  30. package/dist/auth/jose-token-service.d.ts +14 -0
  31. package/dist/auth/login.d.ts +32 -0
  32. package/dist/auth/refresh.d.ts +1 -0
  33. package/dist/factory.d.ts +45 -0
  34. package/dist/features/automations/action-executors/create-entry.executor.d.ts +7 -0
  35. package/dist/features/automations/action-executors/edit-field.executor.d.ts +7 -0
  36. package/dist/features/automations/action-executors/index.d.ts +13 -0
  37. package/dist/features/automations/action-executors/send-mail.executor.d.ts +7 -0
  38. package/dist/features/automations/action-executors/set-variable.executor.d.ts +15 -0
  39. package/dist/features/automations/action-executors/webhook.executor.d.ts +7 -0
  40. package/dist/features/automations/automation-runner.d.ts +13 -0
  41. package/dist/features/automations/automation-runner.utils.d.ts +3 -0
  42. package/dist/features/automations/automations.handler.d.ts +7 -0
  43. package/dist/features/automations/automations.schema.d.ts +191 -0
  44. package/dist/features/automations/context-resolver.d.ts +8 -0
  45. package/dist/features/automations/cron-runner.d.ts +9 -0
  46. package/dist/features/automations/cron-runner.utils.d.ts +1 -0
  47. package/dist/features/automations/filter-translation.d.ts +9 -0
  48. package/dist/features/automations/index.d.ts +7 -0
  49. package/dist/features/automations/template-grammar.d.ts +73 -0
  50. package/dist/features/automations/var-access-resolver.d.ts +6 -0
  51. package/dist/features/automations/when-evaluator.d.ts +3 -0
  52. package/dist/features/automations/when-pushdown.d.ts +2 -0
  53. package/dist/features/backrefs/backrefs.handler.d.ts +3 -0
  54. package/dist/features/backrefs/d1-backref.repository.d.ts +17 -0
  55. package/dist/features/backrefs/index.d.ts +1 -0
  56. package/dist/features/content/constants.d.ts +12 -0
  57. package/dist/features/content/handlers/bulk.handler.d.ts +3 -0
  58. package/dist/features/content/handlers/create.d.ts +3 -0
  59. package/dist/features/content/handlers/delete.d.ts +3 -0
  60. package/dist/features/content/handlers/facets.d.ts +3 -0
  61. package/dist/features/content/handlers/get.d.ts +4 -0
  62. package/dist/features/content/handlers/helpers.d.ts +12 -0
  63. package/dist/features/content/handlers/list.d.ts +3 -0
  64. package/dist/features/content/handlers/update.d.ts +3 -0
  65. package/dist/features/content/index.d.ts +4 -0
  66. package/dist/features/dashboard-layout/dashboard-layout.handler.d.ts +7 -0
  67. package/dist/features/dashboard-layout/index.d.ts +1 -0
  68. package/dist/features/draft/draft.handler.d.ts +4 -0
  69. package/dist/features/draft/draft.middleware.d.ts +9 -0
  70. package/dist/features/draft/index.d.ts +1 -0
  71. package/{src/features/email/email.provider.ts → dist/features/email/email.provider.d.ts} +19 -24
  72. package/dist/features/email/email.service.d.ts +13 -0
  73. package/dist/features/email/email.types.d.ts +94 -0
  74. package/{src/features/email/index.ts → dist/features/email/index.d.ts} +3 -16
  75. package/dist/features/email/providers/resend.d.ts +36 -0
  76. package/dist/features/email/providers/smtp.d.ts +11 -0
  77. package/dist/features/email/templates/automation-mail.d.ts +8 -0
  78. package/dist/features/email/templates/password-changed.d.ts +15 -0
  79. package/dist/features/email/templates/password-reset.d.ts +18 -0
  80. package/dist/features/email/templates/shell.d.ts +58 -0
  81. package/dist/features/notifications/index.d.ts +1 -0
  82. package/dist/features/notifications/notifications.handler.d.ts +15 -0
  83. package/dist/features/password-reset/index.d.ts +6 -0
  84. package/dist/features/password-reset/request.d.ts +10 -0
  85. package/dist/features/password-reset/reset.d.ts +9 -0
  86. package/dist/features/rotate-field/index.d.ts +1 -0
  87. package/dist/features/rotate-field/rotate-field.handler.d.ts +7 -0
  88. package/dist/features/rotate-field/rotate-field.schema.d.ts +11 -0
  89. package/dist/features/schema/schema.handler.d.ts +7 -0
  90. package/dist/features/seeds/index.d.ts +1 -0
  91. package/dist/features/seeds/seeds.handler.d.ts +6 -0
  92. package/dist/features/settings/settings.handler.d.ts +7 -0
  93. package/dist/features/setup/index.d.ts +7 -0
  94. package/dist/features/stats/index.d.ts +1 -0
  95. package/dist/features/stats/stats.handler.d.ts +7 -0
  96. package/dist/features/webhooks/index.d.ts +3 -0
  97. package/dist/index.d.ts +7 -0
  98. package/dist/index.js +9732 -0
  99. package/dist/media-utils.d.ts +25 -0
  100. package/dist/middleware/auth-providers.middleware.d.ts +8 -0
  101. package/dist/middleware/observability.middleware.d.ts +20 -0
  102. package/dist/middleware/queue.middleware.d.ts +11 -0
  103. package/dist/middleware/rate-limit.middleware.d.ts +9 -0
  104. package/dist/middleware/repository.middleware.d.ts +34 -0
  105. package/dist/middleware/seed-registry.middleware.d.ts +10 -0
  106. package/dist/middleware/storage.middleware.d.ts +7 -0
  107. package/dist/middleware.d.ts +11 -0
  108. package/dist/public/access-policy.d.ts +12 -0
  109. package/dist/public/api-key-middleware.d.ts +6 -0
  110. package/dist/public/cache-utils.d.ts +10 -0
  111. package/dist/public/entry-projection.d.ts +2 -0
  112. package/dist/public/idempotency.d.ts +9 -0
  113. package/dist/public/index.d.ts +11 -0
  114. package/dist/public/problem-details.d.ts +31 -0
  115. package/dist/public/public-add.d.ts +3 -0
  116. package/dist/public/public-edit.d.ts +5 -0
  117. package/dist/public/public-errors.d.ts +13 -0
  118. package/dist/public/public-read.d.ts +3 -0
  119. package/dist/public/public-routes.d.ts +3 -0
  120. package/dist/public/query-builder.d.ts +28 -0
  121. package/dist/public/rate-limit-middleware.d.ts +3 -0
  122. package/dist/public/read-list.d.ts +26 -0
  123. package/dist/public/read-single.d.ts +22 -0
  124. package/dist/public/response-builder.d.ts +22 -0
  125. package/dist/public/sanitize.d.ts +23 -0
  126. package/{src/public/slug-utils.ts → dist/public/slug-utils.d.ts} +3 -10
  127. package/dist/rate-limit/cloudflare-rate-limiter.d.ts +6 -0
  128. package/dist/rate-limit/in-memory-rate-limiter.d.ts +7 -0
  129. package/dist/rate-limit/no-op-rate-limiter.d.ts +4 -0
  130. package/dist/search-utils.d.ts +54 -0
  131. package/dist/search.d.ts +6 -0
  132. package/dist/shared/apply-policies.d.ts +10 -0
  133. package/dist/shared/automations.repository.d1.d.ts +12 -0
  134. package/dist/shared/background-notification-service.d.ts +18 -0
  135. package/dist/shared/base.repository.d1.d.ts +18 -0
  136. package/dist/shared/cloudflare-queue-service.d.ts +11 -0
  137. package/dist/shared/content-utils.d.ts +21 -0
  138. package/dist/shared/content.repository.d1.d.ts +68 -0
  139. package/dist/shared/d1-activity-log.repository.d.ts +13 -0
  140. package/dist/shared/d1-activity-logger.d.ts +20 -0
  141. package/dist/shared/d1-analytics.repository.d.ts +20 -0
  142. package/dist/shared/d1-content-scan.repository.d.ts +7 -0
  143. package/dist/shared/d1-notification.repository.d.ts +17 -0
  144. package/dist/shared/d1-password-reset-token.repository.d.ts +10 -0
  145. package/dist/shared/d1-search.repository.d.ts +14 -0
  146. package/dist/shared/d1-session.repository.d.ts +12 -0
  147. package/dist/shared/d1-setup-checklist.repository.d.ts +12 -0
  148. package/dist/shared/d1-user.repository.d.ts +18 -0
  149. package/dist/shared/d1-widget.repository.d.ts +31 -0
  150. package/dist/shared/dashboard-layout.repository.d1.d.ts +9 -0
  151. package/dist/shared/demo-data-sql.d.ts +1 -0
  152. package/dist/shared/demo-data.repository.d1.d.ts +6 -0
  153. package/dist/shared/execution-context-scheduler.d.ts +6 -0
  154. package/dist/shared/fixed-clock.d.ts +13 -0
  155. package/dist/shared/fts-sync.d.ts +1 -0
  156. package/dist/shared/idempotency.repository.d1.d.ts +16 -0
  157. package/dist/shared/in-memory-activity-logger.d.ts +11 -0
  158. package/dist/shared/in-memory-notification-service.d.ts +11 -0
  159. package/dist/shared/in-memory-queue-service.d.ts +16 -0
  160. package/dist/shared/in-memory-seed.repository.d.ts +18 -0
  161. package/dist/shared/media.repository.d1.d.ts +35 -0
  162. package/dist/shared/qstash-notification-service.d.ts +18 -0
  163. package/dist/shared/query-utils.d.ts +36 -0
  164. package/dist/shared/queue-consumer.d.ts +9 -0
  165. package/dist/shared/request-utils.d.ts +13 -0
  166. package/dist/shared/schema-mutator.d1.d.ts +12 -0
  167. package/dist/shared/seed-layout.repository.d1.d.ts +9 -0
  168. package/dist/shared/seed-registry-cache.d.ts +12 -0
  169. package/dist/shared/seed.repository.d1.d.ts +13 -0
  170. package/dist/shared/sequential-id-generator.d.ts +13 -0
  171. package/dist/shared/site-settings.repository.d1.d.ts +7 -0
  172. package/dist/shared/storage/factory.d.ts +8 -0
  173. package/dist/shared/storage/s3-bucket.d.ts +43 -0
  174. package/dist/shared/storage-utils.d.ts +7 -0
  175. package/dist/shared/system-stats.repository.d1.d.ts +25 -0
  176. package/dist/types.d.ts +87 -0
  177. package/dist/upload.d.ts +16 -0
  178. package/dist/widget.d.ts +7 -0
  179. package/migrations/0000_v040_base.sql +265 -265
  180. package/migrations/0029_automations.sql +14 -14
  181. package/migrations/0030_test_seeds.sql +125 -125
  182. package/package.json +28 -18
  183. package/assets/dashboard/assets/chart-BrJFdsGZ.js +0 -39
  184. package/assets/dashboard/assets/index-CIaoMxuB.css +0 -1
  185. package/assets/dashboard/assets/index-wTKgygsg.js +0 -636
  186. package/assets/dashboard/assets/pie-chart-recharts-BEaE1FOE.js +0 -1
  187. package/assets/dashboard/assets/timeseries-chart-recharts-DmWM6imF.js +0 -1
  188. package/src/auth/__fixtures__/in-memory-hash-provider.ts +0 -17
  189. package/src/auth/__fixtures__/static-token-service.ts +0 -22
  190. package/src/auth/bcrypt-hash-provider.ts +0 -24
  191. package/src/auth/constants.ts +0 -14
  192. package/src/auth/generate-refresh-token.test.ts +0 -23
  193. package/src/auth/hash-provider.test.ts +0 -55
  194. package/src/auth/jose-token-service.ts +0 -62
  195. package/src/auth/jwt-claims-passthrough.test.ts +0 -87
  196. package/src/auth/login.test.ts +0 -100
  197. package/src/auth/login.ts +0 -78
  198. package/src/auth/refresh.ts +0 -11
  199. package/src/auth/token-service.test.ts +0 -90
  200. package/src/factory.ts +0 -370
  201. package/src/features/automations/__tests__/action-executors.test.ts +0 -255
  202. package/src/features/automations/__tests__/automation-runner.test.ts +0 -196
  203. package/src/features/automations/__tests__/automation-runner.utils.test.ts +0 -60
  204. package/src/features/automations/__tests__/automations.handler.test.ts +0 -264
  205. package/src/features/automations/__tests__/automations.repository.test.ts +0 -163
  206. package/src/features/automations/__tests__/automations.schema.test.ts +0 -224
  207. package/src/features/automations/__tests__/context-resolver.test.ts +0 -126
  208. package/src/features/automations/__tests__/cron-runner.test.ts +0 -267
  209. package/src/features/automations/__tests__/cron-runner.utils.test.ts +0 -144
  210. package/src/features/automations/__tests__/set-variable.executor.test.ts +0 -383
  211. package/src/features/automations/__tests__/template-grammar.test.ts +0 -308
  212. package/src/features/automations/__tests__/webhook.executor.test.ts +0 -142
  213. package/src/features/automations/__tests__/when-evaluator.test.ts +0 -274
  214. package/src/features/automations/__tests__/when-pushdown.test.ts +0 -281
  215. package/src/features/automations/action-executors/create-entry.executor.ts +0 -27
  216. package/src/features/automations/action-executors/edit-field.executor.ts +0 -26
  217. package/src/features/automations/action-executors/index.ts +0 -37
  218. package/src/features/automations/action-executors/send-mail.executor.ts +0 -53
  219. package/src/features/automations/action-executors/set-variable.executor.ts +0 -159
  220. package/src/features/automations/action-executors/webhook.executor.ts +0 -67
  221. package/src/features/automations/automation-runner.ts +0 -85
  222. package/src/features/automations/automation-runner.utils.ts +0 -47
  223. package/src/features/automations/automations.handler.ts +0 -197
  224. package/src/features/automations/automations.schema.ts +0 -177
  225. package/src/features/automations/context-resolver.ts +0 -152
  226. package/src/features/automations/cron-runner.ts +0 -140
  227. package/src/features/automations/cron-runner.utils.ts +0 -44
  228. package/src/features/automations/filter-translation.ts +0 -46
  229. package/src/features/automations/index.ts +0 -16
  230. package/src/features/automations/template-grammar.ts +0 -245
  231. package/src/features/automations/var-access-resolver.ts +0 -140
  232. package/src/features/automations/when-evaluator.ts +0 -87
  233. package/src/features/automations/when-pushdown.ts +0 -57
  234. package/src/features/backrefs/__tests__/backrefs.handler.test.ts +0 -359
  235. package/src/features/backrefs/backrefs.handler.ts +0 -168
  236. package/src/features/backrefs/d1-backref.repository.ts +0 -84
  237. package/src/features/backrefs/index.ts +0 -5
  238. package/src/features/content/constants.ts +0 -16
  239. package/src/features/content/handlers/bulk.handler.ts +0 -185
  240. package/src/features/content/handlers/create.ts +0 -129
  241. package/src/features/content/handlers/delete.ts +0 -62
  242. package/src/features/content/handlers/facets.ts +0 -49
  243. package/src/features/content/handlers/get.ts +0 -120
  244. package/src/features/content/handlers/helpers.test.ts +0 -180
  245. package/src/features/content/handlers/helpers.ts +0 -93
  246. package/src/features/content/handlers/list.ts +0 -174
  247. package/src/features/content/handlers/update.ts +0 -174
  248. package/src/features/content/index.ts +0 -26
  249. package/src/features/dashboard-layout/__tests__/dashboard-layout.handler.test.ts +0 -388
  250. package/src/features/dashboard-layout/dashboard-layout.handler.ts +0 -206
  251. package/src/features/dashboard-layout/index.ts +0 -5
  252. package/src/features/draft/draft.handler.ts +0 -195
  253. package/src/features/draft/draft.middleware.ts +0 -66
  254. package/src/features/draft/index.ts +0 -5
  255. package/src/features/email/email.service.ts +0 -98
  256. package/src/features/email/email.types.ts +0 -119
  257. package/src/features/email/providers/resend.ts +0 -67
  258. package/src/features/email/providers/smtp.ts +0 -55
  259. package/src/features/email/templates/automation-mail.ts +0 -19
  260. package/src/features/email/templates/password-changed.ts +0 -63
  261. package/src/features/email/templates/password-reset.ts +0 -68
  262. package/src/features/email/templates/shell.ts +0 -96
  263. package/src/features/notifications/index.ts +0 -5
  264. package/src/features/notifications/notifications.handler.ts +0 -105
  265. package/src/features/password-reset/index.ts +0 -19
  266. package/src/features/password-reset/request.ts +0 -92
  267. package/src/features/password-reset/reset.ts +0 -102
  268. package/src/features/rotate-field/index.ts +0 -5
  269. package/src/features/rotate-field/rotate-field.handler.ts +0 -132
  270. package/src/features/rotate-field/rotate-field.schema.ts +0 -17
  271. package/src/features/schema/schema.handler.ts +0 -131
  272. package/src/features/seeds/index.ts +0 -5
  273. package/src/features/seeds/seeds.handler.test.ts +0 -1199
  274. package/src/features/seeds/seeds.handler.ts +0 -558
  275. package/src/features/settings/__tests__/settings.handler.test.ts +0 -555
  276. package/src/features/settings/settings.handler.ts +0 -392
  277. package/src/features/setup/index.ts +0 -288
  278. package/src/features/stats/index.ts +0 -5
  279. package/src/features/stats/stats.handler.ts +0 -420
  280. package/src/features/webhooks/index.ts +0 -63
  281. package/src/index.ts +0 -65
  282. package/src/media-utils.ts +0 -82
  283. package/src/middleware/auth-providers.middleware.test.ts +0 -85
  284. package/src/middleware/auth-providers.middleware.ts +0 -45
  285. package/src/middleware/observability.middleware.test.ts +0 -93
  286. package/src/middleware/observability.middleware.ts +0 -70
  287. package/src/middleware/rate-limit.middleware.ts +0 -45
  288. package/src/middleware/repository.middleware.ts +0 -117
  289. package/src/middleware/seed-registry.middleware.test.ts +0 -97
  290. package/src/middleware/seed-registry.middleware.ts +0 -21
  291. package/src/middleware/storage.middleware.ts +0 -25
  292. package/src/middleware.ts +0 -45
  293. package/src/public/access-policy.ts +0 -27
  294. package/src/public/api-key-middleware.ts +0 -57
  295. package/src/public/cache-utils.ts +0 -38
  296. package/src/public/entry-projection.ts +0 -46
  297. package/src/public/idempotency.ts +0 -23
  298. package/src/public/index.ts +0 -16
  299. package/src/public/problem-details.ts +0 -124
  300. package/src/public/public-add.ts +0 -114
  301. package/src/public/public-edit.ts +0 -163
  302. package/src/public/public-errors.ts +0 -19
  303. package/src/public/public-read.ts +0 -63
  304. package/src/public/public-routes.ts +0 -88
  305. package/src/public/query-builder.test.ts +0 -224
  306. package/src/public/query-builder.ts +0 -156
  307. package/src/public/rate-limit-middleware.ts +0 -34
  308. package/src/public/read-list.ts +0 -54
  309. package/src/public/read-single.ts +0 -48
  310. package/src/public/response-builder.ts +0 -30
  311. package/src/public/sanitize.ts +0 -69
  312. package/src/rate-limit/cloudflare-rate-limiter.test.ts +0 -30
  313. package/src/rate-limit/cloudflare-rate-limiter.ts +0 -15
  314. package/src/rate-limit/in-memory-rate-limiter.test.ts +0 -37
  315. package/src/rate-limit/in-memory-rate-limiter.ts +0 -17
  316. package/src/rate-limit/no-op-rate-limiter.test.ts +0 -22
  317. package/src/rate-limit/no-op-rate-limiter.ts +0 -11
  318. package/src/search-utils.test.ts +0 -211
  319. package/src/search-utils.ts +0 -213
  320. package/src/search.ts +0 -65
  321. package/src/shared/apply-policies.test.ts +0 -81
  322. package/src/shared/apply-policies.ts +0 -67
  323. package/src/shared/automations.repository.d1.ts +0 -150
  324. package/src/shared/background-notification-service.test.ts +0 -62
  325. package/src/shared/background-notification-service.ts +0 -52
  326. package/src/shared/base.repository.d1.ts +0 -32
  327. package/src/shared/content-utils.test.ts +0 -165
  328. package/src/shared/content-utils.ts +0 -86
  329. package/src/shared/content.repository.d1.test.ts +0 -507
  330. package/src/shared/content.repository.d1.ts +0 -851
  331. package/src/shared/d1-activity-log.repository.test.ts +0 -140
  332. package/src/shared/d1-activity-log.repository.ts +0 -105
  333. package/src/shared/d1-activity-logger.test.ts +0 -86
  334. package/src/shared/d1-activity-logger.ts +0 -67
  335. package/src/shared/d1-analytics.repository.test.ts +0 -78
  336. package/src/shared/d1-analytics.repository.ts +0 -85
  337. package/src/shared/d1-content-scan.repository.test.ts +0 -80
  338. package/src/shared/d1-content-scan.repository.ts +0 -37
  339. package/src/shared/d1-notification.repository.test.ts +0 -128
  340. package/src/shared/d1-notification.repository.ts +0 -118
  341. package/src/shared/d1-password-reset-token.repository.test.ts +0 -81
  342. package/src/shared/d1-password-reset-token.repository.ts +0 -56
  343. package/src/shared/d1-search.repository.test.ts +0 -87
  344. package/src/shared/d1-search.repository.ts +0 -88
  345. package/src/shared/d1-session.repository.test.ts +0 -125
  346. package/src/shared/d1-session.repository.ts +0 -102
  347. package/src/shared/d1-setup-checklist.repository.ts +0 -36
  348. package/src/shared/d1-user.repository.test.ts +0 -151
  349. package/src/shared/d1-user.repository.ts +0 -119
  350. package/src/shared/d1-widget.repository.test.ts +0 -267
  351. package/src/shared/d1-widget.repository.ts +0 -385
  352. package/src/shared/dashboard-layout.repository.d1.test.ts +0 -135
  353. package/src/shared/dashboard-layout.repository.d1.ts +0 -58
  354. package/src/shared/demo-data-sql.ts +0 -216
  355. package/src/shared/demo-data.repository.d1.ts +0 -20
  356. package/src/shared/execution-context-scheduler.ts +0 -13
  357. package/src/shared/fixed-clock.ts +0 -25
  358. package/src/shared/fts-sync.ts +0 -8
  359. package/src/shared/idempotency.repository.d1.test.ts +0 -83
  360. package/src/shared/idempotency.repository.d1.ts +0 -60
  361. package/src/shared/in-memory-activity-logger.ts +0 -19
  362. package/src/shared/in-memory-notification-service.ts +0 -19
  363. package/src/shared/in-memory-seed.repository.ts +0 -58
  364. package/src/shared/media.repository.d1.test.ts +0 -107
  365. package/src/shared/media.repository.d1.ts +0 -68
  366. package/src/shared/qstash-notification-service.test.ts +0 -67
  367. package/src/shared/qstash-notification-service.ts +0 -55
  368. package/src/shared/query-utils.ts +0 -141
  369. package/src/shared/request-utils.ts +0 -26
  370. package/src/shared/schema-mutator.d1.test.ts +0 -142
  371. package/src/shared/schema-mutator.d1.ts +0 -64
  372. package/src/shared/seed-layout.repository.d1.test.ts +0 -114
  373. package/src/shared/seed-layout.repository.d1.ts +0 -62
  374. package/src/shared/seed-registry-cache.test.ts +0 -68
  375. package/src/shared/seed-registry-cache.ts +0 -49
  376. package/src/shared/seed.repository.d1.test.ts +0 -143
  377. package/src/shared/seed.repository.d1.ts +0 -98
  378. package/src/shared/sequential-id-generator.ts +0 -33
  379. package/src/shared/site-settings.repository.d1.ts +0 -53
  380. package/src/shared/storage/factory.ts +0 -41
  381. package/src/shared/storage/s3-bucket.ts +0 -195
  382. package/src/shared/storage-utils.ts +0 -40
  383. package/src/shared/system-stats.repository.d1.test.ts +0 -58
  384. package/src/shared/system-stats.repository.d1.ts +0 -48
  385. package/src/types.ts +0 -90
  386. package/src/upload.ts +0 -198
  387. package/src/widget.test.ts +0 -85
  388. package/src/widget.ts +0 -251
@@ -1,85 +0,0 @@
1
- // SPDX-License-Identifier: BUSL-1.1
2
- // Copyright (c) 2024–2026 Flavio De Musso. All rights reserved.
3
- // See LICENSE in the repository root for license terms.
4
-
5
- import { describe, it, expect, vi } from 'vitest'
6
- import { Hono } from 'hono'
7
- import { authProvidersMiddleware } from './auth-providers.middleware'
8
-
9
- describe('authProvidersMiddleware', () => {
10
- it('throws an error if ENV is production and JWT_SECRET is the development default', async () => {
11
- const app = new Hono()
12
- app.use('*', authProvidersMiddleware())
13
- app.get('/test', (c) => c.text('ok'))
14
-
15
- const env = {
16
- ENV: 'production',
17
- JWT_SECRET: 'sviluppo-secret-cambiami-almeno-32-byte-per-sicurezza-hono',
18
- }
19
-
20
- // Since throwing in Hono middleware returns an unhandled exception or 500 error,
21
- // let's run app.request and inspect if the error is thrown. Hono's default errorHandler
22
- // catches it, or we can add a custom error handler to catch it.
23
- let thrownError: Error | null = null
24
- app.onError((err) => {
25
- thrownError = err
26
- return Hono.prototype.json({ error: err.message }, 500)
27
- })
28
-
29
- const res = await app.request('/test', undefined, env)
30
- expect(res.status).toBe(500)
31
- expect(thrownError).not.toBeNull()
32
- expect(thrownError!.message).toContain('JWT_SECRET non configurato')
33
- })
34
-
35
- it('injects hashProvider and tokenService when configuration is correct', async () => {
36
- const app = new Hono()
37
- app.use('*', authProvidersMiddleware())
38
- app.get('/test', (c) => {
39
- const hash = c.get('hashProvider' as never)
40
- const token = c.get('tokenService' as never)
41
- return c.json({
42
- hasHash: !!hash,
43
- hasToken: !!token,
44
- })
45
- })
46
-
47
- const env = {
48
- ENV: 'development',
49
- JWT_SECRET: 'custom-secret-key-that-is-secure-enough',
50
- JWT_ISSUER: 'issuer',
51
- JWT_AUDIENCE: 'audience',
52
- }
53
-
54
- const res = await app.request('/test', undefined, env)
55
- expect(res.status).toBe(200)
56
- const body = await res.json() as any
57
- expect(body.hasHash).toBe(true)
58
- expect(body.hasToken).toBe(true)
59
- })
60
-
61
- it('respects overrides when provided', async () => {
62
- const app = new Hono()
63
- const mockHash = { hash: vi.fn(), verify: vi.fn() }
64
- const mockToken = { sign: vi.fn(), verify: vi.fn() }
65
-
66
- app.use('*', authProvidersMiddleware({
67
- hashProvider: mockHash as any,
68
- tokenService: mockToken as any,
69
- }))
70
-
71
- app.get('/test', (c) => {
72
- const hash = c.get('hashProvider' as never)
73
- const token = c.get('tokenService' as never)
74
- return c.json({
75
- hashIsOverridden: hash === mockHash,
76
- tokenIsOverridden: token === mockToken,
77
- })
78
- })
79
-
80
- const res = await app.request('/test')
81
- const body = await res.json() as any
82
- expect(body.hashIsOverridden).toBe(true)
83
- expect(body.tokenIsOverridden).toBe(true)
84
- })
85
- })
@@ -1,45 +0,0 @@
1
- // SPDX-License-Identifier: BUSL-1.1
2
- // Copyright (c) 2024–2026 Flavio De Musso. All rights reserved.
3
- // See LICENSE in the repository root for license terms.
4
-
5
- import { createMiddleware } from 'hono/factory'
6
- import type { IHashProvider, ITokenService, IClock } from '@beechcms/core'
7
- import { SystemClock } from '@beechcms/core'
8
- import type { AppEnv } from '../types'
9
- import { BcryptHashProvider } from '../auth/bcrypt-hash-provider'
10
- import { JoseTokenService } from '../auth/jose-token-service'
11
-
12
- export interface AuthProviderOverrides {
13
- hashProvider?: IHashProvider
14
- tokenService?: ITokenService
15
- clock?: IClock
16
- }
17
-
18
- // Valore di default presente in .dev.vars.example: mai accettabile in produzione.
19
- const DEV_JWT_SECRET = 'sviluppo-secret-cambiami-almeno-32-byte-per-sicurezza-hono'
20
-
21
- export const authProvidersMiddleware = (overrides?: AuthProviderOverrides) => {
22
- return createMiddleware<AppEnv>(async (context, next) => {
23
- if (context.env.ENV === 'production' && context.env.JWT_SECRET === DEV_JWT_SECRET) {
24
- throw new Error(
25
- 'JWT_SECRET non configurato: in produzione impostare un segreto univoco con `wrangler secret put JWT_SECRET`',
26
- )
27
- }
28
-
29
- const resolvedClock = overrides?.clock ?? SystemClock
30
- const hashProvider = overrides?.hashProvider ?? new BcryptHashProvider()
31
- const tokenService = overrides?.tokenService ?? new JoseTokenService(
32
- context.env.JWT_SECRET,
33
- {
34
- issuer: context.env.JWT_ISSUER,
35
- audience: context.env.JWT_AUDIENCE,
36
- },
37
- resolvedClock,
38
- )
39
-
40
- context.set('hashProvider', hashProvider)
41
- context.set('tokenService', tokenService)
42
-
43
- await next()
44
- })
45
- }
@@ -1,93 +0,0 @@
1
- // SPDX-License-Identifier: BUSL-1.1
2
- // Copyright (c) 2024–2026 Flavio De Musso. All rights reserved.
3
- // See LICENSE in the repository root for license terms.
4
-
5
- import { describe, it, expect, vi } from 'vitest'
6
- import { Hono } from 'hono'
7
- import { observabilityMiddleware } from './observability.middleware'
8
- import type { IClock, IIdGenerator } from '@beechcms/core'
9
-
10
- describe('observabilityMiddleware', () => {
11
- it('injects default activityLogger and background notification service when no overrides are given', async () => {
12
- const app = new Hono()
13
-
14
- app.use('*', async (c, next) => {
15
- c.set('notificationRepository' as never, {} as any)
16
- await next()
17
- })
18
-
19
- app.use('*', observabilityMiddleware())
20
-
21
- app.get('/test', (c) => {
22
- const logger = c.get('activityLogger' as never)
23
- const notifications = c.get('notificationService' as never)
24
- return c.json({
25
- hasLogger: !!logger,
26
- hasNotifications: !!notifications,
27
- })
28
- })
29
-
30
- const executionCtx = {
31
- waitUntil: vi.fn(),
32
- passThroughOnException: vi.fn(),
33
- }
34
-
35
- // Mock env with DB
36
- const res = await app.request('/test', undefined, { DB: {} }, executionCtx)
37
- const body = await res.json() as any
38
- expect(body.hasLogger).toBe(true)
39
- expect(body.hasNotifications).toBe(true)
40
- })
41
-
42
- it('respects overrides when provided', async () => {
43
- const app = new Hono()
44
-
45
- const mockLogger = { log: vi.fn() }
46
- const mockNotifications = { send: vi.fn() }
47
- const mockClock: IClock = { now: () => 12345 }
48
- const mockIdGen: IIdGenerator = { nextId: () => 'custom-id' }
49
-
50
- app.use('*', observabilityMiddleware({
51
- activityLogger: mockLogger as any,
52
- notificationService: mockNotifications as any,
53
- clock: mockClock,
54
- idGenerator: mockIdGen,
55
- }))
56
-
57
- app.get('/test', (c) => {
58
- const logger = c.get('activityLogger' as never)
59
- const notifications = c.get('notificationService' as never)
60
- return c.json({
61
- loggerIsOverridden: logger === mockLogger,
62
- notificationsAreOverridden: notifications === mockNotifications,
63
- })
64
- })
65
-
66
- const res = await app.request('/test')
67
- const body = await res.json() as any
68
- expect(body.loggerIsOverridden).toBe(true)
69
- expect(body.notificationsAreOverridden).toBe(true)
70
- })
71
-
72
- it('uses QStashNotificationService when QSTASH_TOKEN and APP_URL are in Env', async () => {
73
- const app = new Hono()
74
- app.use('*', observabilityMiddleware())
75
-
76
- app.get('/test', (c) => {
77
- const notifications = c.get('notificationService' as never) as any
78
- return c.json({
79
- type: notifications?.constructor?.name,
80
- })
81
- })
82
-
83
- const env = {
84
- QSTASH_TOKEN: 'token',
85
- APP_URL: 'https://my-app.com',
86
- DB: {},
87
- }
88
-
89
- const res = await app.request('/test', undefined, env)
90
- const body = await res.json() as any
91
- expect(body.type).toBe('QStashNotificationService')
92
- })
93
- })
@@ -1,70 +0,0 @@
1
- // SPDX-License-Identifier: BUSL-1.1
2
- // Copyright (c) 2024–2026 Flavio De Musso. All rights reserved.
3
- // See LICENSE in the repository root for license terms.
4
-
5
- import { createMiddleware } from 'hono/factory'
6
- import type { IActivityLogger, INotificationService, IClock, IIdGenerator } from '@beechcms/core'
7
- import { SystemClock, SystemIdGenerator } from '@beechcms/core'
8
- import type { AppEnv } from '../types'
9
- import { D1ActivityLogger } from '../shared/d1-activity-logger'
10
- import { BackgroundNotificationService } from '../shared/background-notification-service'
11
- import { QStashNotificationService } from '../shared/qstash-notification-service'
12
-
13
- export interface ObservabilityOverrides {
14
- activityLogger?: IActivityLogger
15
- notificationService?: INotificationService
16
- clock?: IClock
17
- idGenerator?: IIdGenerator
18
- }
19
-
20
- /**
21
- * Observability middleware.
22
- *
23
- * Injects the activity logger and the notification service into the Hono
24
- * context. Both depend on `executionCtx.waitUntil` to fire-and-forget their
25
- * persistence work in production. The notification service additionally
26
- * depends on the notification repository — `repositoryMiddleware` MUST run
27
- * before this middleware in the factory pipeline.
28
- *
29
- * Tests can pass their own implementations via `overrides` to bypass D1.
30
- */
31
- export const observabilityMiddleware = (overrides?: ObservabilityOverrides) => {
32
- return createMiddleware<AppEnv>(async (context, next) => {
33
- let scheduleBackgroundTask: ((task: Promise<unknown>) => void) | undefined
34
- try {
35
- const executionContext = context.executionCtx
36
- scheduleBackgroundTask = executionContext.waitUntil.bind(executionContext)
37
- } catch {
38
- scheduleBackgroundTask = undefined
39
- }
40
-
41
- const resolvedClock = overrides?.clock ?? SystemClock
42
- const resolvedIdGenerator = overrides?.idGenerator ?? SystemIdGenerator
43
-
44
- const activityLogger =
45
- overrides?.activityLogger ??
46
- new D1ActivityLogger(context.env.DB, resolvedClock, resolvedIdGenerator, scheduleBackgroundTask)
47
-
48
- let notificationService: INotificationService
49
- if (overrides?.notificationService) {
50
- notificationService = overrides.notificationService
51
- } else if (context.env.QSTASH_TOKEN && (context.env.QSTASH_CALLBACK_URL || context.env.APP_URL)) {
52
- notificationService = new QStashNotificationService(
53
- context.env.QSTASH_TOKEN,
54
- (context.env.QSTASH_CALLBACK_URL ?? context.env.APP_URL) as string,
55
- scheduleBackgroundTask,
56
- context.env.QSTASH_URL
57
- )
58
- } else {
59
- notificationService = new BackgroundNotificationService(
60
- context.get('notificationRepository'),
61
- scheduleBackgroundTask
62
- )
63
- }
64
-
65
- context.set('activityLogger', activityLogger)
66
- context.set('notificationService', notificationService)
67
-
68
- await next()
69
- })
70
- }
@@ -1,45 +0,0 @@
1
- // SPDX-License-Identifier: BUSL-1.1
2
- // Copyright (c) 2024–2026 Flavio De Musso. All rights reserved.
3
- // See LICENSE in the repository root for license terms.
4
-
5
- /// <reference types="@cloudflare/workers-types" />
6
- import { createMiddleware } from 'hono/factory'
7
- import type { IRateLimiter } from '@beechcms/core'
8
- import type { AppEnv, Env } from '../types'
9
- import { CloudflareRateLimiter } from '../rate-limit/cloudflare-rate-limiter'
10
- import { NoOpRateLimiter } from '../rate-limit/no-op-rate-limiter'
11
-
12
- export type RateLimiterName =
13
- | 'login'
14
- | 'tokenRefresh'
15
- | 'forgotPassword'
16
- | 'resetPassword'
17
- | 'publicApiRead'
18
- | 'publicApiWrite'
19
-
20
- export interface IRateLimiterRegistry {
21
- getLimiter(name: RateLimiterName): IRateLimiter
22
- }
23
-
24
- const NO_OP = new NoOpRateLimiter()
25
-
26
- function buildDefaultRegistry(env: Env): IRateLimiterRegistry {
27
- const limiters: Record<RateLimiterName, IRateLimiter> = {
28
- login: env.LOGIN_RATE_LIMITER ? new CloudflareRateLimiter(env.LOGIN_RATE_LIMITER) : NO_OP,
29
- tokenRefresh: env.REFRESH_RATE_LIMITER ? new CloudflareRateLimiter(env.REFRESH_RATE_LIMITER) : NO_OP,
30
- forgotPassword: env.FORGOT_PASSWORD_RATE_LIMITER ? new CloudflareRateLimiter(env.FORGOT_PASSWORD_RATE_LIMITER) : NO_OP,
31
- resetPassword: env.RESET_PASSWORD_RATE_LIMITER ? new CloudflareRateLimiter(env.RESET_PASSWORD_RATE_LIMITER) : NO_OP,
32
- publicApiRead: env.PUBLIC_READ_RATE_LIMITER ? new CloudflareRateLimiter(env.PUBLIC_READ_RATE_LIMITER) : NO_OP,
33
- publicApiWrite: env.PUBLIC_WRITE_RATE_LIMITER ? new CloudflareRateLimiter(env.PUBLIC_WRITE_RATE_LIMITER) : NO_OP,
34
- }
35
-
36
- return { getLimiter: (name) => limiters[name] }
37
- }
38
-
39
- export const rateLimiterMiddleware = (overrides?: { registry?: IRateLimiterRegistry }) => {
40
- return createMiddleware<AppEnv>(async (context, next) => {
41
- const registry = overrides?.registry ?? buildDefaultRegistry(context.env)
42
- context.set('rateLimiters', registry)
43
- await next()
44
- })
45
- }
@@ -1,117 +0,0 @@
1
- // SPDX-License-Identifier: BUSL-1.1
2
- // Copyright (c) 2024–2026 Flavio De Musso. All rights reserved.
3
- // See LICENSE in the repository root for license terms.
4
-
5
- import { createMiddleware } from 'hono/factory'
6
- import type { Context } from 'hono'
7
- import { D1ContentRepository } from '../shared/content.repository.d1'
8
- import { D1IdempotencyRepository } from '../shared/idempotency.repository.d1'
9
- import { D1MediaRepository } from '../shared/media.repository.d1'
10
- import { D1SystemStatsRepository } from '../shared/system-stats.repository.d1'
11
- import { D1UserRepository } from '../shared/d1-user.repository'
12
- import { D1SessionRepository } from '../shared/d1-session.repository'
13
- import { D1PasswordResetTokenRepository } from '../shared/d1-password-reset-token.repository'
14
- import { D1ActivityLogRepository } from '../shared/d1-activity-log.repository'
15
- import { D1NotificationRepository } from '../shared/d1-notification.repository'
16
- import { D1WidgetRepository } from '../shared/d1-widget.repository'
17
- import { D1SearchRepository } from '../shared/d1-search.repository'
18
- import { D1AnalyticsRepository } from '../shared/d1-analytics.repository'
19
- import { D1ContentScanRepository } from '../shared/d1-content-scan.repository'
20
- import { D1SiteSettingsRepository } from '../shared/site-settings.repository.d1'
21
- import { D1DemoDataRepository } from '../shared/demo-data.repository.d1'
22
- import { D1SetupChecklistRepository } from '../shared/d1-setup-checklist.repository'
23
- import { D1SeedLayoutRepository } from '../shared/seed-layout.repository.d1'
24
- import { D1DashboardLayoutRepository } from '../shared/dashboard-layout.repository.d1'
25
- import { D1SeedRepository } from '../shared/seed.repository.d1'
26
- import { D1SchemaMutator } from '../shared/schema-mutator.d1'
27
- import { SystemClock, SystemIdGenerator } from '@beechcms/core'
28
- import type { ContentRepository, IdempotencyRepository, MediaRepository, SystemStatsRepository, IUserRepository, ISessionRepository, IPasswordResetTokenRepository, IActivityLogRepository, INotificationRepository, IWidgetRepository, ISearchRepository, IAnalyticsRepository, IContentScanRepository, IClock, IIdGenerator, IAutomationRunner, IAutomationRepository, IScheduler, ISiteSettingsRepository, IDemoDataRepository, ISeedLayoutRepository, ISeedRepository, ISchemaMutator, IDashboardLayoutRepository } from '@beechcms/core'
29
- import { NoOpScheduler } from '@beechcms/core'
30
- import { AutomationRunner } from '../features/automations'
31
- import { D1AutomationRepository } from '../shared/automations.repository.d1'
32
- import { ExecutionContextScheduler } from '../shared/execution-context-scheduler'
33
- import type { Env, Variables } from '../types'
34
-
35
- interface RepositoryOverrides {
36
- repository?: ContentRepository
37
- idempotencyRepository?: IdempotencyRepository
38
- mediaRepository?: MediaRepository
39
- systemStatsRepository?: SystemStatsRepository
40
- userRepository?: IUserRepository
41
- sessionRepository?: ISessionRepository
42
- passwordResetTokenRepository?: IPasswordResetTokenRepository
43
- activityLogRepository?: IActivityLogRepository
44
- notificationRepository?: INotificationRepository
45
- widgetRepository?: IWidgetRepository
46
- searchRepository?: ISearchRepository
47
- analyticsRepository?: IAnalyticsRepository
48
- contentScanRepository?: IContentScanRepository
49
- clock?: IClock
50
- idGenerator?: IIdGenerator
51
- automationRepository?: IAutomationRepository
52
- automationRunner?: IAutomationRunner
53
- scheduler?: IScheduler
54
- siteSettingsRepository?: ISiteSettingsRepository
55
- demoDataRepository?: IDemoDataRepository
56
- seedLayoutRepository?: ISeedLayoutRepository
57
- seedRepository?: ISeedRepository
58
- schemaMutator?: ISchemaMutator
59
- dashboardLayoutRepository?: IDashboardLayoutRepository
60
- }
61
-
62
- function buildScheduler(context: Context): IScheduler {
63
- try {
64
- return new ExecutionContextScheduler(context.executionCtx)
65
- } catch {
66
- return new NoOpScheduler()
67
- }
68
- }
69
-
70
- export const repositoryMiddleware = (overrides?: RepositoryOverrides) => {
71
- return createMiddleware<{ Bindings: Env; Variables: Variables }>(async (context, next) => {
72
- const resolvedClock = overrides?.clock ?? SystemClock
73
- const resolvedIdGenerator = overrides?.idGenerator ?? SystemIdGenerator
74
- const database = context.env.DB
75
-
76
- context.set('repository', overrides?.repository ?? new D1ContentRepository(database))
77
- context.set('idempotencyRepository', overrides?.idempotencyRepository ?? new D1IdempotencyRepository(database))
78
- context.set('mediaRepository', overrides?.mediaRepository ?? new D1MediaRepository(database))
79
- context.set('systemStatsRepository', overrides?.systemStatsRepository ?? new D1SystemStatsRepository(database))
80
- context.set('userRepository', overrides?.userRepository ?? new D1UserRepository(database))
81
- context.set('sessionRepository', overrides?.sessionRepository ?? new D1SessionRepository(database, resolvedClock))
82
- context.set('passwordResetTokenRepository', overrides?.passwordResetTokenRepository ?? new D1PasswordResetTokenRepository(database, resolvedIdGenerator))
83
- context.set('activityLogRepository', overrides?.activityLogRepository ?? new D1ActivityLogRepository(database))
84
- context.set('notificationRepository', overrides?.notificationRepository ?? new D1NotificationRepository(database, resolvedClock, resolvedIdGenerator))
85
- context.set('widgetRepository', overrides?.widgetRepository ?? new D1WidgetRepository(database))
86
- context.set('searchRepository', overrides?.searchRepository ?? new D1SearchRepository(database))
87
- context.set('analyticsRepository', overrides?.analyticsRepository ?? new D1AnalyticsRepository(database, resolvedClock))
88
- context.set('contentScanRepository', overrides?.contentScanRepository ?? new D1ContentScanRepository(database))
89
- context.set('clock', resolvedClock)
90
- context.set('idGenerator', resolvedIdGenerator)
91
- const automationRepository = overrides?.automationRepository
92
- ?? new D1AutomationRepository(database)
93
-
94
- context.set('automationRepository', automationRepository)
95
- // getSeed is set later by seedRegistryMiddleware — capture context by closure so the
96
- // runner reads the live value at call time, not at middleware creation time.
97
- context.set(
98
- 'automationRunner',
99
- overrides?.automationRunner ?? new AutomationRunner({
100
- automationRepository,
101
- contentRepository: context.get('repository'),
102
- getSeed: (slug: string) => context.get('getSeed')?.(slug) ?? null,
103
- idGenerator: resolvedIdGenerator,
104
- env: context.env as unknown as Record<string, string | undefined>,
105
- }),
106
- )
107
- context.set('scheduler', overrides?.scheduler ?? buildScheduler(context))
108
- context.set('siteSettingsRepository', overrides?.siteSettingsRepository ?? new D1SiteSettingsRepository(database))
109
- context.set('demoDataRepository', overrides?.demoDataRepository ?? new D1DemoDataRepository(database))
110
- context.set('setupChecklistRepository', new D1SetupChecklistRepository(database))
111
- context.set('seedLayoutRepository', overrides?.seedLayoutRepository ?? new D1SeedLayoutRepository(database))
112
- context.set('seedRepository', overrides?.seedRepository ?? new D1SeedRepository(database))
113
- context.set('schemaMutator', overrides?.schemaMutator ?? new D1SchemaMutator(database))
114
- context.set('dashboardLayoutRepository', overrides?.dashboardLayoutRepository ?? new D1DashboardLayoutRepository(database))
115
- await next()
116
- })
117
- }
@@ -1,97 +0,0 @@
1
- // SPDX-License-Identifier: BUSL-1.1
2
- // Copyright (c) 2024–2026 Flavio De Musso. All rights reserved.
3
- // See LICENSE in the repository root for license terms.
4
-
5
- import { describe, it, expect, beforeEach, vi } from 'vitest'
6
- import { Hono } from 'hono'
7
- import { seedRegistryMiddleware } from './seed-registry.middleware'
8
- import { __resetSeedRegistryCache } from '../shared/seed-registry-cache'
9
- import type { ISeedRepository, Seed } from '@beechcms/core'
10
-
11
- const mockSeed: Seed = {
12
- slug: 'posts',
13
- label: 'Posts',
14
- displayNameAlias: 'title',
15
- branches: [{ id: 'br_01', alias: 'title', label: 'Title', type: 'text' }],
16
- }
17
-
18
- function makeRepo(seeds: Seed[] = [mockSeed]): ISeedRepository {
19
- return {
20
- listActive: vi.fn().mockResolvedValue(seeds),
21
- listAll: vi.fn().mockResolvedValue([]),
22
- get: vi.fn().mockResolvedValue(null),
23
- upsert: vi.fn().mockResolvedValue(undefined),
24
- softDelete: vi.fn().mockResolvedValue(undefined),
25
- getRegistryVersion: vi.fn().mockResolvedValue(1),
26
- bumpRegistryVersion: vi.fn().mockResolvedValue(2),
27
- }
28
- }
29
-
30
- describe('seedRegistryMiddleware', () => {
31
- beforeEach(() => __resetSeedRegistryCache())
32
-
33
- it('injects seedRegistry, getSeed, and backrefMap into context', async () => {
34
- const app = new Hono()
35
- const repo = makeRepo()
36
-
37
- app.use('*', async (c, next) => {
38
- c.set('seedRepository' as never, repo)
39
- await next()
40
- })
41
- app.use('*', seedRegistryMiddleware())
42
- app.get('/test', (c) => {
43
- const registry = c.get('seedRegistry' as never) as any
44
- const getSeed = c.get('getSeed' as never) as any
45
- const backrefMap = c.get('backrefMap' as never) as any
46
- return c.json({
47
- hasRegistry: !!registry,
48
- hasSeed: !!getSeed('posts'),
49
- hasBackrefMap: !!backrefMap,
50
- })
51
- })
52
-
53
- const res = await app.request('/test')
54
- const body = await res.json() as any
55
- expect(body.hasRegistry).toBe(true)
56
- expect(body.hasSeed).toBe(true)
57
- expect(body.hasBackrefMap).toBe(true)
58
- })
59
-
60
- it('getSeed returns null for unknown slug', async () => {
61
- const app = new Hono()
62
- const repo = makeRepo()
63
-
64
- app.use('*', async (c, next) => {
65
- c.set('seedRepository' as never, repo)
66
- await next()
67
- })
68
- app.use('*', seedRegistryMiddleware())
69
- app.get('/test', (c) => {
70
- const getSeed = c.get('getSeed' as never) as any
71
- return c.json({ result: getSeed('no-such-slug') })
72
- })
73
-
74
- const res = await app.request('/test')
75
- const body = await res.json() as any
76
- expect(body.result).toBeNull()
77
- })
78
-
79
- it('empty seed list yields empty registry without crashing', async () => {
80
- const app = new Hono()
81
- const repo = makeRepo([])
82
-
83
- app.use('*', async (c, next) => {
84
- c.set('seedRepository' as never, repo)
85
- await next()
86
- })
87
- app.use('*', seedRegistryMiddleware())
88
- app.get('/test', (c) => {
89
- const registry = c.get('seedRegistry' as never) as any
90
- return c.json({ count: registry.all().length })
91
- })
92
-
93
- const res = await app.request('/test')
94
- const body = await res.json() as any
95
- expect(body.count).toBe(0)
96
- })
97
- })
@@ -1,21 +0,0 @@
1
- // SPDX-License-Identifier: BUSL-1.1
2
- // Copyright (c) 2024–2026 Flavio De Musso. All rights reserved.
3
- // See LICENSE in the repository root for license terms.
4
-
5
- import { createMiddleware } from 'hono/factory'
6
- import type { Env, Variables } from '../types'
7
- import { getHydratedRegistry } from '../shared/seed-registry-cache'
8
-
9
- /**
10
- * Hydrates the seed registry from D1 and injects seedRegistry, getSeed, and backrefMap
11
- * into the context. Must run AFTER repositoryMiddleware (needs seedRepository) and
12
- * BEFORE any handler that reads the registry.
13
- */
14
- export const seedRegistryMiddleware = () =>
15
- createMiddleware<{ Bindings: Env; Variables: Variables }>(async (context, next) => {
16
- const { registry, backrefMap } = await getHydratedRegistry(context.get('seedRepository'))
17
- context.set('seedRegistry', registry)
18
- context.set('getSeed', (slug: string) => registry.get(slug))
19
- context.set('backrefMap', backrefMap)
20
- await next()
21
- })
@@ -1,25 +0,0 @@
1
- // SPDX-License-Identifier: BUSL-1.1
2
- // Copyright (c) 2024–2026 Flavio De Musso. All rights reserved.
3
- // See LICENSE in the repository root for license terms.
4
-
5
- import { createMiddleware } from 'hono/factory'
6
- import { BeechBucket } from '@beechcms/core'
7
- import { AppEnv } from '../types'
8
- import { createBucketProvider } from '../shared/storage/factory'
9
-
10
- interface StorageOverrides {
11
- bucket?: BeechBucket
12
- }
13
-
14
- export const storageMiddleware = (overrides?: StorageOverrides) => {
15
- return createMiddleware<AppEnv>(async (context, next) => {
16
- if (overrides?.bucket) {
17
- context.set('bucket', overrides.bucket)
18
- } else {
19
- // Determine base URL for getUrl() only if we need to create the provider
20
- const baseUrl = context.env.MEDIA_BASE_URL?.trim().replace(/\/$/, '') || new URL(context.req.url).origin
21
- context.set('bucket', createBucketProvider(context.env, baseUrl))
22
- }
23
- await next()
24
- })
25
- }
package/src/middleware.ts DELETED
@@ -1,45 +0,0 @@
1
- // SPDX-License-Identifier: BUSL-1.1
2
- // Copyright (c) 2024–2026 Flavio De Musso. All rights reserved.
3
- // See LICENSE in the repository root for license terms.
4
-
5
- /// <reference types="@cloudflare/workers-types" />
6
- import type { Context, Next } from 'hono'
7
- import { HTTPException } from 'hono/http-exception'
8
- import type { Env, Variables } from './types'
9
-
10
- const UNAUTHORIZED_JSON = JSON.stringify({ error: 'Unauthorized' })
11
-
12
- function unauthorizedResponse() {
13
- return new Response(UNAUTHORIZED_JSON, {
14
- status: 401,
15
- headers: { 'Content-Type': 'application/json' },
16
- })
17
- }
18
-
19
- /**
20
- * JWT authentication middleware. Reads the Bearer token from the Authorization
21
- * header and delegates verification to the ITokenService injected in context.
22
- * Returns 401 on any missing or invalid token; never exposes failure details.
23
- */
24
- export function authMiddleware() {
25
- return async (c: Context<{ Bindings: Env; Variables: Variables }>, next: Next): Promise<Response | void> => {
26
- const authHeader = c.req.header('Authorization')
27
- if (!authHeader?.startsWith('Bearer ')) {
28
- throw new HTTPException(401, { res: unauthorizedResponse() })
29
- }
30
-
31
- const token = authHeader.slice(7)
32
- if (!token) {
33
- throw new HTTPException(401, { res: unauthorizedResponse() })
34
- }
35
-
36
- const claims = await c.get('tokenService').verify(token)
37
-
38
- if (!claims) {
39
- throw new HTTPException(401, { res: unauthorizedResponse() })
40
- }
41
-
42
- c.set('jwtPayload', claims)
43
- await next()
44
- }
45
- }
@@ -1,27 +0,0 @@
1
- // SPDX-License-Identifier: BUSL-1.1
2
- // Copyright (c) 2024–2026 Flavio De Musso. All rights reserved.
3
- // See LICENSE in the repository root for license terms.
4
-
5
- import type { Seed } from '@beechcms/core'
6
-
7
- export type PublicOperation = 'read' | 'add' | 'edit'
8
-
9
- function isAllowed(seed: Seed, operation: PublicOperation): boolean {
10
- if (operation === 'read') return seed.allowPublicRead === true
11
- if (operation === 'add') return seed.allowPublicPost === true
12
- return seed.allowPublicEdit === true
13
- }
14
-
15
- export function checkPublicOperation(seed: Seed, operation: PublicOperation) {
16
- if (isAllowed(seed, operation)) {
17
- return { ok: true } as const
18
- }
19
-
20
- return {
21
- ok: false,
22
- error: {
23
- error: 'Forbidden',
24
- message: `Public ${operation.toUpperCase()} is not allowed for content type '${seed.slug}'.`,
25
- },
26
- } as const
27
- }