@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,177 +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
- // Mirror: apps/dashboard/src/features/automations/schema/automation.schema.ts — keep structurally identical.
6
- import { z } from 'zod'
7
- import type { WhenNode } from '@beechcms/core'
8
- import { isPrivateHost } from '@beechcms/core'
9
- import { AUTOMATION_RESERVED_WORDS } from './template-grammar'
10
-
11
- // ---------------------------------------------------------------------------
12
- // Trigger conditions — recursive WhenNode schema (Task 14)
13
- // ---------------------------------------------------------------------------
14
-
15
- const whenOperandSchema = z.union([
16
- z.object({ kind: z.literal('literal'), value: z.unknown() }),
17
- z.object({ kind: z.literal('ref'), key: z.string().min(1) }),
18
- ])
19
-
20
- const whenPredicateSchema = z.object({
21
- kind: z.literal('predicate'),
22
- left: whenOperandSchema,
23
- op: z.enum(['eq', 'neq', 'gt', 'gte', 'lt', 'lte', 'contains', 'startswith', 'endswith', 'in', 'notin', 'isempty', 'isnotempty', 'matches']),
24
- right: whenOperandSchema.optional(),
25
- })
26
-
27
- const whenNodeSchema: z.ZodType<WhenNode> = z.lazy(() =>
28
- z.union([
29
- whenPredicateSchema,
30
- z.object({
31
- kind: z.literal('group'),
32
- op: z.enum(['AND', 'OR']),
33
- children: z.array(whenNodeSchema).min(1),
34
- negate: z.boolean().optional(),
35
- }).refine(
36
- (g) => depthOf(g) <= 10,
37
- { message: 'WhenNode nesting exceeds maximum depth of 10' },
38
- ),
39
- ]),
40
- )
41
-
42
- function depthOf(node: unknown, d = 0): number {
43
- if (d > 10) return d
44
- if (typeof node !== 'object' || !node) return d
45
- const n = node as Record<string, unknown>
46
- if (n['kind'] === 'group' && Array.isArray(n['children'])) {
47
- return Math.max(...(n['children'] as unknown[]).map((c) => depthOf(c, d + 1)))
48
- }
49
- return d
50
- }
51
-
52
- const triggerConditionsSchema = whenNodeSchema.nullable().optional()
53
-
54
- const setVariableFilterSchema = z.object({
55
- field: z.string().min(1),
56
- op: z.enum(['eq', 'neq', 'contains', 'gt', 'lt', 'isempty', 'isnotempty']),
57
- value: z.unknown(),
58
- })
59
-
60
- // ---------------------------------------------------------------------------
61
- // Action schemas
62
- // ---------------------------------------------------------------------------
63
-
64
- const setVariableActionSchema = z.object({
65
- type: z.literal('set_variable'),
66
- name: z
67
- .string()
68
- .min(1)
69
- .regex(/^[a-zA-Z_][a-zA-Z0-9_]*$/)
70
- .refine((v) => !AUTOMATION_RESERVED_WORDS.has(v), {
71
- message: 'automations.editor.errors.variableNameReserved',
72
- }),
73
- seed_slug: z.string().min(1).optional(),
74
- fixed_id: z.string().min(1).optional(),
75
- column: z.string().min(1).optional(),
76
- filters: z.array(setVariableFilterSchema).default([]),
77
- order_by: z.string().optional(),
78
- order: z.enum(['asc', 'desc']).optional(),
79
- load_type: z.enum(['fruit', 'branch']).optional(), // accepted but ignored at runtime
80
- })
81
-
82
- const webhookActionSchema = z.object({
83
- type: z.literal('webhook'),
84
- url: z
85
- .string()
86
- .url()
87
- .refine((u) => {
88
- try { return new URL(u).protocol === 'https:' } catch { return false }
89
- }, { message: 'automations.editor.errors.webhookHttpsRequired' })
90
- .refine((u) => {
91
- try { return !isPrivateHost(new URL(u).hostname) } catch { return false }
92
- }, { message: 'automations.editor.errors.webhookPrivateHostBlocked' }),
93
- method: z.enum(['POST', 'GET', 'PUT']).optional(),
94
- headers: z.record(z.string(), z.string()).optional(),
95
- body_template: z.preprocess(
96
- (v) => (v == null ? '' : v),
97
- z.string().min(1, 'automations.editor.errors.bodyRequired'),
98
- ),
99
- })
100
-
101
- const sendMailActionSchema = z.object({
102
- type: z.literal('send_mail'),
103
- to: z.string().email(),
104
- subject_template: z.string().min(1),
105
- body_template: z.string().min(1),
106
- })
107
-
108
- const editFieldActionSchema = z.object({
109
- type: z.literal('edit_field'),
110
- field: z.string().min(1),
111
- value: z.unknown(),
112
- })
113
-
114
- const createEntryActionSchema = z.object({
115
- type: z.literal('create_entry'),
116
- seed_slug: z.string().min(1),
117
- field_map: z.record(z.string(), z.string()),
118
- })
119
-
120
- export const automationActionSchema = z.discriminatedUnion('type', [
121
- setVariableActionSchema,
122
- webhookActionSchema,
123
- sendMailActionSchema,
124
- editFieldActionSchema,
125
- createEntryActionSchema,
126
- ])
127
-
128
- // ---------------------------------------------------------------------------
129
- // Triggers schema
130
- // ---------------------------------------------------------------------------
131
-
132
- const automationTriggerSchema = z.object({
133
- event: z.enum(['create', 'update', 'delete', 'cron']),
134
- cron: z.string().nullable().optional(),
135
- })
136
-
137
- const triggersSchema = z
138
- .array(automationTriggerSchema)
139
- .min(1, 'At least one trigger is required')
140
- .refine(
141
- (triggers) => triggers.filter((t) => t.event === 'cron').length <= 1,
142
- { message: 'Only one cron trigger is allowed per automation' },
143
- )
144
- .refine(
145
- (triggers) => {
146
- const events = triggers.map((t) => t.event)
147
- return new Set(events).size === events.length
148
- },
149
- { message: 'Duplicate trigger events are not allowed' },
150
- )
151
- .refine(
152
- (triggers) => triggers.every((t) => t.event !== 'cron' || !!t.cron),
153
- { message: 'cron expression is required for cron triggers', path: ['cron'] },
154
- )
155
-
156
- // ---------------------------------------------------------------------------
157
- // Automation create/update schemas
158
- // ---------------------------------------------------------------------------
159
-
160
- const createAutomationBaseSchema = z.object({
161
- seed_slug: z.string().min(1),
162
- name: z.string().min(1).max(100),
163
- triggers: triggersSchema,
164
- trigger_conditions: triggerConditionsSchema,
165
- actions: z.array(automationActionSchema).min(1, 'At least one action is required'),
166
- })
167
-
168
- export const createAutomationSchema = createAutomationBaseSchema
169
-
170
- export const updateAutomationSchema = createAutomationBaseSchema.partial()
171
-
172
- export const toggleAutomationSchema = z.object({
173
- enabled: z.boolean(),
174
- })
175
-
176
- export type CreateAutomationBody = z.infer<typeof createAutomationSchema>
177
- export type UpdateAutomationBody = z.infer<typeof updateAutomationSchema>
@@ -1,152 +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 { Automation } from '@beechcms/core'
6
- import type { AutomationContextSelector, ParsedKey } from './template-grammar'
7
- import { resolvePath } from './automation-runner.utils'
8
-
9
- export interface ResolvedContext {
10
- lookup(key: ParsedKey, onMissing?: (field: string) => void): unknown
11
- triggerEntry: Record<string, unknown> | null
12
- }
13
-
14
- const MAX_PLUCK = 100
15
- const AGGREGATE_OPS = new Set(['count', 'sum', 'avg', 'min', 'max', 'pluck'])
16
-
17
- function applyAggregate(
18
- op: string,
19
- field: string | null,
20
- rows: Array<Record<string, unknown>>,
21
- onMissing?: (f: string) => void,
22
- ): unknown {
23
- switch (op) {
24
- case 'count':
25
- return rows.length
26
-
27
- case 'sum': {
28
- if (!field) { if (onMissing) onMissing('sum:field'); return 0 }
29
- return rows.reduce((acc, r) => {
30
- const v = Number(r[field])
31
- if (Number.isNaN(v)) { if (onMissing) onMissing(`sum:${field}:NaN`); return acc }
32
- return acc + v
33
- }, 0)
34
- }
35
-
36
- case 'avg': {
37
- if (!field || rows.length === 0) { if (onMissing && !field) onMissing('avg:field'); return 0 }
38
- const total = rows.reduce((acc, r) => {
39
- const v = Number(r[field])
40
- if (Number.isNaN(v)) { if (onMissing) onMissing(`avg:${field}:NaN`); return acc }
41
- return acc + v
42
- }, 0)
43
- return rows.length > 0 ? total / rows.length : 0
44
- }
45
-
46
- case 'min': {
47
- if (!field || rows.length === 0) { if (onMissing && !field) onMissing('min:field'); return null }
48
- return rows.reduce<number | null>((acc, r) => {
49
- const v = Number(r[field])
50
- if (Number.isNaN(v)) return acc
51
- return acc === null || v < acc ? v : acc
52
- }, null)
53
- }
54
-
55
- case 'max': {
56
- if (!field || rows.length === 0) { if (onMissing && !field) onMissing('max:field'); return null }
57
- return rows.reduce<number | null>((acc, r) => {
58
- const v = Number(r[field])
59
- if (Number.isNaN(v)) return acc
60
- return acc === null || v > acc ? v : acc
61
- }, null)
62
- }
63
-
64
- case 'pluck': {
65
- if (!field) { if (onMissing) onMissing('pluck:field'); return '' }
66
- const values = rows.slice(0, MAX_PLUCK).map((r) => String(r[field] ?? ''))
67
- const truncated = rows.length > MAX_PLUCK
68
- return values.join(', ') + (truncated ? ' …' : '')
69
- }
70
-
71
- default:
72
- return undefined
73
- }
74
- }
75
-
76
- export async function resolveAutomationContext(
77
- _automation: Automation,
78
- triggerEntry: Record<string, unknown> | null,
79
- batchEntries: Array<Record<string, unknown>>,
80
- ): Promise<ResolvedContext> {
81
- function lookup(parsed: ParsedKey, onMissing?: (field: string) => void): unknown {
82
- if (parsed.kind === 'simple') {
83
- if (parsed.path.startsWith('this.')) {
84
- const field = parsed.path.slice(5)
85
- const val = resolvePath(triggerEntry ?? {}, field)
86
- if (val === undefined && onMissing) onMissing(parsed.path)
87
- return val
88
- }
89
- const val = resolvePath(triggerEntry ?? {}, parsed.path)
90
- if (val === undefined && onMissing) onMissing(parsed.path)
91
- return val
92
- }
93
-
94
- if (parsed.kind !== 'scoped') {
95
- if (onMissing) onMissing(parsed.kind === 'var_access' ? parsed.name : 'unknown')
96
- return undefined
97
- }
98
-
99
- const { scope, selector: _selector, op, field } = parsed
100
-
101
- if (scope === 'this') {
102
- if (op !== 'field' || !field) { if (onMissing) onMissing(`this.${field}`); return undefined }
103
- const val = resolvePath(triggerEntry ?? {}, field)
104
- if (val === undefined && onMissing) onMissing(`this.${field}`)
105
- return val
106
- }
107
-
108
- if (scope === 'batch') {
109
- if (op === 'field') {
110
- if (!field) { if (onMissing) onMissing('batch.field'); return undefined }
111
- const val = resolvePath(batchEntries[0] ?? {}, field)
112
- if (val === undefined && onMissing) onMissing(`batch.${field}`)
113
- return val
114
- }
115
- return applyAggregate(op, field, batchEntries, onMissing)
116
- }
117
-
118
- if (onMissing) onMissing(scope)
119
- return undefined
120
- }
121
-
122
- return { lookup, triggerEntry }
123
- }
124
-
125
- export function deriveEntryContext(
126
- base: ResolvedContext,
127
- entry: Record<string, unknown>,
128
- ): ResolvedContext {
129
- return {
130
- lookup(parsed: ParsedKey, onMissing?: (field: string) => void): unknown {
131
- if (parsed.kind === 'simple') {
132
- if (parsed.path.startsWith('this.')) {
133
- const field = parsed.path.slice(5)
134
- const val = resolvePath(entry, field)
135
- if (val === undefined && onMissing) onMissing(parsed.path)
136
- return val
137
- }
138
- const val = resolvePath(entry, parsed.path)
139
- if (val === undefined && onMissing) onMissing(parsed.path)
140
- return val
141
- }
142
- if (parsed.kind === 'scoped' && parsed.scope === 'this') {
143
- if (parsed.op !== 'field' || !parsed.field) { if (onMissing) onMissing('this.field'); return undefined }
144
- const val = resolvePath(entry, parsed.field)
145
- if (val === undefined && onMissing) onMissing(`this.${parsed.field}`)
146
- return val
147
- }
148
- return base.lookup(parsed, onMissing)
149
- },
150
- triggerEntry: entry,
151
- }
152
- }
@@ -1,140 +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 {
6
- Automation,
7
- ContentRepository,
8
- FilterGroup,
9
- IAutomationRepository,
10
- IIdGenerator,
11
- Seed,
12
- } from '@beechcms/core'
13
- import { cronMatches } from './cron-runner.utils'
14
- import { executeAction } from './action-executors'
15
- import { resolveAutomationContext, deriveEntryContext } from './context-resolver'
16
- import { extractPushdownFilters } from './when-pushdown'
17
- import { evaluateWhen } from './when-evaluator'
18
-
19
- export interface CronRunnerDeps {
20
- automationRepository: IAutomationRepository
21
- contentRepository: ContentRepository
22
- getSeed: (slug: string) => Seed | null
23
- env: Record<string, string | undefined>
24
- idGenerator: IIdGenerator
25
- }
26
-
27
- // These actions mutate individual entries and must run once per entry.
28
- // All other actions (send_mail, webhook) run once per automation with a batch context.
29
- const PER_ENTRY_ACTIONS = new Set(['edit_field', 'create_entry'])
30
-
31
- export async function runCronAutomations(
32
- deps: CronRunnerDeps,
33
- scheduledTime: number,
34
- ): Promise<void> {
35
- console.log(`[cron] Starting runCronAutomations at scheduledTime: ${new Date(scheduledTime).toISOString()}`)
36
-
37
- let automations: Automation[]
38
- try {
39
- automations = await deps.automationRepository.findActive('*', 'cron')
40
- } catch (err) {
41
- console.error('[cron] Failed to fetch automations — is migration 0029_automations.sql applied?', err)
42
- return
43
- }
44
-
45
- console.log(`[cron] Found ${automations.length} active cron automation(s)`)
46
-
47
- for (const automation of automations) {
48
- const cronTrigger = automation.triggers.find((t) => t.event === 'cron')
49
- if (!cronMatches(cronTrigger?.cron ?? null, scheduledTime)) {
50
- console.log(`[cron] Skipping "${automation.name}": cron expression "${cronTrigger?.cron}" does not match.`)
51
- continue
52
- }
53
-
54
- const seed = deps.getSeed(automation.seed_slug)
55
- if (!seed) {
56
- console.warn('[cron] unknown seed', { automationId: automation.id, seedSlug: automation.seed_slug })
57
- continue
58
- }
59
-
60
- let entries: Array<Record<string, unknown>> = []
61
- try {
62
- entries = await fetchMatchingEntries(deps.contentRepository, seed, automation)
63
- console.log(`[cron] Fetched ${entries.length} matching entries for automation "${automation.name}"`)
64
- } catch (err) {
65
- console.error('[cron] fetch entries failed', { automationId: automation.id, err })
66
- continue
67
- }
68
-
69
- if (entries.length === 0) continue
70
-
71
- // Build the base ResolvedContext once per automation (shared seed-query cache).
72
- // triggerEntry = first entry; batchEntries = full SQL-filtered list.
73
- const batchResolved = await resolveAutomationContext(
74
- automation,
75
- entries[0] ?? null,
76
- entries,
77
- )
78
-
79
- const variables: Record<string, unknown> = {}
80
- const baseCtx = {
81
- env: deps.env,
82
- repository: deps.contentRepository,
83
- getSeed: deps.getSeed,
84
- seed,
85
- idGenerator: deps.idGenerator,
86
- variables,
87
- }
88
-
89
- for (const action of automation.actions) {
90
- if (PER_ENTRY_ACTIONS.has(action.type)) {
91
- for (const entry of entries) {
92
- // Per-entry: derive a lightweight context whose `this` is the current entry.
93
- // Seed-query cache is reused from batchResolved.
94
- const entryResolved = deriveEntryContext(batchResolved, entry)
95
- // In-memory per-entry condition check (Task 13)
96
- if (!evaluateWhen(automation.trigger_conditions, entryResolved)) continue
97
- try {
98
- await executeAction(action, { ...baseCtx, entry, context: entryResolved })
99
- } catch (err) {
100
- console.error('[cron] entry action failed', {
101
- automationId: automation.id,
102
- entryId: entry['id'],
103
- actionType: action.type,
104
- err,
105
- })
106
- }
107
- }
108
- } else {
109
- // Batch actions run once per automation with the shared batch context.
110
- try {
111
- await executeAction(action, { ...baseCtx, entry: entries[0] ?? {}, context: batchResolved })
112
- } catch (err) {
113
- console.error('[cron] batch action failed', {
114
- automationId: automation.id,
115
- actionType: action.type,
116
- err,
117
- })
118
- }
119
- }
120
- }
121
- }
122
- }
123
-
124
- async function fetchMatchingEntries(
125
- repository: ContentRepository,
126
- seed: Seed,
127
- automation: Automation,
128
- ): Promise<Array<Record<string, unknown>>> {
129
- // Task 12: push down only safe predicates to SQL (this.<field> = literal, AND group only).
130
- // OR branches, cross-seed refs, and gte/lte/etc. ops are evaluated in-memory by evaluateWhen().
131
- const filters: FilterGroup[] = automation.trigger_conditions
132
- ? extractPushdownFilters(automation.trigger_conditions, seed)
133
- : []
134
- const result = await repository.findMany(seed, {
135
- filters,
136
- status: null,
137
- pagination: { limit: 1000, offset: 0 },
138
- })
139
- return result.items
140
- }
@@ -1,44 +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 function cronMatches(expression: string | null, scheduledTime: number): boolean {
6
- if (!expression) return false
7
- const parts = expression.trim().split(/\s+/)
8
- if (parts.length !== 5) return false
9
-
10
- const d = new Date(scheduledTime)
11
- const actual = [
12
- d.getUTCMinutes(),
13
- d.getUTCHours(),
14
- d.getUTCDate(),
15
- d.getUTCMonth() + 1,
16
- d.getUTCDay(),
17
- ] as const
18
-
19
- return parts.every((field, i) => matchField(field, actual[i]))
20
- }
21
-
22
- function matchField(field: string, value: number): boolean {
23
- if (field === '*') return true
24
- if (field.includes(',')) {
25
- return field.split(',').some((part) => matchField(part, value))
26
- }
27
- if (field.includes('/')) {
28
- const [rangePart, stepPart] = field.split('/')
29
- const step = Number(stepPart)
30
- if (!Number.isFinite(step) || step <= 0) return false
31
- if (rangePart === '*') return value % step === 0
32
- if (rangePart.includes('-')) {
33
- const [lo, hi] = rangePart.split('-').map(Number)
34
- return value >= lo && value <= hi && (value - lo) % step === 0
35
- }
36
- return false
37
- }
38
- if (field.includes('-')) {
39
- const [lo, hi] = field.split('-').map(Number)
40
- return Number.isFinite(lo) && Number.isFinite(hi) && value >= lo && value <= hi
41
- }
42
- const n = Number(field)
43
- return Number.isFinite(n) && n === value
44
- }
@@ -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
- /**
6
- * Shared helper: converts a TriggerCondition into a FilterGroup accepted by
7
- * ContentRepository.findMany. Used by cron-runner and context-resolver.
8
- *
9
- * TODO Sprint 8 (Task 12): when-pushdown.ts will call extractPushdownFilters
10
- * to convert safe WhenNode predicates to FilterGroup[] for SQL pre-filtering.
11
- */
12
- import type { BranchType, FilterGroup, FilterOperator, FilterType, Seed, TriggerCondition } from '@beechcms/core'
13
-
14
- const SYSTEM_COLUMNS = new Set(['id', 'slug', 'status', 'created_at', 'updated_at'])
15
-
16
- function mapBranchTypeToFilterType(type: BranchType): FilterType {
17
- switch (type) {
18
- case 'number': return 'number'
19
- case 'boolean': return 'boolean'
20
- case 'date': return 'date'
21
- case 'tags': return 'tags'
22
- case 'json': return 'json'
23
- default: return 'text'
24
- }
25
- }
26
-
27
- function mapOp(op: TriggerCondition['op']): FilterOperator {
28
- switch (op) {
29
- case 'isempty': return 'is_empty'
30
- case 'isnotempty': return 'is_not_empty'
31
- default: return op
32
- }
33
- }
34
-
35
- export function conditionToFilterGroup(c: TriggerCondition, seed: Seed): FilterGroup {
36
- const branch = seed.branches.find((b) => b.alias === c.field)
37
- const type: FilterType = branch
38
- ? mapBranchTypeToFilterType(branch.type)
39
- : SYSTEM_COLUMNS.has(c.field) ? 'system' : 'text'
40
-
41
- return {
42
- column: c.field,
43
- type,
44
- conditions: [{ op: mapOp(c.op), value: c.value as string | number | boolean | null }],
45
- }
46
- }
@@ -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 { AutomationRunner } from './automation-runner'
6
- export type { AutomationRunnerDeps } from './automation-runner'
7
- export { runCronAutomations } from './cron-runner'
8
- export type { CronRunnerDeps } from './cron-runner'
9
- export { automationsApp } from './automations.handler'
10
- export {
11
- createAutomationSchema,
12
- updateAutomationSchema,
13
- toggleAutomationSchema,
14
- automationActionSchema,
15
- } from './automations.schema'
16
- export type { CreateAutomationBody, UpdateAutomationBody } from './automations.schema'