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
@@ -1,24 +1,29 @@
1
- import { n as createDatabase } from "./connection-C9pxzuag.mjs";
2
- import { o as jsonExtractExpr } from "./dialect-helpers-B9uSp2GJ.mjs";
3
- import { n as validateJsonFieldName, r as validatePluginIdentifier, t as validateIdentifier } from "./validate-CqRJb_xU.mjs";
4
- import { i as slugify, r as RevisionRepository, t as ContentRepository } from "./content-zSgdNmnt.mjs";
1
+ import { runWithContext } from "./request-context.mjs";
2
+ import { n as createDatabase } from "./connection-BCNICDWN.mjs";
3
+ import { n as validateJsonFieldName, r as validatePluginIdentifier, t as validateIdentifier } from "./validate-VPnKoIzW.mjs";
4
+ import { o as jsonExtractExpr } from "./dialect-helpers-DhTzaUxP.mjs";
5
+ import { a as slugify, r as RevisionRepository, t as ContentRepository } from "./content-DWi4d0rT.mjs";
5
6
  import { r as encodeBase64, t as decodeBase64 } from "./base64-F8-DUraK.mjs";
6
7
  import { n as decodeCursor, r as encodeCursor, t as DinewayValidationError } from "./types-BawVha09.mjs";
7
8
  import { t as MediaRepository } from "./media-DMTr80Gv.mjs";
8
- import { a as stripCredentialHeaders, f as OptionsRepository, i as ssrfSafeFetch, o as validateExternalUrl, r as SsrfError } from "./apply-CAPvMfoU.mjs";
9
- import { a as withTransaction, i as FTSManager, n as SchemaRegistry } from "./registry-DSd1GWB8.mjs";
10
- import { t as RedirectRepository } from "./redirect-JPqLAbxa.mjs";
11
- import { n as SQL_BATCH_SIZE, r as chunks, t as BylineRepository } from "./byline-DeWCMU_i.mjs";
12
- import { r as isI18nEnabled } from "./config-Cq8H0SfX.mjs";
13
- import { runWithContext } from "./request-context.mjs";
14
- import { n as getDb } from "./loader-qKmo0wAY.mjs";
15
- import { i as pluginManifestSchema } from "./manifest-schema-CTSEyIJ3.mjs";
16
- import { t as generatePreviewToken } from "./tokens-4vgYuXsZ.mjs";
9
+ import { a as ssrfSafeFetch, i as resolveAndValidateExternalUrl, o as stripCredentialHeaders, p as OptionsRepository, r as SsrfError, s as validateExternalUrl } from "./apply-iVSqz2qs.mjs";
10
+ import { t as withTransaction } from "./transaction-Cn2rjY78.mjs";
11
+ import { t as RedirectRepository } from "./redirect-DnEWAkVg.mjs";
12
+ import { n as chunks, t as SQL_BATCH_SIZE } from "./chunks--4F8ddV4.mjs";
13
+ import { t as BylineRepository } from "./byline-OhH2dlRu.mjs";
14
+ import { r as isI18nEnabled } from "./config-BXwuX8Bx.mjs";
15
+ import { i as invalidateRedirectCache } from "./cache-BdSY-gQN.mjs";
16
+ import { i as FTSManager, n as SchemaRegistry } from "./registry-C0zjeB9P.mjs";
17
+ import { n as getDb } from "./loader-sMG4TZ-u.mjs";
18
+ import { n as requestCached } from "./request-cache-Dk5qPSOx.mjs";
19
+ import { n as VERSION, t as COMMIT } from "./version-BKXPsfmJ.mjs";
20
+ import { i as pluginManifestSchema } from "./manifest-schema-D1MSVnoI.mjs";
21
+ import { t as generatePreviewToken } from "./tokens-CJz9ubV6.mjs";
17
22
  import BetterSqlite3 from "better-sqlite3";
18
23
  import { sql } from "kysely";
24
+ import { AsyncLocalStorage } from "node:async_hooks";
19
25
  import { ulid } from "ulidx";
20
26
  import { z } from "astro/zod";
21
- import { AsyncLocalStorage } from "node:async_hooks";
22
27
  import { z as z$1 } from "zod";
23
28
  import { createGzipDecoder, unpackTar } from "modern-tar";
24
29
  import { createHash } from "node:crypto";
@@ -995,6 +1000,13 @@ const SEO_DEFAULTS = {
995
1000
  canonical: null,
996
1001
  noIndex: false
997
1002
  };
1003
+ var ContentUpdateApiError = class extends Error {
1004
+ constructor(code, message) {
1005
+ super(message);
1006
+ this.code = code;
1007
+ this.name = "ContentUpdateApiError";
1008
+ }
1009
+ };
998
1010
  /**
999
1011
  * Check if a collection has SEO enabled.
1000
1012
  */
@@ -1285,34 +1297,18 @@ async function handleContentUpdate(db, collection, id, body) {
1285
1297
  message: `Collection "${collection}" does not have SEO enabled. Remove the seo field or enable SEO on this collection.`
1286
1298
  }
1287
1299
  };
1288
- const repo = new ContentRepository(db);
1289
- const resolvedId = await resolveId(repo, collection, id) ?? id;
1290
- if (body._rev) {
1291
- const existing = await repo.findById(collection, resolvedId);
1292
- if (!existing) return {
1293
- success: false,
1294
- error: {
1295
- code: "NOT_FOUND",
1296
- message: `Content item not found: ${id}`
1297
- }
1298
- };
1299
- const revCheck = validateRev(body._rev, existing);
1300
- if (!revCheck.valid) return {
1301
- success: false,
1302
- error: {
1303
- code: "CONFLICT",
1304
- message: revCheck.message
1305
- }
1306
- };
1307
- }
1300
+ const resolvedId = await resolveId(new ContentRepository(db), collection, id) ?? id;
1308
1301
  const item = await withTransaction(db, async (trx) => {
1309
1302
  const trxRepo = new ContentRepository(trx);
1310
1303
  const bylineRepo = new BylineRepository(trx);
1311
- let oldSlug;
1312
- if (body.slug) {
1313
- const existing = await trxRepo.findById(collection, resolvedId);
1314
- if (existing?.slug && existing.slug !== body.slug) oldSlug = existing.slug;
1304
+ const existing = body._rev || body.slug ? await trxRepo.findById(collection, resolvedId) : null;
1305
+ if (body._rev) {
1306
+ if (!existing) throw new ContentUpdateApiError("NOT_FOUND", `Content item not found: ${id}`);
1307
+ const revCheck = validateRev(body._rev, existing);
1308
+ if (!revCheck.valid) throw new ContentUpdateApiError("CONFLICT", revCheck.message);
1315
1309
  }
1310
+ let oldSlug;
1311
+ if (body.slug && existing?.slug && existing.slug !== body.slug) oldSlug = existing.slug;
1316
1312
  const updated = await trxRepo.update(collection, resolvedId, {
1317
1313
  data: body.data,
1318
1314
  slug: body.slug,
@@ -1326,6 +1322,7 @@ async function handleContentUpdate(db, collection, id, body) {
1326
1322
  if (oldSlug && body.slug) {
1327
1323
  const collectionRow = await trx.selectFrom("_dineway_collections").select("url_pattern").where("slug", "=", collection).executeTakeFirst();
1328
1324
  await new RedirectRepository(trx).createAutoRedirect(collection, oldSlug, body.slug, resolvedId, collectionRow?.url_pattern ?? null);
1325
+ invalidateRedirectCache();
1329
1326
  }
1330
1327
  if (isI18nEnabled() && body.data && updated.translationGroup) await syncNonTranslatableFields(trx, collection, updated.id, updated.translationGroup, body.data);
1331
1328
  if (body.seo && hasSeo) updated.seo = await new SeoRepository(trx).upsert(collection, resolvedId, body.seo);
@@ -1341,6 +1338,13 @@ async function handleContentUpdate(db, collection, id, body) {
1341
1338
  }
1342
1339
  };
1343
1340
  } catch (error) {
1341
+ if (error instanceof ContentUpdateApiError) return {
1342
+ success: false,
1343
+ error: {
1344
+ code: error.code,
1345
+ message: error.message
1346
+ }
1347
+ };
1344
1348
  console.error("Content update error:", error);
1345
1349
  return {
1346
1350
  success: false,
@@ -1473,6 +1477,7 @@ async function handleContentPermanentDelete(db, collection, id) {
1473
1477
  if (wasDeleted) {
1474
1478
  await new SeoRepository(trx).delete(collection, resolvedId);
1475
1479
  await new CommentRepository(trx).deleteByContent(collection, resolvedId);
1480
+ await new RevisionRepository(trx).deleteByEntry(collection, resolvedId);
1476
1481
  }
1477
1482
  return wasDeleted;
1478
1483
  })) return {
@@ -1847,6 +1852,151 @@ async function syncNonTranslatableFields(trx, collectionSlug, updatedItemId, tra
1847
1852
  `.execute(trx);
1848
1853
  }
1849
1854
 
1855
+ //#endregion
1856
+ //#region src/plugins/state.ts
1857
+ function toPluginStatus(value) {
1858
+ if (value === "active") return "active";
1859
+ return "inactive";
1860
+ }
1861
+ function toPluginSource(value) {
1862
+ if (value === "marketplace") return "marketplace";
1863
+ return "config";
1864
+ }
1865
+ /**
1866
+ * Repository for plugin state in the database
1867
+ */
1868
+ var PluginStateRepository = class {
1869
+ constructor(db) {
1870
+ this.db = db;
1871
+ }
1872
+ /**
1873
+ * Get state for a specific plugin
1874
+ */
1875
+ async get(pluginId) {
1876
+ const row = await this.db.selectFrom("_plugin_state").selectAll().where("plugin_id", "=", pluginId).executeTakeFirst();
1877
+ if (!row) return null;
1878
+ return {
1879
+ pluginId: row.plugin_id,
1880
+ status: toPluginStatus(row.status),
1881
+ version: row.version,
1882
+ installedAt: new Date(row.installed_at),
1883
+ activatedAt: row.activated_at ? new Date(row.activated_at) : null,
1884
+ deactivatedAt: row.deactivated_at ? new Date(row.deactivated_at) : null,
1885
+ source: toPluginSource(row.source),
1886
+ marketplaceVersion: row.marketplace_version ?? null,
1887
+ displayName: row.display_name ?? null,
1888
+ description: row.description ?? null
1889
+ };
1890
+ }
1891
+ /**
1892
+ * Get all plugin states
1893
+ */
1894
+ async getAll() {
1895
+ return (await this.db.selectFrom("_plugin_state").selectAll().execute()).map((row) => ({
1896
+ pluginId: row.plugin_id,
1897
+ status: toPluginStatus(row.status),
1898
+ version: row.version,
1899
+ installedAt: new Date(row.installed_at),
1900
+ activatedAt: row.activated_at ? new Date(row.activated_at) : null,
1901
+ deactivatedAt: row.deactivated_at ? new Date(row.deactivated_at) : null,
1902
+ source: toPluginSource(row.source),
1903
+ marketplaceVersion: row.marketplace_version ?? null,
1904
+ displayName: row.display_name ?? null,
1905
+ description: row.description ?? null
1906
+ }));
1907
+ }
1908
+ /**
1909
+ * Get all marketplace-installed plugin states
1910
+ */
1911
+ async getMarketplacePlugins() {
1912
+ return (await this.db.selectFrom("_plugin_state").selectAll().where("source", "=", "marketplace").execute()).map((row) => ({
1913
+ pluginId: row.plugin_id,
1914
+ status: toPluginStatus(row.status),
1915
+ version: row.version,
1916
+ installedAt: new Date(row.installed_at),
1917
+ activatedAt: row.activated_at ? new Date(row.activated_at) : null,
1918
+ deactivatedAt: row.deactivated_at ? new Date(row.deactivated_at) : null,
1919
+ source: toPluginSource(row.source),
1920
+ marketplaceVersion: row.marketplace_version ?? null,
1921
+ displayName: row.display_name ?? null,
1922
+ description: row.description ?? null
1923
+ }));
1924
+ }
1925
+ /**
1926
+ * Create or update plugin state
1927
+ */
1928
+ async upsert(pluginId, version, status, opts) {
1929
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1930
+ const existing = await this.get(pluginId);
1931
+ if (existing) {
1932
+ const updates = {
1933
+ status,
1934
+ version
1935
+ };
1936
+ if (status === "active" && existing.status !== "active") updates.activated_at = now;
1937
+ else if (status === "inactive" && existing.status !== "inactive") updates.deactivated_at = now;
1938
+ if (opts?.source) updates.source = opts.source;
1939
+ if (opts?.marketplaceVersion !== void 0) updates.marketplace_version = opts.marketplaceVersion;
1940
+ if (opts?.displayName !== void 0) updates.display_name = opts.displayName;
1941
+ if (opts?.description !== void 0) updates.description = opts.description;
1942
+ await this.db.updateTable("_plugin_state").set(updates).where("plugin_id", "=", pluginId).execute();
1943
+ } else await this.db.insertInto("_plugin_state").values({
1944
+ plugin_id: pluginId,
1945
+ status,
1946
+ version,
1947
+ installed_at: now,
1948
+ activated_at: status === "active" ? now : null,
1949
+ deactivated_at: null,
1950
+ data: null,
1951
+ source: opts?.source ?? "config",
1952
+ marketplace_version: opts?.marketplaceVersion ?? null,
1953
+ display_name: opts?.displayName ?? null,
1954
+ description: opts?.description ?? null
1955
+ }).execute();
1956
+ return await this.get(pluginId);
1957
+ }
1958
+ /**
1959
+ * Enable a plugin
1960
+ */
1961
+ async enable(pluginId, version) {
1962
+ return this.upsert(pluginId, version, "active");
1963
+ }
1964
+ /**
1965
+ * Disable a plugin
1966
+ */
1967
+ async disable(pluginId, version) {
1968
+ return this.upsert(pluginId, version, "inactive");
1969
+ }
1970
+ /**
1971
+ * Delete plugin state
1972
+ */
1973
+ async delete(pluginId) {
1974
+ return ((await this.db.deleteFrom("_plugin_state").where("plugin_id", "=", pluginId).executeTakeFirst()).numDeletedRows ?? 0) > 0;
1975
+ }
1976
+ };
1977
+
1978
+ //#endregion
1979
+ //#region src/site-context/context-types.ts
1980
+ const SITE_CONTEXT_TYPES = [
1981
+ "brand_voice",
1982
+ "seo_strategy",
1983
+ "audience",
1984
+ "content_guideline",
1985
+ "forbidden_terms",
1986
+ "editorial_policy",
1987
+ "migration_note",
1988
+ "plugin_note",
1989
+ "agent_reasoning",
1990
+ "decision",
1991
+ "risk",
1992
+ "content_gap",
1993
+ "style_exception"
1994
+ ];
1995
+ const SITE_CONTEXT_TYPE_SET = new Set(SITE_CONTEXT_TYPES);
1996
+ function isSiteContextType(value) {
1997
+ return SITE_CONTEXT_TYPE_SET.has(value);
1998
+ }
1999
+
1850
2000
  //#endregion
1851
2001
  //#region src/utils/hash.ts
1852
2002
  /**
@@ -1901,7 +2051,8 @@ async function generateManifest(collections, plugins = {}) {
1901
2051
  };
1902
2052
  }
1903
2053
  return {
1904
- version: "0.1.0",
2054
+ version: VERSION,
2055
+ commit: COMMIT,
1905
2056
  hash: await hashString(JSON.stringify(manifestCollections)),
1906
2057
  collections: manifestCollections,
1907
2058
  plugins
@@ -2238,7 +2389,9 @@ async function handleMediaDelete(db, id) {
2238
2389
  * ```
2239
2390
  */
2240
2391
  async function getCollectionInfo(slug) {
2241
- return getCollectionInfoWithDb(await getDb(), slug);
2392
+ return requestCached(`collection-info:${slug}`, async () => {
2393
+ return getCollectionInfoWithDb(await getDb(), slug);
2394
+ });
2242
2395
  }
2243
2396
  /**
2244
2397
  * Get collection metadata with an explicit db handle.
@@ -2250,129 +2403,6 @@ async function getCollectionInfoWithDb(db, slug) {
2250
2403
  return new SchemaRegistry(db).getCollection(slug);
2251
2404
  }
2252
2405
 
2253
- //#endregion
2254
- //#region src/plugins/state.ts
2255
- function toPluginStatus(value) {
2256
- if (value === "active") return "active";
2257
- return "inactive";
2258
- }
2259
- function toPluginSource(value) {
2260
- if (value === "marketplace") return "marketplace";
2261
- return "config";
2262
- }
2263
- /**
2264
- * Repository for plugin state in the database
2265
- */
2266
- var PluginStateRepository = class {
2267
- constructor(db) {
2268
- this.db = db;
2269
- }
2270
- /**
2271
- * Get state for a specific plugin
2272
- */
2273
- async get(pluginId) {
2274
- const row = await this.db.selectFrom("_plugin_state").selectAll().where("plugin_id", "=", pluginId).executeTakeFirst();
2275
- if (!row) return null;
2276
- return {
2277
- pluginId: row.plugin_id,
2278
- status: toPluginStatus(row.status),
2279
- version: row.version,
2280
- installedAt: new Date(row.installed_at),
2281
- activatedAt: row.activated_at ? new Date(row.activated_at) : null,
2282
- deactivatedAt: row.deactivated_at ? new Date(row.deactivated_at) : null,
2283
- source: toPluginSource(row.source),
2284
- marketplaceVersion: row.marketplace_version ?? null,
2285
- displayName: row.display_name ?? null,
2286
- description: row.description ?? null
2287
- };
2288
- }
2289
- /**
2290
- * Get all plugin states
2291
- */
2292
- async getAll() {
2293
- return (await this.db.selectFrom("_plugin_state").selectAll().execute()).map((row) => ({
2294
- pluginId: row.plugin_id,
2295
- status: toPluginStatus(row.status),
2296
- version: row.version,
2297
- installedAt: new Date(row.installed_at),
2298
- activatedAt: row.activated_at ? new Date(row.activated_at) : null,
2299
- deactivatedAt: row.deactivated_at ? new Date(row.deactivated_at) : null,
2300
- source: toPluginSource(row.source),
2301
- marketplaceVersion: row.marketplace_version ?? null,
2302
- displayName: row.display_name ?? null,
2303
- description: row.description ?? null
2304
- }));
2305
- }
2306
- /**
2307
- * Get all marketplace-installed plugin states
2308
- */
2309
- async getMarketplacePlugins() {
2310
- return (await this.db.selectFrom("_plugin_state").selectAll().where("source", "=", "marketplace").execute()).map((row) => ({
2311
- pluginId: row.plugin_id,
2312
- status: toPluginStatus(row.status),
2313
- version: row.version,
2314
- installedAt: new Date(row.installed_at),
2315
- activatedAt: row.activated_at ? new Date(row.activated_at) : null,
2316
- deactivatedAt: row.deactivated_at ? new Date(row.deactivated_at) : null,
2317
- source: toPluginSource(row.source),
2318
- marketplaceVersion: row.marketplace_version ?? null,
2319
- displayName: row.display_name ?? null,
2320
- description: row.description ?? null
2321
- }));
2322
- }
2323
- /**
2324
- * Create or update plugin state
2325
- */
2326
- async upsert(pluginId, version, status, opts) {
2327
- const now = (/* @__PURE__ */ new Date()).toISOString();
2328
- const existing = await this.get(pluginId);
2329
- if (existing) {
2330
- const updates = {
2331
- status,
2332
- version
2333
- };
2334
- if (status === "active" && existing.status !== "active") updates.activated_at = now;
2335
- else if (status === "inactive" && existing.status !== "inactive") updates.deactivated_at = now;
2336
- if (opts?.source) updates.source = opts.source;
2337
- if (opts?.marketplaceVersion !== void 0) updates.marketplace_version = opts.marketplaceVersion;
2338
- if (opts?.displayName !== void 0) updates.display_name = opts.displayName;
2339
- if (opts?.description !== void 0) updates.description = opts.description;
2340
- await this.db.updateTable("_plugin_state").set(updates).where("plugin_id", "=", pluginId).execute();
2341
- } else await this.db.insertInto("_plugin_state").values({
2342
- plugin_id: pluginId,
2343
- status,
2344
- version,
2345
- installed_at: now,
2346
- activated_at: status === "active" ? now : null,
2347
- deactivated_at: null,
2348
- data: null,
2349
- source: opts?.source ?? "config",
2350
- marketplace_version: opts?.marketplaceVersion ?? null,
2351
- display_name: opts?.displayName ?? null,
2352
- description: opts?.description ?? null
2353
- }).execute();
2354
- return await this.get(pluginId);
2355
- }
2356
- /**
2357
- * Enable a plugin
2358
- */
2359
- async enable(pluginId, version) {
2360
- return this.upsert(pluginId, version, "active");
2361
- }
2362
- /**
2363
- * Disable a plugin
2364
- */
2365
- async disable(pluginId, version) {
2366
- return this.upsert(pluginId, version, "inactive");
2367
- }
2368
- /**
2369
- * Delete plugin state
2370
- */
2371
- async delete(pluginId) {
2372
- return ((await this.db.deleteFrom("_plugin_state").where("plugin_id", "=", pluginId).executeTakeFirst()).numDeletedRows ?? 0) > 0;
2373
- }
2374
- };
2375
-
2376
2406
  //#endregion
2377
2407
  //#region src/sections/index.ts
2378
2408
  /**
@@ -2693,7 +2723,7 @@ const contentListQuery = cursorPaginationQuery.extend({
2693
2723
  const contentCreateBody = z$1.object({
2694
2724
  data: z$1.record(z$1.string(), z$1.unknown()),
2695
2725
  slug: z$1.string().nullish(),
2696
- status: z$1.string().optional(),
2726
+ status: z$1.enum(["draft"]).optional(),
2697
2727
  bylines: z$1.array(contentBylineInputSchema).optional(),
2698
2728
  locale: localeCode.optional(),
2699
2729
  translationOf: z$1.string().optional(),
@@ -2702,7 +2732,7 @@ const contentCreateBody = z$1.object({
2702
2732
  const contentUpdateBody = z$1.object({
2703
2733
  data: z$1.record(z$1.string(), z$1.unknown()).optional(),
2704
2734
  slug: z$1.string().nullish(),
2705
- status: z$1.string().optional(),
2735
+ status: z$1.enum(["draft"]).optional(),
2706
2736
  authorId: z$1.string().nullish(),
2707
2737
  bylines: z$1.array(contentBylineInputSchema).optional(),
2708
2738
  _rev: z$1.string().optional().meta({ description: "Opaque revision token for optimistic concurrency" }),
@@ -2713,6 +2743,10 @@ const contentScheduleBody = z$1.object({ scheduledAt: z$1.string().min(1, "sched
2713
2743
  description: "ISO 8601 datetime for scheduled publishing",
2714
2744
  example: "2025-06-15T09:00:00Z"
2715
2745
  }) }).meta({ id: "ContentScheduleBody" });
2746
+ const contentPublishBody = z$1.object({
2747
+ reviewRequestId: z$1.string().optional().meta({ description: "Approved review request ID for token-authenticated publish execution." }),
2748
+ review_request_id: z$1.string().optional().meta({ description: "Snake-case alias for reviewRequestId." })
2749
+ }).meta({ id: "ContentPublishBody" });
2716
2750
  const contentPreviewUrlBody = z$1.object({
2717
2751
  expiresIn: z$1.union([z$1.string(), z$1.number()]).optional(),
2718
2752
  pathPattern: z$1.string().optional()
@@ -2805,14 +2839,8 @@ const mediaUpdateBody = z$1.object({
2805
2839
  width: z$1.number().int().positive().optional(),
2806
2840
  height: z$1.number().int().positive().optional()
2807
2841
  }).meta({ id: "MediaUpdateBody" });
2808
- /** Maximum allowed file upload size (50 MB). */
2809
- const MAX_UPLOAD_SIZE = 50 * 1024 * 1024;
2810
- const mediaUploadUrlBody = z$1.object({
2811
- filename: z$1.string().min(1, "filename is required"),
2812
- contentType: z$1.string().min(1, "contentType is required"),
2813
- size: z$1.number().int().positive().max(MAX_UPLOAD_SIZE, `File size must not exceed ${MAX_UPLOAD_SIZE / 1024 / 1024}MB`),
2814
- contentHash: z$1.string().optional()
2815
- }).meta({ id: "MediaUploadUrlBody" });
2842
+ /** Default maximum allowed file upload size (50 MB). */
2843
+ const DEFAULT_MAX_UPLOAD_SIZE = 50 * 1024 * 1024;
2816
2844
  const mediaConfirmBody = z$1.object({
2817
2845
  size: z$1.number().int().positive().optional(),
2818
2846
  width: z$1.number().int().positive().optional(),
@@ -2875,9 +2903,11 @@ const collectionSupportValues = z$1.enum([
2875
2903
  "search"
2876
2904
  ]);
2877
2905
  const collectionSourcePattern = /^(template:.+|import:.+|manual|discovered|seed)$/;
2906
+ const urlPatternSchema = z$1.string().refine((value) => !value || value.includes("{slug}"), "URL pattern must include a {slug} placeholder");
2878
2907
  const fieldTypeValues = z$1.enum([
2879
2908
  "string",
2880
2909
  "text",
2910
+ "url",
2881
2911
  "number",
2882
2912
  "integer",
2883
2913
  "boolean",
@@ -2897,6 +2927,7 @@ const repeaterSubFieldSchema = z$1.object({
2897
2927
  type: z$1.enum([
2898
2928
  "string",
2899
2929
  "text",
2930
+ "url",
2900
2931
  "number",
2901
2932
  "integer",
2902
2933
  "boolean",
@@ -2928,7 +2959,7 @@ const createCollectionBody = z$1.object({
2928
2959
  icon: z$1.string().optional(),
2929
2960
  supports: z$1.array(collectionSupportValues).optional(),
2930
2961
  source: z$1.string().regex(collectionSourcePattern).optional(),
2931
- urlPattern: z$1.string().optional(),
2962
+ urlPattern: urlPatternSchema.optional(),
2932
2963
  hasSeo: z$1.boolean().optional()
2933
2964
  }).meta({ id: "CreateCollectionBody" });
2934
2965
  const updateCollectionBody = z$1.object({
@@ -2937,7 +2968,7 @@ const updateCollectionBody = z$1.object({
2937
2968
  description: z$1.string().optional(),
2938
2969
  icon: z$1.string().optional(),
2939
2970
  supports: z$1.array(collectionSupportValues).optional(),
2940
- urlPattern: z$1.string().nullish(),
2971
+ urlPattern: urlPatternSchema.nullish(),
2941
2972
  hasSeo: z$1.boolean().optional(),
2942
2973
  commentsEnabled: z$1.boolean().optional(),
2943
2974
  commentsModeration: z$1.enum([
@@ -3115,6 +3146,148 @@ const commentCountsResponseSchema = z$1.object({
3115
3146
  }).meta({ id: "CommentCountsResponse" });
3116
3147
  const commentBulkResponseSchema = z$1.object({ affected: z$1.number().int() }).meta({ id: "CommentBulkResponse" });
3117
3148
 
3149
+ //#endregion
3150
+ //#region src/api/schemas/context.ts
3151
+ const csvList = z$1.string().optional().transform((value) => value?.split(",").map((item) => item.trim()).filter((item) => item.length > 0));
3152
+ const contextTypesQuery$1 = z$1.string().optional().transform((value, ctx) => {
3153
+ if (!value) return void 0;
3154
+ const types = value.split(",").map((item) => item.trim()).filter((item) => item.length > 0);
3155
+ const invalid = types.find((type) => !isSiteContextType(type));
3156
+ if (invalid) {
3157
+ ctx.addIssue({
3158
+ code: "custom",
3159
+ message: `Invalid context type: ${invalid}`
3160
+ });
3161
+ return z$1.NEVER;
3162
+ }
3163
+ return types;
3164
+ });
3165
+ const optionalBooleanQuery$1 = z$1.enum(["true", "false"]).optional().transform((value) => value === void 0 ? void 0 : value === "true");
3166
+ const contextEntryListQuery = z$1.object({
3167
+ q: z$1.string().optional(),
3168
+ scope: z$1.string().optional(),
3169
+ includeInherited: optionalBooleanQuery$1,
3170
+ contextTypes: contextTypesQuery$1,
3171
+ tags: csvList,
3172
+ createdByActorType: z$1.enum([
3173
+ "user",
3174
+ "api_token",
3175
+ "system"
3176
+ ]).optional(),
3177
+ createdByActorId: z$1.string().optional(),
3178
+ currentOnly: optionalBooleanQuery$1,
3179
+ limit: z$1.coerce.number().int().min(1).max(100).optional(),
3180
+ cursor: z$1.string().optional()
3181
+ }).meta({ id: "ContextEntryListQuery" });
3182
+ const contextEntryStaleQuery = contextEntryListQuery.omit({
3183
+ q: true,
3184
+ currentOnly: true
3185
+ }).extend({ now: z$1.string().optional() }).meta({ id: "ContextEntryStaleQuery" });
3186
+ const contextEntryDiffQuery = z$1.object({
3187
+ since: z$1.string().min(1),
3188
+ scope: z$1.string().optional(),
3189
+ includeInherited: optionalBooleanQuery$1,
3190
+ now: z$1.string().optional()
3191
+ }).meta({ id: "ContextEntryDiffQuery" });
3192
+ const contextEntryCreateBody = z$1.object({
3193
+ scope: z$1.string().min(1),
3194
+ contextType: z$1.enum(SITE_CONTEXT_TYPES),
3195
+ title: z$1.string().min(1).max(200),
3196
+ body: z$1.string().min(1).max(2e4),
3197
+ tags: z$1.array(z$1.string()).max(50).optional(),
3198
+ policyKey: z$1.string().max(200).nullable().optional(),
3199
+ sourceActivityId: z$1.string().nullable().optional(),
3200
+ validUntil: z$1.string().nullable().optional()
3201
+ }).meta({ id: "ContextEntryCreateBody" });
3202
+ const contextEntrySupersedeBody = z$1.object({
3203
+ scope: z$1.string().min(1).optional(),
3204
+ contextType: z$1.enum(SITE_CONTEXT_TYPES).optional(),
3205
+ title: z$1.string().min(1).max(200),
3206
+ body: z$1.string().min(1).max(2e4),
3207
+ tags: z$1.array(z$1.string()).max(50).optional(),
3208
+ policyKey: z$1.string().max(200).nullable().optional(),
3209
+ sourceActivityId: z$1.string().nullable().optional(),
3210
+ validUntil: z$1.string().nullable().optional()
3211
+ }).meta({ id: "ContextEntrySupersedeBody" });
3212
+ const contextEntryReviewBody = z$1.object({
3213
+ reviewNote: z$1.string().max(5e3).nullable().optional(),
3214
+ validUntil: z$1.string().nullable().optional()
3215
+ }).meta({ id: "ContextEntryReviewBody" });
3216
+
3217
+ //#endregion
3218
+ //#region src/api/schemas/briefing.ts
3219
+ const optionalBooleanQuery = z$1.enum(["true", "false"]).optional().transform((value) => value === void 0 ? void 0 : value === "true");
3220
+ const contextTypesQuery = z$1.string().optional().transform((value, ctx) => {
3221
+ if (!value) return void 0;
3222
+ const types = value.split(",").map((item) => item.trim()).filter((item) => item.length > 0);
3223
+ const invalid = types.find((type) => !isSiteContextType(type));
3224
+ if (invalid) {
3225
+ ctx.addIssue({
3226
+ code: "custom",
3227
+ message: `Invalid context type: ${invalid}`
3228
+ });
3229
+ return z$1.NEVER;
3230
+ }
3231
+ return types;
3232
+ });
3233
+ const siteBriefingQuery = z$1.object({
3234
+ scope: z$1.string().optional(),
3235
+ since: z$1.string().optional(),
3236
+ contextTypes: contextTypesQuery,
3237
+ includeStale: optionalBooleanQuery,
3238
+ tokenBudget: z$1.coerce.number().int().min(1).max(1e5).optional(),
3239
+ activityLimit: z$1.coerce.number().int().min(1).max(100).optional()
3240
+ }).meta({ id: "SiteBriefingQuery" });
3241
+
3242
+ //#endregion
3243
+ //#region src/api/schemas/hitl-requests.ts
3244
+ const optionalStatus$1 = z$1.enum([
3245
+ "pending",
3246
+ "approved",
3247
+ "rejected"
3248
+ ]).optional();
3249
+ const optionalPriority = z$1.enum([
3250
+ "low",
3251
+ "normal",
3252
+ "high",
3253
+ "urgent"
3254
+ ]).optional();
3255
+ const hitlRequestListQuery = z$1.object({
3256
+ status: optionalStatus$1,
3257
+ priority: optionalPriority,
3258
+ actionType: z$1.string().optional(),
3259
+ scope: z$1.string().optional(),
3260
+ targetRefType: z$1.string().optional(),
3261
+ targetRefId: z$1.string().optional(),
3262
+ limit: z$1.coerce.number().int().min(1).max(100).optional(),
3263
+ cursor: z$1.string().optional()
3264
+ }).meta({ id: "HitlRequestListQuery" });
3265
+ const hitlRequestResolveBody = z$1.object({
3266
+ decision: z$1.enum(["approved", "rejected"]),
3267
+ reviewNote: z$1.string().max(5e3).nullable().optional()
3268
+ }).meta({ id: "HitlRequestResolveBody" });
3269
+
3270
+ //#endregion
3271
+ //#region src/api/schemas/review-requests.ts
3272
+ const optionalStatus = z$1.enum([
3273
+ "pending",
3274
+ "approved",
3275
+ "rejected"
3276
+ ]).optional();
3277
+ const reviewRequestListQuery = z$1.object({
3278
+ status: optionalStatus,
3279
+ collection: z$1.string().optional(),
3280
+ entryId: z$1.string().optional(),
3281
+ scope: z$1.string().optional(),
3282
+ actionType: z$1.string().optional(),
3283
+ limit: z$1.coerce.number().int().min(1).max(100).optional(),
3284
+ cursor: z$1.string().optional()
3285
+ }).meta({ id: "ReviewRequestListQuery" });
3286
+ const reviewRequestResolveBody = z$1.object({
3287
+ decision: z$1.enum(["approved", "rejected"]),
3288
+ reviewNote: z$1.string().max(5e3).nullable().optional()
3289
+ }).meta({ id: "ReviewRequestResolveBody" });
3290
+
3118
3291
  //#endregion
3119
3292
  //#region src/api/schemas/auth.ts
3120
3293
  const authenticatorTransport$1 = z$1.enum([
@@ -3164,6 +3337,10 @@ const inviteCompleteBody = z$1.object({
3164
3337
  credential: registrationCredential$1,
3165
3338
  name: z$1.string().optional()
3166
3339
  }).meta({ id: "InviteCompleteBody" });
3340
+ const inviteRegisterOptionsBody = z$1.object({
3341
+ token: z$1.string().min(1),
3342
+ name: z$1.string().optional()
3343
+ }).meta({ id: "InviteRegisterOptionsBody" });
3167
3344
  const magicLinkSendBody = z$1.object({ email: z$1.string().email() }).meta({ id: "MagicLinkSendBody" });
3168
3345
  const passkeyOptionsBody = z$1.object({ email: z$1.string().email().optional() }).meta({ id: "PasskeyOptionsBody" });
3169
3346
  const passkeyVerifyBody = z$1.object({ credential: authenticationCredential }).meta({ id: "PasskeyVerifyBody" });
@@ -3400,6 +3577,7 @@ const mediaReference = z$1.object({
3400
3577
  mediaId: z$1.string(),
3401
3578
  alt: z$1.string().optional()
3402
3579
  });
3580
+ const resolvedMediaReference = mediaReference.extend({ url: z$1.string().optional() });
3403
3581
  const socialSettings = z$1.object({
3404
3582
  twitter: z$1.string().optional(),
3405
3583
  github: z$1.string().optional(),
@@ -3430,8 +3608,8 @@ const settingsUpdateBody = z$1.object({
3430
3608
  const siteSettingsSchema = z$1.object({
3431
3609
  title: z$1.string().optional(),
3432
3610
  tagline: z$1.string().optional(),
3433
- logo: mediaReference.optional(),
3434
- favicon: mediaReference.optional(),
3611
+ logo: resolvedMediaReference.optional(),
3612
+ favicon: resolvedMediaReference.optional(),
3435
3613
  url: z$1.string().optional(),
3436
3614
  postsPerPage: z$1.number().int().optional(),
3437
3615
  dateFormat: z$1.string().optional(),
@@ -3713,7 +3891,8 @@ const redirectSchema = z$1.object({
3713
3891
  }).meta({ id: "Redirect" });
3714
3892
  const redirectListResponseSchema = z$1.object({
3715
3893
  items: z$1.array(redirectSchema),
3716
- nextCursor: z$1.string().optional()
3894
+ nextCursor: z$1.string().optional(),
3895
+ loopRedirectIds: z$1.array(z$1.string()).optional()
3717
3896
  }).meta({ id: "RedirectListResponse" });
3718
3897
  const notFoundEntrySchema = z$1.object({
3719
3898
  id: z$1.string(),
@@ -4270,6 +4449,14 @@ function convertCodeBlock(block) {
4270
4449
  };
4271
4450
  }
4272
4451
 
4452
+ //#endregion
4453
+ //#region src/after.ts
4454
+ function after(fn) {
4455
+ Promise.resolve().then(fn).catch((error) => {
4456
+ console.error("[dineway] deferred task failed:", error);
4457
+ });
4458
+ }
4459
+
4273
4460
  //#endregion
4274
4461
  //#region src/preview/sidecar-client.ts
4275
4462
  /**
@@ -5744,6 +5931,35 @@ function resolveHook(hook, pluginId) {
5744
5931
  };
5745
5932
  }
5746
5933
 
5934
+ //#endregion
5935
+ //#region src/auth/trusted-proxy.ts
5936
+ /**
5937
+ * RFC 7230 token characters for HTTP header names.
5938
+ * Invalid names throw when passed to `Headers.get()`.
5939
+ */
5940
+ const HEADER_NAME_PATTERN = /^[!#$%&'*+\-.^_`|~0-9a-z]+$/;
5941
+ /** Cache for the env-derived value. `null` means "not yet parsed". */
5942
+ let envCache = null;
5943
+ function normalizeTrustedHeaders(names) {
5944
+ return names.map((name) => name.trim().toLowerCase()).filter((name) => name.length > 0 && HEADER_NAME_PATTERN.test(name));
5945
+ }
5946
+ function getEnvTrustedHeaders() {
5947
+ if (envCache !== null) return envCache;
5948
+ let raw;
5949
+ try {
5950
+ const importMetaEnv = import.meta.env;
5951
+ raw = (typeof process !== "undefined" ? process.env?.DINEWAY_TRUSTED_PROXY_HEADERS : void 0) || importMetaEnv?.DINEWAY_TRUSTED_PROXY_HEADERS;
5952
+ } catch {
5953
+ raw = void 0;
5954
+ }
5955
+ envCache = raw ? normalizeTrustedHeaders(raw.split(",")) : [];
5956
+ return envCache;
5957
+ }
5958
+ function getTrustedProxyHeaders(config) {
5959
+ if (config?.trustedProxyHeaders !== void 0) return normalizeTrustedHeaders(config.trustedProxyHeaders);
5960
+ return getEnvTrustedHeaders();
5961
+ }
5962
+
5747
5963
  //#endregion
5748
5964
  //#region src/plugins/request-meta.ts
5749
5965
  /**
@@ -5765,6 +5981,18 @@ function parseFirstForwardedIp(header) {
5765
5981
  return IP_PATTERN.test(trimmed) ? trimmed : null;
5766
5982
  }
5767
5983
  /**
5984
+ * Read an IP from an operator-declared trusted header. Forwarded-for style
5985
+ * headers are parsed as comma-separated lists and the first entry is used.
5986
+ */
5987
+ function readIpFromHeader(headers, name) {
5988
+ const value = headers.get(name);
5989
+ if (!value) return null;
5990
+ if (name.endsWith("forwarded-for")) return parseFirstForwardedIp(value);
5991
+ const trimmed = value.trim();
5992
+ if (!trimmed) return null;
5993
+ return IP_PATTERN.test(trimmed) ? trimmed : null;
5994
+ }
5995
+ /**
5768
5996
  * Get the runtime-provided `cf` object from the request, if present.
5769
5997
  */
5770
5998
  function getCfObject(request) {
@@ -5793,13 +6021,15 @@ function extractGeo(cf) {
5793
6021
  * 1. `CF-Connecting-IP` header — only trusted when a `cf` object is
5794
6022
  * present on the request (proving the request came through a trusted
5795
6023
  * edge/runtime that strips or overwrites client-supplied values).
5796
- * 2. `X-Forwarded-For` header (first entry) — best-effort, spoofable
5797
- * when there is no trusted reverse proxy or runtime metadata.
5798
- * 3. `null`
6024
+ * 2. `X-Forwarded-For` header (first entry) — trusted only with runtime
6025
+ * edge metadata.
6026
+ * 3. Operator-declared trusted proxy headers, tried in order.
6027
+ * 4. `null`
5799
6028
  */
5800
- function extractRequestMeta(request) {
6029
+ function extractRequestMeta(request, configOrTrustedHeaders) {
5801
6030
  const headers = request.headers;
5802
6031
  const cf = getCfObject(request);
6032
+ const trustedHeaders = resolveTrustedHeaders(configOrTrustedHeaders);
5803
6033
  let ip = null;
5804
6034
  if (cf) {
5805
6035
  const cfIp = headers.get("cf-connecting-ip")?.trim();
@@ -5809,6 +6039,13 @@ function extractRequestMeta(request) {
5809
6039
  const xff = headers.get("x-forwarded-for");
5810
6040
  ip = xff ? parseFirstForwardedIp(xff) : null;
5811
6041
  }
6042
+ if (!ip) for (const name of trustedHeaders) {
6043
+ const value = readIpFromHeader(headers, name);
6044
+ if (value) {
6045
+ ip = value;
6046
+ break;
6047
+ }
6048
+ }
5812
6049
  const userAgent = headers.get("user-agent")?.trim() || null;
5813
6050
  const referer = headers.get("referer")?.trim() || null;
5814
6051
  const geo = extractGeo(cf);
@@ -5819,6 +6056,10 @@ function extractRequestMeta(request) {
5819
6056
  geo
5820
6057
  };
5821
6058
  }
6059
+ function resolveTrustedHeaders(value) {
6060
+ if (Array.isArray(value)) return normalizeTrustedHeaders(value);
6061
+ return getTrustedProxyHeaders(value);
6062
+ }
5822
6063
  /**
5823
6064
  * Headers that must never cross the RPC boundary to sandboxed plugins.
5824
6065
  * Session tokens, auth credentials, and infrastructure headers are stripped
@@ -5858,6 +6099,7 @@ function sanitizeHeadersForSandbox(headers) {
5858
6099
  */
5859
6100
  /** Stale lock threshold in minutes */
5860
6101
  const STALE_LOCK_MINUTES = 10;
6102
+ const MAX_ONESHOT_RETRIES = 5;
5861
6103
  /**
5862
6104
  * Executes overdue cron tasks.
5863
6105
  *
@@ -5918,12 +6160,30 @@ var CronExecutor = class {
5918
6160
  hookFailed = true;
5919
6161
  console.error(`[cron] Hook failed for ${task.plugin_id}:${task.task_name}:`, error);
5920
6162
  }
5921
- if (task.is_oneshot) if (hookFailed) await sql`
6163
+ if (task.is_oneshot) if (hookFailed) {
6164
+ const retryMeta = parsedData?.__dineway != null && typeof parsedData.__dineway === "object" ? parsedData.__dineway : void 0;
6165
+ const rawRetryCount = retryMeta?.retryCount;
6166
+ const retryCount = typeof rawRetryCount === "number" && Number.isFinite(rawRetryCount) && rawRetryCount > 0 ? Math.floor(rawRetryCount) : 0;
6167
+ if (retryCount >= MAX_ONESHOT_RETRIES) {
6168
+ console.error(`[cron] One-shot task ${task.plugin_id}:${task.task_name} exceeded ${MAX_ONESHOT_RETRIES} retries, removing`);
6169
+ await sql`
6170
+ DELETE FROM _dineway_cron_tasks WHERE id = ${task.id}
6171
+ `.execute(this.db);
6172
+ } else {
6173
+ const backoffMs = 6e4 * Math.pow(2, retryCount);
6174
+ await sql`
5922
6175
  UPDATE _dineway_cron_tasks
5923
- SET status = 'idle', locked_at = NULL, next_run_at = ${new Date(Date.now() + 6e4).toISOString()}
6176
+ SET status = 'idle', locked_at = NULL, next_run_at = ${new Date(Date.now() + backoffMs).toISOString()}, data = ${JSON.stringify({
6177
+ ...parsedData,
6178
+ __dineway: {
6179
+ ...retryMeta,
6180
+ retryCount: retryCount + 1
6181
+ }
6182
+ })}
5924
6183
  WHERE id = ${task.id}
5925
6184
  `.execute(this.db);
5926
- else await sql`
6185
+ }
6186
+ } else await sql`
5927
6187
  DELETE FROM _dineway_cron_tasks WHERE id = ${task.id}
5928
6188
  `.execute(this.db);
5929
6189
  else await sql`
@@ -6174,6 +6434,19 @@ async function assertSeoEnabled(seoRepo, collection, seo) {
6174
6434
  if (seo !== void 0 && !hasSeo) throw new Error(`Collection "${collection}" does not have SEO enabled. Remove the seo field or enable SEO on this collection.`);
6175
6435
  return hasSeo;
6176
6436
  }
6437
+ function toPluginContentItem(item) {
6438
+ return {
6439
+ id: item.id,
6440
+ type: item.type,
6441
+ slug: item.slug,
6442
+ status: item.status,
6443
+ data: item.data,
6444
+ createdAt: item.createdAt,
6445
+ updatedAt: item.updatedAt,
6446
+ publishedAt: item.publishedAt,
6447
+ locale: item.locale
6448
+ };
6449
+ }
6177
6450
  /**
6178
6451
  * Create read-only content access
6179
6452
  */
@@ -6184,13 +6457,7 @@ function createContentAccess(db) {
6184
6457
  async get(collection, id) {
6185
6458
  const item = await contentRepo.findById(collection, id);
6186
6459
  if (!item) return null;
6187
- const result = {
6188
- id: item.id,
6189
- type: item.type,
6190
- data: item.data,
6191
- createdAt: item.createdAt,
6192
- updatedAt: item.updatedAt
6193
- };
6460
+ const result = toPluginContentItem(item);
6194
6461
  if (await seoRepo.isEnabled(collection)) result.seo = await seoRepo.get(collection, item.id);
6195
6462
  return result;
6196
6463
  },
@@ -6206,15 +6473,10 @@ function createContentAccess(db) {
6206
6473
  const result = await contentRepo.findMany(collection, {
6207
6474
  limit: options?.limit ?? 50,
6208
6475
  cursor: options?.cursor,
6209
- orderBy
6476
+ orderBy,
6477
+ where: options?.where
6210
6478
  });
6211
- const items = result.items.map((item) => ({
6212
- id: item.id,
6213
- type: item.type,
6214
- data: item.data,
6215
- createdAt: item.createdAt,
6216
- updatedAt: item.updatedAt
6217
- }));
6479
+ const items = result.items.map(toPluginContentItem);
6218
6480
  if (items.length > 0 && await seoRepo.isEnabled(collection)) {
6219
6481
  const seoMap = await seoRepo.getMany(collection, items.map((i) => i.id));
6220
6482
  for (const item of items) {
@@ -6252,13 +6514,7 @@ function createContentAccessWithWrite(db) {
6252
6514
  type: collection,
6253
6515
  data: fields
6254
6516
  });
6255
- const result = {
6256
- id: item.id,
6257
- type: item.type,
6258
- data: item.data,
6259
- createdAt: item.createdAt,
6260
- updatedAt: item.updatedAt
6261
- };
6517
+ const result = toPluginContentItem(item);
6262
6518
  if (hasSeo) result.seo = seo !== void 0 ? await trxSeoRepo.upsert(collection, item.id, seo) : await trxSeoRepo.get(collection, item.id);
6263
6519
  return result;
6264
6520
  });
@@ -6274,13 +6530,7 @@ function createContentAccessWithWrite(db) {
6274
6530
  if (!existing) throw new Error("Content not found");
6275
6531
  return existing;
6276
6532
  })();
6277
- const result = {
6278
- id: item.id,
6279
- type: item.type,
6280
- data: item.data,
6281
- createdAt: item.createdAt,
6282
- updatedAt: item.updatedAt
6283
- };
6533
+ const result = toPluginContentItem(item);
6284
6534
  if (hasSeo) result.seo = seo !== void 0 ? await trxSeoRepo.upsert(collection, item.id, seo) : await trxSeoRepo.get(collection, item.id);
6285
6535
  return result;
6286
6536
  });
@@ -6340,17 +6590,18 @@ function createMediaAccessWithWrite(db, getUploadUrlFn, storage) {
6340
6590
  getUploadUrl: getUploadUrlFn,
6341
6591
  async upload(filename, contentType, bytes) {
6342
6592
  if (!storage) throw new Error("Media upload() requires a storage backend. Configure storage in PluginContextFactoryOptions.");
6343
- const mediaId = ulid();
6593
+ const keyPrefix = ulid();
6344
6594
  const basename = filename.split("/").pop() ?? filename;
6345
6595
  const dotIdx = basename.lastIndexOf(".");
6346
- const storageKey = `${mediaId}${dotIdx > 0 ? basename.slice(dotIdx).toLowerCase() : ""}`;
6596
+ const storageKey = `${keyPrefix}${dotIdx > 0 ? basename.slice(dotIdx).toLowerCase() : ""}`;
6347
6597
  await storage.upload({
6348
6598
  key: storageKey,
6349
6599
  body: new Uint8Array(bytes),
6350
6600
  contentType
6351
6601
  });
6602
+ let media;
6352
6603
  try {
6353
- await mediaRepo.create({
6604
+ media = await mediaRepo.create({
6354
6605
  filename: basename,
6355
6606
  mimeType: contentType,
6356
6607
  size: bytes.byteLength,
@@ -6364,7 +6615,7 @@ function createMediaAccessWithWrite(db, getUploadUrlFn, storage) {
6364
6615
  throw error;
6365
6616
  }
6366
6617
  return {
6367
- mediaId,
6618
+ mediaId: media.id,
6368
6619
  storageKey,
6369
6620
  url: `/_dineway/api/media/file/${storageKey}`
6370
6621
  };
@@ -6779,6 +7030,8 @@ var HookPipeline = class HookPipeline {
6779
7030
  while (remaining.length > 0) {
6780
7031
  const ready = remaining.filter((hook) => hook.dependencies.every((dep) => sorted.some((s) => s.pluginId === dep)));
6781
7032
  if (ready.length === 0) {
7033
+ const pluginIds = remaining.map((hook) => hook.pluginId).join(", ");
7034
+ console.warn(`[hooks] Hook dependency cycle or missing dependency detected among plugins: ${pluginIds}. Falling back to priority order.`);
6782
7035
  remaining.sort((a, b) => a.priority - b.priority);
6783
7036
  sorted.push(...remaining);
6784
7037
  break;
@@ -6794,7 +7047,15 @@ var HookPipeline = class HookPipeline {
6794
7047
  * Execute a hook with timeout
6795
7048
  */
6796
7049
  async executeWithTimeout(fn, timeout) {
6797
- return Promise.race([fn(), new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error(`Hook timeout after ${timeout}ms`)), timeout))]);
7050
+ let timer;
7051
+ const timeoutPromise = new Promise((_, reject) => {
7052
+ timer = setTimeout(() => reject(/* @__PURE__ */ new Error(`Hook timeout after ${timeout}ms`)), timeout);
7053
+ });
7054
+ try {
7055
+ return await Promise.race([fn(), timeoutPromise]);
7056
+ } finally {
7057
+ if (timer) clearTimeout(timer);
7058
+ }
6798
7059
  }
6799
7060
  /**
6800
7061
  * Run plugin:install hooks
@@ -6956,7 +7217,8 @@ var HookPipeline = class HookPipeline {
6956
7217
  const { handler } = hook;
6957
7218
  const event = {
6958
7219
  id,
6959
- collection
7220
+ collection,
7221
+ permanent: false
6960
7222
  };
6961
7223
  const ctx = this.getContext(hook.pluginId);
6962
7224
  const start = Date.now();
@@ -6987,14 +7249,15 @@ var HookPipeline = class HookPipeline {
6987
7249
  /**
6988
7250
  * Run content:afterDelete hooks
6989
7251
  */
6990
- async runContentAfterDelete(id, collection) {
7252
+ async runContentAfterDelete(id, collection, permanent) {
6991
7253
  const hooks = this.getTypedHooks("content:afterDelete");
6992
7254
  const results = [];
6993
7255
  for (const hook of hooks) {
6994
7256
  const { handler } = hook;
6995
7257
  const event = {
6996
7258
  id,
6997
- collection
7259
+ collection,
7260
+ permanent
6998
7261
  };
6999
7262
  const ctx = this.getContext(hook.pluginId);
7000
7263
  const start = Date.now();
@@ -7709,9 +7972,11 @@ async function devConsoleEmailDeliver(event, _ctx) {
7709
7972
  var PluginRouteHandler = class {
7710
7973
  contextFactory;
7711
7974
  plugin;
7975
+ trustedProxyHeaders;
7712
7976
  constructor(plugin, factoryOptions) {
7713
7977
  this.plugin = plugin;
7714
7978
  this.contextFactory = new PluginContextFactory(factoryOptions);
7979
+ this.trustedProxyHeaders = factoryOptions.trustedProxyHeaders ?? [];
7715
7980
  }
7716
7981
  /**
7717
7982
  * Invoke a route by name
@@ -7744,7 +8009,7 @@ var PluginRouteHandler = class {
7744
8009
  ...this.contextFactory.createContext(this.plugin),
7745
8010
  input: validatedInput,
7746
8011
  request: options.request,
7747
- requestMeta: extractRequestMeta(options.request)
8012
+ requestMeta: extractRequestMeta(options.request, this.trustedProxyHeaders)
7748
8013
  };
7749
8014
  try {
7750
8015
  return {
@@ -7762,11 +8027,12 @@ var PluginRouteHandler = class {
7762
8027
  },
7763
8028
  status: error.status
7764
8029
  };
8030
+ console.error(`[plugin:${this.plugin.id}] Route handler failed:`, error);
7765
8031
  return {
7766
8032
  success: false,
7767
8033
  error: {
7768
8034
  code: "INTERNAL_ERROR",
7769
- message: `Route handler failed: ${error instanceof Error ? error.message : String(error)}`
8035
+ message: "An internal error occurred"
7770
8036
  },
7771
8037
  status: 500
7772
8038
  };
@@ -7922,7 +8188,8 @@ var PluginManager = class {
7922
8188
  this.factoryOptions = {
7923
8189
  db: options.db,
7924
8190
  storage: options.storage,
7925
- getUploadUrl: options.getUploadUrl
8191
+ getUploadUrl: options.getUploadUrl,
8192
+ trustedProxyHeaders: options.trustedProxyHeaders
7926
8193
  };
7927
8194
  }
7928
8195
  /**
@@ -8051,9 +8318,9 @@ var PluginManager = class {
8051
8318
  /**
8052
8319
  * Run content:afterDelete hooks across all active plugins
8053
8320
  */
8054
- async runContentAfterDelete(id, collection) {
8321
+ async runContentAfterDelete(id, collection, permanent) {
8055
8322
  this.ensureInitialized();
8056
- return this.hookPipeline.runContentAfterDelete(id, collection);
8323
+ return this.hookPipeline.runContentAfterDelete(id, collection, permanent);
8057
8324
  }
8058
8325
  /**
8059
8326
  * Run content:afterPublish hooks across all active plugins
@@ -8834,11 +9101,19 @@ function isQueryOptions(value) {
8834
9101
  }
8835
9102
  function isContentListOptions(value) {
8836
9103
  if (!isRecord(value)) return false;
9104
+ if ("where" in value && value.where !== void 0 && !isContentListWhere(value.where)) return false;
8837
9105
  if ("limit" in value && value.limit !== void 0 && typeof value.limit !== "number") return false;
8838
9106
  if ("cursor" in value && value.cursor !== void 0 && typeof value.cursor !== "string") return false;
8839
9107
  if ("orderBy" in value && value.orderBy !== void 0 && !isOrderByRecord(value.orderBy)) return false;
8840
9108
  return true;
8841
9109
  }
9110
+ function isContentListWhere(value) {
9111
+ if (!isRecord(value)) return false;
9112
+ return Object.entries(value).every(([key, item]) => {
9113
+ if (key !== "status" && key !== "locale") return false;
9114
+ return item === void 0 || typeof item === "string";
9115
+ });
9116
+ }
8842
9117
  function isContentWriteInput(value) {
8843
9118
  return isRecord(value);
8844
9119
  }
@@ -9232,7 +9507,7 @@ async function probeUrl(url) {
9232
9507
  let normalizedUrl = url.trim();
9233
9508
  if (!normalizedUrl.startsWith("http")) normalizedUrl = `https://${normalizedUrl}`;
9234
9509
  normalizedUrl = normalizedUrl.replace(TRAILING_SLASHES_PATTERN, "");
9235
- validateExternalUrl(normalizedUrl);
9510
+ await resolveAndValidateExternalUrl(normalizedUrl);
9236
9511
  const results = [];
9237
9512
  const probePromises = getUrlSources().map(async (source) => {
9238
9513
  try {
@@ -10228,8 +10503,10 @@ async function getCommentCountWithDb(db, collection, contentId) {
10228
10503
  * }
10229
10504
  * ```
10230
10505
  */
10231
- async function getMenu(name) {
10232
- return getMenuWithDb(name, await getDb());
10506
+ function getMenu(name) {
10507
+ return requestCached(`menu:${name}`, async () => {
10508
+ return getMenuWithDb(name, await getDb());
10509
+ });
10233
10510
  }
10234
10511
  /**
10235
10512
  * Get menu by name with resolved URLs (with explicit db)
@@ -10369,6 +10646,7 @@ function interpolateUrlPattern(pattern, slug, id) {
10369
10646
  async function resolveContentUrl(collection, entryId, db, urlPatterns) {
10370
10647
  if (!entryId) return null;
10371
10648
  try {
10649
+ validateIdentifier(collection, "menu item collection");
10372
10650
  const row = (await sql`
10373
10651
  SELECT slug FROM ${sql.ref(`ec_${collection}`)} WHERE id = ${entryId} LIMIT 1
10374
10652
  `.execute(db)).rows[0];
@@ -10395,179 +10673,6 @@ async function resolveTaxonomyUrl(taxonomyId, db) {
10395
10673
  return `/${taxonomy.name}/${taxonomy.slug}`;
10396
10674
  }
10397
10675
 
10398
- //#endregion
10399
- //#region src/taxonomies/index.ts
10400
- /**
10401
- * Runtime API for taxonomies
10402
- *
10403
- * Provides functions to query taxonomy definitions and terms.
10404
- */
10405
- /**
10406
- * Get all taxonomy definitions
10407
- */
10408
- async function getTaxonomyDefs() {
10409
- return (await (await getDb()).selectFrom("_dineway_taxonomy_defs").selectAll().execute()).map((row) => ({
10410
- id: row.id,
10411
- name: row.name,
10412
- label: row.label,
10413
- labelSingular: row.label_singular ?? void 0,
10414
- hierarchical: row.hierarchical === 1,
10415
- collections: row.collections ? JSON.parse(row.collections) : []
10416
- }));
10417
- }
10418
- /**
10419
- * Get a single taxonomy definition by name
10420
- */
10421
- async function getTaxonomyDef(name) {
10422
- const row = await (await getDb()).selectFrom("_dineway_taxonomy_defs").selectAll().where("name", "=", name).executeTakeFirst();
10423
- if (!row) return null;
10424
- return {
10425
- id: row.id,
10426
- name: row.name,
10427
- label: row.label,
10428
- labelSingular: row.label_singular ?? void 0,
10429
- hierarchical: row.hierarchical === 1,
10430
- collections: row.collections ? JSON.parse(row.collections) : []
10431
- };
10432
- }
10433
- /**
10434
- * Get all terms for a taxonomy (as tree for hierarchical, flat for tags)
10435
- */
10436
- async function getTaxonomyTerms(taxonomyName) {
10437
- const db = await getDb();
10438
- const def = await getTaxonomyDef(taxonomyName);
10439
- if (!def) return [];
10440
- const rows = await db.selectFrom("taxonomies").selectAll().where("name", "=", taxonomyName).orderBy("label", "asc").execute();
10441
- const countsResult = await db.selectFrom("content_taxonomies").select(["taxonomy_id"]).select((eb) => eb.fn.count("entry_id").as("count")).groupBy("taxonomy_id").execute();
10442
- const counts = /* @__PURE__ */ new Map();
10443
- for (const row of countsResult) counts.set(row.taxonomy_id, row.count);
10444
- const flatTerms = rows.map((row) => ({
10445
- id: row.id,
10446
- name: row.name,
10447
- slug: row.slug,
10448
- label: row.label,
10449
- parent_id: row.parent_id,
10450
- data: row.data
10451
- }));
10452
- if (def.hierarchical) return buildTree(flatTerms, counts);
10453
- return flatTerms.map((term) => ({
10454
- id: term.id,
10455
- name: term.name,
10456
- slug: term.slug,
10457
- label: term.label,
10458
- children: [],
10459
- count: counts.get(term.id) ?? 0
10460
- }));
10461
- }
10462
- /**
10463
- * Get a single term by taxonomy and slug
10464
- */
10465
- async function getTerm(taxonomyName, slug) {
10466
- const db = await getDb();
10467
- const row = await db.selectFrom("taxonomies").selectAll().where("name", "=", taxonomyName).where("slug", "=", slug).executeTakeFirst();
10468
- if (!row) return null;
10469
- const count = (await db.selectFrom("content_taxonomies").select((eb) => eb.fn.count("entry_id").as("count")).where("taxonomy_id", "=", row.id).executeTakeFirst())?.count ?? 0;
10470
- const children = (await db.selectFrom("taxonomies").selectAll().where("parent_id", "=", row.id).orderBy("label", "asc").execute()).map((child) => ({
10471
- id: child.id,
10472
- name: child.name,
10473
- slug: child.slug,
10474
- label: child.label,
10475
- parentId: child.parent_id ?? void 0,
10476
- children: []
10477
- }));
10478
- return {
10479
- id: row.id,
10480
- name: row.name,
10481
- slug: row.slug,
10482
- label: row.label,
10483
- parentId: row.parent_id ?? void 0,
10484
- description: row.data ? JSON.parse(row.data).description : void 0,
10485
- children,
10486
- count
10487
- };
10488
- }
10489
- /**
10490
- * Get terms assigned to an entry
10491
- */
10492
- async function getEntryTerms(collection, entryId, taxonomyName) {
10493
- let query = (await getDb()).selectFrom("content_taxonomies").innerJoin("taxonomies", "taxonomies.id", "content_taxonomies.taxonomy_id").selectAll("taxonomies").where("content_taxonomies.collection", "=", collection).where("content_taxonomies.entry_id", "=", entryId);
10494
- if (taxonomyName) query = query.where("taxonomies.name", "=", taxonomyName);
10495
- return (await query.execute()).map((row) => ({
10496
- id: row.id,
10497
- name: row.name,
10498
- slug: row.slug,
10499
- label: row.label,
10500
- parentId: row.parent_id ?? void 0,
10501
- children: []
10502
- }));
10503
- }
10504
- /**
10505
- * Get terms for multiple entries in a single query (batched API)
10506
- *
10507
- * This is more efficient than calling getEntryTerms for each entry
10508
- * when you need terms for a list of entries.
10509
- *
10510
- * @param collection - The collection type (e.g., "posts")
10511
- * @param entryIds - Array of entry IDs
10512
- * @param taxonomyName - The taxonomy name (e.g., "categories")
10513
- * @returns Map from entry ID to array of terms
10514
- */
10515
- async function getTermsForEntries(collection, entryIds, taxonomyName) {
10516
- const result = /* @__PURE__ */ new Map();
10517
- for (const id of entryIds) result.set(id, []);
10518
- if (entryIds.length === 0) return result;
10519
- const rows = await (await getDb()).selectFrom("content_taxonomies").innerJoin("taxonomies", "taxonomies.id", "content_taxonomies.taxonomy_id").select([
10520
- "content_taxonomies.entry_id",
10521
- "taxonomies.id",
10522
- "taxonomies.name",
10523
- "taxonomies.slug",
10524
- "taxonomies.label",
10525
- "taxonomies.parent_id"
10526
- ]).where("content_taxonomies.collection", "=", collection).where("content_taxonomies.entry_id", "in", entryIds).where("taxonomies.name", "=", taxonomyName).execute();
10527
- for (const row of rows) {
10528
- const entryId = row.entry_id;
10529
- const term = {
10530
- id: row.id,
10531
- name: row.name,
10532
- slug: row.slug,
10533
- label: row.label,
10534
- parentId: row.parent_id ?? void 0,
10535
- children: []
10536
- };
10537
- const terms = result.get(entryId);
10538
- if (terms) terms.push(term);
10539
- }
10540
- return result;
10541
- }
10542
- /**
10543
- * Get entries by term (wraps getDinewayCollection)
10544
- */
10545
- async function getEntriesByTerm(collection, taxonomyName, termSlug) {
10546
- const { getDinewayCollection } = await import("./query-BiaPl_g2.mjs").then((n) => n.a);
10547
- const { entries } = await getDinewayCollection(collection, { where: { [taxonomyName]: termSlug } });
10548
- return entries;
10549
- }
10550
- /**
10551
- * Build tree structure from flat terms
10552
- */
10553
- function buildTree(flatTerms, counts) {
10554
- const map = /* @__PURE__ */ new Map();
10555
- const roots = [];
10556
- for (const term of flatTerms) map.set(term.id, {
10557
- id: term.id,
10558
- name: term.name,
10559
- slug: term.slug,
10560
- label: term.label,
10561
- parentId: term.parent_id ?? void 0,
10562
- description: term.data ? JSON.parse(term.data).description : void 0,
10563
- children: [],
10564
- count: counts.get(term.id) ?? 0
10565
- });
10566
- for (const term of map.values()) if (term.parentId && map.has(term.parentId)) map.get(term.parentId).children.push(term);
10567
- else roots.push(term);
10568
- return roots;
10569
- }
10570
-
10571
10676
  //#endregion
10572
10677
  //#region src/widgets/components.ts
10573
10678
  /**
@@ -10680,18 +10785,52 @@ function getWidgetComponents$1() {
10680
10785
  * Get a widget area by name, with all its widgets
10681
10786
  */
10682
10787
  async function getWidgetArea(name) {
10683
- const db = await getDb();
10684
- const areaRow = await db.selectFrom("_dineway_widget_areas").selectAll().where("name", "=", name).executeTakeFirst();
10685
- if (!areaRow) return null;
10686
- const widgets = (await db.selectFrom("_dineway_widgets").selectAll().$castTo().where("area_id", "=", areaRow.id).orderBy("sort_order", "asc").execute()).map((row) => rowToWidget(row));
10788
+ const rows = await (await getDb()).selectFrom("_dineway_widget_areas as a").leftJoin("_dineway_widgets as w", "w.area_id", "a.id").select([
10789
+ "a.id as a_id",
10790
+ "a.name as a_name",
10791
+ "a.label as a_label",
10792
+ "a.description as a_description",
10793
+ "w.id as w_id",
10794
+ "w.type as w_type",
10795
+ "w.title as w_title",
10796
+ "w.content as w_content",
10797
+ "w.menu_name as w_menu_name",
10798
+ "w.component_id as w_component_id",
10799
+ "w.component_props as w_component_props",
10800
+ "w.area_id as w_area_id",
10801
+ "w.sort_order as w_sort_order",
10802
+ "w.created_at as w_created_at"
10803
+ ]).where("a.name", "=", name).orderBy("w.sort_order", "asc").execute();
10804
+ const first = rows[0];
10805
+ if (!first) return null;
10806
+ const widgets = [];
10807
+ for (const row of rows) {
10808
+ if (!row.w_id || !isWidgetType(row.w_type) || !row.w_area_id || row.w_sort_order === null || !row.w_created_at) continue;
10809
+ const widgetRow = {
10810
+ id: row.w_id,
10811
+ type: row.w_type,
10812
+ title: row.w_title,
10813
+ content: row.w_content,
10814
+ menu_name: row.w_menu_name,
10815
+ component_id: row.w_component_id,
10816
+ component_props: row.w_component_props,
10817
+ area_id: row.w_area_id,
10818
+ sort_order: row.w_sort_order,
10819
+ created_at: row.w_created_at
10820
+ };
10821
+ widgets.push(rowToWidget(widgetRow));
10822
+ }
10687
10823
  return {
10688
- id: areaRow.id,
10689
- name: areaRow.name,
10690
- label: areaRow.label,
10691
- description: areaRow.description ?? void 0,
10824
+ id: first.a_id,
10825
+ name: first.a_name,
10826
+ label: first.a_label,
10827
+ description: first.a_description ?? void 0,
10692
10828
  widgets
10693
10829
  };
10694
10830
  }
10831
+ function isWidgetType(value) {
10832
+ return value === "content" || value === "menu" || value === "component";
10833
+ }
10695
10834
  /**
10696
10835
  * Get all widget areas with their widgets
10697
10836
  */
@@ -10746,6 +10885,9 @@ function rowToWidget(row) {
10746
10885
  const WHITESPACE_SPLIT_PATTERN = /\s+/;
10747
10886
  const FTS_OPERATORS_PATTERN = /\b(AND|OR|NOT|NEAR)\b/i;
10748
10887
  const DOUBLE_QUOTE_PATTERN = /"/g;
10888
+ function searchResultDisplayColumn(searchableFields) {
10889
+ return searchableFields.includes("title") ? "title" : "slug";
10890
+ }
10749
10891
  /**
10750
10892
  * Search across multiple collections
10751
10893
  *
@@ -10836,6 +10978,8 @@ async function searchSingleCollection(db, collection, query, options, weights) {
10836
10978
  const escapedQuery = escapeQuery(query);
10837
10979
  if (!escapedQuery) return [];
10838
10980
  const searchableFields = await ftsManager.getSearchableFields(collection);
10981
+ const displayColumn = searchResultDisplayColumn(searchableFields);
10982
+ const displayColumnSql = sql`c.${sql.ref(displayColumn)}`;
10839
10983
  let bm25Args = "";
10840
10984
  if (weights && searchableFields.length > 0) {
10841
10985
  const weightValues = ["0", "0"];
@@ -10844,13 +10988,13 @@ async function searchSingleCollection(db, collection, query, options, weights) {
10844
10988
  }
10845
10989
  const bm25Expr = bm25Args ? `bm25("${ftsTable}", ${bm25Args})` : `bm25("${ftsTable}")`;
10846
10990
  return (await sql`
10847
- SELECT
10848
- c.id,
10849
- c.slug,
10850
- c.locale,
10851
- c.title,
10852
- snippet("${sql.raw(ftsTable)}", 2, '<mark>', '</mark>', '...', 32) as snippet,
10853
- ${sql.raw(bm25Expr)} as score
10991
+ SELECT
10992
+ c.id,
10993
+ c.slug,
10994
+ c.locale,
10995
+ ${displayColumnSql} as title,
10996
+ snippet("${sql.raw(ftsTable)}", 2, '<mark>', '</mark>', '...', 32) as snippet,
10997
+ ${sql.raw(bm25Expr)} as score
10854
10998
  FROM "${sql.raw(ftsTable)}" f
10855
10999
  JOIN "${sql.raw(contentTable)}" c ON f.id = c.id
10856
11000
  WHERE "${sql.raw(ftsTable)}" MATCH ${escapedQuery}
@@ -10890,18 +11034,20 @@ async function getSuggestions(db, query, options = {}) {
10890
11034
  validateIdentifier(collection, "collection slug");
10891
11035
  const ftsTable = ftsManager.getFtsTableName(collection);
10892
11036
  const contentTable = ftsManager.getContentTableName(collection);
10893
- const prefixQuery = `${escapeQuery(query)}*`;
10894
- if (!prefixQuery || prefixQuery === "*") continue;
11037
+ const displayColumn = searchResultDisplayColumn(await ftsManager.getSearchableFields(collection));
11038
+ const displayColumnSql = sql`c.${sql.ref(displayColumn)}`;
11039
+ const prefixQuery = escapeQuery(query);
11040
+ if (!prefixQuery) continue;
10895
11041
  const results = await sql`
10896
- SELECT
11042
+ SELECT
10897
11043
  c.id,
10898
- c.title
11044
+ ${displayColumnSql} as title
10899
11045
  FROM "${sql.raw(ftsTable)}" f
10900
11046
  JOIN "${sql.raw(contentTable)}" c ON f.id = c.id
10901
11047
  WHERE "${sql.raw(ftsTable)}" MATCH ${prefixQuery}
10902
11048
  AND c.status = 'published'
10903
11049
  AND c.deleted_at IS NULL
10904
- AND c.title IS NOT NULL
11050
+ AND ${displayColumnSql} IS NOT NULL
10905
11051
  ${locale ? sql`AND c.locale = ${locale}` : sql``}
10906
11052
  ORDER BY bm25("${sql.raw(ftsTable)}")
10907
11053
  LIMIT ${limit}
@@ -11051,4 +11197,4 @@ function extractSearchableFields(entry, fields) {
11051
11197
  }
11052
11198
 
11053
11199
  //#endregion
11054
- export { CronExecutor as $, handleContentSchedule as $t, getAllSources as A, handleMediaGet as At, NoopSandboxRunner as B, handleContentCountScheduled as Bt, isPreviewRequest as C, createPluginBundleStore as Ct, parseWxrDate as D, getCollectionInfo as Dt, wordpressRestSource as E, PluginStateRepository as Et, registerSource as F, handleRevisionRestore as Ft, PluginRouteError as G, handleContentDuplicate as Gt, createNoopSandboxRunner as H, handleContentCreate as Ht, importReusableBlocksAsSections as I, generateManifest as It, devConsoleEmailDeliver as J, handleContentList as Jt, PluginRouteRegistry as K, handleContentGet as Kt, isStandardPluginDefinition as L, computeContentHash as Lt, getSource as M, handleMediaUpdate as Mt, getUrlSources as N, handleRevisionGet as Nt, wxrSource as O, handleMediaCreate as Ot, probeUrl as P, handleRevisionList as Pt, resolveExclusiveHooks as Q, handleContentRestore as Qt, NodeSandboxRunner as R, hashString as Rt, getPreviewToken as S, sanitizeHref as St, getPreviewUrl as T, getSections as Tt, PluginManager as U, handleContentDelete as Ut, SandboxNotAvailableError as V, handleContentCountTrashed as Vt, createPluginManager as W, handleContentDiscardDraft as Wt, HookPipeline as X, handleContentPermanentDelete as Xt, EmailPipeline as Y, handleContentListTrashed as Yt, createHookPipeline as Z, handleContentPublish as Zt, getTermsForEntries as _, signPreviewUrl as _t, search as a, portableText as an, createFilePreviewMiddleware as at, getCommentCount as b, prosemirrorToPortableText as bt, getWidgetArea as c, dropSessionDatabaseTables as ct, getEntriesByTerm as d, SessionDatabaseLimitError as dt, handleContentTranslations as en, extractRequestMeta as et, getEntryTerms as f, isBlockedInPreview as ft, getTerm as g, parsePreviewSignatureHeader as gt, getTaxonomyTerms as h, defaultPreviewSidecarClient as ht, getSuggestions as i, validateRev as in, parseWxrString as it, getFileSources as j, handleMediaList as jt, clearSources as k, handleMediaDelete as kt, getWidgetAreas as l, getAppliedSnapshotMeta as lt, getTaxonomyDefs as m, buildPreviewSignatureHeader as mt, extractSearchableFields as n, handleContentUnschedule as nn, definePlugin as nt, searchCollection as o, reference as on, renderPreviewToolbar as ot, getTaxonomyDef as p, renderPreviewLoadingPage as pt, DEV_CONSOLE_EMAIL_PLUGIN_ID as q, handleContentGetIncludingTrashed as qt, getSearchStats as r, handleContentUpdate as rn, parseWxr as rt, searchWithDb as s, image as sn, applySnapshotToDatabase as st, extractPlainText as t, handleContentUnpublish as tn, sanitizeHeadersForSandbox as tt, getWidgetComponents as u, FileSessionDatabaseFactory as ut, getMenu as v, verifyPreviewSignature as vt, buildPreviewUrl as w, getSection as wt, getComments as x, isSafeHref as xt, getMenus as y, portableTextToProsemirror as yt, createNodeSandboxRunner as z, handleContentCompare as zt };
11200
+ export { createFilePreviewMiddleware as $, validateRev as $t, isStandardPluginDefinition as A, generateManifest as At, DEV_CONSOLE_EMAIL_PLUGIN_ID as B, handleContentDuplicate as Bt, getAllSources as C, handleMediaDelete as Ct, probeUrl as D, handleRevisionGet as Dt, getUrlSources as E, handleMediaUpdate as Et, createNoopSandboxRunner as F, handleContentCountScheduled as Ft, resolveExclusiveHooks as G, handleContentPermanentDelete as Gt, EmailPipeline as H, handleContentGetIncludingTrashed as Ht, PluginManager as I, handleContentCountTrashed as It, sanitizeHeadersForSandbox as J, handleContentSchedule as Jt, CronExecutor as K, handleContentPublish as Kt, createPluginManager as L, handleContentCreate as Lt, createNodeSandboxRunner as M, hashString as Mt, NoopSandboxRunner as N, PluginStateRepository as Nt, registerSource as O, handleRevisionList as Ot, SandboxNotAvailableError as P, handleContentCompare as Pt, parseWxrString as Q, handleContentUpdate as Qt, PluginRouteError as R, handleContentDelete as Rt, clearSources as S, handleMediaCreate as St, getSource as T, handleMediaList as Tt, HookPipeline as U, handleContentList as Ut, devConsoleEmailDeliver as V, handleContentGet as Vt, createHookPipeline as W, handleContentListTrashed as Wt, definePlugin as X, handleContentUnpublish as Xt, getTrustedProxyHeaders as Y, handleContentTranslations as Yt, parseWxr as Z, handleContentUnschedule as Zt, buildPreviewUrl as _, sanitizeHref as _t, search as a, SessionDatabaseLimitError as at, parseWxrDate as b, getSections as bt, getWidgetArea as c, buildPreviewSignatureHeader as ct, getMenu as d, signPreviewUrl as dt, portableText as en, renderPreviewToolbar as et, getMenus as f, verifyPreviewSignature as ft, isPreviewRequest as g, isSafeHref as gt, getPreviewToken as h, prosemirrorToPortableText as ht, getSuggestions as i, FileSessionDatabaseFactory as it, NodeSandboxRunner as j, computeContentHash as jt, importReusableBlocksAsSections as k, handleRevisionRestore as kt, getWidgetAreas as l, defaultPreviewSidecarClient as lt, getComments as m, portableTextToProsemirror as mt, extractSearchableFields as n, image as nn, dropSessionDatabaseTables as nt, searchCollection as o, isBlockedInPreview as ot, getCommentCount as p, after as pt, extractRequestMeta as q, handleContentRestore as qt, getSearchStats as r, getAppliedSnapshotMeta as rt, searchWithDb as s, renderPreviewLoadingPage as st, extractPlainText as t, reference as tn, applySnapshotToDatabase as tt, getWidgetComponents as u, parsePreviewSignatureHeader as ut, getPreviewUrl as v, createPluginBundleStore as vt, getFileSources as w, handleMediaGet as wt, wxrSource as x, getCollectionInfo as xt, wordpressRestSource as y, getSection as yt, PluginRouteRegistry as z, handleContentDiscardDraft as zt };