@beechcms/api 0.6.0-preview.1 → 0.6.0-preview.3

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 (373) 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-Cws4Yj6K.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-BjPpppHe.css +1 -0
  11. package/assets/dashboard/assets/index-CrW-zhkA.js +642 -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-CAxoDQp2.js +1 -0
  20. package/assets/dashboard/assets/timeseries-chart-recharts-CixDW-LM.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 +39 -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} +37 -42
  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} +20 -33
  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 +6 -0
  98. package/dist/index.js +9666 -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/rate-limit.middleware.d.ts +9 -0
  103. package/dist/middleware/repository.middleware.d.ts +34 -0
  104. package/dist/middleware/seed-registry.middleware.d.ts +10 -0
  105. package/dist/middleware/storage.middleware.d.ts +7 -0
  106. package/dist/middleware.d.ts +11 -0
  107. package/dist/public/access-policy.d.ts +12 -0
  108. package/dist/public/api-key-middleware.d.ts +6 -0
  109. package/dist/public/cache-utils.d.ts +10 -0
  110. package/dist/public/entry-projection.d.ts +2 -0
  111. package/dist/public/idempotency.d.ts +9 -0
  112. package/dist/public/index.d.ts +11 -0
  113. package/dist/public/problem-details.d.ts +31 -0
  114. package/dist/public/public-add.d.ts +3 -0
  115. package/dist/public/public-edit.d.ts +5 -0
  116. package/dist/public/public-errors.d.ts +13 -0
  117. package/dist/public/public-read.d.ts +3 -0
  118. package/dist/public/public-routes.d.ts +3 -0
  119. package/dist/public/query-builder.d.ts +28 -0
  120. package/dist/public/rate-limit-middleware.d.ts +3 -0
  121. package/dist/public/read-list.d.ts +26 -0
  122. package/dist/public/read-single.d.ts +22 -0
  123. package/dist/public/response-builder.d.ts +22 -0
  124. package/dist/public/sanitize.d.ts +23 -0
  125. package/dist/public/slug-utils.d.ts +11 -0
  126. package/dist/rate-limit/cloudflare-rate-limiter.d.ts +6 -0
  127. package/dist/rate-limit/in-memory-rate-limiter.d.ts +7 -0
  128. package/dist/rate-limit/no-op-rate-limiter.d.ts +4 -0
  129. package/dist/search-utils.d.ts +54 -0
  130. package/dist/search.d.ts +6 -0
  131. package/dist/shared/apply-policies.d.ts +10 -0
  132. package/dist/shared/automations.repository.d1.d.ts +12 -0
  133. package/dist/shared/background-notification-service.d.ts +18 -0
  134. package/dist/shared/base.repository.d1.d.ts +18 -0
  135. package/dist/shared/content-utils.d.ts +21 -0
  136. package/dist/shared/content.repository.d1.d.ts +68 -0
  137. package/dist/shared/d1-activity-log.repository.d.ts +13 -0
  138. package/dist/shared/d1-activity-logger.d.ts +20 -0
  139. package/dist/shared/d1-analytics.repository.d.ts +20 -0
  140. package/dist/shared/d1-content-scan.repository.d.ts +7 -0
  141. package/dist/shared/d1-notification.repository.d.ts +17 -0
  142. package/dist/shared/d1-password-reset-token.repository.d.ts +10 -0
  143. package/dist/shared/d1-search.repository.d.ts +14 -0
  144. package/dist/shared/d1-session.repository.d.ts +12 -0
  145. package/dist/shared/d1-setup-checklist.repository.d.ts +12 -0
  146. package/dist/shared/d1-user.repository.d.ts +18 -0
  147. package/dist/shared/d1-widget.repository.d.ts +31 -0
  148. package/dist/shared/dashboard-layout.repository.d1.d.ts +9 -0
  149. package/dist/shared/demo-data-sql.d.ts +1 -0
  150. package/dist/shared/demo-data.repository.d1.d.ts +6 -0
  151. package/dist/shared/execution-context-scheduler.d.ts +6 -0
  152. package/dist/shared/fixed-clock.d.ts +13 -0
  153. package/dist/shared/fts-sync.d.ts +1 -0
  154. package/dist/shared/idempotency.repository.d1.d.ts +16 -0
  155. package/dist/shared/in-memory-activity-logger.d.ts +11 -0
  156. package/dist/shared/in-memory-notification-service.d.ts +11 -0
  157. package/dist/shared/in-memory-seed.repository.d.ts +18 -0
  158. package/dist/shared/media.repository.d1.d.ts +35 -0
  159. package/dist/shared/qstash-notification-service.d.ts +18 -0
  160. package/dist/shared/query-utils.d.ts +36 -0
  161. package/dist/shared/request-utils.d.ts +13 -0
  162. package/dist/shared/schema-mutator.d1.d.ts +12 -0
  163. package/dist/shared/seed-layout.repository.d1.d.ts +9 -0
  164. package/dist/shared/seed-registry-cache.d.ts +12 -0
  165. package/dist/shared/seed.repository.d1.d.ts +13 -0
  166. package/dist/shared/sequential-id-generator.d.ts +13 -0
  167. package/dist/shared/site-settings.repository.d1.d.ts +7 -0
  168. package/dist/shared/storage/factory.d.ts +8 -0
  169. package/dist/shared/storage/s3-bucket.d.ts +43 -0
  170. package/dist/shared/storage-utils.d.ts +7 -0
  171. package/dist/shared/system-stats.repository.d1.d.ts +25 -0
  172. package/dist/types.d.ts +85 -0
  173. package/dist/upload.d.ts +16 -0
  174. package/dist/widget.d.ts +7 -0
  175. package/migrations/0000_v040_base.sql +265 -265
  176. package/migrations/0029_automations.sql +14 -14
  177. package/migrations/0030_test_seeds.sql +125 -125
  178. package/package.json +27 -18
  179. package/assets/dashboard/assets/index-BSjk0Sx9.js +0 -634
  180. package/assets/dashboard/assets/index-kRCYVN2B.css +0 -1
  181. package/src/auth/__fixtures__/in-memory-hash-provider.ts +0 -17
  182. package/src/auth/__fixtures__/static-token-service.ts +0 -22
  183. package/src/auth/bcrypt-hash-provider.ts +0 -24
  184. package/src/auth/constants.ts +0 -14
  185. package/src/auth/generate-refresh-token.test.ts +0 -23
  186. package/src/auth/hash-provider.test.ts +0 -55
  187. package/src/auth/jose-token-service.ts +0 -62
  188. package/src/auth/jwt-claims-passthrough.test.ts +0 -87
  189. package/src/auth/login.test.ts +0 -100
  190. package/src/auth/login.ts +0 -78
  191. package/src/auth/refresh.ts +0 -11
  192. package/src/auth/token-service.test.ts +0 -90
  193. package/src/factory.ts +0 -368
  194. package/src/features/automations/__tests__/action-executors.test.ts +0 -255
  195. package/src/features/automations/__tests__/automation-runner.test.ts +0 -196
  196. package/src/features/automations/__tests__/automation-runner.utils.test.ts +0 -60
  197. package/src/features/automations/__tests__/automations.handler.test.ts +0 -264
  198. package/src/features/automations/__tests__/automations.repository.test.ts +0 -163
  199. package/src/features/automations/__tests__/automations.schema.test.ts +0 -224
  200. package/src/features/automations/__tests__/context-resolver.test.ts +0 -126
  201. package/src/features/automations/__tests__/cron-runner.test.ts +0 -267
  202. package/src/features/automations/__tests__/cron-runner.utils.test.ts +0 -144
  203. package/src/features/automations/__tests__/set-variable.executor.test.ts +0 -383
  204. package/src/features/automations/__tests__/template-grammar.test.ts +0 -308
  205. package/src/features/automations/__tests__/webhook.executor.test.ts +0 -142
  206. package/src/features/automations/__tests__/when-evaluator.test.ts +0 -274
  207. package/src/features/automations/__tests__/when-pushdown.test.ts +0 -281
  208. package/src/features/automations/action-executors/create-entry.executor.ts +0 -27
  209. package/src/features/automations/action-executors/edit-field.executor.ts +0 -26
  210. package/src/features/automations/action-executors/index.ts +0 -37
  211. package/src/features/automations/action-executors/send-mail.executor.ts +0 -53
  212. package/src/features/automations/action-executors/set-variable.executor.ts +0 -159
  213. package/src/features/automations/action-executors/webhook.executor.ts +0 -67
  214. package/src/features/automations/automation-runner.ts +0 -85
  215. package/src/features/automations/automation-runner.utils.ts +0 -47
  216. package/src/features/automations/automations.handler.ts +0 -197
  217. package/src/features/automations/automations.schema.ts +0 -177
  218. package/src/features/automations/context-resolver.ts +0 -152
  219. package/src/features/automations/cron-runner.ts +0 -140
  220. package/src/features/automations/cron-runner.utils.ts +0 -44
  221. package/src/features/automations/filter-translation.ts +0 -46
  222. package/src/features/automations/index.ts +0 -16
  223. package/src/features/automations/template-grammar.ts +0 -245
  224. package/src/features/automations/var-access-resolver.ts +0 -140
  225. package/src/features/automations/when-evaluator.ts +0 -87
  226. package/src/features/automations/when-pushdown.ts +0 -57
  227. package/src/features/backrefs/__tests__/backrefs.handler.test.ts +0 -359
  228. package/src/features/backrefs/backrefs.handler.ts +0 -168
  229. package/src/features/backrefs/d1-backref.repository.ts +0 -84
  230. package/src/features/backrefs/index.ts +0 -5
  231. package/src/features/content/constants.ts +0 -16
  232. package/src/features/content/handlers/bulk.handler.ts +0 -185
  233. package/src/features/content/handlers/create.ts +0 -129
  234. package/src/features/content/handlers/delete.ts +0 -62
  235. package/src/features/content/handlers/facets.ts +0 -49
  236. package/src/features/content/handlers/get.ts +0 -120
  237. package/src/features/content/handlers/helpers.test.ts +0 -180
  238. package/src/features/content/handlers/helpers.ts +0 -93
  239. package/src/features/content/handlers/list.ts +0 -174
  240. package/src/features/content/handlers/update.ts +0 -174
  241. package/src/features/content/index.ts +0 -26
  242. package/src/features/draft/draft.handler.ts +0 -195
  243. package/src/features/draft/draft.middleware.ts +0 -66
  244. package/src/features/draft/index.ts +0 -5
  245. package/src/features/email/email.service.ts +0 -98
  246. package/src/features/email/email.types.ts +0 -119
  247. package/src/features/email/providers/resend.ts +0 -67
  248. package/src/features/email/providers/smtp.ts +0 -55
  249. package/src/features/email/templates/automation-mail.ts +0 -19
  250. package/src/features/email/templates/password-changed.ts +0 -63
  251. package/src/features/email/templates/password-reset.ts +0 -68
  252. package/src/features/email/templates/shell.ts +0 -96
  253. package/src/features/notifications/index.ts +0 -5
  254. package/src/features/notifications/notifications.handler.ts +0 -105
  255. package/src/features/password-reset/index.ts +0 -19
  256. package/src/features/password-reset/request.ts +0 -92
  257. package/src/features/password-reset/reset.ts +0 -102
  258. package/src/features/rotate-field/index.ts +0 -5
  259. package/src/features/rotate-field/rotate-field.handler.ts +0 -132
  260. package/src/features/rotate-field/rotate-field.schema.ts +0 -17
  261. package/src/features/schema/schema.handler.ts +0 -131
  262. package/src/features/seeds/index.ts +0 -5
  263. package/src/features/seeds/seeds.handler.test.ts +0 -632
  264. package/src/features/seeds/seeds.handler.ts +0 -693
  265. package/src/features/settings/__tests__/settings.handler.test.ts +0 -555
  266. package/src/features/settings/settings.handler.ts +0 -392
  267. package/src/features/setup/index.ts +0 -204
  268. package/src/features/stats/index.ts +0 -5
  269. package/src/features/stats/stats.handler.ts +0 -420
  270. package/src/features/webhooks/index.ts +0 -63
  271. package/src/index.ts +0 -65
  272. package/src/media-utils.ts +0 -82
  273. package/src/middleware/auth-providers.middleware.ts +0 -45
  274. package/src/middleware/observability.middleware.ts +0 -70
  275. package/src/middleware/rate-limit.middleware.ts +0 -45
  276. package/src/middleware/repository.middleware.ts +0 -114
  277. package/src/middleware/seed-registry.middleware.test.ts +0 -97
  278. package/src/middleware/seed-registry.middleware.ts +0 -21
  279. package/src/middleware/storage.middleware.ts +0 -25
  280. package/src/middleware.ts +0 -45
  281. package/src/public/access-policy.ts +0 -27
  282. package/src/public/api-key-middleware.ts +0 -57
  283. package/src/public/cache-utils.ts +0 -38
  284. package/src/public/entry-projection.ts +0 -46
  285. package/src/public/idempotency.ts +0 -23
  286. package/src/public/index.ts +0 -16
  287. package/src/public/problem-details.ts +0 -124
  288. package/src/public/public-add.ts +0 -114
  289. package/src/public/public-edit.ts +0 -163
  290. package/src/public/public-errors.ts +0 -19
  291. package/src/public/public-read.ts +0 -63
  292. package/src/public/public-routes.ts +0 -88
  293. package/src/public/query-builder.test.ts +0 -224
  294. package/src/public/query-builder.ts +0 -156
  295. package/src/public/rate-limit-middleware.ts +0 -34
  296. package/src/public/read-list.ts +0 -54
  297. package/src/public/read-single.ts +0 -48
  298. package/src/public/response-builder.ts +0 -30
  299. package/src/public/sanitize.ts +0 -69
  300. package/src/public/slug-utils.ts +0 -18
  301. package/src/rate-limit/cloudflare-rate-limiter.test.ts +0 -30
  302. package/src/rate-limit/cloudflare-rate-limiter.ts +0 -15
  303. package/src/rate-limit/in-memory-rate-limiter.test.ts +0 -37
  304. package/src/rate-limit/in-memory-rate-limiter.ts +0 -17
  305. package/src/rate-limit/no-op-rate-limiter.test.ts +0 -22
  306. package/src/rate-limit/no-op-rate-limiter.ts +0 -11
  307. package/src/search-utils.test.ts +0 -211
  308. package/src/search-utils.ts +0 -213
  309. package/src/search.ts +0 -65
  310. package/src/shared/apply-policies.test.ts +0 -81
  311. package/src/shared/apply-policies.ts +0 -67
  312. package/src/shared/automations.repository.d1.ts +0 -150
  313. package/src/shared/background-notification-service.test.ts +0 -62
  314. package/src/shared/background-notification-service.ts +0 -52
  315. package/src/shared/base.repository.d1.ts +0 -32
  316. package/src/shared/content-utils.test.ts +0 -165
  317. package/src/shared/content-utils.ts +0 -86
  318. package/src/shared/content.repository.d1.test.ts +0 -458
  319. package/src/shared/content.repository.d1.ts +0 -851
  320. package/src/shared/d1-activity-log.repository.test.ts +0 -140
  321. package/src/shared/d1-activity-log.repository.ts +0 -105
  322. package/src/shared/d1-activity-logger.test.ts +0 -86
  323. package/src/shared/d1-activity-logger.ts +0 -67
  324. package/src/shared/d1-analytics.repository.test.ts +0 -78
  325. package/src/shared/d1-analytics.repository.ts +0 -85
  326. package/src/shared/d1-content-scan.repository.test.ts +0 -80
  327. package/src/shared/d1-content-scan.repository.ts +0 -37
  328. package/src/shared/d1-notification.repository.test.ts +0 -128
  329. package/src/shared/d1-notification.repository.ts +0 -118
  330. package/src/shared/d1-password-reset-token.repository.test.ts +0 -81
  331. package/src/shared/d1-password-reset-token.repository.ts +0 -56
  332. package/src/shared/d1-search.repository.test.ts +0 -87
  333. package/src/shared/d1-search.repository.ts +0 -88
  334. package/src/shared/d1-session.repository.test.ts +0 -125
  335. package/src/shared/d1-session.repository.ts +0 -102
  336. package/src/shared/d1-setup-checklist.repository.ts +0 -36
  337. package/src/shared/d1-user.repository.test.ts +0 -151
  338. package/src/shared/d1-user.repository.ts +0 -119
  339. package/src/shared/d1-widget.repository.test.ts +0 -221
  340. package/src/shared/d1-widget.repository.ts +0 -341
  341. package/src/shared/demo-data-sql.ts +0 -54
  342. package/src/shared/demo-data.repository.d1.ts +0 -20
  343. package/src/shared/execution-context-scheduler.ts +0 -13
  344. package/src/shared/fixed-clock.ts +0 -25
  345. package/src/shared/fts-sync.ts +0 -8
  346. package/src/shared/idempotency.repository.d1.test.ts +0 -83
  347. package/src/shared/idempotency.repository.d1.ts +0 -60
  348. package/src/shared/in-memory-activity-logger.ts +0 -19
  349. package/src/shared/in-memory-notification-service.ts +0 -19
  350. package/src/shared/in-memory-seed.repository.ts +0 -51
  351. package/src/shared/media.repository.d1.test.ts +0 -107
  352. package/src/shared/media.repository.d1.ts +0 -68
  353. package/src/shared/qstash-notification-service.test.ts +0 -67
  354. package/src/shared/qstash-notification-service.ts +0 -55
  355. package/src/shared/query-utils.ts +0 -141
  356. package/src/shared/request-utils.ts +0 -26
  357. package/src/shared/schema-mutator.d1.ts +0 -64
  358. package/src/shared/seed-layout.repository.d1.test.ts +0 -114
  359. package/src/shared/seed-layout.repository.d1.ts +0 -62
  360. package/src/shared/seed-registry-cache.test.ts +0 -68
  361. package/src/shared/seed-registry-cache.ts +0 -49
  362. package/src/shared/seed.repository.d1.test.ts +0 -143
  363. package/src/shared/seed.repository.d1.ts +0 -98
  364. package/src/shared/sequential-id-generator.ts +0 -33
  365. package/src/shared/site-settings.repository.d1.ts +0 -53
  366. package/src/shared/storage/factory.ts +0 -41
  367. package/src/shared/storage/s3-bucket.ts +0 -195
  368. package/src/shared/storage-utils.ts +0 -40
  369. package/src/shared/system-stats.repository.d1.test.ts +0 -58
  370. package/src/shared/system-stats.repository.d1.ts +0 -48
  371. package/src/types.ts +0 -87
  372. package/src/upload.ts +0 -198
  373. package/src/widget.ts +0 -212
@@ -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.APP_URL) {
52
- notificationService = new QStashNotificationService(
53
- context.env.QSTASH_TOKEN,
54
- context.env.APP_URL,
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,114 +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 { D1SeedRepository } from '../shared/seed.repository.d1'
25
- import { D1SchemaMutator } from '../shared/schema-mutator.d1'
26
- import { SystemClock, SystemIdGenerator } from '@beechcms/core'
27
- 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 } from '@beechcms/core'
28
- import { NoOpScheduler } from '@beechcms/core'
29
- import { AutomationRunner } from '../features/automations'
30
- import { D1AutomationRepository } from '../shared/automations.repository.d1'
31
- import { ExecutionContextScheduler } from '../shared/execution-context-scheduler'
32
- import type { Env, Variables } from '../types'
33
-
34
- interface RepositoryOverrides {
35
- repository?: ContentRepository
36
- idempotencyRepository?: IdempotencyRepository
37
- mediaRepository?: MediaRepository
38
- systemStatsRepository?: SystemStatsRepository
39
- userRepository?: IUserRepository
40
- sessionRepository?: ISessionRepository
41
- passwordResetTokenRepository?: IPasswordResetTokenRepository
42
- activityLogRepository?: IActivityLogRepository
43
- notificationRepository?: INotificationRepository
44
- widgetRepository?: IWidgetRepository
45
- searchRepository?: ISearchRepository
46
- analyticsRepository?: IAnalyticsRepository
47
- contentScanRepository?: IContentScanRepository
48
- clock?: IClock
49
- idGenerator?: IIdGenerator
50
- automationRepository?: IAutomationRepository
51
- automationRunner?: IAutomationRunner
52
- scheduler?: IScheduler
53
- siteSettingsRepository?: ISiteSettingsRepository
54
- demoDataRepository?: IDemoDataRepository
55
- seedLayoutRepository?: ISeedLayoutRepository
56
- seedRepository?: ISeedRepository
57
- schemaMutator?: ISchemaMutator
58
- }
59
-
60
- function buildScheduler(context: Context): IScheduler {
61
- try {
62
- return new ExecutionContextScheduler(context.executionCtx)
63
- } catch {
64
- return new NoOpScheduler()
65
- }
66
- }
67
-
68
- export const repositoryMiddleware = (overrides?: RepositoryOverrides) => {
69
- return createMiddleware<{ Bindings: Env; Variables: Variables }>(async (context, next) => {
70
- const resolvedClock = overrides?.clock ?? SystemClock
71
- const resolvedIdGenerator = overrides?.idGenerator ?? SystemIdGenerator
72
- const database = context.env.DB
73
-
74
- context.set('repository', overrides?.repository ?? new D1ContentRepository(database))
75
- context.set('idempotencyRepository', overrides?.idempotencyRepository ?? new D1IdempotencyRepository(database))
76
- context.set('mediaRepository', overrides?.mediaRepository ?? new D1MediaRepository(database))
77
- context.set('systemStatsRepository', overrides?.systemStatsRepository ?? new D1SystemStatsRepository(database))
78
- context.set('userRepository', overrides?.userRepository ?? new D1UserRepository(database))
79
- context.set('sessionRepository', overrides?.sessionRepository ?? new D1SessionRepository(database, resolvedClock))
80
- context.set('passwordResetTokenRepository', overrides?.passwordResetTokenRepository ?? new D1PasswordResetTokenRepository(database, resolvedIdGenerator))
81
- context.set('activityLogRepository', overrides?.activityLogRepository ?? new D1ActivityLogRepository(database))
82
- context.set('notificationRepository', overrides?.notificationRepository ?? new D1NotificationRepository(database, resolvedClock, resolvedIdGenerator))
83
- context.set('widgetRepository', overrides?.widgetRepository ?? new D1WidgetRepository(database))
84
- context.set('searchRepository', overrides?.searchRepository ?? new D1SearchRepository(database))
85
- context.set('analyticsRepository', overrides?.analyticsRepository ?? new D1AnalyticsRepository(database, resolvedClock))
86
- context.set('contentScanRepository', overrides?.contentScanRepository ?? new D1ContentScanRepository(database))
87
- context.set('clock', resolvedClock)
88
- context.set('idGenerator', resolvedIdGenerator)
89
- const automationRepository = overrides?.automationRepository
90
- ?? new D1AutomationRepository(database)
91
-
92
- context.set('automationRepository', automationRepository)
93
- // getSeed is set later by seedRegistryMiddleware — capture context by closure so the
94
- // runner reads the live value at call time, not at middleware creation time.
95
- context.set(
96
- 'automationRunner',
97
- overrides?.automationRunner ?? new AutomationRunner({
98
- automationRepository,
99
- contentRepository: context.get('repository'),
100
- getSeed: (slug: string) => context.get('getSeed')?.(slug) ?? null,
101
- idGenerator: resolvedIdGenerator,
102
- env: context.env as unknown as Record<string, string | undefined>,
103
- }),
104
- )
105
- context.set('scheduler', overrides?.scheduler ?? buildScheduler(context))
106
- context.set('siteSettingsRepository', overrides?.siteSettingsRepository ?? new D1SiteSettingsRepository(database))
107
- context.set('demoDataRepository', overrides?.demoDataRepository ?? new D1DemoDataRepository(database))
108
- context.set('setupChecklistRepository', new D1SetupChecklistRepository(database))
109
- context.set('seedLayoutRepository', overrides?.seedLayoutRepository ?? new D1SeedLayoutRepository(database))
110
- context.set('seedRepository', overrides?.seedRepository ?? new D1SeedRepository(database))
111
- context.set('schemaMutator', overrides?.schemaMutator ?? new D1SchemaMutator(database))
112
- await next()
113
- })
114
- }
@@ -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
- }
@@ -1,57 +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 { Context, Next } from 'hono'
6
- import { PUBLIC_ERRORS } from './public-errors'
7
- import { publicProblem } from './problem-details'
8
-
9
- type PublicBindings = {
10
- PUBLIC_READ_API_KEY?: string
11
- PUBLIC_WRITE_API_KEY?: string
12
- }
13
-
14
- function isReadMethod(method: string): boolean {
15
- return method === 'GET' || method === 'HEAD' || method === 'OPTIONS'
16
- }
17
-
18
- function getConfiguredKey(env: PublicBindings, method: string): string | undefined {
19
- if (isReadMethod(method)) {
20
- return env.PUBLIC_READ_API_KEY
21
- }
22
- return env.PUBLIC_WRITE_API_KEY
23
- }
24
-
25
- /**
26
- * API key auth middleware for Public API routes.
27
- * Uses X-API-Key header only.
28
- */
29
- export function apiKeyMiddleware() {
30
- return async (c: Context, next: Next): Promise<Response | void> => {
31
- const env = c.env as PublicBindings
32
- const configuredKey = getConfiguredKey(env, c.req.method)
33
-
34
- if (!configuredKey) {
35
- return publicProblem(c, {
36
- type: 'public-api-not-configured',
37
- title: PUBLIC_ERRORS.API_KEY_FORBIDDEN.error,
38
- status: 403,
39
- detail: PUBLIC_ERRORS.API_KEY_FORBIDDEN.message,
40
- })
41
- }
42
-
43
- const providedKey = c.req.header('X-API-Key')
44
-
45
- if (!providedKey || providedKey !== configuredKey) {
46
- return publicProblem(c, {
47
- type: 'public-api-key-unauthorized',
48
- title: PUBLIC_ERRORS.API_KEY_UNAUTHORIZED.error,
49
- status: 401,
50
- detail: PUBLIC_ERRORS.API_KEY_UNAUTHORIZED.message,
51
- })
52
- }
53
-
54
- await next()
55
- }
56
- }
57
-
@@ -1,38 +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 { Context } from 'hono'
6
-
7
- type EdgeCache = {
8
- cache: Cache
9
- executionCtx: { waitUntil: (p: Promise<unknown>) => void }
10
- } | null
11
-
12
- export function resolveEdgeCache(c: Context): EdgeCache {
13
- try {
14
- const cache = caches.default
15
- let executionCtx: any
16
- try {
17
- executionCtx = c.executionCtx
18
- } catch {
19
- return null
20
- }
21
-
22
- if (!executionCtx?.waitUntil) return null
23
- return { cache, executionCtx: executionCtx as { waitUntil: (p: Promise<unknown>) => void } }
24
- } catch {
25
- return null
26
- }
27
- }
28
-
29
- export function withCachedResponse(edgeCache: EdgeCache, cacheKey: Request, response: Response): Response {
30
- if (!edgeCache) return response
31
- const cloned = response.clone()
32
- const headers = new Headers(cloned.headers)
33
- headers.set('Cache-Control', 'public, max-age=60')
34
- edgeCache.executionCtx.waitUntil(
35
- edgeCache.cache.put(cacheKey, new Response(cloned.body, { status: cloned.status, headers }))
36
- )
37
- return response
38
- }
@@ -1,46 +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 { resolvePolicies } from '@beechcms/core'
6
- import type { Seed } from '@beechcms/core'
7
-
8
- const SYSTEM_FIELDS = ['id', 'slug', 'status', 'created_at', 'updated_at']
9
- const IDENTITY_FIELDS = ['id', 'slug']
10
-
11
- function applyPublicPolicies(data: Record<string, unknown>, seed: Seed): Record<string, unknown> {
12
- const result: Record<string, unknown> = {}
13
-
14
- for (const key of SYSTEM_FIELDS) {
15
- if (key in data) result[key] = data[key]
16
- }
17
-
18
- for (const branch of seed.branches) {
19
- const value = data[branch.alias]
20
- const { public: isPublic, visibility } = resolvePolicies(branch)
21
- if (!isPublic) continue
22
- if (visibility === 'hidden') continue
23
- result[branch.alias] = visibility === 'masked' && typeof value === 'string' && value.length > 0
24
- ? '••••••••'
25
- : value
26
- }
27
- return result
28
- }
29
-
30
- export function toFlatPublicEntry(data: Record<string, unknown>, seed: Seed, fieldsParam?: string): Record<string, unknown> {
31
- const projected = applyPublicPolicies(data, seed)
32
- const requestedFields = (fieldsParam ?? '').split(',').map(f => f.trim()).filter(Boolean)
33
-
34
- if (requestedFields.length === 0) return projected
35
-
36
- const filtered: Record<string, unknown> = {}
37
- for (const field of requestedFields) {
38
- if (field in projected) filtered[field] = projected[field]
39
- }
40
-
41
- for (const key of IDENTITY_FIELDS) {
42
- if (key in projected && !filtered[key]) filtered[key] = projected[key]
43
- }
44
-
45
- return filtered
46
- }
@@ -1,23 +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 { sha256hex } from '@beechcms/core'
6
-
7
- export function parseIdempotencyKey(rawValue: string | undefined): string | null {
8
- if (!rawValue) return null
9
- const key = rawValue.trim()
10
- if (!key || key.length > 128) return null
11
- return key
12
- }
13
-
14
- type FingerprintInput = {
15
- seedSlug: string
16
- statusValue: unknown
17
- slug: string | null
18
- data: Record<string, unknown>
19
- }
20
-
21
- export function buildRequestFingerprint(input: FingerprintInput): Promise<string> {
22
- return sha256hex(JSON.stringify({ seedSlug: input.seedSlug, statusValue: input.statusValue, slug: input.slug, data: input.data }))
23
- }
@@ -1,16 +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
- export { apiKeyMiddleware } from './api-key-middleware'
6
- export { publicRateLimitMiddleware } from './rate-limit-middleware'
7
- export { publicRoutes } from './public-routes'
8
- export { PUBLIC_ERRORS } from './public-errors'
9
- export { sanitizePublicPayload } from './sanitize'
10
- export { generateEntrySlug, slugify } from './slug-utils'
11
- export { buildPublicListMeta, buildPublicSingleMeta } from './response-builder'
12
- export { parseLatestCount, parsePublicPagination } from './query-builder'
13
- export { publicReadHandler } from './public-read'
14
- export { publicAddHandler } from './public-add'
15
- export { publicEditHandler } from './public-edit'
16
-