@we8/cms 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/README.md +78 -0
  2. package/dist/auth/auth.d.ts +87 -0
  3. package/dist/auth/auth.d.ts.map +1 -0
  4. package/dist/auth/auth.js +90 -0
  5. package/dist/auth/auth.js.map +1 -0
  6. package/dist/auth/routes.admin.d.ts +22 -0
  7. package/dist/auth/routes.admin.d.ts.map +1 -0
  8. package/dist/auth/routes.admin.js +106 -0
  9. package/dist/auth/routes.admin.js.map +1 -0
  10. package/dist/auth/schema.d.ts +1395 -0
  11. package/dist/auth/schema.d.ts.map +1 -0
  12. package/dist/auth/schema.js +76 -0
  13. package/dist/auth/schema.js.map +1 -0
  14. package/dist/env.d.ts +64 -0
  15. package/dist/env.d.ts.map +1 -0
  16. package/dist/env.js +48 -0
  17. package/dist/env.js.map +1 -0
  18. package/dist/index.d.ts +22 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +170 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/keys/middleware.d.ts +54 -0
  23. package/dist/keys/middleware.d.ts.map +1 -0
  24. package/dist/keys/middleware.js +84 -0
  25. package/dist/keys/middleware.js.map +1 -0
  26. package/dist/keys/routes.admin.d.ts +16 -0
  27. package/dist/keys/routes.admin.d.ts.map +1 -0
  28. package/dist/keys/routes.admin.js +34 -0
  29. package/dist/keys/routes.admin.js.map +1 -0
  30. package/dist/keys/service.d.ts +36 -0
  31. package/dist/keys/service.d.ts.map +1 -0
  32. package/dist/keys/service.js +120 -0
  33. package/dist/keys/service.js.map +1 -0
  34. package/dist/lib/bots.d.ts +24 -0
  35. package/dist/lib/bots.d.ts.map +1 -0
  36. package/dist/lib/bots.js +79 -0
  37. package/dist/lib/bots.js.map +1 -0
  38. package/dist/lib/email.d.ts +62 -0
  39. package/dist/lib/email.d.ts.map +1 -0
  40. package/dist/lib/email.js +64 -0
  41. package/dist/lib/email.js.map +1 -0
  42. package/dist/lib/errors.d.ts +12 -0
  43. package/dist/lib/errors.d.ts.map +1 -0
  44. package/dist/lib/errors.js +23 -0
  45. package/dist/lib/errors.js.map +1 -0
  46. package/dist/lib/notify.d.ts +20 -0
  47. package/dist/lib/notify.d.ts.map +1 -0
  48. package/dist/lib/notify.js +60 -0
  49. package/dist/lib/notify.js.map +1 -0
  50. package/dist/lib/retention.d.ts +15 -0
  51. package/dist/lib/retention.d.ts.map +1 -0
  52. package/dist/lib/retention.js +40 -0
  53. package/dist/lib/retention.js.map +1 -0
  54. package/dist/lib/sanitize.d.ts +14 -0
  55. package/dist/lib/sanitize.d.ts.map +1 -0
  56. package/dist/lib/sanitize.js +145 -0
  57. package/dist/lib/sanitize.js.map +1 -0
  58. package/dist/lib/turnstile.d.ts +7 -0
  59. package/dist/lib/turnstile.d.ts.map +1 -0
  60. package/dist/lib/turnstile.js +32 -0
  61. package/dist/lib/turnstile.js.map +1 -0
  62. package/dist/lib/validate.d.ts +11 -0
  63. package/dist/lib/validate.d.ts.map +1 -0
  64. package/dist/lib/validate.js +22 -0
  65. package/dist/lib/validate.js.map +1 -0
  66. package/dist/lib/word-count.d.ts +7 -0
  67. package/dist/lib/word-count.d.ts.map +1 -0
  68. package/dist/lib/word-count.js +14 -0
  69. package/dist/lib/word-count.js.map +1 -0
  70. package/dist/middleware/auth.d.ts +46 -0
  71. package/dist/middleware/auth.d.ts.map +1 -0
  72. package/dist/middleware/auth.js +60 -0
  73. package/dist/middleware/auth.js.map +1 -0
  74. package/dist/middleware/cors.d.ts +33 -0
  75. package/dist/middleware/cors.d.ts.map +1 -0
  76. package/dist/middleware/cors.js +55 -0
  77. package/dist/middleware/cors.js.map +1 -0
  78. package/dist/middleware/module-gate.d.ts +11 -0
  79. package/dist/middleware/module-gate.d.ts.map +1 -0
  80. package/dist/middleware/module-gate.js +18 -0
  81. package/dist/middleware/module-gate.js.map +1 -0
  82. package/dist/middleware/rate-limit.d.ts +13 -0
  83. package/dist/middleware/rate-limit.d.ts.map +1 -0
  84. package/dist/middleware/rate-limit.js +30 -0
  85. package/dist/middleware/rate-limit.js.map +1 -0
  86. package/dist/middleware/request-id.d.ts +8 -0
  87. package/dist/middleware/request-id.d.ts.map +1 -0
  88. package/dist/middleware/request-id.js +11 -0
  89. package/dist/middleware/request-id.js.map +1 -0
  90. package/dist/modules/aeo/checks.d.ts +41 -0
  91. package/dist/modules/aeo/checks.d.ts.map +1 -0
  92. package/dist/modules/aeo/checks.js +127 -0
  93. package/dist/modules/aeo/checks.js.map +1 -0
  94. package/dist/modules/aeo/llms.d.ts +24 -0
  95. package/dist/modules/aeo/llms.d.ts.map +1 -0
  96. package/dist/modules/aeo/llms.js +92 -0
  97. package/dist/modules/aeo/llms.js.map +1 -0
  98. package/dist/modules/aeo/routes.admin.d.ts +12 -0
  99. package/dist/modules/aeo/routes.admin.d.ts.map +1 -0
  100. package/dist/modules/aeo/routes.admin.js +37 -0
  101. package/dist/modules/aeo/routes.admin.js.map +1 -0
  102. package/dist/modules/analytics/db.d.ts +24 -0
  103. package/dist/modules/analytics/db.d.ts.map +1 -0
  104. package/dist/modules/analytics/db.js +24 -0
  105. package/dist/modules/analytics/db.js.map +1 -0
  106. package/dist/modules/analytics/routes.admin.d.ts +6 -0
  107. package/dist/modules/analytics/routes.admin.d.ts.map +1 -0
  108. package/dist/modules/analytics/routes.admin.js +21 -0
  109. package/dist/modules/analytics/routes.admin.js.map +1 -0
  110. package/dist/modules/analytics/routes.public.d.ts +6 -0
  111. package/dist/modules/analytics/routes.public.d.ts.map +1 -0
  112. package/dist/modules/analytics/routes.public.js +33 -0
  113. package/dist/modules/analytics/routes.public.js.map +1 -0
  114. package/dist/modules/analytics/service.d.ts +16 -0
  115. package/dist/modules/analytics/service.d.ts.map +1 -0
  116. package/dist/modules/analytics/service.js +148 -0
  117. package/dist/modules/analytics/service.js.map +1 -0
  118. package/dist/modules/authors/routes.admin.d.ts +6 -0
  119. package/dist/modules/authors/routes.admin.d.ts.map +1 -0
  120. package/dist/modules/authors/routes.admin.js +29 -0
  121. package/dist/modules/authors/routes.admin.js.map +1 -0
  122. package/dist/modules/authors/routes.public.d.ts +6 -0
  123. package/dist/modules/authors/routes.public.d.ts.map +1 -0
  124. package/dist/modules/authors/routes.public.js +11 -0
  125. package/dist/modules/authors/routes.public.js.map +1 -0
  126. package/dist/modules/authors/service.d.ts +26 -0
  127. package/dist/modules/authors/service.d.ts.map +1 -0
  128. package/dist/modules/authors/service.js +116 -0
  129. package/dist/modules/authors/service.js.map +1 -0
  130. package/dist/modules/content/db.d.ts +127 -0
  131. package/dist/modules/content/db.d.ts.map +1 -0
  132. package/dist/modules/content/db.js +203 -0
  133. package/dist/modules/content/db.js.map +1 -0
  134. package/dist/modules/content/publish.d.ts +38 -0
  135. package/dist/modules/content/publish.d.ts.map +1 -0
  136. package/dist/modules/content/publish.js +184 -0
  137. package/dist/modules/content/publish.js.map +1 -0
  138. package/dist/modules/content/routes.admin.d.ts +8 -0
  139. package/dist/modules/content/routes.admin.d.ts.map +1 -0
  140. package/dist/modules/content/routes.admin.js +122 -0
  141. package/dist/modules/content/routes.admin.js.map +1 -0
  142. package/dist/modules/content/routes.public.d.ts +6 -0
  143. package/dist/modules/content/routes.public.d.ts.map +1 -0
  144. package/dist/modules/content/routes.public.js +56 -0
  145. package/dist/modules/content/routes.public.js.map +1 -0
  146. package/dist/modules/content/service.d.ts +137 -0
  147. package/dist/modules/content/service.d.ts.map +1 -0
  148. package/dist/modules/content/service.js +348 -0
  149. package/dist/modules/content/service.js.map +1 -0
  150. package/dist/modules/forms/db.d.ts +42 -0
  151. package/dist/modules/forms/db.d.ts.map +1 -0
  152. package/dist/modules/forms/db.js +62 -0
  153. package/dist/modules/forms/db.js.map +1 -0
  154. package/dist/modules/forms/forms-routes.admin.d.ts +6 -0
  155. package/dist/modules/forms/forms-routes.admin.d.ts.map +1 -0
  156. package/dist/modules/forms/forms-routes.admin.js +37 -0
  157. package/dist/modules/forms/forms-routes.admin.js.map +1 -0
  158. package/dist/modules/forms/forms-service.d.ts +18 -0
  159. package/dist/modules/forms/forms-service.d.ts.map +1 -0
  160. package/dist/modules/forms/forms-service.js +121 -0
  161. package/dist/modules/forms/forms-service.js.map +1 -0
  162. package/dist/modules/forms/routes.public.d.ts +6 -0
  163. package/dist/modules/forms/routes.public.d.ts.map +1 -0
  164. package/dist/modules/forms/routes.public.js +41 -0
  165. package/dist/modules/forms/routes.public.js.map +1 -0
  166. package/dist/modules/forms/submissions-routes.admin.d.ts +6 -0
  167. package/dist/modules/forms/submissions-routes.admin.d.ts.map +1 -0
  168. package/dist/modules/forms/submissions-routes.admin.js +46 -0
  169. package/dist/modules/forms/submissions-routes.admin.js.map +1 -0
  170. package/dist/modules/forms/submissions-service.d.ts +45 -0
  171. package/dist/modules/forms/submissions-service.d.ts.map +1 -0
  172. package/dist/modules/forms/submissions-service.js +174 -0
  173. package/dist/modules/forms/submissions-service.js.map +1 -0
  174. package/dist/modules/media/db.d.ts +15 -0
  175. package/dist/modules/media/db.d.ts.map +1 -0
  176. package/dist/modules/media/db.js +24 -0
  177. package/dist/modules/media/db.js.map +1 -0
  178. package/dist/modules/media/routes.admin.d.ts +6 -0
  179. package/dist/modules/media/routes.admin.d.ts.map +1 -0
  180. package/dist/modules/media/routes.admin.js +30 -0
  181. package/dist/modules/media/routes.admin.js.map +1 -0
  182. package/dist/modules/media/routes.public.d.ts +6 -0
  183. package/dist/modules/media/routes.public.d.ts.map +1 -0
  184. package/dist/modules/media/routes.public.js +35 -0
  185. package/dist/modules/media/routes.public.js.map +1 -0
  186. package/dist/modules/media/service.d.ts +32 -0
  187. package/dist/modules/media/service.d.ts.map +1 -0
  188. package/dist/modules/media/service.js +99 -0
  189. package/dist/modules/media/service.js.map +1 -0
  190. package/dist/modules/openapi/spec.d.ts +21 -0
  191. package/dist/modules/openapi/spec.d.ts.map +1 -0
  192. package/dist/modules/openapi/spec.js +468 -0
  193. package/dist/modules/openapi/spec.js.map +1 -0
  194. package/dist/modules/seo/jsonld.d.ts +25 -0
  195. package/dist/modules/seo/jsonld.d.ts.map +1 -0
  196. package/dist/modules/seo/jsonld.js +67 -0
  197. package/dist/modules/seo/jsonld.js.map +1 -0
  198. package/dist/modules/seo/routes.public.d.ts +6 -0
  199. package/dist/modules/seo/routes.public.d.ts.map +1 -0
  200. package/dist/modules/seo/routes.public.js +39 -0
  201. package/dist/modules/seo/routes.public.js.map +1 -0
  202. package/dist/modules/seo/sitemap.d.ts +3 -0
  203. package/dist/modules/seo/sitemap.d.ts.map +1 -0
  204. package/dist/modules/seo/sitemap.js +39 -0
  205. package/dist/modules/seo/sitemap.js.map +1 -0
  206. package/dist/modules/settings/routes.admin.d.ts +12 -0
  207. package/dist/modules/settings/routes.admin.d.ts.map +1 -0
  208. package/dist/modules/settings/routes.admin.js +27 -0
  209. package/dist/modules/settings/routes.admin.js.map +1 -0
  210. package/dist/modules/site-documents/routes.admin.d.ts +10 -0
  211. package/dist/modules/site-documents/routes.admin.d.ts.map +1 -0
  212. package/dist/modules/site-documents/routes.admin.js +29 -0
  213. package/dist/modules/site-documents/routes.admin.js.map +1 -0
  214. package/dist/modules/site-documents/routes.public.d.ts +6 -0
  215. package/dist/modules/site-documents/routes.public.d.ts.map +1 -0
  216. package/dist/modules/site-documents/routes.public.js +16 -0
  217. package/dist/modules/site-documents/routes.public.js.map +1 -0
  218. package/dist/modules/site-documents/service.d.ts +11 -0
  219. package/dist/modules/site-documents/service.d.ts.map +1 -0
  220. package/dist/modules/site-documents/service.js +42 -0
  221. package/dist/modules/site-documents/service.js.map +1 -0
  222. package/dist/modules/webhooks/dispatch.d.ts +14 -0
  223. package/dist/modules/webhooks/dispatch.d.ts.map +1 -0
  224. package/dist/modules/webhooks/dispatch.js +84 -0
  225. package/dist/modules/webhooks/dispatch.js.map +1 -0
  226. package/dist/shared/constants.d.ts +79 -0
  227. package/dist/shared/constants.d.ts.map +1 -0
  228. package/dist/shared/constants.js +89 -0
  229. package/dist/shared/constants.js.map +1 -0
  230. package/dist/shared/envelope.d.ts +37 -0
  231. package/dist/shared/envelope.d.ts.map +1 -0
  232. package/dist/shared/envelope.js +46 -0
  233. package/dist/shared/envelope.js.map +1 -0
  234. package/dist/shared/hash.d.ts +2 -0
  235. package/dist/shared/hash.d.ts.map +1 -0
  236. package/dist/shared/hash.js +8 -0
  237. package/dist/shared/hash.js.map +1 -0
  238. package/dist/shared/index.d.ts +13 -0
  239. package/dist/shared/index.d.ts.map +1 -0
  240. package/dist/shared/index.js +13 -0
  241. package/dist/shared/index.js.map +1 -0
  242. package/dist/shared/schemas/aeo.d.ts +182 -0
  243. package/dist/shared/schemas/aeo.d.ts.map +1 -0
  244. package/dist/shared/schemas/aeo.js +43 -0
  245. package/dist/shared/schemas/aeo.js.map +1 -0
  246. package/dist/shared/schemas/analytics.d.ts +277 -0
  247. package/dist/shared/schemas/analytics.d.ts.map +1 -0
  248. package/dist/shared/schemas/analytics.js +74 -0
  249. package/dist/shared/schemas/analytics.js.map +1 -0
  250. package/dist/shared/schemas/api-key.d.ts +77 -0
  251. package/dist/shared/schemas/api-key.d.ts.map +1 -0
  252. package/dist/shared/schemas/api-key.js +27 -0
  253. package/dist/shared/schemas/api-key.js.map +1 -0
  254. package/dist/shared/schemas/author.d.ts +147 -0
  255. package/dist/shared/schemas/author.d.ts.map +1 -0
  256. package/dist/shared/schemas/author.js +27 -0
  257. package/dist/shared/schemas/author.js.map +1 -0
  258. package/dist/shared/schemas/form.d.ts +341 -0
  259. package/dist/shared/schemas/form.d.ts.map +1 -0
  260. package/dist/shared/schemas/form.js +117 -0
  261. package/dist/shared/schemas/form.js.map +1 -0
  262. package/dist/shared/schemas/index.d.ts +12 -0
  263. package/dist/shared/schemas/index.d.ts.map +1 -0
  264. package/dist/shared/schemas/index.js +12 -0
  265. package/dist/shared/schemas/index.js.map +1 -0
  266. package/dist/shared/schemas/media.d.ts +42 -0
  267. package/dist/shared/schemas/media.d.ts.map +1 -0
  268. package/dist/shared/schemas/media.js +16 -0
  269. package/dist/shared/schemas/media.js.map +1 -0
  270. package/dist/shared/schemas/pagination.d.ts +34 -0
  271. package/dist/shared/schemas/pagination.d.ts.map +1 -0
  272. package/dist/shared/schemas/pagination.js +21 -0
  273. package/dist/shared/schemas/pagination.js.map +1 -0
  274. package/dist/shared/schemas/post.d.ts +862 -0
  275. package/dist/shared/schemas/post.d.ts.map +1 -0
  276. package/dist/shared/schemas/post.js +187 -0
  277. package/dist/shared/schemas/post.js.map +1 -0
  278. package/dist/shared/schemas/settings.d.ts +839 -0
  279. package/dist/shared/schemas/settings.d.ts.map +1 -0
  280. package/dist/shared/schemas/settings.js +202 -0
  281. package/dist/shared/schemas/settings.js.map +1 -0
  282. package/dist/shared/schemas/site-document.d.ts +38 -0
  283. package/dist/shared/schemas/site-document.d.ts.map +1 -0
  284. package/dist/shared/schemas/site-document.js +21 -0
  285. package/dist/shared/schemas/site-document.js.map +1 -0
  286. package/dist/shared/schemas/webhook.d.ts +39 -0
  287. package/dist/shared/schemas/webhook.d.ts.map +1 -0
  288. package/dist/shared/schemas/webhook.js +20 -0
  289. package/dist/shared/schemas/webhook.js.map +1 -0
  290. package/dist/spa.d.ts +9 -0
  291. package/dist/spa.d.ts.map +1 -0
  292. package/dist/spa.js +57 -0
  293. package/dist/spa.js.map +1 -0
  294. package/migrations/0001_settings.sql +39 -0
  295. package/migrations/0002_content.sql +135 -0
  296. package/migrations/0003_forms.sql +35 -0
  297. package/migrations/0004_analytics.sql +42 -0
  298. package/migrations/0005_media.sql +17 -0
  299. package/migrations/0006_site_documents.sql +18 -0
  300. package/migrations/0007_auth.sql +81 -0
  301. package/migrations/0008_api_keys.sql +20 -0
  302. package/package.json +68 -0
  303. package/scripts/bundle-admin.mjs +54 -0
  304. package/seed/local.sql +63 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/auth/schema.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAYf,CAAC;AAEH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWlB,CAAC;AAEH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmBlB,CAAC;AAEH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAOvB,CAAC;AAEH,oEAAoE;AACpE,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAA2C,CAAC"}
@@ -0,0 +1,76 @@
1
+ import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';
2
+ /**
3
+ * The Better Auth table shape, expressed as Drizzle SQLite tables.
4
+ *
5
+ * This is NOT a second source of truth for the schema: the physical tables are
6
+ * created by migrations/0007_auth.sql, and these objects only describe those
7
+ * exact columns so the Better Auth Drizzle adapter can build typed queries
8
+ * against them. The two are kept in lockstep by hand.
9
+ *
10
+ * Column types follow from how the adapter behaves: it passes native Date and
11
+ * boolean values through to Drizzle rather than pre-serializing them, so date
12
+ * fields are `integer({ mode: 'timestamp' })` (epoch seconds in, Date out) and
13
+ * boolean fields are `integer({ mode: 'boolean' })` (0/1 in, boolean out).
14
+ * Everything else is text, including ids, which are Better Auth's own
15
+ * generated strings.
16
+ *
17
+ * The object KEYS are Better Auth model names (singular), because the adapter
18
+ * resolves a column as `schema[model][field]`; the string passed to each column
19
+ * helper is the physical SQL column name, kept identical to the field name.
20
+ */
21
+ export const user = sqliteTable('user', {
22
+ id: text('id').primaryKey(),
23
+ name: text('name').notNull(),
24
+ email: text('email').notNull().unique(),
25
+ emailVerified: integer('emailVerified', { mode: 'boolean' }).notNull().default(false),
26
+ image: text('image'),
27
+ createdAt: integer('createdAt', { mode: 'timestamp' }).notNull(),
28
+ updatedAt: integer('updatedAt', { mode: 'timestamp' }).notNull(),
29
+ // This package's own additional field: 'owner' or 'member'. Declared with
30
+ // input: false in the auth config, so it is assigned server-side on creation
31
+ // and unreachable from the account-update endpoint.
32
+ role: text('role'),
33
+ });
34
+ export const session = sqliteTable('session', {
35
+ id: text('id').primaryKey(),
36
+ expiresAt: integer('expiresAt', { mode: 'timestamp' }).notNull(),
37
+ token: text('token').notNull().unique(),
38
+ createdAt: integer('createdAt', { mode: 'timestamp' }).notNull(),
39
+ updatedAt: integer('updatedAt', { mode: 'timestamp' }).notNull(),
40
+ ipAddress: text('ipAddress'),
41
+ userAgent: text('userAgent'),
42
+ userId: text('userId')
43
+ .notNull()
44
+ .references(() => user.id, { onDelete: 'cascade' }),
45
+ });
46
+ export const account = sqliteTable('account', {
47
+ id: text('id').primaryKey(),
48
+ // Who vouches for this identity: the local credential issuer for an email
49
+ // and password login. (issuer, accountId) is the identity's unique key.
50
+ issuer: text('issuer').notNull(),
51
+ accountId: text('accountId').notNull(),
52
+ providerId: text('providerId').notNull(),
53
+ userId: text('userId')
54
+ .notNull()
55
+ .references(() => user.id, { onDelete: 'cascade' }),
56
+ accessToken: text('accessToken'),
57
+ refreshToken: text('refreshToken'),
58
+ idToken: text('idToken'),
59
+ accessTokenExpiresAt: integer('accessTokenExpiresAt', { mode: 'timestamp' }),
60
+ refreshTokenExpiresAt: integer('refreshTokenExpiresAt', { mode: 'timestamp' }),
61
+ scope: text('scope'),
62
+ password: text('password'),
63
+ createdAt: integer('createdAt', { mode: 'timestamp' }).notNull(),
64
+ updatedAt: integer('updatedAt', { mode: 'timestamp' }).notNull(),
65
+ });
66
+ export const verification = sqliteTable('verification', {
67
+ id: text('id').primaryKey(),
68
+ identifier: text('identifier').notNull(),
69
+ value: text('value').notNull(),
70
+ expiresAt: integer('expiresAt', { mode: 'timestamp' }).notNull(),
71
+ createdAt: integer('createdAt', { mode: 'timestamp' }).notNull(),
72
+ updatedAt: integer('updatedAt', { mode: 'timestamp' }).notNull(),
73
+ });
74
+ /** The single object handed to `drizzleAdapter(db, { schema })`. */
75
+ export const authSchema = { user, session, account, verification };
76
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/auth/schema.ts"],"names":[],"mappings":"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"}
package/dist/env.d.ts ADDED
@@ -0,0 +1,64 @@
1
+ import { type SiteSettings, type SiteSettingsUpdateInput } from './shared/index.js';
2
+ /**
3
+ * Everything this worker consumes from its environment. One site, one
4
+ * database, one bucket: there is no tenant id, no dispatch namespace, and no
5
+ * control plane, because there is nothing above this worker to belong to.
6
+ */
7
+ export interface Bindings {
8
+ /** The site's D1 database. Content, forms, analytics, auth, and keys all live here. */
9
+ DB: D1Database;
10
+ /** The site's R2 bucket, holding uploaded media bytes. */
11
+ MEDIA: R2Bucket;
12
+ /**
13
+ * The built admin portal, served from this same worker. Optional: a headless
14
+ * install deploys with an empty assets directory and runs API-only, and the
15
+ * SPA fallback in src/spa.ts stands down when there is nothing behind this.
16
+ */
17
+ ASSETS?: Fetcher;
18
+ /** The public origin of the site this CMS backs, e.g. `https://example.com`. */
19
+ SITE_URL: string;
20
+ /** The version string reported by /v1/health. Set from the package version at deploy time. */
21
+ CMS_VERSION: string;
22
+ /**
23
+ * The secret Better Auth signs sessions with. A deployment MUST set this;
24
+ * `wrangler secret put BETTER_AUTH_SECRET` in production, `.dev.vars`
25
+ * locally. Sign-in is refused when it is missing rather than falling back to
26
+ * a default, because a predictable session secret is a forged session.
27
+ */
28
+ BETTER_AUTH_SECRET?: string;
29
+ /**
30
+ * The origin Better Auth builds its own URLs from and trusts as an origin.
31
+ * Defaults to SITE_URL, which is correct when the CMS and the site share an
32
+ * origin; set it when the admin lives somewhere else.
33
+ */
34
+ AUTH_URL?: string;
35
+ /** Optional. Only enforced for forms with settings.turnstileEnabled. */
36
+ TURNSTILE_SECRET?: string;
37
+ /**
38
+ * Which EmailSender to resolve: `console` logs the message, anything else
39
+ * (including unset) drops it. The Cloudflare pack supplies a real sender.
40
+ */
41
+ EMAIL_MODE?: string;
42
+ /** The from-address a real sender uses. Carried here so the seam is configured in one place. */
43
+ EMAIL_FROM?: string;
44
+ }
45
+ /**
46
+ * Loads site settings from the site_settings key/value table, validated and
47
+ * defaulted through siteSettingsSchema, cached in memory for 60s per isolate.
48
+ * Every module reads its configuration through this one function, so a fresh
49
+ * database with no settings rows still yields a fully-formed settings object.
50
+ */
51
+ export declare function getSettings(db: D1Database, now?: number): Promise<SiteSettings>;
52
+ /**
53
+ * Persists a partial settings update. Shallow-merges onto the current settings
54
+ * (each top-level key is one site_settings row, so a changed `modules` or
55
+ * `webhooks` value replaces that whole row; this matches the read side, which
56
+ * reassembles the full object one row per key), re-validates the merged result
57
+ * through the same schema `getSettings` uses, then writes every key back and
58
+ * refreshes the in-isolate cache immediately so a follow-up read in the same
59
+ * request never sees stale data for the rest of the 60s TTL.
60
+ */
61
+ export declare function setSettings(db: D1Database, patch: SiteSettingsUpdateInput, now?: number): Promise<SiteSettings>;
62
+ /** Test-only: clears the module-scope cache between test cases. */
63
+ export declare function clearSettingsCacheForTests(): void;
64
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,YAAY,EAAE,KAAK,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAExG;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,uFAAuF;IACvF,EAAE,EAAE,UAAU,CAAC;IACf,0DAA0D;IAC1D,KAAK,EAAE,QAAQ,CAAC;IAChB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gFAAgF;IAChF,QAAQ,EAAE,MAAM,CAAC;IACjB,8FAA8F;IAC9F,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gGAAgG;IAChG,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAiBD;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,EAAE,EAAE,UAAU,EAAE,GAAG,GAAE,MAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAiBjG;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAC/B,EAAE,EAAE,UAAU,EACd,KAAK,EAAE,uBAAuB,EAC9B,GAAG,GAAE,MAAmB,GACvB,OAAO,CAAC,YAAY,CAAC,CAcvB;AAED,mEAAmE;AACnE,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD"}
package/dist/env.js ADDED
@@ -0,0 +1,48 @@
1
+ import { siteSettingsSchema } from './shared/index.js';
2
+ const SETTINGS_CACHE_TTL_MS = 60_000;
3
+ /** Per-isolate cache; module-scope state is the standard Workers pattern for this. */
4
+ let cache = null;
5
+ /**
6
+ * Loads site settings from the site_settings key/value table, validated and
7
+ * defaulted through siteSettingsSchema, cached in memory for 60s per isolate.
8
+ * Every module reads its configuration through this one function, so a fresh
9
+ * database with no settings rows still yields a fully-formed settings object.
10
+ */
11
+ export async function getSettings(db, now = Date.now()) {
12
+ if (cache && cache.expiresAt > now) {
13
+ return cache.value;
14
+ }
15
+ const { results } = await db
16
+ .prepare('SELECT key, value FROM site_settings')
17
+ .all();
18
+ const raw = {};
19
+ for (const row of results) {
20
+ raw[row.key] = JSON.parse(row.value);
21
+ }
22
+ const value = siteSettingsSchema.parse(raw);
23
+ cache = { value, expiresAt: now + SETTINGS_CACHE_TTL_MS };
24
+ return value;
25
+ }
26
+ /**
27
+ * Persists a partial settings update. Shallow-merges onto the current settings
28
+ * (each top-level key is one site_settings row, so a changed `modules` or
29
+ * `webhooks` value replaces that whole row; this matches the read side, which
30
+ * reassembles the full object one row per key), re-validates the merged result
31
+ * through the same schema `getSettings` uses, then writes every key back and
32
+ * refreshes the in-isolate cache immediately so a follow-up read in the same
33
+ * request never sees stale data for the rest of the 60s TTL.
34
+ */
35
+ export async function setSettings(db, patch, now = Date.now()) {
36
+ const current = await getSettings(db, now);
37
+ const merged = siteSettingsSchema.parse({ ...current, ...patch });
38
+ await db.batch(Object.entries(merged).map(([key, value]) => db
39
+ .prepare('INSERT OR REPLACE INTO site_settings (key, value) VALUES (?1, ?2)')
40
+ .bind(key, JSON.stringify(value))));
41
+ cache = { value: merged, expiresAt: now + SETTINGS_CACHE_TTL_MS };
42
+ return merged;
43
+ }
44
+ /** Test-only: clears the module-scope cache between test cases. */
45
+ export function clearSettingsCacheForTests() {
46
+ cache = null;
47
+ }
48
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAmD,MAAM,mBAAmB,CAAC;AAmDxG,MAAM,qBAAqB,GAAG,MAAM,CAAC;AAErC,sFAAsF;AACtF,IAAI,KAAK,GAA8B,IAAI,CAAC;AAO5C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,EAAc,EAAE,MAAc,IAAI,CAAC,GAAG,EAAE;IACxE,IAAI,KAAK,IAAI,KAAK,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC;QACnC,OAAO,KAAK,CAAC,KAAK,CAAC;IACrB,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE;SACzB,OAAO,CAAC,sCAAsC,CAAC;SAC/C,GAAG,EAAkB,CAAC;IAEzB,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IAED,MAAM,KAAK,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC5C,KAAK,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,GAAG,qBAAqB,EAAE,CAAC;IAC1D,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,EAAc,EACd,KAA8B,EAC9B,MAAc,IAAI,CAAC,GAAG,EAAE;IAExB,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;IAElE,MAAM,EAAE,CAAC,KAAK,CACZ,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAC1C,EAAE;SACC,OAAO,CAAC,mEAAmE,CAAC;SAC5E,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CACpC,CACF,CAAC;IAEF,KAAK,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,GAAG,qBAAqB,EAAE,CAAC;IAClE,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,0BAA0B;IACxC,KAAK,GAAG,IAAI,CAAC;AACf,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { Hono } from 'hono';
2
+ import { type Bindings } from './env.js';
3
+ import { type KeyVariables } from './keys/middleware.js';
4
+ import { type AuthVariables } from './middleware/auth.js';
5
+ import { type RequestIdVariables } from './middleware/request-id.js';
6
+ /**
7
+ * The email seam, re-exported so a composed worker can plug a pack's sender in
8
+ * without reaching into the package's internals. A scaffolded project calls
9
+ * `registerEmailSender(cloudflareEmailSender)` at module scope and is done.
10
+ */
11
+ export { registerEmailSender, type EmailMessage, type EmailSender, type EmailSenderFactory, } from './lib/email.js';
12
+ type Variables = RequestIdVariables & AuthVariables & KeyVariables;
13
+ export declare const app: Hono<{
14
+ Bindings: Bindings;
15
+ Variables: Variables;
16
+ }, import("hono/types").BlankSchema, "/">;
17
+ declare const _default: {
18
+ fetch: (request: Request, env?: {} | Bindings | undefined, executionCtx?: import("hono").ExecutionContext) => Response | Promise<Response>;
19
+ scheduled(_controller: ScheduledController, env: Bindings, _ctx: ExecutionContext<unknown>): Promise<void>;
20
+ };
21
+ export default _default;
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAK5B,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAItD,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAe,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGvE,OAAO,EAAa,KAAK,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAqBhF;;;;GAIG;AACH,OAAO,EACL,mBAAmB,EACnB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,kBAAkB,GACxB,MAAM,gBAAgB,CAAC;AAExB,KAAK,SAAS,GAAG,kBAAkB,GAAG,aAAa,GAAG,YAAY,CAAC;AAKnE,eAAO,MAAM,GAAG;cAAwB,QAAQ;eAAa,SAAS;yCAAK,CAAC;;;;;AA+I5E,wBASsC"}
package/dist/index.js ADDED
@@ -0,0 +1,170 @@
1
+ import { Hono } from 'hono';
2
+ import { createMiddleware } from 'hono/factory';
3
+ import { ok } from './shared/index.js';
4
+ import { AUTH_BASE_PATH, createAuth, isBootstrapOpen } from './auth/auth.js';
5
+ import { usersAdminRoutes } from './auth/routes.admin.js';
6
+ import { getSettings } from './env.js';
7
+ import { HttpError, errorBoundary, notFoundHandler } from './lib/errors.js';
8
+ import { runRetentionCleanup } from './lib/retention.js';
9
+ import { keysAdminRoutes } from './keys/routes.admin.js';
10
+ import { publicApiAuth } from './keys/middleware.js';
11
+ import { sessionAuth } from './middleware/auth.js';
12
+ import { corsMiddleware } from './middleware/cors.js';
13
+ import { moduleGate } from './middleware/module-gate.js';
14
+ import { requestId } from './middleware/request-id.js';
15
+ import { aeoAdminRoutes } from './modules/aeo/routes.admin.js';
16
+ import { resolveLlmsTxt } from './modules/aeo/llms.js';
17
+ import { analyticsAdminRoutes } from './modules/analytics/routes.admin.js';
18
+ import { analyticsPublicRoutes } from './modules/analytics/routes.public.js';
19
+ import { authorsAdminRoutes } from './modules/authors/routes.admin.js';
20
+ import { authorsPublicRoutes } from './modules/authors/routes.public.js';
21
+ import { contentAdminRoutes } from './modules/content/routes.admin.js';
22
+ import { contentPublicRoutes } from './modules/content/routes.public.js';
23
+ import { formsAdminRoutes } from './modules/forms/forms-routes.admin.js';
24
+ import { formsPublicRoutes } from './modules/forms/routes.public.js';
25
+ import { submissionsAdminRoutes } from './modules/forms/submissions-routes.admin.js';
26
+ import { mediaAdminRoutes } from './modules/media/routes.admin.js';
27
+ import { mediaPublicRoutes } from './modules/media/routes.public.js';
28
+ import { buildOpenApiSpec } from './modules/openapi/spec.js';
29
+ import { seoPublicRoutes } from './modules/seo/routes.public.js';
30
+ import { serveSpaShell } from './spa.js';
31
+ import { settingsAdminRoutes } from './modules/settings/routes.admin.js';
32
+ import { siteDocumentsAdminRoutes } from './modules/site-documents/routes.admin.js';
33
+ import { siteDocumentsPublicRoutes } from './modules/site-documents/routes.public.js';
34
+ /**
35
+ * The email seam, re-exported so a composed worker can plug a pack's sender in
36
+ * without reaching into the package's internals. A scaffolded project calls
37
+ * `registerEmailSender(cloudflareEmailSender)` at module scope and is done.
38
+ */
39
+ export { registerEmailSender, } from './lib/email.js';
40
+ // Named export as well as default, so tests can call app.request(...) directly:
41
+ // the default export is the plain {fetch, scheduled} object Cloudflare's module
42
+ // Worker format expects, which has no .request() of its own.
43
+ export const app = new Hono();
44
+ app.onError(errorBoundary);
45
+ /**
46
+ * Nothing matched a route. When an admin bundle is bound as static assets,
47
+ * a document request for one of its client-side routes gets the SPA shell;
48
+ * everything else, including every API path, keeps the envelope 404 it has
49
+ * always had. See src/spa.ts for why the fallback is this narrow.
50
+ */
51
+ app.notFound(async (c) => (await serveSpaShell(c.req.raw, c.env)) ?? notFoundHandler(c));
52
+ app.use('*', requestId);
53
+ // ---------------------------------------------------------------------------
54
+ // Embedded auth
55
+ // ---------------------------------------------------------------------------
56
+ /**
57
+ * Public sign-up is open exactly once, to create the first user, who becomes
58
+ * the owner. After that this closes and further accounts are created by the
59
+ * owner through /v1/admin/users.
60
+ *
61
+ * Gating at the HTTP layer rather than through the library's own disableSignUp
62
+ * is deliberate: the flag is static, the condition is not, and the owner's
63
+ * account-creation route needs the same underlying sign-up path to stay open
64
+ * server-side. One rule, applied where the request arrives.
65
+ */
66
+ const bootstrapGate = createMiddleware(async (c, next) => {
67
+ if (!(await isBootstrapOpen(c.env.DB))) {
68
+ throw new HttpError('forbidden', 'sign-up is closed; ask an owner for an account');
69
+ }
70
+ await next();
71
+ });
72
+ app.use(`${AUTH_BASE_PATH}/*`, corsMiddleware('admin'));
73
+ app.use(`${AUTH_BASE_PATH}/sign-up/*`, bootstrapGate);
74
+ app.all(`${AUTH_BASE_PATH}/*`, async (c) => {
75
+ if (!c.env.BETTER_AUTH_SECRET) {
76
+ throw new HttpError('internal', 'BETTER_AUTH_SECRET is not configured');
77
+ }
78
+ return createAuth(c.env).handler(c.req.raw);
79
+ });
80
+ // ---------------------------------------------------------------------------
81
+ // Gates
82
+ // ---------------------------------------------------------------------------
83
+ app.use('/v1/*', publicApiAuth);
84
+ app.use('/v1/admin/*', corsMiddleware('admin'), sessionAuth);
85
+ // ---------------------------------------------------------------------------
86
+ // Meta
87
+ // ---------------------------------------------------------------------------
88
+ app.use('/v1/health', corsMiddleware('publicRead'));
89
+ app.get('/v1/health', async (c) => {
90
+ const settings = await getSettings(c.env.DB);
91
+ return c.json(ok({ cmsVersion: c.env.CMS_VERSION, modules: settings.modules }));
92
+ });
93
+ // Self-describing API: keyless, so any developer can read the contract before
94
+ // they have a key. Not module-gated either; it documents whatever is enabled
95
+ // and is cheap and static.
96
+ app.use('/v1/openapi.json', corsMiddleware('publicRead'));
97
+ app.get('/v1/openapi.json', (c) => c.json(buildOpenApiSpec(c.env.SITE_URL)));
98
+ /**
99
+ * The AEO document, at the root path answer engines actually look for. Served
100
+ * from the authored site document when there is one, otherwise generated from
101
+ * settings and published content; 404 when a site has turned it off, because
102
+ * an empty file would claim the site has nothing to say.
103
+ */
104
+ app.use('/llms.txt', corsMiddleware('publicRead'));
105
+ app.get('/llms.txt', async (c) => {
106
+ const body = await resolveLlmsTxt(c.env.DB, c.env.SITE_URL);
107
+ if (body === null)
108
+ throw new HttpError('not_found', 'not found');
109
+ return c.body(body, 200, {
110
+ 'Content-Type': 'text/plain; charset=UTF-8',
111
+ 'Cache-Control': 'public, max-age=900',
112
+ });
113
+ });
114
+ // ---------------------------------------------------------------------------
115
+ // Module gates
116
+ // ---------------------------------------------------------------------------
117
+ // Authors gate on the content flag: a byline is part of content, and there is
118
+ // no separate authors module. Admin routes get the same gate as their public
119
+ // counterpart, since a module turned off entirely has no reason to leave its
120
+ // management API reachable.
121
+ app.use('/v1/posts/*', moduleGate('content'));
122
+ app.use('/v1/authors/*', moduleGate('content'));
123
+ app.use('/v1/admin/posts/*', moduleGate('content'));
124
+ app.use('/v1/admin/authors/*', moduleGate('content'));
125
+ app.use('/v1/sitemap.xml', moduleGate('seo'));
126
+ app.use('/v1/forms/*', moduleGate('forms'));
127
+ app.use('/v1/admin/forms/*', moduleGate('forms'));
128
+ app.use('/v1/admin/submissions/*', moduleGate('forms'));
129
+ app.use('/v1/events/*', moduleGate('analytics'));
130
+ app.use('/v1/admin/visits', moduleGate('analytics'));
131
+ app.use('/v1/admin/visits/stats', moduleGate('analytics'));
132
+ app.use('/v1/admin/consent/stats', moduleGate('analytics'));
133
+ app.use('/v1/media/*', moduleGate('media'));
134
+ app.use('/v1/admin/media/*', moduleGate('media'));
135
+ // ---------------------------------------------------------------------------
136
+ // Routes
137
+ // ---------------------------------------------------------------------------
138
+ app.route('/v1/posts', contentPublicRoutes);
139
+ app.route('/v1/authors', authorsPublicRoutes);
140
+ app.route('/v1/admin/posts', contentAdminRoutes);
141
+ app.route('/v1/admin/authors', authorsAdminRoutes);
142
+ app.route('/v1', seoPublicRoutes);
143
+ app.route('/v1/forms', formsPublicRoutes);
144
+ app.route('/v1/admin/forms', formsAdminRoutes);
145
+ app.route('/v1/admin/submissions', submissionsAdminRoutes);
146
+ app.route('/v1/events', analyticsPublicRoutes);
147
+ // Bare /v1/admin, not /v1/admin/analytics: these endpoints are /visits,
148
+ // /visits/stats, and /consent/stats with no module-name segment. app.route only
149
+ // prepends this prefix to the router's own sub-paths, so it cannot swallow the
150
+ // other /v1/admin mounts around it.
151
+ app.route('/v1/admin', analyticsAdminRoutes);
152
+ app.route('/v1/media', mediaPublicRoutes);
153
+ app.route('/v1/admin/media', mediaAdminRoutes);
154
+ app.route('/v1/admin/settings', settingsAdminRoutes);
155
+ app.route('/v1/documents', siteDocumentsPublicRoutes);
156
+ app.route('/v1/admin/documents', siteDocumentsAdminRoutes);
157
+ app.route('/v1/admin/aeo', aeoAdminRoutes);
158
+ app.route('/v1/admin/keys', keysAdminRoutes);
159
+ app.route('/v1/admin/users', usersAdminRoutes);
160
+ export default {
161
+ fetch: app.fetch,
162
+ // The daily retention sweep. The schedule is configured in wrangler.jsonc's
163
+ // triggers.crons.
164
+ async scheduled(_controller, env, _ctx) {
165
+ const settings = await getSettings(env.DB);
166
+ const result = await runRetentionCleanup(env.DB, settings.retentionDays);
167
+ console.log(`[retention] cleanup complete: ${JSON.stringify(result)}`);
168
+ },
169
+ };
170
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import { type ApiKeyKind } from '../shared/index.js';
2
+ import type { Bindings } from '../env.js';
3
+ export type KeyVariables = {
4
+ /** The kind of key this public request presented, once one has been validated. */
5
+ keyKind: ApiKeyKind;
6
+ };
7
+ /**
8
+ * Key validation for the public API, done inside this worker.
9
+ *
10
+ * In managed we8 the dispatch router validates the key before a request ever
11
+ * reaches a tenant, and the engine simply trusts what arrives. Standalone,
12
+ * this worker IS the front door, so the same pk/sk dialect is resolved here:
13
+ * the presented secret is hashed and looked up, an unknown or revoked key is
14
+ * a 401, and the resolved kind is put on the context for anything that cares.
15
+ *
16
+ * A handful of routes are deliberately keyless (see KEYLESS_PUBLIC_ROUTES in
17
+ * src/index.ts) and never mount this.
18
+ */
19
+ export declare const publicKeyAuth: import("hono").MiddlewareHandler<{
20
+ Bindings: Bindings;
21
+ Variables: KeyVariables;
22
+ }, string, {}, Response>;
23
+ /**
24
+ * The public routes that need no key.
25
+ *
26
+ * Each one is keyless because its reader cannot hold a key. A crawler fetching
27
+ * the sitemap has no credential to present; an image in published HTML cannot
28
+ * carry a rotating secret without every historical page breaking on the next
29
+ * rotation; health and the OpenAPI document exist to be discovered before
30
+ * anyone has a key at all.
31
+ *
32
+ * Treat the media exemption as irreversible: once keyless media URLs are in
33
+ * published content, re-gating them breaks that content permanently.
34
+ */
35
+ export declare function isKeylessPublicRoute(method: string, pathname: string): boolean;
36
+ /**
37
+ * The gate mounted across /v1/*. Admin routes fall through untouched: they are
38
+ * gated by session instead, and an API key presented on one is refused
39
+ * outright (see middleware/auth.ts).
40
+ */
41
+ export declare const publicApiAuth: import("hono").MiddlewareHandler<{
42
+ Bindings: Bindings;
43
+ Variables: KeyVariables;
44
+ }, string, {}, Response>;
45
+ /**
46
+ * Narrows an already-validated public request to a secret key. A publishable
47
+ * key travels in browser code by design, so anything a `pk_` holder must not
48
+ * be able to do mounts this behind publicKeyAuth.
49
+ */
50
+ export declare const requireSecretKey: import("hono").MiddlewareHandler<{
51
+ Bindings: Bindings;
52
+ Variables: KeyVariables;
53
+ }, string, {}, Response>;
54
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/keys/middleware.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAI1C,MAAM,MAAM,YAAY,GAAG;IACzB,kFAAkF;IAClF,OAAO,EAAE,UAAU,CAAC;CACrB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa;cAAgC,QAAQ;eAAa,YAAY;wBAe1F,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAO9E;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa;cAAgC,QAAQ;eAAa,YAAY;wBAa1F,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;cAAgC,QAAQ;eAAa,YAAY;wBAO7F,CAAC"}
@@ -0,0 +1,84 @@
1
+ import { createMiddleware } from 'hono/factory';
2
+ import { sha256Hex } from '../shared/index.js';
3
+ import { HttpError } from '../lib/errors.js';
4
+ import { extractApiKey, lookupApiKeyByHash } from './service.js';
5
+ /**
6
+ * Key validation for the public API, done inside this worker.
7
+ *
8
+ * In managed we8 the dispatch router validates the key before a request ever
9
+ * reaches a tenant, and the engine simply trusts what arrives. Standalone,
10
+ * this worker IS the front door, so the same pk/sk dialect is resolved here:
11
+ * the presented secret is hashed and looked up, an unknown or revoked key is
12
+ * a 401, and the resolved kind is put on the context for anything that cares.
13
+ *
14
+ * A handful of routes are deliberately keyless (see KEYLESS_PUBLIC_ROUTES in
15
+ * src/index.ts) and never mount this.
16
+ */
17
+ export const publicKeyAuth = createMiddleware(async (c, next) => {
18
+ const presented = extractApiKey(c);
19
+ if (!presented) {
20
+ throw new HttpError('unauthorized', 'missing API key');
21
+ }
22
+ const resolved = await lookupApiKeyByHash(c.env.DB, await sha256Hex(presented));
23
+ if (!resolved || resolved.revoked) {
24
+ throw new HttpError('unauthorized', 'unknown or revoked API key');
25
+ }
26
+ c.set('keyKind', resolved.kind);
27
+ await next();
28
+ });
29
+ /**
30
+ * The public routes that need no key.
31
+ *
32
+ * Each one is keyless because its reader cannot hold a key. A crawler fetching
33
+ * the sitemap has no credential to present; an image in published HTML cannot
34
+ * carry a rotating secret without every historical page breaking on the next
35
+ * rotation; health and the OpenAPI document exist to be discovered before
36
+ * anyone has a key at all.
37
+ *
38
+ * Treat the media exemption as irreversible: once keyless media URLs are in
39
+ * published content, re-gating them breaks that content permanently.
40
+ */
41
+ export function isKeylessPublicRoute(method, pathname) {
42
+ const isRead = method === 'GET' || method === 'HEAD';
43
+ if (!isRead)
44
+ return false;
45
+ if (pathname === '/v1/health')
46
+ return true;
47
+ if (pathname === '/v1/openapi.json')
48
+ return true;
49
+ if (pathname === '/v1/sitemap.xml')
50
+ return true;
51
+ return pathname.startsWith('/v1/media/');
52
+ }
53
+ /**
54
+ * The gate mounted across /v1/*. Admin routes fall through untouched: they are
55
+ * gated by session instead, and an API key presented on one is refused
56
+ * outright (see middleware/auth.ts).
57
+ */
58
+ export const publicApiAuth = createMiddleware(async (c, next) => {
59
+ // A CORS preflight can never present the key it is asking permission to
60
+ // send: the browser strips custom headers and credentials from OPTIONS.
61
+ // Demanding one here would 401 every cross-origin browser call before
62
+ // route-level CORS could answer, so the preflight passes through and the
63
+ // key check runs on the real request that follows it.
64
+ if (c.req.method === 'OPTIONS')
65
+ return next();
66
+ const pathname = new URL(c.req.url).pathname;
67
+ if (pathname.startsWith('/v1/admin'))
68
+ return next();
69
+ if (isKeylessPublicRoute(c.req.method, pathname))
70
+ return next();
71
+ return publicKeyAuth(c, next);
72
+ });
73
+ /**
74
+ * Narrows an already-validated public request to a secret key. A publishable
75
+ * key travels in browser code by design, so anything a `pk_` holder must not
76
+ * be able to do mounts this behind publicKeyAuth.
77
+ */
78
+ export const requireSecretKey = createMiddleware(async (c, next) => {
79
+ if (c.get('keyKind') !== 'sk') {
80
+ throw new HttpError('forbidden', 'this endpoint requires a secret key');
81
+ }
82
+ await next();
83
+ });
84
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/keys/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,SAAS,EAAmB,MAAM,oBAAoB,CAAC;AAEhE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAOjE;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,gBAAgB,CAC3C,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;IAChB,MAAM,SAAS,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,cAAc,EAAE,iBAAiB,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC;IAChF,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;QAClC,MAAM,IAAI,SAAS,CAAC,cAAc,EAAE,4BAA4B,CAAC,CAAC;IACpE,CAAC;IAED,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,IAAI,EAAE,CAAC;AACf,CAAC,CACF,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAc,EAAE,QAAgB;IACnE,MAAM,MAAM,GAAG,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,CAAC;IACrD,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,IAAI,QAAQ,KAAK,YAAY;QAAE,OAAO,IAAI,CAAC;IAC3C,IAAI,QAAQ,KAAK,kBAAkB;QAAE,OAAO,IAAI,CAAC;IACjD,IAAI,QAAQ,KAAK,iBAAiB;QAAE,OAAO,IAAI,CAAC;IAChD,OAAO,QAAQ,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AAC3C,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,gBAAgB,CAC3C,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;IAChB,wEAAwE;IACxE,wEAAwE;IACxE,sEAAsE;IACtE,yEAAyE;IACzE,sDAAsD;IACtD,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,IAAI,EAAE,CAAC;IAC9C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;IAC7C,IAAI,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,IAAI,EAAE,CAAC;IACpD,IAAI,oBAAoB,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC;QAAE,OAAO,IAAI,EAAE,CAAC;IAChE,OAAO,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC,CACF,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,gBAAgB,CAC9C,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;IAChB,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE,CAAC;QAC9B,MAAM,IAAI,SAAS,CAAC,WAAW,EAAE,qCAAqC,CAAC,CAAC;IAC1E,CAAC;IACD,MAAM,IAAI,EAAE,CAAC;AACf,CAAC,CACF,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { Hono } from 'hono';
2
+ import type { Bindings } from '../env.js';
3
+ import { type AuthVariables } from '../middleware/auth.js';
4
+ /**
5
+ * API key management, owner-only.
6
+ *
7
+ * A key is site-wide credentials, and a secret key is a standing grant to
8
+ * whoever holds it, so minting and revoking sit with the owner rather than
9
+ * with every editor. The list is safe to read but stays behind the same gate:
10
+ * splitting the two would only mean two rules to remember.
11
+ */
12
+ export declare const keysAdminRoutes: Hono<{
13
+ Bindings: Bindings;
14
+ Variables: AuthVariables;
15
+ }, import("hono/types").BlankSchema, "/">;
16
+ //# sourceMappingURL=routes.admin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.admin.d.ts","sourceRoot":"","sources":["../../src/keys/routes.admin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGzE;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe;cAAwB,QAAQ;eAAa,aAAa;yCAAK,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { Hono } from 'hono';
2
+ import { apiKeyCreateInputSchema, ok } from '../shared/index.js';
3
+ import { parseOrThrow } from '../lib/validate.js';
4
+ import { requireOwner } from '../middleware/auth.js';
5
+ import { createApiKey, listApiKeys, revokeApiKey } from './service.js';
6
+ /**
7
+ * API key management, owner-only.
8
+ *
9
+ * A key is site-wide credentials, and a secret key is a standing grant to
10
+ * whoever holds it, so minting and revoking sit with the owner rather than
11
+ * with every editor. The list is safe to read but stays behind the same gate:
12
+ * splitting the two would only mean two rules to remember.
13
+ */
14
+ export const keysAdminRoutes = new Hono();
15
+ keysAdminRoutes.use('*', requireOwner);
16
+ keysAdminRoutes.get('/', async (c) => {
17
+ const items = await listApiKeys(c.env.DB);
18
+ return c.json(ok({ items }));
19
+ });
20
+ /**
21
+ * The one response in this API that carries a secret. The plaintext exists
22
+ * here and nowhere else, ever again, so the admin must show it once and say
23
+ * so; every later read returns the prefix only.
24
+ */
25
+ keysAdminRoutes.post('/', async (c) => {
26
+ const input = parseOrThrow(apiKeyCreateInputSchema, await c.req.json());
27
+ const key = await createApiKey(c.env.DB, input.kind, input.label);
28
+ return c.json(ok({ key }), 201);
29
+ });
30
+ keysAdminRoutes.delete('/:id', async (c) => {
31
+ const key = await revokeApiKey(c.env.DB, c.req.param('id'));
32
+ return c.json(ok({ key }));
33
+ });
34
+ //# sourceMappingURL=routes.admin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.admin.js","sourceRoot":"","sources":["../../src/keys/routes.admin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,uBAAuB,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAEjE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAsB,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEvE;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,IAAI,EAAoD,CAAC;AAE5F,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;AAEvC,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACnC,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC1C,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;AAC/B,CAAC,CAAC,CAAC;AAEH;;;;GAIG;AACH,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACpC,MAAM,KAAK,GAAG,YAAY,CAAC,uBAAuB,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACxE,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAClE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;AAClC,CAAC,CAAC,CAAC;AAEH,eAAe,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACzC,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5D,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;AAC7B,CAAC,CAAC,CAAC"}