dineway 0.1.48 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (420) hide show
  1. package/dist/{activity-events-C9u37D5z.mjs → activity-events-y6eT8UW6.mjs} +6 -38
  2. package/dist/actor-CrObAPV0.mjs +37 -0
  3. package/dist/after-BfniwgIf.mjs +9 -0
  4. package/dist/{allowed-origins-DhipQNLb.mjs → allowed-origins-_oeyP6x-.mjs} +1 -1
  5. package/dist/api/route-utils.d.mts +10 -10
  6. package/dist/api/route-utils.mjs +17 -14
  7. package/dist/api/schemas/index.d.mts +2 -2
  8. package/dist/api/schemas/index.mjs +5 -4
  9. package/dist/{api-Eiy8_zVZ.mjs → api-ByrU2q-Z.mjs} +61 -37
  10. package/dist/{api-tokens-DtvdtIkm.mjs → api-tokens-CjVMQT-X.mjs} +6 -2
  11. package/dist/{apply-CX3no7XE.mjs → apply-bZswmZPm.mjs} +117 -77
  12. package/dist/astro/image-endpoint.d.mts +7 -0
  13. package/dist/astro/image-endpoint.mjs +54 -0
  14. package/dist/astro/index.d.mts +35 -11
  15. package/dist/astro/index.mjs +157 -23
  16. package/dist/astro/integration/shims/use-sync-external-store-with-selector.js +71 -0
  17. package/dist/astro/integration/shims/use-sync-external-store.js +1 -0
  18. package/dist/astro/middleware/auth.d.mts +10 -10
  19. package/dist/astro/middleware/auth.mjs +42 -24
  20. package/dist/astro/middleware/redirect.mjs +14 -5
  21. package/dist/astro/middleware/request-context.mjs +9 -6
  22. package/dist/astro/middleware/seed.d.mts +1 -1
  23. package/dist/astro/middleware/seed.mjs +2 -2
  24. package/dist/astro/middleware/setup.mjs +1 -1
  25. package/dist/astro/middleware.mjs +334 -193
  26. package/dist/astro/routes/admin.astro +6 -1
  27. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +7 -6
  28. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +7 -6
  29. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +4 -4
  30. package/dist/astro/routes/api/admin/api-tokens/index.mjs +6 -6
  31. package/dist/astro/routes/api/admin/briefing.mjs +22 -18
  32. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +4 -4
  33. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +9 -8
  34. package/dist/astro/routes/api/admin/byline-fields/index.mjs +9 -8
  35. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +9 -8
  36. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +18 -15
  37. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +18 -15
  38. package/dist/astro/routes/api/admin/bylines/index.mjs +18 -15
  39. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +15 -13
  40. package/dist/astro/routes/api/admin/comments/_id_.mjs +7 -6
  41. package/dist/astro/routes/api/admin/comments/bulk.mjs +12 -10
  42. package/dist/astro/routes/api/admin/comments/counts.mjs +7 -6
  43. package/dist/astro/routes/api/admin/comments/index.mjs +12 -10
  44. package/dist/astro/routes/api/admin/context/_id_/history.mjs +27 -25
  45. package/dist/astro/routes/api/admin/context/_id_/index.mjs +27 -25
  46. package/dist/astro/routes/api/admin/context/_id_/review.mjs +32 -29
  47. package/dist/astro/routes/api/admin/context/_id_/supersede.mjs +32 -29
  48. package/dist/astro/routes/api/admin/context/diff.mjs +31 -28
  49. package/dist/astro/routes/api/admin/context/index.mjs +32 -29
  50. package/dist/astro/routes/api/admin/context/stale.mjs +31 -28
  51. package/dist/astro/routes/api/admin/hitl-requests/_id_/index.mjs +27 -25
  52. package/dist/astro/routes/api/admin/hitl-requests/_id_/resolve.mjs +31 -28
  53. package/dist/astro/routes/api/admin/hitl-requests/index.mjs +31 -28
  54. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +28 -26
  55. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
  56. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +6 -6
  57. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +6 -6
  58. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +56 -52
  59. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +56 -52
  60. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +48 -44
  61. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +54 -50
  62. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +53 -49
  63. package/dist/astro/routes/api/admin/plugins/index.mjs +48 -44
  64. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +2 -2
  65. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +47 -43
  66. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +53 -49
  67. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +47 -43
  68. package/dist/astro/routes/api/admin/plugins/updates.mjs +47 -43
  69. package/dist/astro/routes/api/admin/review-requests/_id_/index.mjs +6 -6
  70. package/dist/astro/routes/api/admin/review-requests/_id_/resolve.mjs +32 -28
  71. package/dist/astro/routes/api/admin/review-requests/index.mjs +11 -10
  72. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +47 -43
  73. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +2 -2
  74. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +47 -43
  75. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +3 -3
  76. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +2 -2
  77. package/dist/astro/routes/api/admin/users/_id_/index.mjs +8 -7
  78. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +4 -4
  79. package/dist/astro/routes/api/admin/users/index.mjs +7 -6
  80. package/dist/astro/routes/api/auth/dev-bypass.mjs +4 -4
  81. package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
  82. package/dist/astro/routes/api/auth/invite/complete.mjs +12 -11
  83. package/dist/astro/routes/api/auth/invite/index.mjs +9 -8
  84. package/dist/astro/routes/api/auth/invite/register-options.mjs +11 -10
  85. package/dist/astro/routes/api/auth/logout.mjs +2 -2
  86. package/dist/astro/routes/api/auth/magic-link/send.mjs +11 -10
  87. package/dist/astro/routes/api/auth/magic-link/verify.mjs +3 -3
  88. package/dist/astro/routes/api/auth/me.mjs +10 -9
  89. package/dist/astro/routes/api/auth/mode.mjs +1 -1
  90. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +3 -3
  91. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  92. package/dist/astro/routes/api/auth/passkey/_id_.mjs +6 -5
  93. package/dist/astro/routes/api/auth/passkey/index.mjs +1 -1
  94. package/dist/astro/routes/api/auth/passkey/options.mjs +12 -11
  95. package/dist/astro/routes/api/auth/passkey/register/options.mjs +10 -9
  96. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +11 -10
  97. package/dist/astro/routes/api/auth/passkey/verify.mjs +11 -10
  98. package/dist/astro/routes/api/auth/setup-token/index.mjs +6 -6
  99. package/dist/astro/routes/api/auth/setup-token/verify.mjs +2 -2
  100. package/dist/astro/routes/api/auth/signup/complete.mjs +12 -11
  101. package/dist/astro/routes/api/auth/signup/request.mjs +11 -10
  102. package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
  103. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +16 -14
  104. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.d.mts +8 -0
  105. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +160 -0
  106. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +2 -2
  107. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +6 -6
  108. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +6 -6
  109. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +6 -6
  110. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +12 -11
  111. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +11 -10
  112. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +6 -6
  113. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +2 -2
  114. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +11 -10
  115. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +17 -15
  116. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +2 -2
  117. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +6 -6
  118. package/dist/astro/routes/api/content/_collection_/_id_.mjs +11 -10
  119. package/dist/astro/routes/api/content/_collection_/authors.mjs +2 -2
  120. package/dist/astro/routes/api/content/_collection_/index.mjs +11 -10
  121. package/dist/astro/routes/api/content/_collection_/trash.mjs +7 -6
  122. package/dist/astro/routes/api/dashboard.mjs +10 -9
  123. package/dist/astro/routes/api/dev/emails.mjs +2 -2
  124. package/dist/astro/routes/api/health.mjs +1 -1
  125. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  126. package/dist/astro/routes/api/import/probe.mjs +23 -11
  127. package/dist/astro/routes/api/import/wordpress/analyze.mjs +9 -6
  128. package/dist/astro/routes/api/import/wordpress/execute.d.mts +19 -1
  129. package/dist/astro/routes/api/import/wordpress/execute.mjs +85 -38
  130. package/dist/astro/routes/api/import/wordpress/media.d.mts +13 -1
  131. package/dist/astro/routes/api/import/wordpress/media.mjs +20 -14
  132. package/dist/astro/routes/api/import/wordpress/prepare.mjs +36 -33
  133. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +18 -1
  134. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +121 -101
  135. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  136. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +25 -13
  137. package/dist/astro/routes/api/import/wordpress-plugin/callback.mjs +1 -1
  138. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +56 -2
  139. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +284 -56
  140. package/dist/astro/routes/api/manifest.mjs +14 -5
  141. package/dist/astro/routes/api/mcp.mjs +266 -70
  142. package/dist/astro/routes/api/media/_id_/confirm.mjs +39 -11
  143. package/dist/astro/routes/api/media/_id_.mjs +11 -7
  144. package/dist/astro/routes/api/media/file/_...key_.mjs +1 -1
  145. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +2 -2
  146. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +2 -2
  147. package/dist/astro/routes/api/media/providers/index.mjs +2 -2
  148. package/dist/astro/routes/api/media/upload-url.mjs +12 -11
  149. package/dist/astro/routes/api/media.mjs +28 -35
  150. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +32 -29
  151. package/dist/astro/routes/api/menus/_name_/items.mjs +32 -29
  152. package/dist/astro/routes/api/menus/_name_/reorder.mjs +32 -29
  153. package/dist/astro/routes/api/menus/_name_/translations.mjs +32 -29
  154. package/dist/astro/routes/api/menus/_name_.mjs +32 -29
  155. package/dist/astro/routes/api/menus/index.mjs +32 -29
  156. package/dist/astro/routes/api/oauth/authorize.mjs +7 -7
  157. package/dist/astro/routes/api/oauth/device/authorize.mjs +6 -6
  158. package/dist/astro/routes/api/oauth/device/code.mjs +9 -9
  159. package/dist/astro/routes/api/oauth/device/token.mjs +8 -8
  160. package/dist/astro/routes/api/oauth/register.mjs +4 -4
  161. package/dist/astro/routes/api/oauth/token/refresh.mjs +6 -6
  162. package/dist/astro/routes/api/oauth/token/revoke.mjs +6 -6
  163. package/dist/astro/routes/api/oauth/token.mjs +6 -6
  164. package/dist/astro/routes/api/openapi.json.mjs +4 -3
  165. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +30 -30
  166. package/dist/astro/routes/api/redirects/404s/index.mjs +12 -11
  167. package/dist/astro/routes/api/redirects/404s/summary.mjs +12 -11
  168. package/dist/astro/routes/api/redirects/_id_.mjs +33 -30
  169. package/dist/astro/routes/api/redirects/index.mjs +33 -30
  170. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +2 -2
  171. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +2 -2
  172. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +48 -44
  173. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +48 -44
  174. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +48 -44
  175. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +48 -44
  176. package/dist/astro/routes/api/schema/collections/index.mjs +48 -44
  177. package/dist/astro/routes/api/schema/index.mjs +13 -14
  178. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +47 -43
  179. package/dist/astro/routes/api/schema/orphans/index.mjs +47 -43
  180. package/dist/astro/routes/api/search/enable.mjs +12 -11
  181. package/dist/astro/routes/api/search/index.mjs +11 -10
  182. package/dist/astro/routes/api/search/rebuild.mjs +12 -11
  183. package/dist/astro/routes/api/search/stats.mjs +7 -7
  184. package/dist/astro/routes/api/search/suggest.mjs +11 -10
  185. package/dist/astro/routes/api/sections/_slug_.mjs +32 -29
  186. package/dist/astro/routes/api/sections/index.mjs +32 -29
  187. package/dist/astro/routes/api/settings/email.mjs +4 -4
  188. package/dist/astro/routes/api/settings.mjs +32 -29
  189. package/dist/astro/routes/api/setup/admin-verify.mjs +14 -13
  190. package/dist/astro/routes/api/setup/admin.mjs +12 -11
  191. package/dist/astro/routes/api/setup/dev-bypass.mjs +32 -26
  192. package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
  193. package/dist/astro/routes/api/setup/index.mjs +30 -26
  194. package/dist/astro/routes/api/setup/status.mjs +3 -3
  195. package/dist/astro/routes/api/snapshot.mjs +9 -8
  196. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +35 -32
  197. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +35 -32
  198. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +35 -32
  199. package/dist/astro/routes/api/taxonomies/index.mjs +35 -32
  200. package/dist/astro/routes/api/themes/preview.mjs +6 -6
  201. package/dist/astro/routes/api/typegen.mjs +4 -4
  202. package/dist/astro/routes/api/well-known/auth.mjs +3 -3
  203. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +3 -3
  204. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +3 -3
  205. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +31 -28
  206. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +32 -29
  207. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +32 -29
  208. package/dist/astro/routes/api/widget-areas/_name_.mjs +29 -27
  209. package/dist/astro/routes/api/widget-areas/index.mjs +32 -29
  210. package/dist/astro/routes/api/widget-components.mjs +2 -2
  211. package/dist/astro/routes/robots.txt.mjs +9 -8
  212. package/dist/astro/routes/sitemap-_collection_.xml.mjs +24 -15
  213. package/dist/astro/routes/sitemap.xml.mjs +10 -9
  214. package/dist/astro/session-driver.d.mts +1 -1
  215. package/dist/astro/session-driver.mjs +3 -3
  216. package/dist/astro/types.d.mts +21 -13
  217. package/dist/{audit-D1cbG7xH.mjs → audit-ByVKIwWF.mjs} +1 -1
  218. package/dist/auth/providers/github.d.mts +1 -1
  219. package/dist/auth/providers/google.d.mts +1 -1
  220. package/dist/{auth-control-guard-Dr14I98m.mjs → auth-control-guard-CqeUmQsv.mjs} +1 -1
  221. package/dist/{authorize-BLO0m7fW.mjs → authorize-CcBxcHtz.mjs} +1 -1
  222. package/dist/{briefing-CObXGOGz.mjs → briefing-BJaJI8dm.mjs} +2 -1
  223. package/dist/{briefing-gKWiGLt1.mjs → briefing-CawZ59CY.mjs} +90 -28
  224. package/dist/bundle-7C_DpkEq.mjs +602 -0
  225. package/dist/{byline-1ntDwv8c.mjs → byline-e51-fWRs.mjs} +30 -62
  226. package/dist/{byline-fields-BX7rWKNU.d.mts → byline-fields-CUvbslGc.d.mts} +49 -6
  227. package/dist/{byline-fields-C9_iaPaM.mjs → byline-fields-D-N5qVIG.mjs} +1 -1
  228. package/dist/{byline-fields-B-ZkoVft.mjs → byline-fields-DOJO16Gm.mjs} +3 -3
  229. package/dist/{byline-registry-CUSvkasJ.mjs → byline-registry-87nNnYl4.mjs} +2 -2
  230. package/dist/{bylines-bC15ZqAv.mjs → bylines-CMQNCNFh.mjs} +9 -3
  231. package/dist/{bylines-DtxChhN_.mjs → bylines-y4LO-dTj.mjs} +5 -5
  232. package/dist/{cache-DbKyr60Q.mjs → cache-C-FNTFYK.mjs} +2 -2
  233. package/dist/{chunks-C5zp2xir.mjs → chunks-CxBt-GxR.mjs} +1 -1
  234. package/dist/cli/index.mjs +820 -1276
  235. package/dist/client/external-auth-headers.d.mts +1 -1
  236. package/dist/client/index.d.mts +1 -1
  237. package/dist/client/index.mjs +2 -1
  238. package/dist/{comment-CXDOQ93N.mjs → comment-DlA4iChg.mjs} +13 -3
  239. package/dist/comment-reaction-DfFao1ST.mjs +58 -0
  240. package/dist/{comments-hK-rdzJ9.mjs → comments-DApFGMsP.mjs} +1 -1
  241. package/dist/{content-QaryevFO.mjs → content-Bh4BDjv8.mjs} +51 -34
  242. package/dist/content-refresh-CgutSUfO.mjs +1576 -0
  243. package/dist/{context-CoYb_fvK.mjs → context-C5W3G18y.mjs} +111 -50
  244. package/dist/{context-DBL1ib4v.mjs → context-CK4ym2Sf.mjs} +2 -2
  245. package/dist/{context-route-helpers-CYQVmbIm.mjs → context-route-helpers-MASyGgWf.mjs} +2 -1
  246. package/dist/{cron-DxCAU_Sn.mjs → cron-cKcNTix_.mjs} +7 -3
  247. package/dist/{dashboard-DNlqsknJ.mjs → dashboard-DQkVT7Ei.mjs} +4 -4
  248. package/dist/db/index.d.mts +3 -3
  249. package/dist/db/index.mjs +1 -1
  250. package/dist/db/libsql.d.mts +1 -1
  251. package/dist/db/postgres.d.mts +1 -1
  252. package/dist/db/sqlite.d.mts +1 -1
  253. package/dist/{device-flow-DygsFPGL.mjs → device-flow-BnqRH-T9.mjs} +5 -5
  254. package/dist/{placeholder-BDo81Is5.mjs → enrich-DIFIFA8O.mjs} +36 -9
  255. package/dist/{error-DCSuUAZW.mjs → error-CytFlgcd.mjs} +5 -0
  256. package/dist/field-defs-cache-DRNdhBJv.mjs +49 -0
  257. package/dist/{fts-manager-CIZlScg5.mjs → fts-manager-Crzypjqu.mjs} +1 -1
  258. package/dist/hitl-Hw1RmWOq.mjs +677 -0
  259. package/dist/{hitl-requests-CGQwOEiq.mjs → hitl-requests-B4Vbcmaq.mjs} +2 -2
  260. package/dist/{hitl-route-helpers-GSDLNPpN.mjs → hitl-route-helpers-hEVzvP8l.mjs} +5 -4
  261. package/dist/import-Bh9biJfx.mjs +1354 -0
  262. package/dist/{index-CwRuZ-u8.d.mts → index-D4y6NGiy.d.mts} +75 -3
  263. package/dist/index.d.mts +17 -16
  264. package/dist/index.mjs +81 -69
  265. package/dist/{jsonld-DZ67souc.d.mts → jsonld-Dq0gsnOH.d.mts} +8 -4
  266. package/dist/{load-xE01Jm0V.mjs → load-DmYeniXl.mjs} +1 -1
  267. package/dist/{loader-tg63WSY2.mjs → loader-CjWqjweO.mjs} +117 -31
  268. package/dist/{manifest-schema-qh2P7RDX.mjs → manifest-schema-BxVPYMJR.mjs} +34 -1
  269. package/dist/mcp-reviewed-executor-TwVbMzG6.mjs +555 -0
  270. package/dist/media/image-endpoint.d.mts +32 -0
  271. package/dist/media/image-endpoint.mjs +111 -0
  272. package/dist/media/index.d.mts +27 -2
  273. package/dist/media/index.mjs +5 -3
  274. package/dist/media/local-runtime.d.mts +16 -11
  275. package/dist/media/local-runtime.mjs +10 -8
  276. package/dist/{media-DUAjMfvR.mjs → media-DMj0grzC.mjs} +3 -1
  277. package/dist/{media-allowlist-BsXkT9RK.mjs → media-allowlist-BlVCSzHx.mjs} +1 -1
  278. package/dist/media-url-lEKSrpr9.mjs +20 -0
  279. package/dist/{menus-WpFRMXjz.mjs → menus-TaW1gKnk.mjs} +19 -5
  280. package/dist/{menus-DU1eZqw_.mjs → menus-xvsnVZXw.mjs} +80 -15
  281. package/dist/{normalize-DUnoXAa9.mjs → normalize-5ek_z7de.mjs} +8 -1
  282. package/dist/{oauth-authorization-D-1p52Je.mjs → oauth-authorization-DiaGvRVz.mjs} +5 -5
  283. package/dist/{oauth-clients-CzeMGyUU.mjs → oauth-clients-Dl9E8dEM.mjs} +2 -2
  284. package/dist/object-cache/memory.d.mts +14 -0
  285. package/dist/object-cache/memory.mjs +55 -0
  286. package/dist/object-cache-D51qOseS.mjs +419 -0
  287. package/dist/page/index.d.mts +4 -3
  288. package/dist/page/index.mjs +2 -2
  289. package/dist/{parse-CneSgl7-.mjs → parse-CbymENaR.mjs} +1 -1
  290. package/dist/{parser-DxfsARXL.mjs → parser-C1nYd-81.mjs} +151 -9
  291. package/dist/{placeholder-CXfoCtCd.d.mts → placeholder-uvNRZBX9.d.mts} +12 -4
  292. package/dist/plugin-utils.d.mts +9 -9
  293. package/dist/plugins/adapt-sandbox-entry.d.mts +9 -9
  294. package/dist/plugins/adapt-sandbox-entry.mjs +11 -2
  295. package/dist/{plugins-C57YQi4l.mjs → plugins-BolVa-tl.mjs} +832 -64
  296. package/dist/{transport-LSdZVXHF.mjs → portable-text-dA_UlJwW.mjs} +1 -134
  297. package/dist/{preview-D5rvDhRt.mjs → preview-vSVg6fwG.mjs} +4 -3
  298. package/dist/process-cache-7xgAO9JY.mjs +106 -0
  299. package/dist/{provider-loader-9it4vd6L.d.mts → provider-loader-MD8zAbnH.d.mts} +1 -1
  300. package/dist/{public-url-DLUM5OOv.mjs → public-url-BEz_sM9n.mjs} +24 -18
  301. package/dist/{public-url-B5HaoGzj.d.mts → public-url-gsp3oUbu.d.mts} +5 -4
  302. package/dist/{query-BYc3oruA.mjs → query-CfRCdaL3.mjs} +281 -76
  303. package/dist/{query-DKEwzobh.mjs → query-jaAmw8E1.mjs} +11 -6
  304. package/dist/{rate-limit-i0G3IAOX.mjs → rate-limit-ZLdyWoZF.mjs} +2 -2
  305. package/dist/{redirect-C2zXRj3c.mjs → redirect-BAjt4Z6b.mjs} +2 -2
  306. package/dist/{redirects-YZo_znWG.mjs → redirects-BTdwpQtE.mjs} +47 -24
  307. package/dist/{redirects-ocRJmQHP.mjs → redirects-CA-xylPG.mjs} +19 -11
  308. package/dist/{registry-CTkbIDB9.mjs → registry-CtyVedcN.mjs} +130 -77
  309. package/dist/request-context.d.mts +2 -0
  310. package/dist/{request-meta-DAb6xaP9.mjs → request-meta-CUypToDJ.mjs} +1 -1
  311. package/dist/{review-requests-C0un5kdV.mjs → review-requests-C9Ff11Vq.mjs} +1 -1
  312. package/dist/{review-requests-gGMyYYhy.mjs → review-requests-DUyEmtmG.mjs} +1 -1
  313. package/dist/{runner-D4FL9usy.d.mts → runner-1tC2tIRV.d.mts} +1 -1
  314. package/dist/runner-DB7CRfOF.mjs +6740 -0
  315. package/dist/{runtime-DEWQpZ-4.d.mts → runtime-BOeiQsCv.d.mts} +2028 -1564
  316. package/dist/runtime.d.mts +10 -10
  317. package/dist/runtime.mjs +4 -4
  318. package/dist/schema-DXdYj4R3.mjs +8 -0
  319. package/dist/{search-axGQ1KY3.mjs → search-DSaLgEFI.mjs} +5 -3
  320. package/dist/{secrets-062Izo8i.mjs → secrets-CDZo2k8L.mjs} +15 -12
  321. package/dist/{sections-OLKgXL10.mjs → sections-PVVXHGfp.mjs} +2 -2
  322. package/dist/seed/index.d.mts +2 -2
  323. package/dist/seed/index.mjs +22 -19
  324. package/dist/seo/index.d.mts +1 -1
  325. package/dist/seo/index.mjs +3 -12
  326. package/dist/{seo-Cd45Po8L.mjs → seo-CQG3GCHQ.mjs} +5 -2
  327. package/dist/{seo-contributions-CqVvReEj.mjs → seo-contributions-C1EnikHB.mjs} +11 -3
  328. package/dist/{seo-5lJOtB5J.mjs → seo-qa7Dn0jK.mjs} +22 -4
  329. package/dist/{service-Bwad8s5h.mjs → service-DiN4ZuPp.mjs} +2 -2
  330. package/dist/session-user-CAKImna3.mjs +22 -0
  331. package/dist/{settings-yLjz_I4T.mjs → settings-BbqgHWpU.mjs} +28 -55
  332. package/dist/{settings-lAHjaUit.mjs → settings-i4VPP8bT.mjs} +2 -2
  333. package/dist/{setup-complete--PradA4R.mjs → setup-complete-B8fl-mjV.mjs} +1 -1
  334. package/dist/{site-activity-D7Xyropw.mjs → site-activity-Dy3FROs0.mjs} +1 -1
  335. package/dist/{site-context-DaN9Z91j.mjs → site-context-DQiL8Fl5.mjs} +23 -652
  336. package/dist/{site-url-DpGZo9Z6.mjs → site-url-BML3GQYm.mjs} +1 -1
  337. package/dist/status-DANd8ERo.mjs +21 -0
  338. package/dist/storage/local.d.mts +1 -1
  339. package/dist/storage/local.mjs +1 -1
  340. package/dist/storage/s3.d.mts +1 -1
  341. package/dist/storage/s3.mjs +1 -1
  342. package/dist/{taxonomies-uXVEoQso.mjs → taxonomies-9s-v03H-.mjs} +36 -29
  343. package/dist/taxonomies-DRiixp_E.mjs +443 -0
  344. package/dist/{taxonomy-CBmkmMuU.mjs → taxonomy-Dvsw6BOs.mjs} +44 -9
  345. package/dist/{tokens-CjSgb0AC.mjs → tokens-1RK1n6ED.mjs} +1 -1
  346. package/dist/transport-BNmCqLu7.mjs +134 -0
  347. package/dist/types-4garmdWa.mjs +66 -0
  348. package/dist/{types-DSPGWjxO.d.mts → types-C8XW6L19.d.mts} +225 -4
  349. package/dist/{types-GaCtZ1k9.d.mts → types-CDpH6MA4.d.mts} +18 -0
  350. package/dist/{types-DRIKLmJI.d.mts → types-C_ly5eTp.d.mts} +17 -2
  351. package/dist/types-DF7ZuGGk.d.mts +118 -0
  352. package/dist/types-DU0bU2Wu.d.mts +2392 -0
  353. package/dist/{types-CwawBUTa.d.mts → types-DW_-sFyz.d.mts} +2 -1
  354. package/dist/{types-DfuD0Afl.mjs → types-Dq1qT19x.mjs} +2 -2
  355. package/dist/ui/server-runtime.d.mts +15 -15
  356. package/dist/ui/server-runtime.mjs +25 -21
  357. package/dist/url-Cac7a9QZ.mjs +33 -0
  358. package/dist/{user-DtNmjNYt.mjs → user-BIZPzCb9.mjs} +2 -2
  359. package/dist/{utils-wv-zvC-Y.mjs → utils-CMDhr5Xd.mjs} +129 -7
  360. package/dist/{validate-BMs11tan.d.mts → validate-CZvb-BKB.d.mts} +10 -7
  361. package/dist/{validate-7SYRbz2f.mjs → validate-DNs0pTSc.mjs} +11 -6
  362. package/dist/version-BTvfRGc6.mjs +6 -0
  363. package/dist/{widgets-DR8EHuRO.mjs → widgets-f0ibZUIq.mjs} +46 -43
  364. package/dist/{wordpress-slugs-Dvhxh4cl.mjs → wordpress-slugs-BhHJX8XE.mjs} +1 -1
  365. package/dist/{zod-generator-BS9-umbk.mjs → zod-generator-B7TMjyFJ.mjs} +41 -13
  366. package/package.json +31 -8
  367. package/src/components/Block.astro +50 -0
  368. package/src/components/Comments.astro +143 -1
  369. package/src/components/DinewayHead.astro +19 -2
  370. package/src/components/DinewayImage.astro +66 -33
  371. package/src/components/DinewayMedia.astro +1 -2
  372. package/src/components/Image.astro +85 -40
  373. package/src/components/InlinePortableTextEditor.tsx +12 -2
  374. package/src/components/JsonLdScript.astro +9 -0
  375. package/src/components/LiveSearch.astro +40 -4
  376. package/src/components/index.ts +4 -0
  377. package/src/components/live-search-routing.ts +30 -0
  378. package/src/components/portable-text-text-align.ts +15 -0
  379. package/src/ui.ts +2 -0
  380. package/dist/entity-aliases-Egjmqc7I.mjs +0 -51
  381. package/dist/import-CvHY6sf5.mjs +0 -684
  382. package/dist/runner-B-tbV751.mjs +0 -2741
  383. package/dist/schema-B6zyB-Xn.mjs +0 -8
  384. package/dist/taxonomies-CNOGeC-3.mjs +0 -327
  385. package/dist/types-eu5UDgHN.d.mts +0 -652
  386. package/dist/version-xlzMSXF2.mjs +0 -6
  387. /package/dist/{adapters-OQCImOL7.d.mts → adapters-NVSs4UH7.d.mts} +0 -0
  388. /package/dist/{api-tokens-CYUoFGo7.mjs → api-tokens-2r7OWi_I.mjs} +0 -0
  389. /package/dist/{base64-C1Q9yr0B.mjs → base64-F8-DUraK.mjs} +0 -0
  390. /package/dist/{challenge-store-CRSz-Xim.mjs → challenge-store-Bjlepa2E.mjs} +0 -0
  391. /package/dist/{components--pg6zBvu.mjs → components-Bclf98Be.mjs} +0 -0
  392. /package/dist/{context-types-DQh_XKkn.mjs → context-types-DqTo6C79.mjs} +0 -0
  393. /package/dist/{default-B6iaLvP7.mjs → default--K40jqm0.mjs} +0 -0
  394. /package/dist/{email-console-BOVqIYpB.mjs → email-console-ChgKFO8-.mjs} +0 -0
  395. /package/dist/{escape-BDgouFFY.mjs → escape-Bd4P_xKg.mjs} +0 -0
  396. /package/dist/{experimental-workflows-Dh4DUoD_.mjs → experimental-workflows-BMsUnIAw.mjs} +0 -0
  397. /package/dist/{mime-8pAB8-77.mjs → mime-CA7Lgovc.mjs} +0 -0
  398. /package/dist/{mode-CpyEz8pe.mjs → mode-C4CIyjtR.mjs} +0 -0
  399. /package/dist/{oauth-state-store-qncPB_IU.mjs → oauth-state-store-CNoXafF7.mjs} +0 -0
  400. /package/dist/{oauth-user-lookup-BFjWF8wK.mjs → oauth-user-lookup-Ygw4bNyt.mjs} +0 -0
  401. /package/dist/{options-BvJoSSJR.mjs → options-DQPTH5n0.mjs} +0 -0
  402. /package/dist/{passkey-config-DzHQK90v.mjs → passkey-config-BUwu8BA3.mjs} +0 -0
  403. /package/dist/{patterns-r-0n824Y.mjs → patterns-BhAvqO0S.mjs} +0 -0
  404. /package/dist/{provider-loader-DzUxejk7.mjs → provider-loader-D0w9dqjm.mjs} +0 -0
  405. /package/dist/{redirect-BjIBtDWY.mjs → redirect-wphRBv4y.mjs} +0 -0
  406. /package/dist/{request-cache-CYMbwZc6.mjs → request-cache-D9GQBxMP.mjs} +0 -0
  407. /package/dist/{resolve-DTuDyYKs.mjs → resolve-Cb6Dbz-C.mjs} +0 -0
  408. /package/dist/{setup-nonce-pyGfc9hV.mjs → setup-nonce-CoyjILvW.mjs} +0 -0
  409. /package/dist/{sidecar-client-mJxwayYN.mjs → sidecar-client-C3mqXg4C.mjs} +0 -0
  410. /package/dist/{slugify-BzGxlOFx.mjs → slugify-KSsVD_D3.mjs} +0 -0
  411. /package/dist/{ssrf-DiKqWd3N.mjs → ssrf-DWe8jwAp.mjs} +0 -0
  412. /package/dist/{transaction-CShMWIej.mjs → transaction-C2EOMTJA.mjs} +0 -0
  413. /package/dist/{transport-BnsNxh2l.d.mts → transport-CcJu3Co8.d.mts} +0 -0
  414. /package/dist/{trusted-proxy-BgIIcbsN.mjs → trusted-proxy-DTXQ2IMv.mjs} +0 -0
  415. /package/dist/{types-BO8TGjS8.mjs → types-B3t5cxhU.mjs} +0 -0
  416. /package/dist/{types-nP9vGUFq.d.mts → types-C46EvNdc.d.mts} +0 -0
  417. /package/dist/{types-Cg276-3z.mjs → types-C5CVgwsV.mjs} +0 -0
  418. /package/dist/{types-DZpT-PnG.d.mts → types-POH8PQZh.d.mts} +0 -0
  419. /package/dist/{types-Dryvv7LH.d.mts → types-Rc3gQqqw.d.mts} +0 -0
  420. /package/dist/{url-w7Mp5qAD.mjs → url-CpyFDFpO.mjs} +0 -0
@@ -0,0 +1,1354 @@
1
+ import { n as slugify } from "./slugify-KSsVD_D3.mjs";
2
+ import { t as TaxonomyRepository } from "./taxonomy-Dvsw6BOs.mjs";
3
+ import { t as OptionsRepository } from "./options-DQPTH5n0.mjs";
4
+ import { o as invalidateSiteSettingsCache } from "./settings-BbqgHWpU.mjs";
5
+ import { i as resolveLocaleChain } from "./resolve-Cb6Dbz-C.mjs";
6
+ import { l as invalidateTermCache } from "./taxonomies-DRiixp_E.mjs";
7
+ import { n as parseWxrString } from "./parser-C1nYd-81.mjs";
8
+ import { a as validateExternalUrl, n as resolveAndValidateExternalUrl, r as ssrfSafeFetch } from "./ssrf-DWe8jwAp.mjs";
9
+ import { _ as sanitizeFieldSlug, a as getFilenameFromUrl, c as isInternalMetaKey, d as mapMetaKeyToField, f as mapPostTypeToCollection, h as relativizeContentLinks, i as checkSchemaCompatibility, l as isInternalPostType, m as normalizeUrl$1, n as FEATURED_IMAGE_FIELD, o as guessMimeType, p as mapWpStatus, r as buildAttachmentMap, s as inferMetaType, t as BASE_REQUIRED_FIELDS, u as isPluginBookkeepingMeta } from "./utils-CMDhr5Xd.mjs";
10
+ import { ulid } from "ulidx";
11
+ import { gutenbergToPortableText } from "@dineway-ai/gutenberg-to-portable-text";
12
+
13
+ //#region src/import/menus.ts
14
+ /**
15
+ * Import navigation menus from Plugin API
16
+ *
17
+ * @param menus - Menus from plugin API
18
+ * @param db - Database connection
19
+ * @param contentIdMap - Map from WP post ID to Dineway content ID
20
+ * @returns Import result with counts and ID mapping
21
+ */
22
+ async function importMenusFromPlugin(menus, db, contentIdMap) {
23
+ const result = {
24
+ menusCreated: 0,
25
+ itemsCreated: 0,
26
+ menuIdMap: /* @__PURE__ */ new Map(),
27
+ errors: []
28
+ };
29
+ for (const menu of menus) try {
30
+ const existing = await db.selectFrom("_dineway_menus").select("id").where("name", "=", menu.name).executeTakeFirst();
31
+ if (existing) {
32
+ result.menuIdMap.set(menu.name, existing.id);
33
+ continue;
34
+ }
35
+ const menuId = ulid();
36
+ await db.insertInto("_dineway_menus").values({
37
+ id: menuId,
38
+ name: menu.name,
39
+ label: menu.label,
40
+ translation_group: menuId
41
+ }).execute();
42
+ result.menusCreated++;
43
+ result.menuIdMap.set(menu.name, menuId);
44
+ const itemsCreated = await importPluginMenuItems(menu.items, menuId, db, contentIdMap);
45
+ result.itemsCreated += itemsCreated;
46
+ } catch (error) {
47
+ result.errors.push({
48
+ menu: menu.name,
49
+ error: error instanceof Error ? error.message : String(error)
50
+ });
51
+ }
52
+ return result;
53
+ }
54
+ /**
55
+ * Import menu items from Plugin API format
56
+ */
57
+ async function importPluginMenuItems(items, menuId, db, contentIdMap) {
58
+ const itemIdMap = /* @__PURE__ */ new Map();
59
+ let count = 0;
60
+ const sortedItems = items.toSorted((a, b) => a.sort_order - b.sort_order);
61
+ for (const item of sortedItems) {
62
+ const itemId = ulid();
63
+ itemIdMap.set(item.id, itemId);
64
+ const { type, collection, referenceId, customUrl } = mapPluginMenuItem(item, contentIdMap);
65
+ await db.insertInto("_dineway_menu_items").values({
66
+ id: itemId,
67
+ menu_id: menuId,
68
+ parent_id: null,
69
+ sort_order: item.sort_order,
70
+ type,
71
+ reference_collection: collection,
72
+ reference_id: referenceId,
73
+ custom_url: customUrl,
74
+ label: item.title,
75
+ title_attr: null,
76
+ target: item.target || null,
77
+ css_classes: item.classes || null,
78
+ translation_group: itemId
79
+ }).execute();
80
+ count++;
81
+ }
82
+ for (const item of sortedItems) if (item.parent_id) {
83
+ const itemId = itemIdMap.get(item.id);
84
+ const parentId = itemIdMap.get(item.parent_id);
85
+ if (itemId && parentId) await db.updateTable("_dineway_menu_items").set({ parent_id: parentId }).where("id", "=", itemId).execute();
86
+ }
87
+ return count;
88
+ }
89
+ /**
90
+ * Map Plugin menu item to Dineway format
91
+ */
92
+ function mapPluginMenuItem(item, contentIdMap) {
93
+ switch (item.type) {
94
+ case "custom": return {
95
+ type: "custom",
96
+ collection: null,
97
+ referenceId: null,
98
+ customUrl: item.url || "#"
99
+ };
100
+ case "post_type": {
101
+ const collection = mapObjectToCollection(item.object);
102
+ const referenceId = item.object_id ? contentIdMap.get(item.object_id) || null : null;
103
+ if (!referenceId && item.url) return {
104
+ type: "custom",
105
+ collection: null,
106
+ referenceId: null,
107
+ customUrl: item.url
108
+ };
109
+ return {
110
+ type: collection === "pages" ? "page" : "post",
111
+ collection,
112
+ referenceId,
113
+ customUrl: null
114
+ };
115
+ }
116
+ case "taxonomy": return {
117
+ type: "custom",
118
+ collection: null,
119
+ referenceId: null,
120
+ customUrl: item.url || "#"
121
+ };
122
+ default: return {
123
+ type: "custom",
124
+ collection: null,
125
+ referenceId: null,
126
+ customUrl: item.url || "#"
127
+ };
128
+ }
129
+ }
130
+ /**
131
+ * Map WordPress object type to Dineway collection name
132
+ */
133
+ function mapObjectToCollection(objectType) {
134
+ if (!objectType) return "posts";
135
+ return {
136
+ post: "posts",
137
+ page: "pages",
138
+ product: "products",
139
+ portfolio: "portfolio"
140
+ }[objectType] || objectType;
141
+ }
142
+
143
+ //#endregion
144
+ //#region src/import/comments.ts
145
+ /**
146
+ * Import comments from the plugin API.
147
+ *
148
+ * Preserves original timestamps and threading. Comments whose post was
149
+ * not imported (no entry in `contentIdMap`) are skipped. Re-running the
150
+ * import is idempotent: a comment with the same post, author email,
151
+ * timestamp, and body is not created twice.
152
+ *
153
+ * @param comments - Comments from the plugin API (all pages, flat)
154
+ * @param db - Database connection
155
+ * @param contentIdMap - WP post ID -> Dineway content ID
156
+ * @param collectionMap - WP post ID -> Dineway collection slug
157
+ */
158
+ async function importCommentsFromPlugin(comments, db, contentIdMap, collectionMap) {
159
+ const result = {
160
+ imported: 0,
161
+ skipped: 0,
162
+ errors: []
163
+ };
164
+ const rootIdMap = /* @__PURE__ */ new Map();
165
+ const sorted = comments.toSorted((a, b) => a.id - b.id);
166
+ for (const comment of sorted) {
167
+ const label = `${comment.author_name || "Anonymous"} (${comment.date_gmt})`;
168
+ try {
169
+ const contentId = contentIdMap.get(comment.post_id);
170
+ const collection = collectionMap.get(comment.post_id);
171
+ if (!contentId || !collection) {
172
+ result.skipped++;
173
+ continue;
174
+ }
175
+ const parsed = new Date(comment.date_gmt);
176
+ const createdAt = Number.isNaN(parsed.getTime()) ? (/* @__PURE__ */ new Date()).toISOString() : parsed.toISOString();
177
+ const existing = await db.selectFrom("_dineway_comments").select("id").where("content_id", "=", contentId).where("author_email", "=", comment.author_email).where("created_at", "=", createdAt).where("body", "=", comment.body).executeTakeFirst();
178
+ const parentId = comment.parent_id !== null ? rootIdMap.get(comment.parent_id) ?? null : null;
179
+ if (existing) {
180
+ rootIdMap.set(comment.id, parentId ?? existing.id);
181
+ result.skipped++;
182
+ continue;
183
+ }
184
+ const id = ulid();
185
+ await db.insertInto("_dineway_comments").values({
186
+ id,
187
+ collection,
188
+ content_id: contentId,
189
+ parent_id: parentId,
190
+ author_name: comment.author_name || "Anonymous",
191
+ author_email: comment.author_email,
192
+ author_user_id: null,
193
+ body: comment.body,
194
+ status: comment.status,
195
+ ip_hash: null,
196
+ user_agent: null,
197
+ moderation_metadata: null,
198
+ created_at: createdAt,
199
+ updated_at: createdAt
200
+ }).execute();
201
+ rootIdMap.set(comment.id, parentId ?? id);
202
+ result.imported++;
203
+ } catch (error) {
204
+ result.errors.push({
205
+ comment: label,
206
+ error: error instanceof Error ? error.message : String(error)
207
+ });
208
+ }
209
+ }
210
+ return result;
211
+ }
212
+
213
+ //#endregion
214
+ //#region src/import/sections.ts
215
+ /**
216
+ * Import reusable blocks (wp_block post type) from WXR as sections
217
+ *
218
+ * @param posts - All posts from WXR (will filter to wp_block)
219
+ * @param db - Database connection
220
+ * @returns Import result with counts
221
+ */
222
+ async function importReusableBlocksAsSections(posts, db) {
223
+ const result = {
224
+ sectionsCreated: 0,
225
+ sectionsSkipped: 0,
226
+ errors: []
227
+ };
228
+ const reusableBlocks = posts.filter((post) => post.postType === "wp_block");
229
+ if (reusableBlocks.length === 0) return result;
230
+ for (const block of reusableBlocks) try {
231
+ const slug = block.postName || slugify(block.title || `block-${block.id || Date.now()}`);
232
+ if (await db.selectFrom("_dineway_sections").select("id").where("slug", "=", slug).executeTakeFirst()) {
233
+ result.sectionsSkipped++;
234
+ continue;
235
+ }
236
+ const content = block.content ? gutenbergToPortableText(block.content) : [];
237
+ const id = ulid();
238
+ const now = (/* @__PURE__ */ new Date()).toISOString();
239
+ await db.insertInto("_dineway_sections").values({
240
+ id,
241
+ slug,
242
+ title: block.title || "Untitled Block",
243
+ description: null,
244
+ keywords: null,
245
+ content: JSON.stringify(content),
246
+ preview_media_id: null,
247
+ source: "import",
248
+ theme_id: null,
249
+ created_at: now,
250
+ updated_at: now
251
+ }).execute();
252
+ result.sectionsCreated++;
253
+ } catch (error) {
254
+ result.errors.push({
255
+ title: block.title || "Untitled Block",
256
+ error: error instanceof Error ? error.message : String(error)
257
+ });
258
+ }
259
+ return result;
260
+ }
261
+
262
+ //#endregion
263
+ //#region src/import/settings.ts
264
+ /** Options key prefix used by the site settings module (`settings/index.ts`). */
265
+ const SETTINGS_PREFIX = "site:";
266
+ /**
267
+ * Import site settings from analysis into Dineway site settings.
268
+ *
269
+ * Writes the `site:*` options consumed by `getSiteSettings()` and invalidates
270
+ * the settings cache. Logo/favicon are only applied when the caller resolved
271
+ * them to Dineway media IDs.
272
+ *
273
+ * @param settings - Site settings analysis
274
+ * @param db - Database connection
275
+ * @param overwrite - Whether to overwrite existing settings
276
+ * @param media - Resolved media IDs for logo/favicon
277
+ */
278
+ async function importSiteSettings(settings, db, overwrite = false, media = {}) {
279
+ const result = {
280
+ applied: [],
281
+ skipped: [],
282
+ errors: []
283
+ };
284
+ const updates = [];
285
+ if (settings.title) updates.push({
286
+ setting: "title",
287
+ value: settings.title
288
+ });
289
+ if (settings.tagline) updates.push({
290
+ setting: "tagline",
291
+ value: settings.tagline
292
+ });
293
+ if (media.logoMediaId) updates.push({
294
+ setting: "logo",
295
+ value: { mediaId: media.logoMediaId }
296
+ });
297
+ if (media.faviconMediaId) updates.push({
298
+ setting: "favicon",
299
+ value: { mediaId: media.faviconMediaId }
300
+ });
301
+ if (updates.length === 0) return result;
302
+ const options = new OptionsRepository(db);
303
+ try {
304
+ for (const { setting, value } of updates) try {
305
+ const key = `${SETTINGS_PREFIX}${setting}`;
306
+ if (!overwrite) {
307
+ if (await options.get(key) !== null) {
308
+ result.skipped.push(setting);
309
+ continue;
310
+ }
311
+ }
312
+ await options.set(key, value);
313
+ result.applied.push(setting);
314
+ } catch (error) {
315
+ result.errors.push({
316
+ setting,
317
+ error: error instanceof Error ? error.message : String(error)
318
+ });
319
+ }
320
+ } finally {
321
+ if (result.applied.length > 0) invalidateSiteSettingsCache();
322
+ }
323
+ return result;
324
+ }
325
+ /**
326
+ * Parse site settings from WordPress plugin options response.
327
+ */
328
+ function parseSiteSettingsFromPlugin(options) {
329
+ const settings = {};
330
+ if (typeof options.blogname === "string" && options.blogname.trim() !== "") settings.title = options.blogname;
331
+ if (typeof options.blogdescription === "string" && options.blogdescription.trim() !== "") settings.tagline = options.blogdescription;
332
+ if (typeof options.custom_logo_url === "string" && options.custom_logo_url !== "") settings.logo = {
333
+ url: options.custom_logo_url,
334
+ id: typeof options.custom_logo === "number" ? options.custom_logo : void 0
335
+ };
336
+ if (typeof options.site_icon_url === "string" && options.site_icon_url !== "") settings.favicon = {
337
+ url: options.site_icon_url,
338
+ id: typeof options.site_icon === "number" ? options.site_icon : void 0
339
+ };
340
+ return settings;
341
+ }
342
+
343
+ //#endregion
344
+ //#region src/import/registry.ts
345
+ /**
346
+ * Import source registry
347
+ *
348
+ * Manages available import sources and provides URL probing.
349
+ */
350
+ const TRAILING_SLASHES_PATTERN = /\/+$/;
351
+ /** Registered import sources */
352
+ const sources = /* @__PURE__ */ new Map();
353
+ /**
354
+ * Register an import source
355
+ */
356
+ function registerSource(source) {
357
+ sources.set(source.id, source);
358
+ }
359
+ /**
360
+ * Get a source by ID
361
+ */
362
+ function getSource(id) {
363
+ return sources.get(id);
364
+ }
365
+ /**
366
+ * Get all registered sources
367
+ */
368
+ function getAllSources() {
369
+ return [...sources.values()];
370
+ }
371
+ /**
372
+ * Get sources that can handle file uploads
373
+ */
374
+ function getFileSources() {
375
+ return getAllSources().filter((s) => s.requiresFile);
376
+ }
377
+ /**
378
+ * Get sources that can probe URLs
379
+ */
380
+ function getUrlSources() {
381
+ return getAllSources().filter((s) => s.canProbe);
382
+ }
383
+ /**
384
+ * Probe a URL against all registered sources
385
+ *
386
+ * Returns probe results sorted by confidence (definite > likely > possible)
387
+ */
388
+ async function probeUrl(url) {
389
+ let normalizedUrl = url.trim();
390
+ if (!normalizedUrl.startsWith("http")) normalizedUrl = `https://${normalizedUrl}`;
391
+ normalizedUrl = normalizedUrl.replace(TRAILING_SLASHES_PATTERN, "");
392
+ await resolveAndValidateExternalUrl(normalizedUrl);
393
+ const results = [];
394
+ const probePromises = getUrlSources().map(async (source) => {
395
+ try {
396
+ const result = await source.probe?.(normalizedUrl);
397
+ if (result) return result;
398
+ } catch (error) {
399
+ console.debug(`Probe failed for ${source.id}:`, error);
400
+ }
401
+ return null;
402
+ });
403
+ const probeResults = await Promise.allSettled(probePromises);
404
+ for (const result of probeResults) if (result.status === "fulfilled" && result.value) results.push(result.value);
405
+ const confidenceOrder = {
406
+ definite: 0,
407
+ likely: 1,
408
+ possible: 2
409
+ };
410
+ results.sort((a, b) => confidenceOrder[a.confidence] - confidenceOrder[b.confidence]);
411
+ return {
412
+ url: normalizedUrl,
413
+ isWordPress: results.length > 0,
414
+ bestMatch: results[0] ?? null,
415
+ allMatches: results
416
+ };
417
+ }
418
+ /**
419
+ * Clear all registered sources (useful for testing)
420
+ */
421
+ function clearSources() {
422
+ sources.clear();
423
+ }
424
+
425
+ //#endregion
426
+ //#region src/import/sources/wxr.ts
427
+ /**
428
+ * WXR (WordPress eXtended RSS) import source
429
+ *
430
+ * Handles WordPress export file uploads (.xml).
431
+ * This wraps the existing WXR parsing and analysis logic.
432
+ */
433
+ const wxrSource = {
434
+ id: "wxr",
435
+ name: "WordPress Export File",
436
+ description: "Upload a WordPress export file (.xml)",
437
+ icon: "upload",
438
+ requiresFile: true,
439
+ canProbe: false,
440
+ async analyze(input, context) {
441
+ if (input.type !== "file") throw new Error("WXR source requires a file input");
442
+ return analyzeWxrData(await parseWxrString(await input.file.text()), context.getExistingCollections ? await context.getExistingCollections() : /* @__PURE__ */ new Map());
443
+ },
444
+ async *fetchContent(input, options) {
445
+ if (input.type !== "file") throw new Error("WXR source requires a file input");
446
+ const wxr = await parseWxrString(await input.file.text());
447
+ const attachmentMap = buildAttachmentMap(wxr.attachments);
448
+ let count = 0;
449
+ for (const post of wxr.posts) {
450
+ const postType = post.postType || "post";
451
+ if (!options.postTypes.includes(postType)) continue;
452
+ if (isInternalPostType(postType)) continue;
453
+ if (!options.includeDrafts && post.status !== "publish") continue;
454
+ yield wxrPostToNormalizedItem(post, attachmentMap, wxr.site.link || "");
455
+ count++;
456
+ if (options.limit && count >= options.limit) break;
457
+ }
458
+ }
459
+ };
460
+ /**
461
+ * Analyze WXR data and return normalized ImportAnalysis
462
+ */
463
+ function analyzeWxrData(wxr, existingCollections) {
464
+ const postTypeCounts = /* @__PURE__ */ new Map();
465
+ const postTypesWithThumbnails = /* @__PURE__ */ new Set();
466
+ const metaKeys = /* @__PURE__ */ new Map();
467
+ const authorPostCounts = /* @__PURE__ */ new Map();
468
+ for (const post of wxr.posts) {
469
+ const type = post.postType || "post";
470
+ postTypeCounts.set(type, (postTypeCounts.get(type) || 0) + 1);
471
+ if (post.creator) authorPostCounts.set(post.creator, (authorPostCounts.get(post.creator) || 0) + 1);
472
+ if (post.meta.has("_thumbnail_id")) postTypesWithThumbnails.add(type);
473
+ for (const [key, value] of post.meta) {
474
+ const existing = metaKeys.get(key);
475
+ if (existing) {
476
+ existing.count++;
477
+ if (existing.samples.length < 3 && value) existing.samples.push(value.slice(0, 100));
478
+ } else metaKeys.set(key, {
479
+ count: 1,
480
+ samples: value ? [value.slice(0, 100)] : [],
481
+ isInternal: isInternalMetaKey(key)
482
+ });
483
+ }
484
+ }
485
+ const customFields = [...metaKeys.entries()].filter(([_, info]) => !info.isInternal).map(([key, info]) => ({
486
+ key,
487
+ count: info.count,
488
+ samples: info.samples,
489
+ suggestedField: mapMetaKeyToField(key),
490
+ suggestedType: inferMetaType(key, info.samples[0]),
491
+ isInternal: info.isInternal
492
+ })).toSorted((a, b) => b.count - a.count);
493
+ const postTypes = [...postTypeCounts.entries()].filter(([type]) => !isInternalPostType(type)).map(([name, count]) => {
494
+ const suggestedCollection = mapPostTypeToCollection(name);
495
+ const existingCollection = existingCollections.get(suggestedCollection);
496
+ const requiredFields = [...BASE_REQUIRED_FIELDS];
497
+ if (postTypesWithThumbnails.has(name)) requiredFields.push(FEATURED_IMAGE_FIELD);
498
+ return {
499
+ name,
500
+ count,
501
+ suggestedCollection,
502
+ requiredFields,
503
+ schemaStatus: checkSchemaCompatibility(requiredFields, existingCollection)
504
+ };
505
+ }).toSorted((a, b) => b.count - a.count);
506
+ const attachmentItems = wxr.attachments.map((att) => {
507
+ const filename = att.url ? getFilenameFromUrl(att.url) : void 0;
508
+ const mimeType = filename ? guessMimeType(filename) : void 0;
509
+ return {
510
+ id: att.id,
511
+ title: att.title,
512
+ url: att.url,
513
+ filename,
514
+ mimeType
515
+ };
516
+ });
517
+ const navMenus = wxr.navMenus.map((menu) => ({
518
+ name: menu.name,
519
+ label: menu.label,
520
+ itemCount: menu.items.length
521
+ }));
522
+ const taxonomyMap = /* @__PURE__ */ new Map();
523
+ for (const term of wxr.terms) {
524
+ if (term.taxonomy === "category" || term.taxonomy === "post_tag" || term.taxonomy === "nav_menu") continue;
525
+ const existing = taxonomyMap.get(term.taxonomy);
526
+ if (existing) {
527
+ existing.count++;
528
+ if (existing.samples.length < 3) existing.samples.push(term.name);
529
+ } else taxonomyMap.set(term.taxonomy, {
530
+ count: 1,
531
+ samples: [term.name]
532
+ });
533
+ }
534
+ const customTaxonomies = Array.from(taxonomyMap.entries(), ([slug, info]) => ({
535
+ slug,
536
+ termCount: info.count,
537
+ sampleTerms: info.samples
538
+ })).toSorted((a, b) => b.termCount - a.termCount);
539
+ const reusableBlocks = wxr.posts.filter((post) => post.postType === "wp_block").map((post) => ({
540
+ id: post.id || 0,
541
+ title: post.title || "Untitled Block",
542
+ slug: post.postName || slugify(post.title || `block-${post.id || Date.now()}`)
543
+ }));
544
+ return {
545
+ sourceId: "wxr",
546
+ site: {
547
+ title: wxr.site.title || "WordPress Site",
548
+ url: wxr.site.link || ""
549
+ },
550
+ postTypes,
551
+ attachments: {
552
+ count: wxr.attachments.length,
553
+ items: attachmentItems
554
+ },
555
+ categories: wxr.categories.length,
556
+ tags: wxr.tags.length,
557
+ authors: wxr.authors.map((a) => ({
558
+ id: a.id,
559
+ login: a.login,
560
+ email: a.email,
561
+ displayName: a.displayName || a.login || "Unknown",
562
+ postCount: a.login ? authorPostCounts.get(a.login) || 0 : 0
563
+ })),
564
+ navMenus: navMenus.length > 0 ? navMenus : void 0,
565
+ customTaxonomies: customTaxonomies.length > 0 ? customTaxonomies : void 0,
566
+ reusableBlocks: reusableBlocks.length > 0 ? reusableBlocks : void 0,
567
+ customFields
568
+ };
569
+ }
570
+ /**
571
+ * Convert a WXR post to a normalized item
572
+ */
573
+ function wxrPostToNormalizedItem(post, attachmentMap, siteUrl = "") {
574
+ const content = post.content ? gutenbergToPortableText(post.content) : [];
575
+ if (siteUrl) relativizeContentLinks(content, siteUrl);
576
+ const thumbnailId = post.meta.get("_thumbnail_id");
577
+ const featuredImage = thumbnailId ? attachmentMap.get(String(thumbnailId)) : void 0;
578
+ let customTaxonomies;
579
+ if (post.customTaxonomies && post.customTaxonomies.size > 0) {
580
+ const filtered = Object.fromEntries([...post.customTaxonomies].filter(([taxonomy]) => taxonomy !== "language"));
581
+ if (Object.keys(filtered).length > 0) customTaxonomies = filtered;
582
+ }
583
+ return {
584
+ sourceId: post.id || 0,
585
+ postType: post.postType || "post",
586
+ status: mapWpStatus(post.status),
587
+ slug: post.postName || slugify(post.title || `post-${post.id || Date.now()}`),
588
+ title: post.title || "Untitled",
589
+ content,
590
+ excerpt: post.excerpt,
591
+ date: parseWxrDate(post.postDateGmt, post.pubDate, post.postDate) ?? /* @__PURE__ */ new Date(),
592
+ modified: parseWxrDate(post.postModifiedGmt, void 0, post.postModified),
593
+ author: post.creator,
594
+ categories: post.categories,
595
+ tags: post.tags,
596
+ meta: Object.fromEntries(post.meta),
597
+ featuredImage,
598
+ parentId: post.postParent && post.postParent !== 0 ? post.postParent : void 0,
599
+ menuOrder: post.menuOrder,
600
+ customTaxonomies,
601
+ locale: post.locale,
602
+ translationGroup: post.translationGroup
603
+ };
604
+ }
605
+ /**
606
+ * WordPress uses "0000-00-00 00:00:00" as a sentinel for missing GMT dates
607
+ * (e.g. unpublished drafts). This must be treated as absent.
608
+ */
609
+ const WXR_ZERO_DATE = "0000-00-00 00:00:00";
610
+ /**
611
+ * Parse a WXR date with the correct fallback chain:
612
+ * 1. GMT date (always UTC, most reliable)
613
+ * 2. pubDate (RFC 2822, includes timezone offset)
614
+ * 3. Site-local date (MySQL datetime without timezone, imprecise but best available)
615
+ *
616
+ * Returns undefined when none of the inputs yield a valid date.
617
+ * Callers that need a guaranteed Date should use `?? new Date()`.
618
+ */
619
+ function parseWxrDate(gmtDate, pubDate, localDate) {
620
+ if (gmtDate && gmtDate !== WXR_ZERO_DATE) return /* @__PURE__ */ new Date(gmtDate.replace(" ", "T") + "Z");
621
+ if (pubDate) {
622
+ const d = new Date(pubDate);
623
+ if (!isNaN(d.getTime())) return d;
624
+ }
625
+ if (localDate) {
626
+ const d = new Date(localDate.replace(" ", "T"));
627
+ if (!isNaN(d.getTime())) return d;
628
+ }
629
+ }
630
+
631
+ //#endregion
632
+ //#region src/import/wxr-taxonomies.ts
633
+ var WxrTaxonomyConflictError = class extends Error {
634
+ publicMessage;
635
+ constructor(publicMessage, options) {
636
+ super(publicMessage, options);
637
+ this.name = "WxrTaxonomyConflictError";
638
+ this.publicMessage = publicMessage;
639
+ }
640
+ };
641
+ function isWxrTaxonomyConflictError(error) {
642
+ return error instanceof WxrTaxonomyConflictError;
643
+ }
644
+ function makeState() {
645
+ return { plan: {
646
+ termsCreated: {},
647
+ termsReused: {},
648
+ missingTaxonomies: [],
649
+ termIdByNameAndSlug: /* @__PURE__ */ new Map(),
650
+ collectionsByTaxonomy: /* @__PURE__ */ new Map(),
651
+ translationGroupByTermId: /* @__PURE__ */ new Map()
652
+ } };
653
+ }
654
+ function bump(record, key) {
655
+ record[key] = (record[key] ?? 0) + 1;
656
+ }
657
+ function rememberTerm(state, taxonomyName, slug, termId) {
658
+ let bySlug = state.plan.termIdByNameAndSlug.get(taxonomyName);
659
+ if (!bySlug) {
660
+ bySlug = /* @__PURE__ */ new Map();
661
+ state.plan.termIdByNameAndSlug.set(taxonomyName, bySlug);
662
+ }
663
+ bySlug.set(slug, termId);
664
+ }
665
+ function parseDefCollections(raw) {
666
+ if (!raw) return [];
667
+ try {
668
+ const parsed = JSON.parse(raw);
669
+ if (Array.isArray(parsed)) return parsed.filter((collection) => typeof collection === "string");
670
+ } catch {}
671
+ return [];
672
+ }
673
+ async function findTaxonomyDef(db, name, locale) {
674
+ const chain = resolveLocaleChain(locale);
675
+ if (chain.length === 0) {
676
+ const row = await db.selectFrom("_dineway_taxonomy_defs").selectAll().where("name", "=", name).orderBy("locale", "asc").executeTakeFirst();
677
+ return row ? {
678
+ id: row.id,
679
+ collections: parseDefCollections(row.collections)
680
+ } : null;
681
+ }
682
+ for (const tryLocale of chain) {
683
+ const row = await db.selectFrom("_dineway_taxonomy_defs").selectAll().where("name", "=", name).where("locale", "=", tryLocale).executeTakeFirst();
684
+ if (row) return {
685
+ id: row.id,
686
+ collections: parseDefCollections(row.collections)
687
+ };
688
+ }
689
+ return null;
690
+ }
691
+ async function ensureTerm(repo, state, taxonomyName, slug, label, description, locale) {
692
+ const cached = state.plan.termIdByNameAndSlug.get(taxonomyName)?.get(slug);
693
+ if (cached) return cached;
694
+ const existing = await repo.findBySlug(taxonomyName, slug, locale);
695
+ if (existing) {
696
+ bump(state.plan.termsReused, taxonomyName);
697
+ rememberTerm(state, taxonomyName, slug, existing.id);
698
+ return existing.id;
699
+ }
700
+ const translationOf = (await repo.findBySlug(taxonomyName, slug))?.id;
701
+ const created = await repo.create({
702
+ name: taxonomyName,
703
+ slug,
704
+ label,
705
+ data: description ? { description } : void 0,
706
+ locale,
707
+ translationOf
708
+ });
709
+ bump(state.plan.termsCreated, taxonomyName);
710
+ rememberTerm(state, taxonomyName, slug, created.id);
711
+ return created.id;
712
+ }
713
+ function labelFor(post, taxonomy, slug) {
714
+ const key = `${taxonomy}\u0000${slug}`;
715
+ return post.taxonomyLabels?.get(key) ?? slug;
716
+ }
717
+ async function preImportWxrTaxonomies(db, posts, categories, tags, terms, locale) {
718
+ const state = makeState();
719
+ const repo = new TaxonomyRepository(db);
720
+ const defCache = /* @__PURE__ */ new Map();
721
+ const lookupDef = async (name) => {
722
+ if (defCache.has(name)) return defCache.get(name) ?? null;
723
+ const def = await findTaxonomyDef(db, name, locale);
724
+ defCache.set(name, def);
725
+ if (def) state.plan.collectionsByTaxonomy.set(name, new Set(def.collections));
726
+ return def;
727
+ };
728
+ const categoryDef = await lookupDef("category");
729
+ if (categoryDef) for (const category of categories) {
730
+ const slug = category.nicename;
731
+ const label = category.name;
732
+ if (!slug || !label) continue;
733
+ await ensureTerm(repo, state, "category", slug, label, category.description, locale);
734
+ }
735
+ else if (categories.length > 0) state.plan.missingTaxonomies.push("category");
736
+ const tagDef = await lookupDef("tag");
737
+ if (tagDef) for (const tag of tags) {
738
+ const slug = tag.slug;
739
+ const label = tag.name;
740
+ if (!slug || !label) continue;
741
+ await ensureTerm(repo, state, "tag", slug, label, tag.description, locale);
742
+ }
743
+ else if (tags.length > 0) state.plan.missingTaxonomies.push("tag");
744
+ for (const term of terms) {
745
+ if (term.taxonomy === "nav_menu" || term.taxonomy === "language") continue;
746
+ const taxonomyName = term.taxonomy === "post_tag" ? "tag" : term.taxonomy;
747
+ if (!await lookupDef(taxonomyName)) {
748
+ if (!state.plan.missingTaxonomies.includes(taxonomyName)) state.plan.missingTaxonomies.push(taxonomyName);
749
+ continue;
750
+ }
751
+ await ensureTerm(repo, state, taxonomyName, term.slug, term.name, term.description, locale);
752
+ }
753
+ let recordedMissingCategoryFromPosts = false;
754
+ let recordedMissingTagFromPosts = false;
755
+ for (const post of posts) {
756
+ for (const slug of post.categories) {
757
+ if (!categoryDef) {
758
+ if (!recordedMissingCategoryFromPosts && !state.plan.missingTaxonomies.includes("category")) {
759
+ state.plan.missingTaxonomies.push("category");
760
+ recordedMissingCategoryFromPosts = true;
761
+ }
762
+ break;
763
+ }
764
+ if (state.plan.termIdByNameAndSlug.get("category")?.has(slug)) continue;
765
+ await ensureTerm(repo, state, "category", slug, labelFor(post, "category", slug), void 0, locale);
766
+ }
767
+ for (const slug of post.tags) {
768
+ if (!tagDef) {
769
+ if (!recordedMissingTagFromPosts && !state.plan.missingTaxonomies.includes("tag")) {
770
+ state.plan.missingTaxonomies.push("tag");
771
+ recordedMissingTagFromPosts = true;
772
+ }
773
+ break;
774
+ }
775
+ if (state.plan.termIdByNameAndSlug.get("tag")?.has(slug)) continue;
776
+ await ensureTerm(repo, state, "tag", slug, labelFor(post, "tag", slug), void 0, locale);
777
+ }
778
+ if (!post.customTaxonomies) continue;
779
+ for (const [rawName, slugs] of post.customTaxonomies) {
780
+ if (rawName === "nav_menu" || rawName === "language") continue;
781
+ const taxonomyName = rawName === "post_tag" ? "tag" : rawName;
782
+ if (!await lookupDef(taxonomyName)) {
783
+ if (!state.plan.missingTaxonomies.includes(taxonomyName)) state.plan.missingTaxonomies.push(taxonomyName);
784
+ continue;
785
+ }
786
+ for (const slug of slugs) {
787
+ if (state.plan.termIdByNameAndSlug.get(taxonomyName)?.has(slug)) continue;
788
+ await ensureTerm(repo, state, taxonomyName, slug, labelFor(post, taxonomyName, slug), void 0, locale);
789
+ }
790
+ }
791
+ }
792
+ invalidateTermCache();
793
+ return state.plan;
794
+ }
795
+ function resolvePostTermAssignments(collection, post, plan) {
796
+ const result = /* @__PURE__ */ new Map();
797
+ const seen = /* @__PURE__ */ new Set();
798
+ const tryResolve = (taxonomyName, slug) => {
799
+ const termId = plan.termIdByNameAndSlug.get(taxonomyName)?.get(slug);
800
+ if (!termId) return;
801
+ const collectionFilter = plan.collectionsByTaxonomy.get(taxonomyName);
802
+ if (collectionFilter && collectionFilter.size > 0 && !collectionFilter.has(collection)) return;
803
+ const dedupeKey = `${taxonomyName}\u0000${termId}`;
804
+ if (seen.has(dedupeKey)) return;
805
+ seen.add(dedupeKey);
806
+ const existing = result.get(taxonomyName);
807
+ if (existing) existing.push(termId);
808
+ else result.set(taxonomyName, [termId]);
809
+ };
810
+ for (const slug of post.categories) tryResolve("category", slug);
811
+ for (const slug of post.tags) tryResolve("tag", slug);
812
+ if (post.customTaxonomies) for (const [rawName, slugs] of post.customTaxonomies) {
813
+ if (rawName === "nav_menu" || rawName === "language") continue;
814
+ const taxonomyName = rawName === "post_tag" ? "tag" : rawName;
815
+ for (const slug of slugs) tryResolve(taxonomyName, slug);
816
+ }
817
+ return result;
818
+ }
819
+ async function attachPostTaxonomies(db, collection, entryId, post, plan) {
820
+ const repo = new TaxonomyRepository(db);
821
+ const resolved = resolvePostTermAssignments(collection, post, plan);
822
+ let attached = 0;
823
+ for (const [, termIds] of resolved) for (const termId of termIds) if (await attachToEntryCountingInserts(db, repo, plan, collection, entryId, termId)) attached++;
824
+ return attached;
825
+ }
826
+ async function setPostTermAssignmentsReplacing(db, collection, entryId, post, plan) {
827
+ const repo = new TaxonomyRepository(db);
828
+ const resolved = resolvePostTermAssignments(collection, post, plan);
829
+ let attached = 0;
830
+ for (const [taxonomyName, termIds] of resolved) {
831
+ await repo.setTermsForEntry(collection, entryId, taxonomyName, termIds);
832
+ attached += termIds.length;
833
+ }
834
+ return attached;
835
+ }
836
+ async function termTranslationGroup(repo, plan, termId) {
837
+ const cached = plan.translationGroupByTermId.get(termId);
838
+ if (cached !== void 0) return cached;
839
+ const group = (await repo.findById(termId))?.translationGroup ?? null;
840
+ plan.translationGroupByTermId.set(termId, group);
841
+ return group;
842
+ }
843
+ async function attachToEntryCountingInserts(db, repo, plan, collection, entryId, termId) {
844
+ const group = await termTranslationGroup(repo, plan, termId);
845
+ if (!group) return false;
846
+ if (await db.selectFrom("content_taxonomies").select("collection").where("collection", "=", collection).where("entry_id", "=", entryId).where("taxonomy_id", "=", group).executeTakeFirst()) return false;
847
+ await repo.attachToEntry(collection, entryId, termId);
848
+ return true;
849
+ }
850
+ async function mirrorTermsToLocales(db, plan, postLocales, canonicalLocale) {
851
+ const localeSet = /* @__PURE__ */ new Set();
852
+ for (const locale of postLocales) {
853
+ if (!locale || locale === canonicalLocale) continue;
854
+ localeSet.add(locale);
855
+ }
856
+ if (localeSet.size === 0) return;
857
+ const repo = new TaxonomyRepository(db);
858
+ for (const [taxonomyName, bySlug] of plan.termIdByNameAndSlug) for (const [slug, canonicalTermId] of bySlug) {
859
+ const canonicalGroup = await termTranslationGroup(repo, plan, canonicalTermId);
860
+ if (!canonicalGroup) continue;
861
+ for (const locale of localeSet) {
862
+ const existing = await repo.findBySlug(taxonomyName, slug, locale);
863
+ if (existing) {
864
+ if (existing.translationGroup !== canonicalGroup) throw new WxrTaxonomyConflictError(`Cannot import: term "${taxonomyName}/${slug}" already exists at locale "${locale}" in a different translation group than the canonical row at this import's locale. Reconcile the rows in the admin and retry.`);
865
+ continue;
866
+ }
867
+ try {
868
+ await repo.create({
869
+ name: taxonomyName,
870
+ slug,
871
+ label: slug,
872
+ locale,
873
+ translationOf: canonicalTermId
874
+ });
875
+ } catch (error) {
876
+ const message = error instanceof Error ? error.message.toLowerCase() : "";
877
+ if (!(message.includes("unique constraint failed") || message.includes("duplicate key"))) throw error;
878
+ const winner = await repo.findBySlug(taxonomyName, slug, locale);
879
+ if (!winner) throw new WxrTaxonomyConflictError(`Cannot import: term "${taxonomyName}/${slug}" raced UNIQUE at locale "${locale}" but no row is visible afterwards. Retry the import.`, { cause: error });
880
+ if (winner.translationGroup !== canonicalGroup) throw new WxrTaxonomyConflictError(`Cannot import: term "${taxonomyName}/${slug}" raced UNIQUE at locale "${locale}" with a different translation group. Reconcile the rows in the admin and retry.`, { cause: error });
881
+ }
882
+ }
883
+ }
884
+ }
885
+
886
+ //#endregion
887
+ //#region src/import/sources/wordpress-rest.ts
888
+ /**
889
+ * WordPress REST API probe
890
+ *
891
+ * Probes self-hosted WordPress sites to detect capabilities.
892
+ * This source is probe-only - it tells users what's available
893
+ * and suggests next steps (usually: upload WXR file).
894
+ */
895
+ const TRAILING_SLASHES = /\/+$/;
896
+ const WP_JSON_SUFFIX = /\/wp-json\/?$/;
897
+ const wordpressRestSource = {
898
+ id: "wordpress-rest",
899
+ name: "WordPress Site",
900
+ description: "Connect to a self-hosted WordPress site",
901
+ icon: "globe",
902
+ requiresFile: false,
903
+ canProbe: true,
904
+ async probe(url) {
905
+ try {
906
+ const siteUrl = normalizeUrl(url);
907
+ validateExternalUrl(siteUrl);
908
+ const response = await ssrfSafeFetch(`${siteUrl}/wp-json/`, {
909
+ headers: { Accept: "application/json" },
910
+ signal: AbortSignal.timeout(1e4)
911
+ });
912
+ if (!response.ok) {
913
+ if (!(await ssrfSafeFetch(`${siteUrl}/?rest_route=/`, {
914
+ headers: { Accept: "application/json" },
915
+ signal: AbortSignal.timeout(1e4)
916
+ })).ok) return null;
917
+ }
918
+ const data = await response.json();
919
+ if (!data.namespaces?.includes("wp/v2")) return null;
920
+ const preview = await getPublicContentCounts(siteUrl);
921
+ const hasAppPasswords = !!data.authentication?.["application-passwords"];
922
+ return {
923
+ sourceId: "wordpress-rest",
924
+ confidence: "definite",
925
+ detected: {
926
+ platform: "wordpress",
927
+ siteTitle: data.name,
928
+ siteUrl: data.url || data.home || siteUrl
929
+ },
930
+ capabilities: {
931
+ publicContent: true,
932
+ privateContent: false,
933
+ customPostTypes: false,
934
+ allMeta: false,
935
+ mediaStream: true
936
+ },
937
+ auth: hasAppPasswords ? {
938
+ type: "password",
939
+ instructions: "To import drafts and private content, create an Application Password in WordPress → Users → Your Profile → Application Passwords"
940
+ } : void 0,
941
+ preview,
942
+ suggestedAction: {
943
+ type: "upload",
944
+ instructions: "For a complete import including drafts, custom post types, and all metadata, export your content from WordPress (Tools → Export) and upload the file here."
945
+ }
946
+ };
947
+ } catch {
948
+ return null;
949
+ }
950
+ },
951
+ async analyze(_input, _context) {
952
+ throw new Error("Direct REST API import not implemented. Please upload a WXR export file.");
953
+ },
954
+ async *fetchContent(_input, _options) {
955
+ throw new Error("Direct REST API import not implemented. Please upload a WXR export file.");
956
+ }
957
+ };
958
+ /**
959
+ * Normalize a URL for API requests
960
+ */
961
+ function normalizeUrl(url) {
962
+ let normalized = url.trim();
963
+ if (!normalized.startsWith("http")) normalized = `https://${normalized}`;
964
+ normalized = normalized.replace(TRAILING_SLASHES, "");
965
+ normalized = normalized.replace(WP_JSON_SUFFIX, "");
966
+ return normalized;
967
+ }
968
+ /**
969
+ * Get public content counts from REST API
970
+ */
971
+ async function getPublicContentCounts(siteUrl) {
972
+ const result = {};
973
+ try {
974
+ const [postsRes, pagesRes, mediaRes] = await Promise.allSettled([
975
+ ssrfSafeFetch(`${siteUrl}/wp-json/wp/v2/posts?per_page=1`, { signal: AbortSignal.timeout(5e3) }),
976
+ ssrfSafeFetch(`${siteUrl}/wp-json/wp/v2/pages?per_page=1`, { signal: AbortSignal.timeout(5e3) }),
977
+ ssrfSafeFetch(`${siteUrl}/wp-json/wp/v2/media?per_page=1`, { signal: AbortSignal.timeout(5e3) })
978
+ ]);
979
+ if (postsRes.status === "fulfilled" && postsRes.value.ok) {
980
+ const total = postsRes.value.headers.get("X-WP-Total");
981
+ if (total) result.posts = parseInt(total, 10);
982
+ }
983
+ if (pagesRes.status === "fulfilled" && pagesRes.value.ok) {
984
+ const total = pagesRes.value.headers.get("X-WP-Total");
985
+ if (total) result.pages = parseInt(total, 10);
986
+ }
987
+ if (mediaRes.status === "fulfilled" && mediaRes.value.ok) {
988
+ const total = mediaRes.value.headers.get("X-WP-Total");
989
+ if (total) result.media = parseInt(total, 10);
990
+ }
991
+ } catch {}
992
+ return result;
993
+ }
994
+
995
+ //#endregion
996
+ //#region src/import/sources/wordpress-plugin.ts
997
+ /**
998
+ * WordPress Plugin (Dineway Exporter) import source
999
+ *
1000
+ * Connects to self-hosted WordPress sites running the Dineway Exporter plugin.
1001
+ * Provides full access to all content including drafts, custom post types, and ACF fields.
1002
+ */
1003
+ const LEADING_SLASHES = /^\/+/;
1004
+ const TRAILING_SLASH = /\/$/;
1005
+ const FIELD_KEY_SEPARATORS = /[_-]+/;
1006
+ const CORE_TAXONOMY_NAMES = new Set([
1007
+ "category",
1008
+ "categories",
1009
+ "post_tag",
1010
+ "tags"
1011
+ ]);
1012
+ const VALID_INFERRED_TYPES = new Set([
1013
+ "string",
1014
+ "text",
1015
+ "number",
1016
+ "integer",
1017
+ "boolean",
1018
+ "datetime",
1019
+ "json",
1020
+ "reference"
1021
+ ]);
1022
+ const wordpressPluginSource = {
1023
+ id: "wordpress-plugin",
1024
+ name: "WordPress (Dineway Exporter)",
1025
+ description: "Import from WordPress sites with the Dineway Exporter plugin installed",
1026
+ icon: "plug",
1027
+ requiresFile: false,
1028
+ canProbe: true,
1029
+ async probe(url) {
1030
+ try {
1031
+ const siteUrl = normalizeUrl$1(url);
1032
+ validateExternalUrl(siteUrl);
1033
+ const response = await fetchPluginApi(siteUrl, "probe", {}, { Accept: "application/json" }, 1e4);
1034
+ if (!response.ok) return null;
1035
+ const data = await response.json();
1036
+ if (!data.dineway_exporter) return null;
1037
+ return {
1038
+ sourceId: "wordpress-plugin",
1039
+ confidence: "definite",
1040
+ detected: {
1041
+ platform: "wordpress",
1042
+ version: data.wordpress_version,
1043
+ siteTitle: data.site.title,
1044
+ siteUrl: data.site.url
1045
+ },
1046
+ capabilities: {
1047
+ publicContent: true,
1048
+ privateContent: true,
1049
+ customPostTypes: true,
1050
+ allMeta: true,
1051
+ mediaStream: true
1052
+ },
1053
+ auth: data.capabilities.application_passwords ? {
1054
+ type: "password",
1055
+ instructions: data.auth_instructions.instructions
1056
+ } : void 0,
1057
+ preview: {
1058
+ posts: data.post_types.find((p) => p.name === "post")?.count,
1059
+ pages: data.post_types.find((p) => p.name === "page")?.count,
1060
+ media: data.media_count
1061
+ },
1062
+ suggestedAction: { type: "proceed" },
1063
+ i18n: pluginI18nToDetection(data.i18n)
1064
+ };
1065
+ } catch {
1066
+ return null;
1067
+ }
1068
+ },
1069
+ async analyze(input, context) {
1070
+ const { siteUrl, headers } = getRequestConfig(input);
1071
+ const response = await fetchPluginApi(siteUrl, "analyze", {}, headers, 3e4);
1072
+ if (!response.ok) {
1073
+ const error = await response.json().catch(() => ({}));
1074
+ throw new Error(error.message || `Failed to analyze site: ${response.statusText}`);
1075
+ }
1076
+ const data = await response.json();
1077
+ const existingCollections = context.getExistingCollections ? await context.getExistingCollections() : /* @__PURE__ */ new Map();
1078
+ const postTypes = data.post_types.filter((pt) => pt.total > 0).map((pt) => {
1079
+ const suggestedCollection = mapPostTypeToCollection(pt.name);
1080
+ const existingCollection = existingCollections.get(suggestedCollection);
1081
+ const requiredFields = pt.supports && "thumbnail" in pt.supports ? [...BASE_REQUIRED_FIELDS, FEATURED_IMAGE_FIELD] : [...BASE_REQUIRED_FIELDS];
1082
+ const knownSlugs = new Set(requiredFields.map((field) => field.slug));
1083
+ for (const customField of pt.custom_fields ?? []) {
1084
+ if (isPluginBookkeepingMeta(customField.key)) continue;
1085
+ const slug = sanitizeFieldSlug(customField.key);
1086
+ if (knownSlugs.has(slug)) continue;
1087
+ knownSlugs.add(slug);
1088
+ requiredFields.push({
1089
+ slug,
1090
+ label: fieldLabelFromKey(customField.key),
1091
+ type: mapInferredFieldType(customField.inferred_type),
1092
+ required: false
1093
+ });
1094
+ }
1095
+ return {
1096
+ name: pt.name,
1097
+ count: pt.total,
1098
+ suggestedCollection,
1099
+ requiredFields,
1100
+ schemaStatus: checkSchemaCompatibility(requiredFields, existingCollection)
1101
+ };
1102
+ });
1103
+ const attachments = [];
1104
+ if (data.attachments.count > 0) try {
1105
+ let page = 1;
1106
+ let totalPages = 1;
1107
+ while (page <= totalPages) {
1108
+ const mediaResponse = await fetchPluginApi(siteUrl, "media", {
1109
+ page,
1110
+ per_page: 500
1111
+ }, headers, 3e4);
1112
+ if (!mediaResponse.ok) break;
1113
+ const mediaData = await mediaResponse.json();
1114
+ totalPages = Math.max(1, mediaData.pages || 1);
1115
+ for (const item of mediaData.items) attachments.push({
1116
+ id: item.id,
1117
+ url: item.url,
1118
+ filename: item.filename,
1119
+ mimeType: item.mime_type,
1120
+ title: item.title,
1121
+ alt: item.alt,
1122
+ caption: item.caption,
1123
+ width: item.width,
1124
+ height: item.height
1125
+ });
1126
+ page++;
1127
+ }
1128
+ } catch (e) {
1129
+ console.warn("Failed to fetch media list:", e);
1130
+ }
1131
+ const categoryTaxonomy = data.taxonomies.find((t) => t.name === "category");
1132
+ const tagTaxonomy = data.taxonomies.find((t) => t.name === "post_tag");
1133
+ return {
1134
+ sourceId: "wordpress-plugin",
1135
+ site: {
1136
+ title: data.site.title,
1137
+ url: data.site.url
1138
+ },
1139
+ postTypes,
1140
+ attachments: {
1141
+ count: data.attachments.count,
1142
+ items: attachments
1143
+ },
1144
+ categories: categoryTaxonomy?.term_count ?? 0,
1145
+ tags: tagTaxonomy?.term_count ?? 0,
1146
+ authors: data.authors.map((a) => ({
1147
+ id: a.id,
1148
+ login: a.login,
1149
+ email: a.email,
1150
+ displayName: a.display_name,
1151
+ postCount: a.post_count
1152
+ })),
1153
+ i18n: pluginI18nToDetection(data.i18n)
1154
+ };
1155
+ },
1156
+ async *fetchContent(input, options) {
1157
+ const { siteUrl, headers } = getRequestConfig(input);
1158
+ for (const postType of options.postTypes) {
1159
+ let page = 1;
1160
+ let totalPages = 1;
1161
+ let yielded = 0;
1162
+ while (page <= totalPages) {
1163
+ const status = options.includeDrafts ? "any" : "publish";
1164
+ const response = await fetchPluginApi(siteUrl, "content", {
1165
+ page,
1166
+ per_page: 100,
1167
+ post_type: postType,
1168
+ status
1169
+ }, headers, 6e4);
1170
+ if (!response.ok) throw new Error(`Failed to fetch ${postType}: ${response.statusText}`);
1171
+ const data = await response.json();
1172
+ totalPages = data.pages;
1173
+ for (const post of data.items) {
1174
+ yield pluginPostToNormalizedItem(post, siteUrl);
1175
+ yielded++;
1176
+ if (options.limit && yielded >= options.limit) return;
1177
+ }
1178
+ page++;
1179
+ }
1180
+ }
1181
+ },
1182
+ async fetchMedia(url, _input) {
1183
+ validateExternalUrl(url);
1184
+ const response = await ssrfSafeFetch(url);
1185
+ if (!response.ok) throw new Error(`Failed to fetch media: ${response.statusText}`);
1186
+ return response.blob();
1187
+ }
1188
+ };
1189
+ /**
1190
+ * Convert plugin i18n info to the shared I18nDetection type.
1191
+ * Returns undefined when no multilingual plugin is detected.
1192
+ */
1193
+ function pluginI18nToDetection(i18n) {
1194
+ if (!i18n) return void 0;
1195
+ return {
1196
+ plugin: i18n.plugin,
1197
+ defaultLocale: i18n.default_locale,
1198
+ locales: i18n.locales
1199
+ };
1200
+ }
1201
+ function mapInferredFieldType(inferredType) {
1202
+ return VALID_INFERRED_TYPES.has(inferredType) ? inferredType : "string";
1203
+ }
1204
+ function fieldLabelFromKey(key) {
1205
+ return key.split(FIELD_KEY_SEPARATORS).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
1206
+ }
1207
+ function pluginApiUrl(siteUrl, endpoint, params = {}, restRoute = false) {
1208
+ const cleanEndpoint = endpoint.replace(LEADING_SLASHES, "");
1209
+ const url = restRoute ? new URL(`${siteUrl.replace(TRAILING_SLASH, "")}/`) : new URL(`${siteUrl.replace(TRAILING_SLASH, "")}/wp-json/dineway/v1/${cleanEndpoint}`);
1210
+ if (restRoute) url.searchParams.set("rest_route", `/dineway/v1/${cleanEndpoint}`);
1211
+ for (const [key, value] of Object.entries(params)) if (value !== void 0) url.searchParams.set(key, String(value));
1212
+ return url.toString();
1213
+ }
1214
+ async function fetchPluginApi(siteUrl, endpoint, params, headers, timeoutMs) {
1215
+ try {
1216
+ const response = await ssrfSafeFetch(pluginApiUrl(siteUrl, endpoint, params), {
1217
+ headers,
1218
+ signal: AbortSignal.timeout(timeoutMs)
1219
+ });
1220
+ if (response.status !== 404) return response;
1221
+ } catch {}
1222
+ return ssrfSafeFetch(pluginApiUrl(siteUrl, endpoint, params, true), {
1223
+ headers,
1224
+ signal: AbortSignal.timeout(timeoutMs)
1225
+ });
1226
+ }
1227
+ /**
1228
+ * Get request configuration from input
1229
+ */
1230
+ function getRequestConfig(input) {
1231
+ if (input.type === "url") {
1232
+ const siteUrl = normalizeUrl$1(input.url);
1233
+ validateExternalUrl(siteUrl);
1234
+ const headers = { Accept: "application/json" };
1235
+ if (input.token) headers["Authorization"] = `Basic ${input.token}`;
1236
+ return {
1237
+ siteUrl,
1238
+ headers
1239
+ };
1240
+ }
1241
+ if (input.type === "oauth") {
1242
+ const oauthSiteUrl = normalizeUrl$1(input.url);
1243
+ validateExternalUrl(oauthSiteUrl);
1244
+ return {
1245
+ siteUrl: oauthSiteUrl,
1246
+ headers: {
1247
+ Accept: "application/json",
1248
+ Authorization: `Bearer ${input.accessToken}`
1249
+ }
1250
+ };
1251
+ }
1252
+ throw new Error("WordPress plugin source requires URL or OAuth input");
1253
+ }
1254
+ /**
1255
+ * Convert plugin post to normalized item
1256
+ */
1257
+ function pluginPostToNormalizedItem(post, siteUrl) {
1258
+ const content = post.content ? gutenbergToPortableText(post.content) : [];
1259
+ relativizeContentLinks(content, siteUrl);
1260
+ const categories = post.taxonomies?.category?.map((c) => c.slug) ?? post.taxonomies?.categories?.map((c) => c.slug) ?? [];
1261
+ const tags = post.taxonomies?.post_tag?.map((t) => t.slug) ?? post.taxonomies?.tags?.map((t) => t.slug) ?? [];
1262
+ const customTaxonomies = {};
1263
+ for (const [name, terms] of Object.entries(post.taxonomies ?? {})) {
1264
+ if (CORE_TAXONOMY_NAMES.has(name)) continue;
1265
+ if (terms.length > 0) customTaxonomies[name] = terms.map((term) => term.slug);
1266
+ }
1267
+ const meta = { ...post.meta };
1268
+ if (post.acf) meta._acf = post.acf;
1269
+ if (post.yoast) meta._yoast = post.yoast;
1270
+ if (post.rankmath) meta._rankmath = post.rankmath;
1271
+ return {
1272
+ sourceId: post.id,
1273
+ postType: post.post_type,
1274
+ status: mapWpStatus(post.status),
1275
+ slug: post.slug,
1276
+ title: post.title,
1277
+ content,
1278
+ excerpt: post.excerpt || void 0,
1279
+ date: new Date(post.date_gmt || post.date),
1280
+ modified: post.modified_gmt ? new Date(post.modified_gmt) : new Date(post.modified),
1281
+ author: post.author?.login,
1282
+ categories,
1283
+ tags,
1284
+ customTaxonomies: Object.keys(customTaxonomies).length > 0 ? customTaxonomies : void 0,
1285
+ meta,
1286
+ featuredImage: post.featured_image?.url,
1287
+ locale: post.locale,
1288
+ translationGroup: post.translation_group
1289
+ };
1290
+ }
1291
+ /**
1292
+ * Fetch navigation menus from plugin API.
1293
+ * Returns an empty array when the endpoint doesn't exist on older plugins.
1294
+ */
1295
+ async function fetchPluginMenus(siteUrl, authToken) {
1296
+ const normalizedSiteUrl = normalizeUrl$1(siteUrl);
1297
+ validateExternalUrl(normalizedSiteUrl);
1298
+ const response = await fetchPluginApi(normalizedSiteUrl, "menus", {}, {
1299
+ Accept: "application/json",
1300
+ Authorization: `Basic ${authToken}`
1301
+ }, 3e4);
1302
+ if (response.status === 404) return [];
1303
+ if (!response.ok) throw new Error(`Failed to fetch menus: ${response.statusText}`);
1304
+ return response.json();
1305
+ }
1306
+ /**
1307
+ * Fetch site options from plugin API.
1308
+ */
1309
+ async function fetchPluginOptions(siteUrl, authToken) {
1310
+ const normalizedSiteUrl = normalizeUrl$1(siteUrl);
1311
+ validateExternalUrl(normalizedSiteUrl);
1312
+ const response = await fetchPluginApi(normalizedSiteUrl, "options", {}, {
1313
+ Accept: "application/json",
1314
+ Authorization: `Basic ${authToken}`
1315
+ }, 3e4);
1316
+ if (!response.ok) throw new Error(`Failed to fetch options: ${response.statusText}`);
1317
+ return response.json();
1318
+ }
1319
+ /**
1320
+ * Fetch all comments from plugin API, paginating through every page.
1321
+ * Returns an empty array when the endpoint doesn't exist on older plugins.
1322
+ */
1323
+ async function fetchPluginComments(siteUrl, authToken) {
1324
+ const normalizedSiteUrl = normalizeUrl$1(siteUrl);
1325
+ validateExternalUrl(normalizedSiteUrl);
1326
+ const comments = [];
1327
+ let page = 1;
1328
+ let totalPages = 1;
1329
+ while (page <= totalPages) {
1330
+ const response = await fetchPluginApi(normalizedSiteUrl, "comments", {
1331
+ page,
1332
+ per_page: 500
1333
+ }, {
1334
+ Accept: "application/json",
1335
+ Authorization: `Basic ${authToken}`
1336
+ }, 3e4);
1337
+ if (response.status === 404) return [];
1338
+ if (!response.ok) throw new Error(`Failed to fetch comments: ${response.statusText}`);
1339
+ const data = await response.json();
1340
+ totalPages = Math.max(1, data.pages || 1);
1341
+ comments.push(...data.items);
1342
+ page++;
1343
+ }
1344
+ return comments;
1345
+ }
1346
+
1347
+ //#endregion
1348
+ //#region src/import/index.ts
1349
+ registerSource(wordpressPluginSource);
1350
+ registerSource(wordpressRestSource);
1351
+ registerSource(wxrSource);
1352
+
1353
+ //#endregion
1354
+ export { importMenusFromPlugin as C, importCommentsFromPlugin as S, probeUrl as _, attachPostTaxonomies as a, parseSiteSettingsFromPlugin as b, preImportWxrTaxonomies as c, wxrSource as d, clearSources as f, getUrlSources as g, getSource as h, wordpressRestSource as i, setPostTermAssignmentsReplacing as l, getFileSources as m, fetchPluginMenus as n, isWxrTaxonomyConflictError as o, getAllSources as p, fetchPluginOptions as r, mirrorTermsToLocales as s, fetchPluginComments as t, parseWxrDate as u, registerSource as v, importReusableBlocksAsSections as x, importSiteSettings as y };