@beechcms/api 0.5.0 → 0.6.0-preview.2

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 (225) hide show
  1. package/assets/dashboard/BeechLogo.svg +18 -18
  2. package/assets/dashboard/BeechLogoLIght.svg +48 -48
  3. package/assets/dashboard/Searching.svg +1 -0
  4. package/assets/dashboard/assets/chart-BrJFdsGZ.js +39 -0
  5. package/assets/dashboard/assets/index-CIaoMxuB.css +1 -0
  6. package/assets/dashboard/assets/index-wTKgygsg.js +636 -0
  7. package/assets/dashboard/assets/pie-chart-recharts-BEaE1FOE.js +1 -0
  8. package/assets/dashboard/assets/timeseries-chart-recharts-DmWM6imF.js +1 -0
  9. package/assets/dashboard/beechLogoDark.svg +48 -48
  10. package/assets/dashboard/index.html +18 -18
  11. package/assets/dashboard/noResult.svg +43 -0
  12. package/assets/dashboard/sol.svg +3 -3
  13. package/assets/dashboard/undraw_enter_nwx3.svg +36 -36
  14. package/assets/dashboard/working.svg +1 -0
  15. package/migrations/0000_v040_base.sql +265 -238
  16. package/migrations/0029_automations.sql +14 -14
  17. package/migrations/0030_test_seeds.sql +125 -125
  18. package/package.json +13 -9
  19. package/src/auth/{in-memory-hash-provider.ts → __fixtures__/in-memory-hash-provider.ts} +17 -13
  20. package/src/auth/{static-token-service.ts → __fixtures__/static-token-service.ts} +22 -18
  21. package/src/auth/bcrypt-hash-provider.ts +24 -20
  22. package/src/auth/constants.ts +14 -10
  23. package/src/auth/generate-refresh-token.test.ts +23 -19
  24. package/src/auth/hash-provider.test.ts +55 -46
  25. package/src/auth/jose-token-service.ts +62 -55
  26. package/src/auth/jwt-claims-passthrough.test.ts +87 -0
  27. package/src/auth/login.test.ts +100 -92
  28. package/src/auth/login.ts +78 -74
  29. package/src/auth/refresh.ts +11 -5
  30. package/src/auth/token-service.test.ts +90 -82
  31. package/src/factory.ts +370 -347
  32. package/src/features/automations/__tests__/action-executors.test.ts +255 -268
  33. package/src/features/automations/__tests__/automation-runner.test.ts +196 -192
  34. package/src/features/automations/__tests__/automation-runner.utils.test.ts +60 -56
  35. package/src/features/automations/__tests__/automations.handler.test.ts +264 -260
  36. package/src/features/automations/__tests__/automations.repository.test.ts +163 -159
  37. package/src/features/automations/__tests__/automations.schema.test.ts +224 -134
  38. package/src/features/automations/__tests__/context-resolver.test.ts +126 -122
  39. package/src/features/automations/__tests__/cron-runner.test.ts +267 -263
  40. package/src/features/automations/__tests__/cron-runner.utils.test.ts +144 -140
  41. package/src/features/automations/__tests__/set-variable.executor.test.ts +383 -306
  42. package/src/features/automations/__tests__/template-grammar.test.ts +308 -304
  43. package/src/features/automations/__tests__/webhook.executor.test.ts +142 -0
  44. package/src/features/automations/__tests__/when-evaluator.test.ts +274 -270
  45. package/src/features/automations/__tests__/when-pushdown.test.ts +281 -277
  46. package/src/features/automations/action-executors/create-entry.executor.ts +27 -23
  47. package/src/features/automations/action-executors/edit-field.executor.ts +26 -22
  48. package/src/features/automations/action-executors/index.ts +37 -33
  49. package/src/features/automations/action-executors/send-mail.executor.ts +53 -42
  50. package/src/features/automations/action-executors/set-variable.executor.ts +159 -146
  51. package/src/features/automations/action-executors/webhook.executor.ts +67 -25
  52. package/src/features/automations/automation-runner.ts +85 -81
  53. package/src/features/automations/automation-runner.utils.ts +47 -43
  54. package/src/features/automations/automations.handler.ts +197 -193
  55. package/src/features/automations/automations.schema.ts +177 -160
  56. package/src/features/automations/context-resolver.ts +152 -148
  57. package/src/features/automations/cron-runner.ts +140 -136
  58. package/src/features/automations/cron-runner.utils.ts +44 -40
  59. package/src/features/automations/filter-translation.ts +46 -42
  60. package/src/features/automations/index.ts +16 -12
  61. package/src/features/automations/template-grammar.ts +245 -241
  62. package/src/features/automations/var-access-resolver.ts +140 -136
  63. package/src/features/automations/when-evaluator.ts +87 -83
  64. package/src/features/automations/when-pushdown.ts +57 -53
  65. package/src/features/backrefs/__tests__/backrefs.handler.test.ts +359 -0
  66. package/src/features/backrefs/backrefs.handler.ts +168 -0
  67. package/src/features/backrefs/d1-backref.repository.ts +84 -0
  68. package/src/features/backrefs/index.ts +5 -0
  69. package/src/features/content/constants.ts +16 -10
  70. package/src/features/content/handlers/bulk.handler.ts +185 -0
  71. package/src/features/content/handlers/create.ts +129 -165
  72. package/src/features/content/handlers/delete.ts +62 -87
  73. package/src/features/content/handlers/facets.ts +49 -45
  74. package/src/features/content/handlers/get.ts +120 -116
  75. package/src/features/content/handlers/helpers.test.ts +180 -0
  76. package/src/features/content/handlers/helpers.ts +93 -0
  77. package/src/features/content/handlers/list.ts +174 -88
  78. package/src/features/content/handlers/update.ts +174 -219
  79. package/src/features/content/index.ts +26 -20
  80. package/src/features/dashboard-layout/__tests__/dashboard-layout.handler.test.ts +388 -0
  81. package/src/features/dashboard-layout/dashboard-layout.handler.ts +206 -0
  82. package/src/features/dashboard-layout/index.ts +5 -0
  83. package/src/features/draft/draft.handler.ts +195 -170
  84. package/src/features/draft/draft.middleware.ts +66 -62
  85. package/src/features/draft/index.ts +5 -1
  86. package/src/features/email/email.provider.ts +42 -38
  87. package/src/features/email/email.service.ts +98 -93
  88. package/src/features/email/email.types.ts +119 -108
  89. package/src/features/email/index.ts +33 -29
  90. package/src/features/email/providers/resend.ts +67 -63
  91. package/src/features/email/providers/smtp.ts +55 -0
  92. package/src/features/email/templates/automation-mail.ts +19 -15
  93. package/src/features/email/templates/password-changed.ts +63 -59
  94. package/src/features/email/templates/password-reset.ts +68 -64
  95. package/src/features/email/templates/shell.ts +96 -92
  96. package/src/features/notifications/index.ts +5 -1
  97. package/src/features/notifications/notifications.handler.ts +105 -101
  98. package/src/features/password-reset/index.ts +19 -15
  99. package/src/features/password-reset/request.ts +92 -82
  100. package/src/features/password-reset/reset.ts +102 -92
  101. package/src/features/rotate-field/index.ts +5 -1
  102. package/src/features/rotate-field/rotate-field.handler.ts +132 -128
  103. package/src/features/rotate-field/rotate-field.schema.ts +17 -13
  104. package/src/features/schema/schema.handler.ts +131 -16
  105. package/src/features/seeds/index.ts +5 -0
  106. package/src/features/seeds/seeds.handler.test.ts +1199 -0
  107. package/src/features/seeds/seeds.handler.ts +558 -0
  108. package/src/features/settings/__tests__/settings.handler.test.ts +555 -0
  109. package/src/features/settings/settings.handler.ts +392 -302
  110. package/src/features/setup/index.ts +288 -91
  111. package/src/features/stats/index.ts +5 -1
  112. package/src/features/stats/stats.handler.ts +420 -430
  113. package/src/features/webhooks/index.ts +63 -0
  114. package/src/index.ts +65 -56
  115. package/src/media-utils.ts +82 -78
  116. package/src/middleware/auth-providers.middleware.test.ts +85 -0
  117. package/src/middleware/auth-providers.middleware.ts +45 -32
  118. package/src/middleware/observability.middleware.test.ts +93 -0
  119. package/src/middleware/observability.middleware.ts +70 -52
  120. package/src/middleware/rate-limit.middleware.ts +45 -41
  121. package/src/middleware/repository.middleware.ts +117 -91
  122. package/src/middleware/seed-registry.middleware.test.ts +97 -0
  123. package/src/middleware/seed-registry.middleware.ts +21 -0
  124. package/src/middleware/storage.middleware.ts +25 -21
  125. package/src/middleware.ts +45 -47
  126. package/src/public/access-policy.ts +27 -23
  127. package/src/public/api-key-middleware.ts +57 -53
  128. package/src/public/cache-utils.ts +38 -34
  129. package/src/public/entry-projection.ts +46 -42
  130. package/src/public/idempotency.ts +23 -19
  131. package/src/public/index.ts +16 -12
  132. package/src/public/problem-details.ts +124 -53
  133. package/src/public/public-add.ts +114 -110
  134. package/src/public/public-edit.ts +163 -159
  135. package/src/public/public-errors.ts +19 -15
  136. package/src/public/public-read.ts +63 -59
  137. package/src/public/public-routes.ts +88 -84
  138. package/src/public/query-builder.test.ts +224 -220
  139. package/src/public/query-builder.ts +156 -152
  140. package/src/public/rate-limit-middleware.ts +34 -30
  141. package/src/public/read-list.ts +54 -50
  142. package/src/public/read-single.ts +48 -44
  143. package/src/public/response-builder.ts +30 -26
  144. package/src/public/sanitize.ts +69 -65
  145. package/src/public/slug-utils.ts +18 -14
  146. package/src/rate-limit/cloudflare-rate-limiter.test.ts +30 -26
  147. package/src/rate-limit/cloudflare-rate-limiter.ts +15 -11
  148. package/src/rate-limit/in-memory-rate-limiter.test.ts +37 -33
  149. package/src/rate-limit/in-memory-rate-limiter.ts +17 -13
  150. package/src/rate-limit/no-op-rate-limiter.test.ts +22 -18
  151. package/src/rate-limit/no-op-rate-limiter.ts +11 -7
  152. package/src/search-utils.test.ts +211 -207
  153. package/src/search-utils.ts +213 -209
  154. package/src/search.ts +65 -61
  155. package/src/shared/apply-policies.test.ts +81 -77
  156. package/src/shared/apply-policies.ts +67 -63
  157. package/src/shared/automations.repository.d1.ts +150 -146
  158. package/src/shared/background-notification-service.test.ts +62 -58
  159. package/src/shared/background-notification-service.ts +52 -48
  160. package/src/shared/base.repository.d1.ts +32 -28
  161. package/src/shared/content-utils.test.ts +165 -161
  162. package/src/shared/content-utils.ts +86 -82
  163. package/src/shared/content.repository.d1.test.ts +507 -312
  164. package/src/shared/content.repository.d1.ts +851 -382
  165. package/src/shared/d1-activity-log.repository.test.ts +140 -136
  166. package/src/shared/d1-activity-log.repository.ts +105 -101
  167. package/src/shared/d1-activity-logger.test.ts +86 -82
  168. package/src/shared/d1-activity-logger.ts +67 -63
  169. package/src/shared/d1-analytics.repository.test.ts +78 -74
  170. package/src/shared/d1-analytics.repository.ts +85 -81
  171. package/src/shared/d1-content-scan.repository.test.ts +80 -76
  172. package/src/shared/d1-content-scan.repository.ts +37 -29
  173. package/src/shared/d1-notification.repository.test.ts +128 -124
  174. package/src/shared/d1-notification.repository.ts +118 -114
  175. package/src/shared/d1-password-reset-token.repository.test.ts +81 -77
  176. package/src/shared/d1-password-reset-token.repository.ts +56 -52
  177. package/src/shared/d1-search.repository.test.ts +87 -83
  178. package/src/shared/d1-search.repository.ts +88 -84
  179. package/src/shared/d1-session.repository.test.ts +125 -121
  180. package/src/shared/d1-session.repository.ts +102 -98
  181. package/src/shared/d1-setup-checklist.repository.ts +36 -0
  182. package/src/shared/d1-user.repository.test.ts +151 -147
  183. package/src/shared/d1-user.repository.ts +119 -109
  184. package/src/shared/d1-widget.repository.test.ts +267 -217
  185. package/src/shared/d1-widget.repository.ts +385 -337
  186. package/src/shared/dashboard-layout.repository.d1.test.ts +135 -0
  187. package/src/shared/dashboard-layout.repository.d1.ts +58 -0
  188. package/src/shared/demo-data-sql.ts +216 -0
  189. package/src/shared/demo-data.repository.d1.ts +20 -0
  190. package/src/shared/execution-context-scheduler.ts +13 -9
  191. package/src/shared/fixed-clock.ts +25 -21
  192. package/src/shared/fts-sync.ts +8 -4
  193. package/src/shared/idempotency.repository.d1.test.ts +83 -79
  194. package/src/shared/idempotency.repository.d1.ts +60 -56
  195. package/src/shared/in-memory-activity-logger.ts +19 -15
  196. package/src/shared/in-memory-notification-service.ts +19 -15
  197. package/src/shared/in-memory-seed.repository.ts +58 -0
  198. package/src/shared/media.repository.d1.test.ts +107 -103
  199. package/src/shared/media.repository.d1.ts +68 -64
  200. package/src/shared/qstash-notification-service.test.ts +67 -0
  201. package/src/shared/qstash-notification-service.ts +55 -0
  202. package/src/shared/query-utils.ts +141 -137
  203. package/src/shared/request-utils.ts +26 -22
  204. package/src/shared/schema-mutator.d1.test.ts +142 -0
  205. package/src/shared/schema-mutator.d1.ts +64 -0
  206. package/src/shared/seed-layout.repository.d1.test.ts +114 -0
  207. package/src/shared/seed-layout.repository.d1.ts +62 -0
  208. package/src/shared/seed-registry-cache.test.ts +68 -0
  209. package/src/shared/seed-registry-cache.ts +49 -0
  210. package/src/shared/seed.repository.d1.test.ts +143 -0
  211. package/src/shared/seed.repository.d1.ts +98 -0
  212. package/src/shared/sequential-id-generator.ts +33 -22
  213. package/src/shared/site-settings.repository.d1.ts +53 -0
  214. package/src/shared/storage/factory.ts +41 -40
  215. package/src/shared/storage/s3-bucket.ts +195 -163
  216. package/src/shared/storage-utils.ts +40 -36
  217. package/src/shared/system-stats.repository.d1.test.ts +58 -54
  218. package/src/shared/system-stats.repository.d1.ts +48 -44
  219. package/src/types.ts +90 -67
  220. package/src/upload.ts +198 -187
  221. package/src/widget.test.ts +85 -0
  222. package/src/widget.ts +251 -208
  223. package/assets/dashboard/assets/index-B1mUfgiK.css +0 -1
  224. package/assets/dashboard/assets/index-CHxxc_id.js +0 -629
  225. package/src/shared/storage/r2-binding-bucket.ts +0 -81
@@ -1,84 +1,88 @@
1
- import { Hono } from 'hono'
2
- import type { AppEnv } from '../types'
3
- import { publicReadHandler } from './public-read'
4
- import { publicAddHandler } from './public-add'
5
- import { publicEditHandler } from './public-edit'
6
-
7
- const publicApp = new Hono<AppEnv>()
8
-
9
- publicApp.get('/health', (c) => {
10
- return c.json({ ok: true, service: 'public-api' }, 200)
11
- })
12
-
13
- /** Returns the public-facing schema: only seeds with public read or post enabled. */
14
- publicApp.get('/schema', (c) => {
15
- const registry = c.get('seedRegistry')
16
- const publicSeeds = registry.all()
17
- .filter(seed => seed.allowPublicRead === true || seed.allowPublicPost === true || seed.allowPublicEdit === true)
18
- .map(seed => ({
19
- slug: seed.slug,
20
- label: seed.label,
21
- labelPlural: seed.labelPlural,
22
- allowPublicRead: seed.allowPublicRead ?? false,
23
- allowPublicPost: seed.allowPublicPost ?? false,
24
- allowPublicEdit: seed.allowPublicEdit ?? false,
25
- branches: (seed.branches ?? []).map(branch => ({
26
- alias: branch.alias,
27
- type: branch.type,
28
- label: branch.label,
29
- requiredOnCreate: branch.requiredOnCreate ?? false,
30
- policies: {
31
- public: branch.policies?.public ?? true,
32
- visibility: branch.policies?.visibility ?? 'full',
33
- },
34
- })),
35
- }))
36
- return c.json({ seeds: publicSeeds })
37
- })
38
-
39
- /** HTML render of the public schema for quick browser inspection. */
40
- publicApp.get('/schema.html', (c) => {
41
- const registry = c.get('seedRegistry')
42
- const publicSeeds = registry.all()
43
- .filter(seed => seed.allowPublicRead === true || seed.allowPublicPost === true || seed.allowPublicEdit === true)
44
-
45
- const seedHtml = publicSeeds.map(seed => {
46
- const ops = [
47
- seed.allowPublicRead && 'GET /:seed',
48
- seed.allowPublicPost && 'POST /:seed/add',
49
- seed.allowPublicEdit && 'PUT /:seed/edit/:id',
50
- ].filter(Boolean).join(', ')
51
-
52
- const branchRows = (seed.branches ?? []).map(b =>
53
- `<tr><td>${b.alias}</td><td>${b.type}</td><td>${b.label}</td><td>${b.requiredOnCreate ? 'yes' : ''}</td><td>${(b.policies?.public ?? true) ? 'readable' : 'hidden'}</td></tr>`
54
- ).join('')
55
-
56
- return `<section>
57
- <h2>${seed.label} <code>${seed.slug}</code></h2>
58
- <p><strong>Allowed operations:</strong> ${ops || 'none'}</p>
59
- <table><thead><tr><th>alias</th><th>type</th><th>label</th><th>required</th><th>public access</th></tr></thead>
60
- <tbody>${branchRows}</tbody></table>
61
- </section>`
62
- }).join('\n')
63
-
64
- const html = `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8">
65
- <title>BeechCMS Public Schema</title>
66
- <style>body{font-family:system-ui,sans-serif;max-width:900px;margin:2rem auto;padding:0 1rem;color:#222}
67
- code{background:#f3f4f6;padding:2px 6px;border-radius:4px}
68
- table{border-collapse:collapse;width:100%}th,td{text-align:left;padding:6px 10px;border:1px solid #e5e7eb}
69
- th{background:#f9fafb}h2{margin-top:2rem}section{margin-bottom:2rem}</style>
70
- </head><body>
71
- <h1>BeechCMS — Public API Schema</h1>
72
- <p>Only content types with public access enabled are listed here.</p>
73
- ${seedHtml || '<p><em>No content types with public access configured.</em></p>'}
74
- </body></html>`
75
-
76
- return c.html(html)
77
- })
78
-
79
- publicApp.get('/:seed', publicReadHandler)
80
- publicApp.post('/:seed/add', publicAddHandler)
81
- publicApp.put('/:seed/edit/:id', publicEditHandler)
82
-
83
- export const publicRoutes = publicApp
84
-
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 { Hono } from 'hono'
6
+ import type { AppEnv } from '../types'
7
+ import { publicReadHandler } from './public-read'
8
+ import { publicAddHandler } from './public-add'
9
+ import { publicEditHandler } from './public-edit'
10
+
11
+ const publicApp = new Hono<AppEnv>()
12
+
13
+ publicApp.get('/health', (c) => {
14
+ return c.json({ ok: true, service: 'public-api' }, 200)
15
+ })
16
+
17
+ /** Returns the public-facing schema: only seeds with public read or post enabled. */
18
+ publicApp.get('/schema', (c) => {
19
+ const registry = c.get('seedRegistry')
20
+ const publicSeeds = registry.all()
21
+ .filter(seed => seed.allowPublicRead === true || seed.allowPublicPost === true || seed.allowPublicEdit === true)
22
+ .map(seed => ({
23
+ slug: seed.slug,
24
+ label: seed.label,
25
+ labelPlural: seed.labelPlural,
26
+ allowPublicRead: seed.allowPublicRead ?? false,
27
+ allowPublicPost: seed.allowPublicPost ?? false,
28
+ allowPublicEdit: seed.allowPublicEdit ?? false,
29
+ branches: (seed.branches ?? []).map(branch => ({
30
+ alias: branch.alias,
31
+ type: branch.type,
32
+ label: branch.label,
33
+ requiredOnCreate: branch.requiredOnCreate ?? false,
34
+ policies: {
35
+ public: branch.policies?.public ?? true,
36
+ visibility: branch.policies?.visibility ?? 'full',
37
+ },
38
+ })),
39
+ }))
40
+ return c.json({ seeds: publicSeeds })
41
+ })
42
+
43
+ /** HTML render of the public schema for quick browser inspection. */
44
+ publicApp.get('/schema.html', (c) => {
45
+ const registry = c.get('seedRegistry')
46
+ const publicSeeds = registry.all()
47
+ .filter(seed => seed.allowPublicRead === true || seed.allowPublicPost === true || seed.allowPublicEdit === true)
48
+
49
+ const seedHtml = publicSeeds.map(seed => {
50
+ const ops = [
51
+ seed.allowPublicRead && 'GET /:seed',
52
+ seed.allowPublicPost && 'POST /:seed/add',
53
+ seed.allowPublicEdit && 'PUT /:seed/edit/:id',
54
+ ].filter(Boolean).join(', ')
55
+
56
+ const branchRows = (seed.branches ?? []).map(b =>
57
+ `<tr><td>${b.alias}</td><td>${b.type}</td><td>${b.label}</td><td>${b.requiredOnCreate ? 'yes' : ''}</td><td>${(b.policies?.public ?? true) ? 'readable' : 'hidden'}</td></tr>`
58
+ ).join('')
59
+
60
+ return `<section>
61
+ <h2>${seed.label} <code>${seed.slug}</code></h2>
62
+ <p><strong>Allowed operations:</strong> ${ops || 'none'}</p>
63
+ <table><thead><tr><th>alias</th><th>type</th><th>label</th><th>required</th><th>public access</th></tr></thead>
64
+ <tbody>${branchRows}</tbody></table>
65
+ </section>`
66
+ }).join('\n')
67
+
68
+ const html = `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8">
69
+ <title>BeechCMS Public Schema</title>
70
+ <style>body{font-family:system-ui,sans-serif;max-width:900px;margin:2rem auto;padding:0 1rem;color:#222}
71
+ code{background:#f3f4f6;padding:2px 6px;border-radius:4px}
72
+ table{border-collapse:collapse;width:100%}th,td{text-align:left;padding:6px 10px;border:1px solid #e5e7eb}
73
+ th{background:#f9fafb}h2{margin-top:2rem}section{margin-bottom:2rem}</style>
74
+ </head><body>
75
+ <h1>BeechCMS — Public API Schema</h1>
76
+ <p>Only content types with public access enabled are listed here.</p>
77
+ ${seedHtml || '<p><em>No content types with public access configured.</em></p>'}
78
+ </body></html>`
79
+
80
+ return c.html(html)
81
+ })
82
+
83
+ publicApp.get('/:seed', publicReadHandler)
84
+ publicApp.post('/:seed/add', publicAddHandler)
85
+ publicApp.put('/:seed/edit/:id', publicEditHandler)
86
+
87
+ export const publicRoutes = publicApp
88
+