dineway 0.1.3 → 0.1.5

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 (296) hide show
  1. package/README.md +6 -3
  2. package/dist/{apply-CAPvMfoU.mjs → apply-iVSqz2qs.mjs} +132 -39
  3. package/dist/astro/index.d.mts +18 -9
  4. package/dist/astro/index.mjs +238 -16
  5. package/dist/astro/middleware/auth.d.mts +16 -5
  6. package/dist/astro/middleware/auth.mjs +74 -37
  7. package/dist/astro/middleware/redirect.mjs +24 -8
  8. package/dist/astro/middleware/request-context.mjs +18 -5
  9. package/dist/astro/middleware/setup.mjs +1 -1
  10. package/dist/astro/middleware.mjs +411 -169
  11. package/dist/astro/types.d.mts +25 -8
  12. package/dist/{byline-DeWCMU_i.mjs → byline-OhH2dlRu.mjs} +6 -21
  13. package/dist/{bylines-DyqBV9EQ.mjs → bylines-BGpD9_hy.mjs} +16 -6
  14. package/dist/cache-BdSY-gQN.mjs +42 -0
  15. package/dist/chunks--4F8ddV4.mjs +18 -0
  16. package/dist/cli/index.mjs +935 -15
  17. package/dist/client/external-auth-headers.d.mts +1 -1
  18. package/dist/client/index.d.mts +11 -3
  19. package/dist/client/index.mjs +4 -3
  20. package/dist/{connection-C9pxzuag.mjs → connection-BCNICDWN.mjs} +22 -5
  21. package/dist/{content-zSgdNmnt.mjs → content-DWi4d0rT.mjs} +41 -2
  22. package/dist/database/instrumentation.d.mts +34 -0
  23. package/dist/database/instrumentation.mjs +53 -0
  24. package/dist/db/index.d.mts +3 -3
  25. package/dist/db/index.mjs +2 -2
  26. package/dist/db/libsql.d.mts +1 -1
  27. package/dist/db/libsql.mjs +11 -5
  28. package/dist/db/postgres.d.mts +1 -1
  29. package/dist/db/sqlite.d.mts +1 -1
  30. package/dist/db/sqlite.mjs +7 -1
  31. package/dist/db-errors-CEqD7qH9.mjs +23 -0
  32. package/dist/{default-WYlzADZL.mjs → default-VjJyuuG9.mjs} +2 -0
  33. package/dist/{dialect-helpers-B9uSp2GJ.mjs → dialect-helpers-DhTzaUxP.mjs} +3 -0
  34. package/dist/{error-DrxtnGPg.mjs → error-BmL6QipT.mjs} +7 -3
  35. package/dist/{index-C-jx21qs.d.mts → index-yvc6E_17.d.mts} +157 -30
  36. package/dist/index.d.mts +11 -11
  37. package/dist/index.mjs +24 -22
  38. package/dist/{loader-qKmo0wAY.mjs → loader-sMG4TZ-u.mjs} +9 -3
  39. package/dist/media/index.d.mts +1 -1
  40. package/dist/media/index.mjs +1 -1
  41. package/dist/media/local-runtime.d.mts +7 -7
  42. package/dist/page/index.d.mts +10 -2
  43. package/dist/page/index.mjs +22 -1
  44. package/dist/patterns-CrCYkMBb.mjs +92 -0
  45. package/dist/{placeholder-bOx1xCTY.d.mts → placeholder--wOi4TbO.d.mts} +1 -1
  46. package/dist/{placeholder-B3knXwNc.mjs → placeholder-Cp8g5Emj.mjs} +1 -1
  47. package/dist/plugins/adapt-sandbox-entry.d.mts +5 -5
  48. package/dist/plugins/adapt-sandbox-entry.mjs +1 -1
  49. package/dist/{query-BiaPl_g2.mjs → query-kDmwCsHh.mjs} +118 -50
  50. package/dist/{redirect-JPqLAbxa.mjs → redirect-DnEWAkVg.mjs} +43 -99
  51. package/dist/{registry-DSd1GWB8.mjs → registry-C0zjeB9P.mjs} +191 -123
  52. package/dist/request-cache-Dk5qPSOx.mjs +66 -0
  53. package/dist/request-context.d.mts +4 -16
  54. package/dist/{runner-B5l1JfOj.d.mts → runner-CFI6B6J2.d.mts} +1 -1
  55. package/dist/{runner-BGUGywgG.mjs → runner-DWZm2KQm.mjs} +589 -137
  56. package/dist/runtime.d.mts +6 -6
  57. package/dist/runtime.mjs +2 -2
  58. package/dist/{search-BNruJHDL.mjs → search-ByRGV2pq.mjs} +570 -424
  59. package/dist/seed/index.d.mts +2 -2
  60. package/dist/seed/index.mjs +11 -10
  61. package/dist/seo/index.d.mts +1 -1
  62. package/dist/storage/local.d.mts +1 -1
  63. package/dist/storage/local.mjs +1 -1
  64. package/dist/storage/s3.d.mts +11 -3
  65. package/dist/storage/s3.mjs +78 -15
  66. package/dist/taxonomies-1s5PaS_8.mjs +266 -0
  67. package/dist/transaction-Cn2rjY78.mjs +27 -0
  68. package/dist/{types-BgQeVaPj.d.mts → types-BuMDPy5C.d.mts} +52 -3
  69. package/dist/{types-DuNbGKjF.mjs → types-COeOq9nK.mjs} +6 -1
  70. package/dist/{types-ju-_ORz7.d.mts → types-CWbdtiux.d.mts} +13 -5
  71. package/dist/{types-D38djUXv.d.mts → types-Cj0KMIZV.d.mts} +16 -3
  72. package/dist/{types-DkvMXalq.d.mts → types-DOrVigru.d.mts} +159 -0
  73. package/dist/{validate-CXnRKfJK.mjs → validate-BZ5wnLLp.mjs} +2 -1
  74. package/dist/{validate-DVKJJ-M_.d.mts → validate-IPf8n4Fj.d.mts} +4 -51
  75. package/dist/{validate-CqRJb_xU.mjs → validate-VPnKoIzW.mjs} +10 -10
  76. package/dist/version-BKXPsfmJ.mjs +6 -0
  77. package/package.json +53 -39
  78. package/src/astro/routes/PluginRegistry.tsx +21 -0
  79. package/src/astro/routes/admin.astro +99 -0
  80. package/src/astro/routes/api/admin/allowed-domains/[domain].ts +112 -0
  81. package/src/astro/routes/api/admin/allowed-domains/index.ts +108 -0
  82. package/src/astro/routes/api/admin/api-tokens/[id].ts +44 -0
  83. package/src/astro/routes/api/admin/api-tokens/index.ts +90 -0
  84. package/src/astro/routes/api/admin/briefing.ts +76 -0
  85. package/src/astro/routes/api/admin/bylines/[id]/index.ts +90 -0
  86. package/src/astro/routes/api/admin/bylines/index.ts +74 -0
  87. package/src/astro/routes/api/admin/comments/[id]/status.ts +120 -0
  88. package/src/astro/routes/api/admin/comments/[id].ts +64 -0
  89. package/src/astro/routes/api/admin/comments/bulk.ts +42 -0
  90. package/src/astro/routes/api/admin/comments/counts.ts +30 -0
  91. package/src/astro/routes/api/admin/comments/index.ts +46 -0
  92. package/src/astro/routes/api/admin/context/[id]/history.ts +35 -0
  93. package/src/astro/routes/api/admin/context/[id]/index.ts +35 -0
  94. package/src/astro/routes/api/admin/context/[id]/review.ts +57 -0
  95. package/src/astro/routes/api/admin/context/[id]/supersede.ts +58 -0
  96. package/src/astro/routes/api/admin/context/diff.ts +35 -0
  97. package/src/astro/routes/api/admin/context/index.ts +69 -0
  98. package/src/astro/routes/api/admin/context/stale.ts +35 -0
  99. package/src/astro/routes/api/admin/hitl-requests/[id]/index.ts +38 -0
  100. package/src/astro/routes/api/admin/hitl-requests/[id]/resolve.ts +54 -0
  101. package/src/astro/routes/api/admin/hitl-requests/index.ts +38 -0
  102. package/src/astro/routes/api/admin/hooks/exclusive/[hookName].ts +132 -0
  103. package/src/astro/routes/api/admin/hooks/exclusive/index.ts +51 -0
  104. package/src/astro/routes/api/admin/oauth-clients/[id].ts +137 -0
  105. package/src/astro/routes/api/admin/oauth-clients/index.ts +95 -0
  106. package/src/astro/routes/api/admin/plugins/[id]/disable.ts +91 -0
  107. package/src/astro/routes/api/admin/plugins/[id]/enable.ts +91 -0
  108. package/src/astro/routes/api/admin/plugins/[id]/index.ts +38 -0
  109. package/src/astro/routes/api/admin/plugins/[id]/uninstall.ts +98 -0
  110. package/src/astro/routes/api/admin/plugins/[id]/update.ts +154 -0
  111. package/src/astro/routes/api/admin/plugins/index.ts +32 -0
  112. package/src/astro/routes/api/admin/plugins/marketplace/[id]/icon.ts +62 -0
  113. package/src/astro/routes/api/admin/plugins/marketplace/[id]/index.ts +33 -0
  114. package/src/astro/routes/api/admin/plugins/marketplace/[id]/install.ts +135 -0
  115. package/src/astro/routes/api/admin/plugins/marketplace/index.ts +38 -0
  116. package/src/astro/routes/api/admin/plugins/updates.ts +28 -0
  117. package/src/astro/routes/api/admin/review-requests/[id]/index.ts +35 -0
  118. package/src/astro/routes/api/admin/review-requests/[id]/resolve.ts +52 -0
  119. package/src/astro/routes/api/admin/review-requests/index.ts +35 -0
  120. package/src/astro/routes/api/admin/themes/marketplace/[id]/index.ts +33 -0
  121. package/src/astro/routes/api/admin/themes/marketplace/[id]/thumbnail.ts +62 -0
  122. package/src/astro/routes/api/admin/themes/marketplace/index.ts +45 -0
  123. package/src/astro/routes/api/admin/users/[id]/disable.ts +72 -0
  124. package/src/astro/routes/api/admin/users/[id]/enable.ts +48 -0
  125. package/src/astro/routes/api/admin/users/[id]/index.ts +166 -0
  126. package/src/astro/routes/api/admin/users/[id]/send-recovery.ts +72 -0
  127. package/src/astro/routes/api/admin/users/index.ts +66 -0
  128. package/src/astro/routes/api/auth/dev-bypass.ts +139 -0
  129. package/src/astro/routes/api/auth/invite/accept.ts +52 -0
  130. package/src/astro/routes/api/auth/invite/complete.ts +86 -0
  131. package/src/astro/routes/api/auth/invite/index.ts +99 -0
  132. package/src/astro/routes/api/auth/invite/register-options.ts +73 -0
  133. package/src/astro/routes/api/auth/logout.ts +40 -0
  134. package/src/astro/routes/api/auth/magic-link/send.ts +90 -0
  135. package/src/astro/routes/api/auth/magic-link/verify.ts +71 -0
  136. package/src/astro/routes/api/auth/me.ts +60 -0
  137. package/src/astro/routes/api/auth/oauth/[provider]/callback.ts +221 -0
  138. package/src/astro/routes/api/auth/oauth/[provider].ts +120 -0
  139. package/src/astro/routes/api/auth/passkey/[id].ts +124 -0
  140. package/src/astro/routes/api/auth/passkey/index.ts +54 -0
  141. package/src/astro/routes/api/auth/passkey/options.ts +85 -0
  142. package/src/astro/routes/api/auth/passkey/register/options.ts +88 -0
  143. package/src/astro/routes/api/auth/passkey/register/verify.ts +119 -0
  144. package/src/astro/routes/api/auth/passkey/verify.ts +72 -0
  145. package/src/astro/routes/api/auth/signup/complete.ts +87 -0
  146. package/src/astro/routes/api/auth/signup/request.ts +89 -0
  147. package/src/astro/routes/api/auth/signup/verify.ts +53 -0
  148. package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +310 -0
  149. package/src/astro/routes/api/content/[collection]/[id]/compare.ts +28 -0
  150. package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +68 -0
  151. package/src/astro/routes/api/content/[collection]/[id]/duplicate.ts +77 -0
  152. package/src/astro/routes/api/content/[collection]/[id]/permanent.ts +42 -0
  153. package/src/astro/routes/api/content/[collection]/[id]/preview-url.ts +107 -0
  154. package/src/astro/routes/api/content/[collection]/[id]/publish.ts +100 -0
  155. package/src/astro/routes/api/content/[collection]/[id]/restore.ts +64 -0
  156. package/src/astro/routes/api/content/[collection]/[id]/revisions.ts +31 -0
  157. package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +129 -0
  158. package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +143 -0
  159. package/src/astro/routes/api/content/[collection]/[id]/translations.ts +50 -0
  160. package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +69 -0
  161. package/src/astro/routes/api/content/[collection]/[id].ts +173 -0
  162. package/src/astro/routes/api/content/[collection]/index.ts +103 -0
  163. package/src/astro/routes/api/content/[collection]/trash.ts +33 -0
  164. package/src/astro/routes/api/dashboard.ts +32 -0
  165. package/src/astro/routes/api/dev/emails.ts +36 -0
  166. package/src/astro/routes/api/health.ts +54 -0
  167. package/src/astro/routes/api/import/probe.ts +47 -0
  168. package/src/astro/routes/api/import/wordpress/analyze.ts +523 -0
  169. package/src/astro/routes/api/import/wordpress/execute.ts +330 -0
  170. package/src/astro/routes/api/import/wordpress/media.ts +338 -0
  171. package/src/astro/routes/api/import/wordpress/prepare.ts +212 -0
  172. package/src/astro/routes/api/import/wordpress/rewrite-urls.ts +425 -0
  173. package/src/astro/routes/api/import/wordpress-plugin/analyze.ts +111 -0
  174. package/src/astro/routes/api/import/wordpress-plugin/callback.ts +58 -0
  175. package/src/astro/routes/api/import/wordpress-plugin/execute.ts +399 -0
  176. package/src/astro/routes/api/manifest.ts +75 -0
  177. package/src/astro/routes/api/mcp.ts +125 -0
  178. package/src/astro/routes/api/media/[id]/confirm.ts +93 -0
  179. package/src/astro/routes/api/media/[id].ts +145 -0
  180. package/src/astro/routes/api/media/file/[...key].ts +79 -0
  181. package/src/astro/routes/api/media/providers/[providerId]/[itemId].ts +91 -0
  182. package/src/astro/routes/api/media/providers/[providerId]/index.ts +111 -0
  183. package/src/astro/routes/api/media/providers/index.ts +30 -0
  184. package/src/astro/routes/api/media/upload-url.ts +146 -0
  185. package/src/astro/routes/api/media.ts +204 -0
  186. package/src/astro/routes/api/menus/[name]/items.ts +206 -0
  187. package/src/astro/routes/api/menus/[name]/reorder.ts +79 -0
  188. package/src/astro/routes/api/menus/[name].ts +145 -0
  189. package/src/astro/routes/api/menus/index.ts +91 -0
  190. package/src/astro/routes/api/oauth/authorize.ts +430 -0
  191. package/src/astro/routes/api/oauth/device/authorize.ts +45 -0
  192. package/src/astro/routes/api/oauth/device/code.ts +56 -0
  193. package/src/astro/routes/api/oauth/device/token.ts +70 -0
  194. package/src/astro/routes/api/oauth/register.ts +182 -0
  195. package/src/astro/routes/api/oauth/token/refresh.ts +38 -0
  196. package/src/astro/routes/api/oauth/token/revoke.ts +38 -0
  197. package/src/astro/routes/api/oauth/token.ts +195 -0
  198. package/src/astro/routes/api/openapi.json.ts +33 -0
  199. package/src/astro/routes/api/plugins/[pluginId]/[...path].ts +109 -0
  200. package/src/astro/routes/api/redirects/404s/index.ts +72 -0
  201. package/src/astro/routes/api/redirects/404s/summary.ts +33 -0
  202. package/src/astro/routes/api/redirects/[id].ts +183 -0
  203. package/src/astro/routes/api/redirects/index.ts +100 -0
  204. package/src/astro/routes/api/revisions/[revisionId]/index.ts +29 -0
  205. package/src/astro/routes/api/revisions/[revisionId]/restore.ts +62 -0
  206. package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +104 -0
  207. package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +67 -0
  208. package/src/astro/routes/api/schema/collections/[slug]/fields/reorder.ts +45 -0
  209. package/src/astro/routes/api/schema/collections/[slug]/index.ts +107 -0
  210. package/src/astro/routes/api/schema/collections/index.ts +61 -0
  211. package/src/astro/routes/api/schema/index.ts +109 -0
  212. package/src/astro/routes/api/schema/orphans/[slug].ts +36 -0
  213. package/src/astro/routes/api/schema/orphans/index.ts +26 -0
  214. package/src/astro/routes/api/search/enable.ts +64 -0
  215. package/src/astro/routes/api/search/index.ts +52 -0
  216. package/src/astro/routes/api/search/rebuild.ts +72 -0
  217. package/src/astro/routes/api/search/stats.ts +35 -0
  218. package/src/astro/routes/api/search/suggest.ts +50 -0
  219. package/src/astro/routes/api/sections/[slug].ts +203 -0
  220. package/src/astro/routes/api/sections/index.ts +107 -0
  221. package/src/astro/routes/api/settings/email.ts +150 -0
  222. package/src/astro/routes/api/settings.ts +116 -0
  223. package/src/astro/routes/api/setup/admin-verify.ts +122 -0
  224. package/src/astro/routes/api/setup/admin.ts +104 -0
  225. package/src/astro/routes/api/setup/dev-bypass.ts +200 -0
  226. package/src/astro/routes/api/setup/dev-reset.ts +40 -0
  227. package/src/astro/routes/api/setup/index.ts +128 -0
  228. package/src/astro/routes/api/setup/status.ts +122 -0
  229. package/src/astro/routes/api/snapshot.ts +76 -0
  230. package/src/astro/routes/api/taxonomies/[name]/terms/[slug].ts +232 -0
  231. package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +131 -0
  232. package/src/astro/routes/api/taxonomies/index.ts +114 -0
  233. package/src/astro/routes/api/themes/preview.ts +78 -0
  234. package/src/astro/routes/api/typegen.ts +114 -0
  235. package/src/astro/routes/api/well-known/auth.ts +71 -0
  236. package/src/astro/routes/api/well-known/oauth-authorization-server.ts +48 -0
  237. package/src/astro/routes/api/well-known/oauth-protected-resource.ts +39 -0
  238. package/src/astro/routes/api/widget-areas/[name]/reorder.ts +114 -0
  239. package/src/astro/routes/api/widget-areas/[name]/widgets/[id].ts +213 -0
  240. package/src/astro/routes/api/widget-areas/[name]/widgets.ts +126 -0
  241. package/src/astro/routes/api/widget-areas/[name].ts +135 -0
  242. package/src/astro/routes/api/widget-areas/index.ts +149 -0
  243. package/src/astro/routes/api/widget-components.ts +22 -0
  244. package/src/astro/routes/robots.txt.ts +81 -0
  245. package/src/astro/routes/sitemap-[collection].xml.ts +104 -0
  246. package/src/astro/routes/sitemap.xml.ts +92 -0
  247. package/src/components/Break.astro +45 -0
  248. package/src/components/Button.astro +71 -0
  249. package/src/components/Buttons.astro +49 -0
  250. package/src/components/Code.astro +59 -0
  251. package/src/components/Columns.astro +59 -0
  252. package/src/components/CommentForm.astro +315 -0
  253. package/src/components/Comments.astro +232 -0
  254. package/src/components/Cover.astro +128 -0
  255. package/src/components/DinewayBodyEnd.astro +32 -0
  256. package/src/components/DinewayBodyStart.astro +32 -0
  257. package/src/components/DinewayHead.astro +61 -0
  258. package/src/components/DinewayImage.astro +178 -0
  259. package/src/components/DinewayMedia.astro +167 -0
  260. package/src/components/Embed.astro +128 -0
  261. package/src/components/File.astro +122 -0
  262. package/src/components/Gallery.astro +93 -0
  263. package/src/components/HtmlBlock.astro +33 -0
  264. package/src/components/Image.astro +178 -0
  265. package/src/components/InlineEditor.astro +27 -0
  266. package/src/components/InlinePortableTextEditor.tsx +1937 -0
  267. package/src/components/LiveSearch.astro +614 -0
  268. package/src/components/PortableText.astro +51 -0
  269. package/src/components/Pullquote.astro +51 -0
  270. package/src/components/Table.astro +135 -0
  271. package/src/components/WidgetArea.astro +22 -0
  272. package/src/components/WidgetRenderer.astro +72 -0
  273. package/src/components/index.ts +106 -0
  274. package/src/components/marks/Link.astro +31 -0
  275. package/src/components/marks/StrikeThrough.astro +7 -0
  276. package/src/components/marks/Subscript.astro +7 -0
  277. package/src/components/marks/Superscript.astro +7 -0
  278. package/src/components/marks/Underline.astro +7 -0
  279. package/src/components/marks.ts +19 -0
  280. package/src/components/widgets/Archives.astro +65 -0
  281. package/src/components/widgets/Categories.astro +35 -0
  282. package/src/components/widgets/RecentPosts.astro +51 -0
  283. package/src/components/widgets/Search.astro +18 -0
  284. package/src/components/widgets/Tags.astro +38 -0
  285. package/src/ui.ts +75 -0
  286. package/LICENSE +0 -9
  287. /package/dist/{adapters-BlzWJG82.d.mts → adapters-C2ypTrZZ.d.mts} +0 -0
  288. /package/dist/{config-Cq8H0SfX.mjs → config-BXwuX8Bx.mjs} +0 -0
  289. /package/dist/{load-C6FCD1FU.mjs → load-Coc9HpHH.mjs} +0 -0
  290. /package/dist/{manifest-schema-CTSEyIJ3.mjs → manifest-schema-D1MSVnoI.mjs} +0 -0
  291. /package/dist/{mode-BlyYtIFO.mjs → mode-47goXBBK.mjs} +0 -0
  292. /package/dist/{tokens-4vgYuXsZ.mjs → tokens-CJz9ubV6.mjs} +0 -0
  293. /package/dist/{transport-C5FYnid7.mjs → transport-DB5eDN4x.mjs} +0 -0
  294. /package/dist/{transport-gIL-e43D.d.mts → transport-Wge_IzKl.d.mts} +0 -0
  295. /package/dist/{types-CLLdsG3g.d.mts → types-BzcUjoqg.d.mts} +0 -0
  296. /package/dist/{types-DShnjzb6.mjs → types-griIBQOQ.mjs} +0 -0
@@ -0,0 +1,122 @@
1
+ /**
2
+ * GET /_dineway/api/setup/status
3
+ *
4
+ * Returns setup status and seed file information
5
+ */
6
+
7
+ import type { APIRoute } from "astro";
8
+
9
+ export const prerender = false;
10
+
11
+ import { apiError, apiSuccess, handleError } from "#api/error.js";
12
+ import { getAuthMode } from "#auth/mode.js";
13
+ import { loadUserSeed } from "#seed/load.js";
14
+
15
+ export const GET: APIRoute = async ({ locals }) => {
16
+ const { dineway } = locals;
17
+
18
+ if (!dineway?.db) {
19
+ return apiError("NOT_CONFIGURED", "Dineway is not initialized", 500);
20
+ }
21
+
22
+ try {
23
+ // Check if setup is complete
24
+ const setupComplete = await dineway.db
25
+ .selectFrom("options")
26
+ .select("value")
27
+ .where("name", "=", "dineway:setup_complete")
28
+ .executeTakeFirst();
29
+
30
+ // Value is JSON-encoded, parse it. Accepts both boolean true and string "true"
31
+ const isComplete =
32
+ setupComplete &&
33
+ (() => {
34
+ try {
35
+ const parsed = JSON.parse(setupComplete.value);
36
+ return parsed === true || parsed === "true";
37
+ } catch {
38
+ return false;
39
+ }
40
+ })();
41
+
42
+ // Also check if users exist
43
+ let hasUsers = false;
44
+ try {
45
+ const userCount = await dineway.db
46
+ .selectFrom("users")
47
+ .select((eb) => eb.fn.countAll<number>().as("count"))
48
+ .executeTakeFirstOrThrow();
49
+ hasUsers = userCount.count > 0;
50
+ } catch {
51
+ // Users table might not exist yet
52
+ }
53
+
54
+ // Setup is complete only if flag is set AND users exist
55
+ if (isComplete && hasUsers) {
56
+ return apiSuccess({
57
+ needsSetup: false,
58
+ });
59
+ }
60
+
61
+ // Determine current step
62
+ // step: "start" | "site" | "admin" | "complete"
63
+ let step: "start" | "site" | "admin" = "start";
64
+
65
+ // Get setup state if it exists
66
+ const setupState = await dineway.db
67
+ .selectFrom("options")
68
+ .select("value")
69
+ .where("name", "=", "dineway:setup_state")
70
+ .executeTakeFirst();
71
+
72
+ if (setupState) {
73
+ try {
74
+ const state = JSON.parse(setupState.value);
75
+ if (state.step === "admin") {
76
+ step = "admin";
77
+ } else if (state.step === "site") {
78
+ step = "site";
79
+ }
80
+ } catch {
81
+ // Invalid state, stay at start
82
+ }
83
+ }
84
+
85
+ // If setup_complete but no users, jump to admin step
86
+ if (isComplete && !hasUsers) {
87
+ step = "admin";
88
+ }
89
+
90
+ // Check auth mode
91
+ const authMode = getAuthMode(dineway.config);
92
+ const useExternalAuth = authMode.type === "external";
93
+
94
+ // In external auth mode, setup is complete if flag is set (no users required initially)
95
+ if (useExternalAuth && isComplete) {
96
+ return apiSuccess({
97
+ needsSetup: false,
98
+ });
99
+ }
100
+
101
+ // Setup needed - try to load seed file info
102
+ const seed = await loadUserSeed();
103
+ const seedInfo = seed
104
+ ? {
105
+ name: seed.meta?.name || "Unknown Template",
106
+ description: seed.meta?.description || "",
107
+ collections: seed.collections?.length || 0,
108
+ hasContent: !!(seed.content && Object.keys(seed.content).length > 0),
109
+ }
110
+ : null;
111
+
112
+ return apiSuccess({
113
+ needsSetup: true,
114
+ step,
115
+ seedInfo,
116
+ // Tell the wizard which auth mode is active
117
+ authMode: useExternalAuth ? authMode.providerType : "passkey",
118
+ });
119
+ } catch (error) {
120
+ return handleError(error, "Failed to check setup status", "SETUP_STATUS_ERROR");
121
+ }
122
+ };
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Snapshot endpoint — exports a portable database snapshot for preview mode.
3
+ *
4
+ * Security:
5
+ * - Authenticated users: requires content:read + schema:read permissions
6
+ * - Preview services: requires valid X-Preview-Signature header (HMAC-SHA256)
7
+ * - Excludes auth/user/session/token tables
8
+ */
9
+
10
+ import type { APIRoute } from "astro";
11
+
12
+ import { requirePerm } from "#api/authorize.js";
13
+ import { apiError, apiSuccess, handleError } from "#api/error.js";
14
+ import {
15
+ generateSnapshot,
16
+ parsePreviewSignatureHeader,
17
+ verifyPreviewSignature,
18
+ } from "#api/handlers/snapshot.js";
19
+ import { getPublicOrigin } from "#api/public-url.js";
20
+
21
+ export const prerender = false;
22
+
23
+ export const GET: APIRoute = async ({ request, locals, url }) => {
24
+ const { dineway, user } = locals;
25
+
26
+ if (!dineway?.db) {
27
+ return apiError("NOT_CONFIGURED", "Dineway is not initialized", 500);
28
+ }
29
+
30
+ // Check for preview signature auth (used by preview sidecars)
31
+ const previewSig = request.headers.get("X-Preview-Signature");
32
+ let authorized = false;
33
+
34
+ if (previewSig) {
35
+ const secret = import.meta.env.DINEWAY_PREVIEW_SECRET || import.meta.env.PREVIEW_SECRET || "";
36
+ if (!secret) {
37
+ console.warn(
38
+ "[snapshot] X-Preview-Signature header present but no PREVIEW_SECRET configured",
39
+ );
40
+ } else {
41
+ const parsed = parsePreviewSignatureHeader(previewSig);
42
+ if (!parsed) {
43
+ console.warn("[snapshot] Failed to parse X-Preview-Signature header");
44
+ } else {
45
+ authorized = await verifyPreviewSignature(parsed.source, parsed.exp, parsed.sig, secret);
46
+ if (!authorized) {
47
+ console.warn("[snapshot] Preview signature verification failed", {
48
+ source: parsed.source,
49
+ exp: parsed.exp,
50
+ expired: parsed.exp < Date.now() / 1000,
51
+ });
52
+ }
53
+ }
54
+ }
55
+ }
56
+
57
+ if (!authorized) {
58
+ // Fall back to standard user auth
59
+ const contentDenied = requirePerm(user, "content:read");
60
+ if (contentDenied) return contentDenied;
61
+ const schemaDenied = requirePerm(user, "schema:read");
62
+ if (schemaDenied) return schemaDenied;
63
+ }
64
+
65
+ try {
66
+ const includeDrafts = url.searchParams.get("drafts") === "true";
67
+ const snapshot = await generateSnapshot(dineway.db, {
68
+ includeDrafts,
69
+ origin: getPublicOrigin(url, dineway.config),
70
+ });
71
+
72
+ return apiSuccess(snapshot);
73
+ } catch (error) {
74
+ return handleError(error, "Failed to generate snapshot", "SNAPSHOT_ERROR");
75
+ }
76
+ };
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Single term endpoint
3
+ *
4
+ * GET /_dineway/api/taxonomies/:name/terms/:slug - Get a single term
5
+ * PUT /_dineway/api/taxonomies/:name/terms/:slug - Update a term
6
+ * DELETE /_dineway/api/taxonomies/:name/terms/:slug - Delete a term
7
+ */
8
+
9
+ import type { APIRoute } from "astro";
10
+ import { z } from "zod";
11
+
12
+ import { requirePerm } from "#api/authorize.js";
13
+ import { apiError, handleError, requireDb, unwrapResult } from "#api/error.js";
14
+ import { handleTermDelete, handleTermGet, handleTermUpdate } from "#api/handlers/taxonomies.js";
15
+ import {
16
+ ensureWorkflowHitlRouteRequest,
17
+ hitlRequiredRouteError,
18
+ resolveHitlRouteActor,
19
+ } from "#api/hitl-route-helpers.js";
20
+ import { isParseError, parseBody, parseQuery } from "#api/parse.js";
21
+ import { updateTermBody } from "#api/schemas.js";
22
+ import {
23
+ activityChangedKeys,
24
+ logTaxonomyActivity,
25
+ RiskPolicyEvaluator,
26
+ taxonomyApiRouteSource,
27
+ TaxonomyHitlPayloadBuilder,
28
+ } from "#site-context/index.js";
29
+
30
+ export const prerender = false;
31
+
32
+ const updateTermHitlBody = updateTermBody.extend({
33
+ hitlRequestId: z.string().min(1).optional(),
34
+ });
35
+
36
+ const deleteTermQuery = z.object({
37
+ hitlRequestId: z.string().min(1).optional(),
38
+ });
39
+
40
+ /**
41
+ * Get a single term
42
+ */
43
+ export const GET: APIRoute = async ({ params, locals }) => {
44
+ const { dineway, user } = locals;
45
+ const { name, slug } = params;
46
+
47
+ if (!name || !slug) {
48
+ return apiError("VALIDATION_ERROR", "Taxonomy name and slug required", 400);
49
+ }
50
+
51
+ const dbErr = requireDb(dineway?.db);
52
+ if (dbErr) return dbErr;
53
+
54
+ const denied = requirePerm(user, "taxonomies:read");
55
+ if (denied) return denied;
56
+
57
+ try {
58
+ const result = await handleTermGet(dineway.db, name, slug);
59
+ return unwrapResult(result);
60
+ } catch (error) {
61
+ return handleError(error, "Failed to get term", "TERM_GET_ERROR");
62
+ }
63
+ };
64
+
65
+ /**
66
+ * Update a term
67
+ */
68
+ export const PUT: APIRoute = async ({ params, request, locals }) => {
69
+ const { dineway, user } = locals;
70
+ const { name, slug } = params;
71
+
72
+ if (!name || !slug) {
73
+ return apiError("VALIDATION_ERROR", "Taxonomy name and slug required", 400);
74
+ }
75
+
76
+ const dbErr = requireDb(dineway?.db);
77
+ if (dbErr) return dbErr;
78
+
79
+ const denied = requirePerm(user, "taxonomies:manage");
80
+ if (denied) return denied;
81
+
82
+ try {
83
+ const body = await parseBody(request, updateTermHitlBody);
84
+ if (isParseError(body)) return body;
85
+
86
+ const current = await handleTermGet(dineway.db, name, slug);
87
+ if (!current.success) return unwrapResult(current);
88
+
89
+ const { hitlRequestId, ...termInput } = body;
90
+ const actor = resolveHitlRouteActor(locals);
91
+ const evaluator = new RiskPolicyEvaluator({
92
+ db: dineway.db,
93
+ handlers: dineway,
94
+ });
95
+ let approvedHitlRequestId: string | null = null;
96
+
97
+ if (evaluator.requiresWorkflowHitl(actor.identity)) {
98
+ const payloadBuilder = new TaxonomyHitlPayloadBuilder(dineway.db);
99
+ const taxonomy = await payloadBuilder.loadTaxonomyDefinition(name);
100
+ if (!taxonomy) {
101
+ return apiError("NOT_FOUND", `Taxonomy '${name}' not found`, 404);
102
+ }
103
+
104
+ const action = await payloadBuilder.buildUpdateTermRequest({
105
+ taxonomy,
106
+ currentTerm: {
107
+ id: current.data.term.id,
108
+ name: current.data.term.name,
109
+ slug: current.data.term.slug,
110
+ label: current.data.term.label,
111
+ parentId: current.data.term.parentId,
112
+ description: current.data.term.description ?? null,
113
+ },
114
+ ...termInput,
115
+ });
116
+ const decision = await evaluator.evaluateWorkflowHitl({
117
+ actor: actor.identity,
118
+ hitlRequestId,
119
+ action,
120
+ });
121
+ if (!decision.allowed) {
122
+ const ensured = await ensureWorkflowHitlRouteRequest(dineway.db, locals, decision.action);
123
+ return hitlRequiredRouteError(decision, ensured);
124
+ }
125
+ approvedHitlRequestId = decision.hitlRequest.id;
126
+ }
127
+
128
+ const result = await handleTermUpdate(dineway.db, name, slug, termInput);
129
+ if (result.success) {
130
+ await logTaxonomyActivity(dineway.db, locals, {
131
+ action: "term_updated",
132
+ taxonomyName: name,
133
+ termId: result.data.term.id,
134
+ termSlug: result.data.term.slug,
135
+ ...taxonomyApiRouteSource("term_updated"),
136
+ detail: {
137
+ changedKeys: activityChangedKeys(termInput),
138
+ label: result.data.term.label,
139
+ parentId: result.data.term.parentId,
140
+ description: result.data.term.description ?? null,
141
+ hitlRequestId: approvedHitlRequestId,
142
+ },
143
+ });
144
+ }
145
+ return unwrapResult(result);
146
+ } catch (error) {
147
+ return handleError(error, "Failed to update term", "TERM_UPDATE_ERROR");
148
+ }
149
+ };
150
+
151
+ /**
152
+ * Delete a term
153
+ */
154
+ export const DELETE: APIRoute = async ({ params, request, locals }) => {
155
+ const { dineway, user } = locals;
156
+ const { name, slug } = params;
157
+
158
+ if (!name || !slug) {
159
+ return apiError("VALIDATION_ERROR", "Taxonomy name and slug required", 400);
160
+ }
161
+
162
+ const dbErr = requireDb(dineway?.db);
163
+ if (dbErr) return dbErr;
164
+
165
+ const denied = requirePerm(user, "taxonomies:manage");
166
+ if (denied) return denied;
167
+
168
+ const query = parseQuery(new URL(request.url), deleteTermQuery);
169
+ if (isParseError(query)) return query;
170
+
171
+ try {
172
+ const current = await handleTermGet(dineway.db, name, slug);
173
+ if (!current.success) return unwrapResult(current);
174
+
175
+ const actor = resolveHitlRouteActor(locals);
176
+ const evaluator = new RiskPolicyEvaluator({
177
+ db: dineway.db,
178
+ handlers: dineway,
179
+ });
180
+ let approvedHitlRequestId: string | null = null;
181
+
182
+ if (evaluator.requiresWorkflowHitl(actor.identity)) {
183
+ const payloadBuilder = new TaxonomyHitlPayloadBuilder(dineway.db);
184
+ const taxonomy = await payloadBuilder.loadTaxonomyDefinition(name);
185
+ if (!taxonomy) {
186
+ return apiError("NOT_FOUND", `Taxonomy '${name}' not found`, 404);
187
+ }
188
+
189
+ const action = await payloadBuilder.buildDeleteTermRequest({
190
+ taxonomy,
191
+ currentTerm: {
192
+ id: current.data.term.id,
193
+ name: current.data.term.name,
194
+ slug: current.data.term.slug,
195
+ label: current.data.term.label,
196
+ parentId: current.data.term.parentId,
197
+ description: current.data.term.description ?? null,
198
+ },
199
+ });
200
+ const decision = await evaluator.evaluateWorkflowHitl({
201
+ actor: actor.identity,
202
+ hitlRequestId: query.hitlRequestId,
203
+ action,
204
+ });
205
+ if (!decision.allowed) {
206
+ const ensured = await ensureWorkflowHitlRouteRequest(dineway.db, locals, decision.action);
207
+ return hitlRequiredRouteError(decision, ensured);
208
+ }
209
+ approvedHitlRequestId = decision.hitlRequest.id;
210
+ }
211
+
212
+ const result = await handleTermDelete(dineway.db, name, slug);
213
+ if (result.success) {
214
+ await logTaxonomyActivity(dineway.db, locals, {
215
+ action: "term_deleted",
216
+ taxonomyName: name,
217
+ termId: current.data.term.id,
218
+ termSlug: current.data.term.slug,
219
+ ...taxonomyApiRouteSource("term_deleted"),
220
+ detail: {
221
+ label: current.data.term.label,
222
+ parentId: current.data.term.parentId,
223
+ description: current.data.term.description ?? null,
224
+ hitlRequestId: approvedHitlRequestId,
225
+ },
226
+ });
227
+ }
228
+ return unwrapResult(result);
229
+ } catch (error) {
230
+ return handleError(error, "Failed to delete term", "TERM_DELETE_ERROR");
231
+ }
232
+ };
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Taxonomy terms list and create endpoint
3
+ *
4
+ * GET /_dineway/api/taxonomies/:name/terms - List all terms (tree for hierarchical)
5
+ * POST /_dineway/api/taxonomies/:name/terms - Create a new term
6
+ */
7
+
8
+ import type { APIRoute } from "astro";
9
+ import { z } from "zod";
10
+
11
+ import { requirePerm } from "#api/authorize.js";
12
+ import { apiError, handleError, requireDb, unwrapResult } from "#api/error.js";
13
+ import { handleTermCreate, handleTermList } from "#api/handlers/taxonomies.js";
14
+ import {
15
+ ensureWorkflowHitlRouteRequest,
16
+ hitlRequiredRouteError,
17
+ resolveHitlRouteActor,
18
+ } from "#api/hitl-route-helpers.js";
19
+ import { isParseError, parseBody } from "#api/parse.js";
20
+ import { createTermBody } from "#api/schemas.js";
21
+ import {
22
+ logTaxonomyActivity,
23
+ RiskPolicyEvaluator,
24
+ taxonomyApiRouteSource,
25
+ TaxonomyHitlPayloadBuilder,
26
+ } from "#site-context/index.js";
27
+
28
+ export const prerender = false;
29
+
30
+ const createTermHitlBody = createTermBody.extend({
31
+ hitlRequestId: z.string().min(1).optional(),
32
+ });
33
+
34
+ /**
35
+ * List all terms for a taxonomy
36
+ */
37
+ export const GET: APIRoute = async ({ params, locals }) => {
38
+ const { dineway, user } = locals;
39
+ const { name } = params;
40
+
41
+ if (!name) {
42
+ return apiError("VALIDATION_ERROR", "Taxonomy name required", 400);
43
+ }
44
+
45
+ const dbErr = requireDb(dineway?.db);
46
+ if (dbErr) return dbErr;
47
+
48
+ const denied = requirePerm(user, "taxonomies:read");
49
+ if (denied) return denied;
50
+
51
+ try {
52
+ const result = await handleTermList(dineway.db, name);
53
+ return unwrapResult(result);
54
+ } catch (error) {
55
+ return handleError(error, "Failed to list terms", "TERM_LIST_ERROR");
56
+ }
57
+ };
58
+
59
+ /**
60
+ * Create a new term
61
+ */
62
+ export const POST: APIRoute = async ({ params, request, locals }) => {
63
+ const { dineway, user } = locals;
64
+ const { name } = params;
65
+
66
+ if (!name) {
67
+ return apiError("VALIDATION_ERROR", "Taxonomy name required", 400);
68
+ }
69
+
70
+ const dbErr = requireDb(dineway?.db);
71
+ if (dbErr) return dbErr;
72
+
73
+ const denied = requirePerm(user, "taxonomies:manage");
74
+ if (denied) return denied;
75
+
76
+ try {
77
+ const body = await parseBody(request, createTermHitlBody);
78
+ if (isParseError(body)) return body;
79
+
80
+ const { hitlRequestId, ...termInput } = body;
81
+ const actor = resolveHitlRouteActor(locals);
82
+ const evaluator = new RiskPolicyEvaluator({
83
+ db: dineway.db,
84
+ handlers: dineway,
85
+ });
86
+ let approvedHitlRequestId: string | null = null;
87
+
88
+ if (evaluator.requiresWorkflowHitl(actor.identity)) {
89
+ const payloadBuilder = new TaxonomyHitlPayloadBuilder(dineway.db);
90
+ const taxonomy = await payloadBuilder.loadTaxonomyDefinition(name);
91
+ if (!taxonomy) {
92
+ return apiError("NOT_FOUND", `Taxonomy '${name}' not found`, 404);
93
+ }
94
+
95
+ const action = await payloadBuilder.buildCreateTermRequest({
96
+ taxonomy,
97
+ ...termInput,
98
+ });
99
+ const decision = await evaluator.evaluateWorkflowHitl({
100
+ actor: actor.identity,
101
+ hitlRequestId,
102
+ action,
103
+ });
104
+ if (!decision.allowed) {
105
+ const ensured = await ensureWorkflowHitlRouteRequest(dineway.db, locals, decision.action);
106
+ return hitlRequiredRouteError(decision, ensured);
107
+ }
108
+ approvedHitlRequestId = decision.hitlRequest.id;
109
+ }
110
+
111
+ const result = await handleTermCreate(dineway.db, name, termInput);
112
+ if (result.success) {
113
+ await logTaxonomyActivity(dineway.db, locals, {
114
+ action: "term_created",
115
+ taxonomyName: name,
116
+ termId: result.data.term.id,
117
+ termSlug: result.data.term.slug,
118
+ ...taxonomyApiRouteSource("term_created"),
119
+ detail: {
120
+ label: result.data.term.label,
121
+ parentId: result.data.term.parentId,
122
+ description: result.data.term.description ?? null,
123
+ hitlRequestId: approvedHitlRequestId,
124
+ },
125
+ });
126
+ }
127
+ return unwrapResult(result, 201);
128
+ } catch (error) {
129
+ return handleError(error, "Failed to create term", "TERM_CREATE_ERROR");
130
+ }
131
+ };
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Taxonomy definitions endpoint
3
+ *
4
+ * GET /_dineway/api/taxonomies - List all taxonomy definitions
5
+ * POST /_dineway/api/taxonomies - Create a custom taxonomy definition
6
+ */
7
+
8
+ import type { APIRoute } from "astro";
9
+ import { z } from "zod";
10
+
11
+ import { requirePerm } from "#api/authorize.js";
12
+ import { handleError, requireDb, unwrapResult } from "#api/error.js";
13
+ import { handleTaxonomyCreate, handleTaxonomyList } from "#api/handlers/taxonomies.js";
14
+ import {
15
+ ensureWorkflowHitlRouteRequest,
16
+ hitlRequiredRouteError,
17
+ resolveHitlRouteActor,
18
+ } from "#api/hitl-route-helpers.js";
19
+ import { isParseError, parseBody } from "#api/parse.js";
20
+ import { createTaxonomyDefBody } from "#api/schemas.js";
21
+ import {
22
+ logTaxonomyActivity,
23
+ RiskPolicyEvaluator,
24
+ taxonomyApiRouteSource,
25
+ TaxonomyHitlPayloadBuilder,
26
+ } from "#site-context/index.js";
27
+
28
+ export const prerender = false;
29
+
30
+ const createTaxonomyHitlBody = createTaxonomyDefBody.extend({
31
+ hitlRequestId: z.string().min(1).optional(),
32
+ });
33
+
34
+ /**
35
+ * List taxonomy definitions
36
+ */
37
+ export const GET: APIRoute = async ({ locals }) => {
38
+ const { dineway, user } = locals;
39
+
40
+ const dbErr = requireDb(dineway?.db);
41
+ if (dbErr) return dbErr;
42
+
43
+ const denied = requirePerm(user, "taxonomies:read");
44
+ if (denied) return denied;
45
+
46
+ try {
47
+ const result = await handleTaxonomyList(dineway.db);
48
+ return unwrapResult(result);
49
+ } catch (error) {
50
+ return handleError(error, "Failed to list taxonomies", "TAXONOMY_LIST_ERROR");
51
+ }
52
+ };
53
+
54
+ /**
55
+ * Create a custom taxonomy definition
56
+ */
57
+ export const POST: APIRoute = async ({ request, locals }) => {
58
+ const { dineway, user } = locals;
59
+
60
+ const dbErr = requireDb(dineway?.db);
61
+ if (dbErr) return dbErr;
62
+
63
+ const denied = requirePerm(user, "taxonomies:manage");
64
+ if (denied) return denied;
65
+
66
+ try {
67
+ const body = await parseBody(request, createTaxonomyHitlBody);
68
+ if (isParseError(body)) return body;
69
+
70
+ const { hitlRequestId, ...taxonomyInput } = body;
71
+ const actor = resolveHitlRouteActor(locals);
72
+ const evaluator = new RiskPolicyEvaluator({
73
+ db: dineway.db,
74
+ handlers: dineway,
75
+ });
76
+ let approvedHitlRequestId: string | null = null;
77
+
78
+ if (evaluator.requiresWorkflowHitl(actor.identity)) {
79
+ const action = await new TaxonomyHitlPayloadBuilder(dineway.db).buildCreateTaxonomyRequest(
80
+ taxonomyInput,
81
+ );
82
+ const decision = await evaluator.evaluateWorkflowHitl({
83
+ actor: actor.identity,
84
+ hitlRequestId,
85
+ action,
86
+ });
87
+ if (!decision.allowed) {
88
+ const ensured = await ensureWorkflowHitlRouteRequest(dineway.db, locals, decision.action);
89
+ return hitlRequiredRouteError(decision, ensured);
90
+ }
91
+ approvedHitlRequestId = decision.hitlRequest.id;
92
+ }
93
+
94
+ const result = await handleTaxonomyCreate(dineway.db, taxonomyInput);
95
+ if (result.success) dineway.invalidateManifest();
96
+ if (result.success) {
97
+ await logTaxonomyActivity(dineway.db, locals, {
98
+ action: "created",
99
+ taxonomyId: result.data.taxonomy.id,
100
+ taxonomyName: result.data.taxonomy.name,
101
+ ...taxonomyApiRouteSource("created"),
102
+ detail: {
103
+ label: result.data.taxonomy.label,
104
+ hierarchical: result.data.taxonomy.hierarchical,
105
+ collections: result.data.taxonomy.collections,
106
+ hitlRequestId: approvedHitlRequestId,
107
+ },
108
+ });
109
+ }
110
+ return unwrapResult(result, 201);
111
+ } catch (error) {
112
+ return handleError(error, "Failed to create taxonomy", "TAXONOMY_CREATE_ERROR");
113
+ }
114
+ };